VHDL のコンパイラである GHDL を cygwin で使ってみました。
まずは cygwin(64bit) 上でのコンパイル
GHDL のコンパイルには Ada の環境が必要です。cygwin の setup から gcc-ada:GNU Compiler Collection(Ada) をインストールします。バージョンは 4.9.3-1 です。
Ada がちゃんとインストールされていれば gnatmake というコマンドがインストールされているはずです。Ada のプログラムを書きコンパイル・実行できるか確認してみます。
次のプログラムを example.adb としてセーブします。
procedure Example is
begin
null;
end Example;
その後、gnatmake example とうちコンパイル可能であることを確認します。
hanzer/gVHDL を入手しコンパイル
オリジナルの GHDL は 32bit 環境しか対応していないらしくうまくいきませんでした。そこで、github にある hanzer さんの gVHDL を入手します。
hanzer/gVHDL
また、ghdl のコンパイルに必要な gcc の環境 gcc-4.9.3 のソースも展開しておきます。その後 gVHDL で configure および make copy-sources を実行します。
> $ ./configure --with-gcc=/path/to/gcc/source/dir
> $ make copy-sources
with-gcc にはgcc-4.9.3 のソースディレクトリを指定します。すると gcc-4.9.3 に ghdl のソースがコピーされます。あとは gcc のコンパイルと同じ要領で enable-languages に vhdl を指定してコンパイル、そしてインストールを実行します。
> $ .configure --enable-languages=vhdl --disable-bootstrap
> $ make
> $ make install
GHDL で Hello World
インストールした ghdl がちゃんと動くか Hello World プログラムで確認します。
-- Hello world program.
use std.textio.all; -- Imports the standard textio package.
-- Defines a design entity, without any ports.
entity hello_world is
end hello_world;
architecture behaviour of hello_world is
begin
process
variable l : line;
begin
write (l, String'("Hello world!"));
writeline (output, l);
wait;
end process;
end behaviour;
ghdl では -a でアナライズ、-e でエラボレートすることができます。アナライズでは vhdl のプログラムを解析して cf というファイルにモジュールの情報を生成するようです。-e で実際の実行可能なオブジェクトを生成します。
>$ ghdl -a hello.vhdl
>$ ghdl -e hello.vhdl
>ghdl: bad unit name 'hello.vhdl'
>ghdl: (a unit name is required instead of a filename)
>$ ghdl -e hello_world
>$ ls
e~hello_world.o hello.o hello.vhdl hello_world.exe* work-obj93.cf
>$ ./hello_world.exe
Hello world!
簡単なテストベンチを動かしてみる
次の簡単なテストベンチを動かしてみます。
ibrary IEEE, std;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.numeric_std_unsigned.all;
use IEEE.std_logic_textio.all;
use std.textio.all;
entity text_io_example is
end text_io_example;
architecture beh of text_io_example is
signal v : std_logic_vector(5 downto 0);
signal i : integer;
begin
process is
variable line0 : line;
variable c : std_logic;
begin
c := '0';
write(line0, c);
writeline(output, line0);
v <= v - 1;
i <= i - 1;
wait;
end process;
end beh;
ghdl では makefile をつくるオプションがあります。単純に --gen-makefile を
実行しただけだとエラーになるので、その前に -a で vhdl ファイルを解析しておきます。
> $ghdl --gen-makefile --std=08 text_io_example
> ghdl: cannot find entity or configuration text_io_example
> $ghdl -a --std=08 test_tb.vhdl
> $ls
> test_tb.o test_tb.vhdl text_io_example.exe* work-obj08.cf
> $ghdl --gen-makefile --std=08 text_io_example > makefile
> $ls
> makefile test_tb.o test_tb.vhdl text_io_example.exe* work-obj08.cf
> $make
> ghdl -e --std=08 text_io_example
ここでは --std=08 オプションをつけています。ghdl は表示に厳密に IEEE のライブラリを定義していて numeric_std は v87(指定なしの時のバージョン) にはありますが、numeric_std_unsigned がありません。各ベンダーは IEEE の正式なライブラリを無視しているようです。std_logic_vecotr への足し算引き算ができるようになるために numeric_std_unsigned が本当は必要なようです。
Xilinx の FIFO を使用してみる
手元の PC では Vivado の 2015.3 をインストールしてあったので FIFO を使ってみることにします。FIFO を使うには unisims と unimacro を -i でインポートする必要があります。ここでは先の厳密な IEEE の問題を回避するために --ieee=synopsys というオプションを使っています。
> $ghdl -i --ieee=synopsys --work=unisim <パス>/unisims/*.vhd
> $$ghdl -i --ieee=synopsys --work=unisim <パス>/unisims/primitive/*.vhd
> $ghdl -i --ieee=synopsys --work=unimacro <パス>/unimacro/*.vhd
> $ls -1 *.cf
unimacro-obj93.cf
unisim-obj93.cf
これで unisim と unimacor の cf というファイルができました。さらに自分で作った fifo_test.vhdl(FIFO_DUALCLOCK_MACRO を使用したプログラム) と fifo_tb.vhdl(テストベンチ) をアナライズします。
> $ghdl -a --ieee=synopsys fifo_test.vhdl
> $ghdl -a --ieee=synopsys fifo_tb.vhdl
依存関係をチェックしなくて済むように -m というオプションで一気にコンパイルが可能です。
> $ ghdl -m --ieee=synopsys fifo_test
> <ワーニング中略>
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:631:20: no declaration ?for "fifo18"
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:631:20: component name expected
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:664:23: no declaration for "fifo18_36"
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:664:23: component name expected
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:696:20: no declaration for "fifo36"
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:696:20: component name expected
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:729:23: no declaration for "fifo36_72"
> unimacro/FIFO_DUALCLOCK_MACRO.vhd:729:23: component name expected
残念、エラーです。FIFO_DUALCLOCK_MACRO に Virtex5 用の記述があって primitive にはそれがないようです。unimacro/FIFO_DUALCLOCK_MACRO.vhd の 627 行目からの 137 行を何とかすると何とかなりそうです。
> $ghdl -m --ieee=synopsys fifo_test
> <ワーニング中略>
> analyze unisims/unisim_VCOMP.vhd
> analyze unimacro/unimacro_VCOMP.vhd
> analyze fifo_test.vhdl
> analyze unimacro/FIFO_DUALCLOCK_MACRO.vhd
> analyze unisims/unisim_VPKG.vhd
> analyze unisims/primitive/FIFO18E1.vhd
> analyze unisims/primitive/FIFO36E1.vhd
> elaborate fifo_test
V5 の記述をうまく回避するとコンパイルが通りました。当然実行することが出来ます。--stop-time でシミュレーションの時間 --vcd で vcd ファイルの指定ができます。
> $ ./fifo_test.exe --stop-time=10us --vcd=fifo_test.vcd
> $ ls *.vcd
fifo_test.vcd
これで cygwin + ghdl + vi (あるいは emacs ) というシミュレーション環境を構築することができました。vi を使っている人は開発効率があがるでしょう。