GHDL on OS X
学科の課題でVHDLを書く必要があったのだけれど、持ち合わせてるPCがMacだけだったので、環境構築でいろいろと苦労した。
推奨環境はAltera社のQuartus II Webpackだったのだが、残念ながら今のところwineを使ってもうまく動かせなかったのでGHDLを使うことにした。
(ちなみにXilinx社のISEは驚くべきことにwineで動作したので、またまとめたいと思っている)
GHDLの使い方
ひとまず全加算器を動かしてみる。
full_adder.vhd
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.all; entity full_adder is port ( a : in STD_LOGIC; b : in STD_LOGIC; c : in STD_LOGIC; s : out STD_LOGIC; cout : out STD_LOGIC); end full_adder; architecture Behavioral of full_adder is begin s <= a xor b xor c; cout <= (a and b) or (b and c) or (c and a); end Behavioral;
全加算器の実装は回路をそのままVHDLに起こしただけ。
full_adder_tb.vhd
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity full_adder_tb is end full_adder_tb; architecture Behavioral of full_adder_tb is component full_adder port ( a : in STD_LOGIC; b : in STD_LOGIC; c : in STD_LOGIC; s : out STD_LOGIC; cout : out STD_LOGIC); end component; signal a : STD_LOGIC; signal b : STD_LOGIC; signal c : STD_LOGIC; signal s : STD_LOGIC; signal cout : STD_LOGIC; begin u0: full_adder port map ( a => a, b => b, c => c, s => s, cout => cout); process type pattern_type is record a : STD_LOGIC; b : STD_LOGIC; c : STD_LOGIC; s : STD_LOGIC; cout : STD_LOGIC; end record; type pattern_array is array (natural range <>) of pattern_type; constant patterns : pattern_array := (('0','0','0','0','0'), ('0','0','1','1','0'), ('0','1','0','1','0'), ('0','1','1','0','1'), ('1','0','0','1','0'), ('1','0','1','0','1'), ('1','1','0','0','1'), ('1','1','1','1','1')); begin for i in patterns'range loop a <= patterns(i).a; b <= patterns(i).b; c <= patterns(i).c; wait for 1 ns; assert patterns(i).s = s and patterns(i).cout = cout report "wrong result for patterns " & integer'image(i) severity error; end loop; assert false report "end of test" severity note; wait; end process; end Behavioral;
テストベンチの方は入力の総パターン8つを入れて、それぞれに対応する正しい結果とつきあわせる。
まずは本体のコンパイル。
ghdl -a --ieee=synopsys full_adder.vhd
synopsysはSTD_LOGIC_UNSIGNEDを利用するのに必要そう。
そしてテストベンチをコンパイル。
ghdl -a --ieee=synopsys full_adder_tb.vhd
次にテストベンチをelaborateする(僕は詳細に何をやっているのかわかっていないが、チュートリアルを見る限りこの手順を踏む必要がありそう)。
ghdl -e full_adder_tb
最後にテストベンチを走らせる。
ghdl -r full_adder_tb --vcd=full_adder.vcd
ghdl -a --ieee=synopsys full_adder.vhd
ghdl -a --ieee=synopsys full_adder_tb.vhd
ghdl -e --ieee=synopsys full_adder_tb
ghdl -r --ieee=synopsys full_adder_tb --vcd=full_adder.vcd
full_adder_tb.vhd:62:8:@8ns:(assertion note): end of test
こんな風にwrong resultのassertが出ずにend of testが出ればテストが通ったことに鳴る。
ちなみに、実行時にvcdファイルを生成しておくと、gtkwaveでシミュレーション結果を見ることができる。
gtkwave full_adder.vcd
gtkwaveが立ち上がったら、まずは左下ペインの波形ソースを全部ドラッグして右側の黒い領域に引っ張り込む。
それだけだと波形に変化がなくて失敗したのかと思うけど、gtkwaveのデフォルトのレンジが1fs単位になっていてこれがメチャクチャ細かいので、上部ツールバーの虫眼鏡アイコンのマイナスの方を推しまくって縮尺を小さくする。
すると上のキャプチャのように見えると思う。