VHDLを試してみた。

この記事はIS17er Advent Calendar 2016 - Adventar23日目の記事として書かれました。

VHDLとは?

VHDL(Very High Speed Integrated Circuit Hardware Description Language)は米国防総省で作られたハードウェア記述言語の一種で、現在はIEEEによって標準化されている。
Adaを参考に作られた言語なので知っていると少し学習しやすいかもしれない...らしい。
(GHDLドキュメント http://ghdl.readthedocs.io/en/latest/Introduction.htmlより)
IS2017erにとってはハードウェア構成法のレポートで推奨されている言語なので、とりあえず動かしてみたときの記録を書く。

開発環境(GHDL/GTKWave)

GHDLというオープンソースVHDLシミュレータと、GHDL推奨の波形表示ソフトGTKWaveを用いる。
導入は下記サイトを参考にした。 lv4.hateblo.jp

VHDLの基本構成

VHDLは基本的に、ライブラリ宣言部、エンティティ宣言部、アーキテクチャ宣言部の3つの部分から構成される。
全加算器を例に見てみよう。
adder.vhdl

-- ライブラリ宣言
library IEEE ;
use IEEE.STD_LOGIC_1164.ALL ;

--エンティティ宣言部
entity adder is
  port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
end adder;

--アーキテクチャ宣言部
architecture rtl of adder is
begin
   s <= i0 xor i1 xor ci;
   co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
end rtl;

ちなみに、このコードはほぼGHDLのドキュメントhttp://ghdl.readthedocs.io/en/latest/Starting_with_GHDL.htmlのコピー。
ghdlで日本語のコメントが弾かれたので、実際はコメントを消去して保存した。

ライブラリ宣言

C言語でいうincliude文のようなもの。
libraryで使用するライブラリを指定し、useでそのライブラリ中のパッケージ(アイテム)を指定する。 このサンプルコードでは説明のため宣言したが、実際にはライブラリは使用していない。
(#include<stdlib.h>したのにprintfしか使ってない感覚。)

エンティティ宣言

C言語での関数プロトタイプ宣言のようなもの。
エンティティ名、変数名、型、モード(in,out等)を指定する。

アーキテクチャ宣言

C言語での実際の関数記述部分に近い。
内部信号(ローカル変数)を使う際はisとbegeinの間に宣言する。

テストベンチ

上のコードでは単に全加算器を定義しただけなので、実際に動かすためにテストコード(テストベンチと呼ぶことが多いっぽい)
adder_tb.vhdl

--  A testbench has no ports.
entity adder_tb is
end adder_tb;

architecture behav of adder_tb is
   --  Declaration of the component that will be instantiated.
   component adder
     port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
   end component;

   --  Specifies which entity is bound with the component.
   for adder_0: adder use entity work.adder;
   signal i0, i1, ci, s, co : bit;
begin
   --  Component instantiation.
   adder_0: adder port map (i0 => i0, i1 => i1, ci => ci,
                            s => s, co => co);

   --  This process does the real job.
   process
      type pattern_type is record
         --  The inputs of the adder.
         i0, i1, ci : bit;
         --  The expected outputs of the adder.
         s, co : bit;
      end record;
      --  The patterns to apply.
      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
      --  Check each pattern.
      for i in patterns'range loop
         --  Set the inputs.
         i0 <= patterns(i).i0;
         i1 <= patterns(i).i1;
         ci <= patterns(i).ci;
         --  Wait for the results.
         wait for 1 ns;
         --  Check the outputs.
         assert s = patterns(i).s
            report "bad sum value" severity error;
         assert co = patterns(i).co
            report "bad carry out value" severity error;
      end loop;
      assert false report "end of test" severity note;
      --  Wait forever; this will finish the simulation.
      wait;
   end process;
end behav;

adder.vhdl同様 http://ghdl.readthedocs.io/en/latest/Starting_with_GHDL.htmlから引用。

シミュレーションしてみる

GCCでCのコードをコンパイルするのと同様に、GHDLでVHDLのコードを analysis、elaborateして実行ファイルを生成する。

$ ghdl -a adder.vhdl
$ ghdl -a adder_tb.vhdl
$ ghdl -e adder_tb

オプション-r で実行する際に、--vcd=で波形データを出力できる

$ ghdl -r adder_tb --vcd=adder_tb.vcd

生成されたファイルはgtkwaveで参照できる

$ gtkwave adder_tb.vcd

gtkwaveのウィンドウが表示されたら、 左下のciとかioとかをメインの黒い部分にドラッグアンドドロップして左上の一番左の虫眼鏡のアイコンで縮尺を合わせると以下の様に表示された。 f:id:gonta42:20161223170430p:plain

時間がないのでとりあえずここで終了

VHDLの基本的な論理演算と型(VHDL入門その1) - 情報系学生ランナーの備忘録

参考サイト

初めてでも使えるVHDL文法ガイド ―― 文法ガイド編|Tech Village (テックビレッジ) / CQ出版株式会社

初めてでも使えるVHDL文法ガイド ―― 記述スタイル編|Tech Village (テックビレッジ) / CQ出版株式会社

GHDL on OS X - Handwriting

Starting with GHDL — GHDL 0.33 documentation