5と30のリビジョン間の差分 (その間の編集: 25回)
2011-05-09 16:05:10時点のリビジョン5
サイズ: 1752
編集者: TakuyaKuwahara
コメント:
2011-05-25 22:52:01時点のリビジョン30
サイズ: 11187
編集者: NU-MA
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 5: 行 5:

== 第3回課題 ==
== 資料 ==
=== Xilinx のマニュアル ===
 * [[http://japan.xilinx.com/support/documentation/sw_manuals/xilinx12_1/xst.pdf|ちょっとバージョン古いけど日本語版]]
VHDLでの例とか載ってて便利。その通りに書いて、上手くコンパイル通らないなら、新しいバージョンを参照してね! -- [[NU-MA]]
=== VHDLの書き方とか ===
 * [[http://homepage3.nifty.com/hdl_design/vhdl.htm|分かり易そうな解説]] -- [[NU-MA]]


== 第3回課題 ==
行 20: 行 27:
== 第4回課題 ==
 *配布されているfull-Adderのシミュレーションファイルについて。
== 第4回課題 ==
 *配布されているフルアダーの部品定義ファイルについて。
4fulladr.vhd中の

{{{
type IX is range 4 to 7;
  subtype I16 is INTEGER range 0 to 15;
  type J16 is range 0 to 15;
  type BIT_STREAM is array(I16 range<>) of BIT;
  type MEMORY_COMMAND is (NOP, READ, WRITE);
  type DECODE_TABLE is array(I16) of BIT;
  type std_logic_vector2 is array(NATURAL range <>, NATURAL range <>) of std_logic;
  signal TST : DECODE_TABLE;
  signal MC :MEMORY_COMMAND;

  signal BS : std_logic_vector(15 downto 0);
  signal BS2 : std_logic_vector2(7 downto 0, 3 downto 0);
  signal message : string(1 to 5) := "HELLO";
  signal OCTET : BIT_VECTOR(7 downto 0);
  constant OCTET2 : BIT_VECTOR := ('0', '1', '0', '1', '0', '1', '0', '1');
  signal address_buffer : std_logic_vector(63 downto 0);
type MEMORY_TRANSACTION is
  record
    comm : MEMORY_COMMAND;
    address : std_logic_vector(63 downto 0);
    data : std_logic_vector(63 downto 0);
  end record;

  signal MT : MEMORY_TRANSACTION;
}}}

の箇所と、STRUCTURE中の

{{{

MC <= NOP;

  MT.comm <= READ;
  MT.data <= (others => '0');
  MT.address <= address_buffer;

}}}

の部分はフルアダーと全く関係ないです。(つまり、この部分まるまる削除しても普通にシミュレーションが通る)

ここを削除するとコードがかなり読みやすくなるのでオススメ。-- TakuyaKuwahara





 *配布されているフルアダーのシミュレーションファイルについて。
行 25: 行 82:
配布ファイル3つ(ハーフアダー・フルアダー・シミュレーション用)をダウンロードしても、 配布ファイル3つ(ハーフアダー・フルアダー・シミュレーション用)をダウンロードしてコンパイルしても、
行 30: 行 87:
{{{
行 34: 行 91:
}}}
行 38: 行 95:
{{{
行 42: 行 99:
}}}
行 46: 行 103:
{{{
行 48: 行 105:
}}}
行 52: 行 109:
{{{
行 54: 行 111:


と変えて、元のフルアダーのポート名と合わせてやるとシミュレーションが通ります。-- TakuyaKuwahara

}}}

と変えて、元のフルアダーのポート名と合わせてやるとシミュレーションが通ります。

また、このシミュレーションファイルは1 fsごとにインクリメントする仕様になってますが、いくらなんでも短いのでせめて1 psか1 nsくらいに直した方がいいです。
このシミュレーションファイルを改変してスライスアダーのシミュレーションやろうとしてる人も同様です。-- TakuyaKuwahara


実機で動かすために、前回の課題で配布されたRS232Cの通信用ソースを修正して用います。
具体的には、top.vhdを修正すればよいでしょう。

文字を表示するためにはプロセスrom_inf内でrom_oにasciiコードで表された文字を直接渡します。
配布ソースでは配列rom_tに格納された文字を、rom_addrに指定されたインデックスで表示しています。

自分はsend_msg中でビットスライスアダーへの入力を更新しました。
こんなかんじ。
{{{
if uart_busy='0' and uart_go='0' then
...
V := V + 1;
input_A <= conv_std_logic_vector(V, 8);
...
}}}

論理合成後は前回と同様にunicomで動作確認が可能です。
自分はOCamlで書かれた動作確認用ソースは用いませんでした。(あとであることに気づいた) -- perim

== 第5回課題 ==

再利用性の高いコンポーネントを書くと、シミュレーションでは動くのに、FPGAに焼くと動かない事態が発生します。
これは最適化のせいで、port - 信号線の接続がラッチ挟まれたり挟まれなかったりする事が原因らしいです。(上の代の方情報。真偽不明。)
各signal/port等々がどのように最適化されるのかを知るのは面倒なので、
 1. 全パーツCLKを入れてさらに無駄な入出力を作らずうまく信号線の接続をする?(=パイプライン化?) もちろんこれでも駄目な時は駄目。
 1. なるべくコンポーネントに分けず、最適化が来ない事を祈る。
 1. VHDL/ISEマスターとなって最適化を操る。
等の対策を取る必要があります。時間が無いなら2が一番いいよね。 -- [[Naoaki Iwakiri]]

----
== もうmodelsimとかの使い方忘れた人用 ==

第4回課題の手順にそって大体の流れを書いときますね。

--(第三回でやったのに既に忘れていた自分のための覚書でもあったりなかったり)--

 *'''modelsim'''

1.部品定義ファイル、シミュレーション用ファイル(第四回課題ならそれぞれ8bitスライスアダーの定義ファイルとそれを0~255(1~256)までの全数でチェックするファイル + コンポーネント)などを用意する。

2. modelsim起動
「. ~/bin/use-msim.sh ; . ~/bin/use-ise.sh」を入力してから「vsim &」で起動。

3. プロジェクトを新規に作ってからファイルを全部加えて「Compile All」(右クリックメニュー)

→エラーが起こったらやり直し。コンポーネントとしてフルアダーとか使ってるならそのファイルも一緒にコンパイルしないと通らないので注意。

4. 「Library」タブで表示されるメニューから、「work」の中のシミュレーション用ファイルを選択し、「Simulate」

5.Wave画面を表示して左のウインドウのsimタブ内の中から出力を見たいものを選んでAdd -> To Wave -> All item in region

6.「Run -All」ボタンを押すか下に直にコマンド入力で「run 30ns -all」とかでシミュレーション開始。ボタンで開始した場合は適当に隣のStopボタンで止める。

7.動いたらおめでとうございます。


 *'''ise'''

1. さっきのファイルに加え、top.vhdとか、FPGAとの送受信に必要なファイルを全て用意する。

2. 適当に新しいプロジェクトを生成。

3.「Hierarchy」ウインドウ(左上の)の中で右クリック→Add Sourceでファイルをすべてプロジェクトに突っ込む。

スライスアダーとかのファイルもいる……と思う(未確認)

4.「xc5vlx……」をクリック → Design Utilities → Compile HDL Simulation

そのままコンパイルしても多分通らない。すぐ左にある「Edit Process Property」ボタンをクリック

5.General Optionタブで右の方にスクロールしてくと

「Please Specify」って項目あるんで「Modelsim SE VHDL」を選択。

6.「Compile HDL Simulation」を右クリック&「Run」

7.待つ。

8.コンパイルが通ったら第一段階クリア

9.できたら今度は「Hierarchy」ウインドウで今度はtopを選択&「Generate Programming File」をダブルクリック。
通ったらクリア。

 *'''impact'''

1.FPGAを繋ぐ

2.適当にプロジェクト作成&FPGAが認識されているか確認。
(一個ダメになってるコードがあるっぽいです。--(ってか多分俺が何かやらかした)--)

3.top.bitファイルがiseによって生成されているはずなので、それを選択&緑色のチップ(?)みたいなのを右クリックして「Program」
で実行。(ここら辺の細かい手順忘れました……備忘録なのに……)

4.minicomやらで出力を見る。詳しくは第三回の課題ページ。

OCamlでかかれたプログラムが課題ページにありますが、使ってないので謎。


以上。だいたい合ってるはずですが(現在進行形で確かめながら書いてますので)細かいところで間違ってるかもです。

でも大まかな流れは上の通りなはずです。-- TakuyaKuwahara

== ちょっとハマりポイント ==
 * ISEのプロジェクトを作成するときに指定するDesign Propertiesを今一度確認してください。
  * SimulatorにModelsim-SE VHDLを指定した方がうまくいくっぽい -- [[carbon_twelve]]
 * ISEで合成する際に、top.ucfを忘れないようにしてください。-- [[carbon_twelve]]

== signalとvariable ==

毎クロックprogram_counterを0~8の変域でインクリメントするサンプル。
{{{
signal program_counter : integer := 0;

send_msg: process(clk)
     begin
     if rising_edge(clk) then
          program_counter <= program_counter + 1;
          if program_counter = 9 then
               program_counter <= 0;
          end if;
    end if;
end process;
}}}
これはダメ。<<BR>>
program_counterの値が更新されるのはこのprocess文を抜けたあとなので、正しい記述の一例としては
{{{
signal program_counter : integer := 0;

send_msg: process(clk)
    
     variable tmp : integer := 0;
     
     begin
     if rising_edge(clk) then
          V := program_counter + 1;
          program_counter <= V;
          if V = 9 then
               program_counter <= 0;
          end if;
    end if;
end process;
}}}
こんな感じ。<<BR>>
(そもそも program_counter : integer range 0 to 8 と宣言すれば分岐する必要はない?(8の時に+1したら0になることを期待)でも筆者のコード・環境ではそれをしたらバグりました...情報求む) -- [[fujima]]

ハードウェア実験Tips

資料

Xilinx のマニュアル

VHDLでの例とか載ってて便利。その通りに書いて、上手くコンパイル通らないなら、新しいバージョンを参照してね! -- NU-MA

VHDLの書き方とか

第3回課題

  • iseでコンパイルが通らない。

配布ファイルがデフォルト設定に合っていない。 top.ucfの1行目、

CONFIG PART=5VLX50TFF1136-1 ;

CONFIG PART=xc5VLX50TFF1136-2 ;

に書き変えるか、プロジェクト設定のSpeedを末尾の数字に合わせる。(頭のxcは無くても通りはするよ)

第4回課題

  • 配布されているフルアダーの部品定義ファイルについて。

4fulladr.vhd中の

type IX is range 4 to 7;
  subtype I16 is INTEGER range 0 to 15;
  type J16 is range 0 to 15;
  type BIT_STREAM is array(I16 range<>) of BIT;
  type MEMORY_COMMAND is (NOP, READ, WRITE);
  type DECODE_TABLE is array(I16) of BIT;
  type std_logic_vector2 is array(NATURAL range <>, NATURAL range <>) of std_logic;
  signal TST : DECODE_TABLE;
  signal MC :MEMORY_COMMAND;

  signal BS : std_logic_vector(15 downto 0);
  signal BS2 : std_logic_vector2(7 downto 0, 3 downto 0);
  signal message : string(1 to 5) := "HELLO";
  signal OCTET : BIT_VECTOR(7 downto 0);
  constant OCTET2 : BIT_VECTOR := ('0', '1', '0', '1', '0', '1', '0', '1');
  signal address_buffer : std_logic_vector(63 downto 0);
type MEMORY_TRANSACTION is
  record
    comm    : MEMORY_COMMAND;
    address : std_logic_vector(63 downto 0);
    data    : std_logic_vector(63 downto 0);
  end record;

  signal MT : MEMORY_TRANSACTION;

の箇所と、STRUCTURE中の

MC <= NOP;

  MT.comm <= READ;
  MT.data <= (others => '0');
  MT.address <= address_buffer;

の部分はフルアダーと全く関係ないです。(つまり、この部分まるまる削除しても普通にシミュレーションが通る)

ここを削除するとコードがかなり読みやすくなるのでオススメ。-- TakuyaKuwahara

  • 配布されているフルアダーのシミュレーションファイルについて。

課題で必須ではないですが、確認のため走らせようとしてもなぜかそのままでは通らないのでちょっと加筆。

配布ファイル3つ(ハーフアダー・フルアダー・シミュレーション用)をダウンロードしてコンパイルしても、 そのままだとフルアダー定義ファイルのポート名とシミュレーション用ファイル中にコンポーネントとして宣言されたフルアダーのポート名との間に整合がとれておらず、おそらくコンパイルが通ってもシミュレートできません。

配布されているシミュレーション用ファイル(4drvfa.vhd)の

 port (IN0,IN1,CIN : in std_logic;

          S,COUT : out std_logic);

の箇所を

port (A,B,CIN : in std_logic;

          S,CO : out std_logic);

に改変し、

port map (A=>IN0,B=>IN1,CIN=>CIN,S=>S,CO=>COUT);

の部分も

port map (A=>A,B=>B,CIN=>CIN,S=>S,CO=>CO);

と変えて、元のフルアダーのポート名と合わせてやるとシミュレーションが通ります。

また、このシミュレーションファイルは1 fsごとにインクリメントする仕様になってますが、いくらなんでも短いのでせめて1 psか1 nsくらいに直した方がいいです。 このシミュレーションファイルを改変してスライスアダーのシミュレーションやろうとしてる人も同様です。-- TakuyaKuwahara

実機で動かすために、前回の課題で配布されたRS232Cの通信用ソースを修正して用います。 具体的には、top.vhdを修正すればよいでしょう。

文字を表示するためにはプロセスrom_inf内でrom_oにasciiコードで表された文字を直接渡します。 配布ソースでは配列rom_tに格納された文字を、rom_addrに指定されたインデックスで表示しています。

自分はsend_msg中でビットスライスアダーへの入力を更新しました。 こんなかんじ。

if uart_busy='0' and uart_go='0' then
...
V := V + 1;
input_A <= conv_std_logic_vector(V, 8);
...

論理合成後は前回と同様にunicomで動作確認が可能です。 自分はOCamlで書かれた動作確認用ソースは用いませんでした。(あとであることに気づいた) -- perim

第5回課題

再利用性の高いコンポーネントを書くと、シミュレーションでは動くのに、FPGAに焼くと動かない事態が発生します。 これは最適化のせいで、port - 信号線の接続がラッチ挟まれたり挟まれなかったりする事が原因らしいです。(上の代の方情報。真偽不明。) 各signal/port等々がどのように最適化されるのかを知るのは面倒なので、

  1. 全パーツCLKを入れてさらに無駄な入出力を作らずうまく信号線の接続をする?(=パイプライン化?) もちろんこれでも駄目な時は駄目。
  2. なるべくコンポーネントに分けず、最適化が来ない事を祈る。
  3. VHDL/ISEマスターとなって最適化を操る。

等の対策を取る必要があります。時間が無いなら2が一番いいよね。 -- Naoaki Iwakiri


もうmodelsimとかの使い方忘れた人用

第4回課題の手順にそって大体の流れを書いときますね。

第三回でやったのに既に忘れていた自分のための覚書でもあったりなかったり

  • modelsim

1.部品定義ファイル、シミュレーション用ファイル(第四回課題ならそれぞれ8bitスライスアダーの定義ファイルとそれを0~255(1~256)までの全数でチェックするファイル + コンポーネント)などを用意する。

2. modelsim起動 「. ~/bin/use-msim.sh ; . ~/bin/use-ise.sh」を入力してから「vsim &」で起動。

3. プロジェクトを新規に作ってからファイルを全部加えて「Compile All」(右クリックメニュー)

→エラーが起こったらやり直し。コンポーネントとしてフルアダーとか使ってるならそのファイルも一緒にコンパイルしないと通らないので注意。

4. 「Library」タブで表示されるメニューから、「work」の中のシミュレーション用ファイルを選択し、「Simulate」

5.Wave画面を表示して左のウインドウのsimタブ内の中から出力を見たいものを選んでAdd -> To Wave -> All item in region

6.「Run -All」ボタンを押すか下に直にコマンド入力で「run 30ns -all」とかでシミュレーション開始。ボタンで開始した場合は適当に隣のStopボタンで止める。

7.動いたらおめでとうございます。

  • ise

1. さっきのファイルに加え、top.vhdとか、FPGAとの送受信に必要なファイルを全て用意する。

2. 適当に新しいプロジェクトを生成。

3.「Hierarchy」ウインドウ(左上の)の中で右クリック→Add Sourceでファイルをすべてプロジェクトに突っ込む。

スライスアダーとかのファイルもいる……と思う(未確認)

4.「xc5vlx……」をクリック → Design Utilities → Compile HDL Simulation

そのままコンパイルしても多分通らない。すぐ左にある「Edit Process Property」ボタンをクリック

5.General Optionタブで右の方にスクロールしてくと

「Please Specify」って項目あるんで「Modelsim SE VHDL」を選択。

6.「Compile HDL Simulation」を右クリック&「Run」

7.待つ。

8.コンパイルが通ったら第一段階クリア

9.できたら今度は「Hierarchy」ウインドウで今度はtopを選択&「Generate Programming File」をダブルクリック。 通ったらクリア。

  • impact

1.FPGAを繋ぐ

2.適当にプロジェクト作成&FPGAが認識されているか確認。 (一個ダメになってるコードがあるっぽいです。ってか多分俺が何かやらかした

3.top.bitファイルがiseによって生成されているはずなので、それを選択&緑色のチップ(?)みたいなのを右クリックして「Program」 で実行。(ここら辺の細かい手順忘れました……備忘録なのに……)

4.minicomやらで出力を見る。詳しくは第三回の課題ページ。

OCamlでかかれたプログラムが課題ページにありますが、使ってないので謎。

以上。だいたい合ってるはずですが(現在進行形で確かめながら書いてますので)細かいところで間違ってるかもです。

でも大まかな流れは上の通りなはずです。-- TakuyaKuwahara

ちょっとハマりポイント

  • ISEのプロジェクトを作成するときに指定するDesign Propertiesを今一度確認してください。
    • SimulatorにModelsim-SE VHDLを指定した方がうまくいくっぽい -- carbon_twelve

  • ISEで合成する際に、top.ucfを忘れないようにしてください。-- carbon_twelve

signalとvariable

毎クロックprogram_counterを0~8の変域でインクリメントするサンプル。

signal program_counter : integer := 0;

send_msg: process(clk)
     begin
     if rising_edge(clk) then
          program_counter <= program_counter + 1;
          if program_counter = 9 then
               program_counter <= 0;
          end if; 
    end if;
end process;

これはダメ。
program_counterの値が更新されるのはこのprocess文を抜けたあとなので、正しい記述の一例としては

signal program_counter : integer := 0;

send_msg: process(clk)
    
     variable tmp : integer := 0;
     
     begin
     if rising_edge(clk) then
          V := program_counter + 1;
          program_counter <= V;
          if V = 9 then
               program_counter <= 0;
          end if; 
    end if;
end process;

こんな感じ。
(そもそも program_counter : integer range 0 to 8 と宣言すれば分岐する必要はない?(8の時に+1したら0になることを期待)でも筆者のコード・環境ではそれをしたらバグりました...情報求む) -- fujima


Categoryノート

ハードウェア実験/Tips (最終更新日時 2011-06-07 07:00:27 更新者 fujima)