本章では、組み合わせ回路の一つである「2 入力 1 出力のセレクタ回路 」を例にして、EDAツールによる回路設計の概要を説明します。この回路は、セレクト入力S1 が 0 か 1 かによって、データ入力D0あるいはD1の値を Yに出力します。
2 入力 1 出力のセレクタ回路
第1日目の実験では、この回路をVHDLで記述し、回路設計を行います。一般にEDAツールによる設計は次のような手順を経て行われます。
まずは本テキストに書かれている通りに実行し、EDAツールによる回路設計の概要を把握してください。
VHDLによる回路動作の記述はmuleなどのエディタ上で行います。ファイル名として基本的にどのようなものを用いても構いませんが、拡張子は「.vhd」とすることが多いです。ツールによってはこれは必須で、更にエンティティ名とファイル名が同じである必要があるものもあります。
以下に、「2 入力 1 出力のセレクタ回路」の VHDL 記述ファイル「mux21.vhd」を示します。この例では、「S1, D0, D1」のいずれかが変化した時に、「Y」への代入の右辺を計算し、5 ns (ナノ秒) 後に「Y」へ代入することを表しています。代入文(Y <= ,,,,,)中の「not, and, or」は論理演算です。
-- ライブラリの指定 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- エンティティ宣言 entity mux21 is port (S1, D0, D1: in std_logic; Y: out std_logic ); end mux21; -- アーキテクチャ記述 architecture behavior1 of mux21 is begin Y <= (not S1 and D0) or ( S1 and D1) after 5 ns; end behavior1; |
この記述を例に、VHDL の基本構造を見ていきましょう。
この例のような論理演算による単純な代入は組合せ論理回路の記述となります。「after」による回路の遅延時間指定は、シミュレーション上は意味がありますが、論理合成を行なう時には無視されます。
最後にVHDLでの一般的な構文をまとめます。
-- ライブラリの指定 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- エンティティ宣言 entity エンティティ名 is port (ポート名, ポート名: タイプ; ポート名, ポート名: タイプ ); end エンティティ名; -- アーキテクチャ記述 architecture アーキテクチャ名 of エンティティ名 is begin -- アーキテクチャステートメント部 end アーキテクチャ名; |
回路の動作を確認するためには、回路に入力を与えて出力を観測する必要があります。入力を与えるために、HDL シミュレータ固有のコマンドを用いる方法もありますが、回路をテストするための枠組、即ちテストベンチを HDL で記述して用意する方法が汎用性が高く一般的です。テストベンチは、設計された対象回路が本来組み込まれる環境をシミュレートするように記述します。つまり、適当な入力波形を発生し、コンポーネントとして呼び出した対象回路に入力する動作を記述すればよいのです。以下に、前述の 2-1 セレクタ回路「mux21」のためのテストベンチファイル「test_mux21.vhd」を示します。
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity test_mux21 is end test_mux21; architecture structure1 of test_mux21 is component mux21 port (S1,D0,D1 : in std_logic; Y : out std_logic); end component; for module1: mux21 use entity work.mux21(behavior1); signal S1,D0,D1 : std_logic; signal Y : std_logic; begin module1: mux21 port map (S1,D0,D1,Y); S1 <= '1'; D0 <= '0'; D1 <= '1'; end structure1; |
「mux21」をコンポーネントとして呼び出し、入力を発生しています。なお「S1, D0, D1」には、「' '」で区切られた値がそれぞれ代入されます。
VHDLで記述した回路が正しく動作するかどうかを調べるために、「論理シミュレータ」というものを用います。論理シミュレータでは、VHDLファイルをシミュレーションのための中間ファイルに変換する「アナライズ」が最初に行われ、回路への入出力シグナルをトレースする「シミュレーション」が行われます。なお本実験では、Synopsys 社の論理シミュレータ VSS を使用します。適切な環境設定をしたのち、以下の手順でシミュレーションを行います。
「vhdlan [ファイル名]」 で VHDL 記述ファイルをシミュレーションのための中間ファイルに変換します。本実験では、「mux21.vhd」と「test-mux21.vhd」についてアナライズを行います。
vhdlan mux21.vhd |
test_mux21.vhdのアナライズ
vhdlan test_mux21.vhd
「vhdldbx」で起動します。
vhdldbx |
そして表示されるウィンドウの中から、テストベンチ用のファイル(今回の例題では「TEST_MUX21_STRUCTURE1」)を選択し、OKをクリックします。なお起動時にシミュレーション対象の名前を引数として書いてもよいです。「vhdldbx」の内部で「vhdlsim」が起動されます。「vhdlsim」を直接起動する場合はシミュレーション対象を指定する必要があります。後の操作は「dbx」デバッガなどと同様と考えれば理解しやすいでしょう。
テストベンチ用のファイルを選択
最下行のコマンド入力から、「ls, cd」などの通常のファイル操作コマンドと同様の方法で、設計の内部のシグナル名などの空間を表示できます。「trace [シグナル名]」で波形を表示するシグナルを指定します。
vhdldbxの画面
次にコマンドラインに「run 500」と入力してシミュレーションを実行してみて下さい(シミュレーションが終了するまでに多少時間がかかります)。
run 500 |
「run [時間]」でシミュレーションを実行します。上記の例は500ナノ秒の間、回路を動作させるというコマンドです。単位は「.synopsys_vss.setup」で指定した「timebase」です。途中で止める場合は「Intr.」ボタンをクリックします。詳しくは、「sold」でオンラインドキュメンテーションを読んでください。
シミュレーションの起動画面
シミュレーション実行後の画面
シミュレーションによって、回路が正常に動作することを確認したら、次は「論理合成」という操作を行い、回路を最適化します。本実験では、Synopsys 社の論理合成系 Design Compiler を使用します。論理合成は以下の手順で行います。
「design_analyzer」で起動します。
design_analyzer |
デザインアナライザ起動後の初期画面
Design Compiler のユーザインタフェースは「design_analyzer」の他に コマンドライン入出力の「dc_shell」があります。「design_analyzer」から、「Setup -> Command Window...」で「dc_shell」のインタフェースを呼び出すこともできます。以下では「design_analyzer」の操作の後に「dc_shell」でのコマンドを併記します。
設計の読み込み
- 設計の読み込みが終了すると以下のような画面が表示されます。
mux21.vhdを読み込んだ後の画面
先の画面の中央をダブルクリックすると表示される画面
- さらにもう一度、画面中央をクリックすると以下のような回路図が表示されます。これが今回、設計した回路です。
mux_21.vhdの回路図
上向き矢印ボタンを押し続ける
ボタンを押し続けて最初の画面に戻った状態
- ウィンドウの中央の四角を1クリックして選択した状態で、「Tools -> Design Optimization...」を選ぶと、新たなウィンドウが表示されます。何も変更せずにそのまま「OK」ボタンを押します。すると回路が自動的に最適化されます。
- 次に前述した「回路図表示」の作業を行い、回路を表示してみて下さい。以下のような回路が生成されます。
最適化した例
コマンドウィンドウとコマンドライン
「report_area」を入力したのちの画面
「report_timing」を入力したのちの画面
回路のシミュレーションならびに論理合成を行っても、それが本当に実際のハードウェア上で実現できるかどうかは100%保証の限りではありません。そのため設計した回路が動作するかどうかをFPGA(書き換え可能なゲートアレイ)を搭載した評価用のボード上で調べることで、回路の評価を行います。本実験では、「Altera UP1 ボード」を用いて実験します。
Altera UP1 ボードは MAX7000 と FLEX10K の 2 個の FPGA を搭載した実験用ボードです。入出力は MAX7000, FLEX10K それぞれ独立です。左の MAX7000 は 16 個の DIP スイッチと 2 個のプッシュスイッチを入力、16 個の個別の LED と 2 桁の 7 セグメント LED を出力として利用できます。右の FLEX10K は 8 個の DIP スイッチと 2 個のプッシュスイッチを入力、2 桁の 7 セグメント LED を出力としています。このボード単体では少ないですが、この他にマウス、キーボードを接続できる PS/2 コネクタとディスプレイを接続できる VGA コネクタが接続されています。
Altera UP1 ボード
Altera UP1 ボードを電源ならびにシリアルインタフェースに接続した状態
library ieee; use ieee.std_logic_1164.all; package porttype is type segarray is array (3 downto 0) of std_logic_vector(7 downto 0); end porttype; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; library work; use work.porttype.all; -- 使うスイッチの指定 entity mux21_fpga is port (switch : in std_logic_vector(10 downto 8); seg : out segarray); end mux21_fpga; architecture behavior1 of mux21_fpga is -- mux21の使用を宣言 component mux21 port (S1, D0, D1: in std_logic; Y: out std_logic ); end component; -- インスタンスの宣言 for mux21_0: mux21 use entity work.mux21(behavior1); signal S1,D1,D0,Y : std_logic; type digitarray is array (3 downto 0) of std_logic_vector(3 downto 0); signal digit: digitarray; signal dot: std_logic_vector(3 downto 0); begin -- ポートの割り当て mux21_0: mux21 port map (S1,D1,D0,Y); -- DIP スイッチの割り当て S1 <= not switch(10); D0 <= not switch(9); D1 <= not switch(8); -- 7 セグメント LED の割り当て digit(0) <= "000" & Y; digit(1) <= "0000"; digit(2) <= "0000"; digit(3) <= "0000"; dot(0) <= '0'; dot(1) <= '0'; dot(2) <= '0'; dot(3) <= '0'; -- LED DISPLAY ドライバ -------------------------------- LED: for I in 3 downto 0 generate seg(I) <= dot(I) & "1000000" when digit(I) = "0000" else dot(I) & "1111001" when digit(I) = "0001" else dot(I) & "0100100" when digit(I) = "0010" else dot(I) & "0110000" when digit(I) = "0011" else dot(I) & "0011001" when digit(I) = "0100" else dot(I) & "0010010" when digit(I) = "0101" else dot(I) & "0000010" when digit(I) = "0110" else dot(I) & "1011000" when digit(I) = "0111" else dot(I) & "0000000" when digit(I) = "1000" else dot(I) & "0010000" when digit(I) = "1001" else dot(I) & "0001000" when digit(I) = "1010" else dot(I) & "0000011" when digit(I) = "1011" else dot(I) & "0100111" when digit(I) = "1100" else dot(I) & "0100001" when digit(I) = "1101" else dot(I) & "0000110" when digit(I) = "1110" else dot(I) & "0001110" ; end generate; end behavior1; |
acfファイルの一部
Altera MAX+PlusII は Altera FPGA 用の開発ソフトウェアです。設計した回路は、MAX+PlusII を用いて以下の手順で UP1 ボードにダウンロードし動作させます。
MAX+PlusII の起動後の画面
「Multi-Device JTAG Chain Setup」を選択したのちに表示される画面
- 「Programmer」のウィンドウの「Configure」を押すと FPGA へのダウンロードが開始されます。