コマンドラインでのVHDLシミュレーション

Altera Quartus Prime 16.0同梱のModelsimを使って、Ubuntu 16.04の上でVHDLによる回路のコンパイルとシミュレーションを行いました。

Quartus Primeによる回路のコンパイルとシミュレーションは春頃にすでに行っています。しかし、あれはすべてGUIアプリケーションによるものです。実際に何らかのアプリケーションをVHDLで開発するとなると、執拗にテストを走らせなければなりません。その場合、テストは自動化すべきで、結果的にコマンドラインからのコンパイルとシミュレーションが必要になります。

先週ちょこちょこと再構築したVHDL処理環境を使って、週末にこの目標に挑戦しました。なお、実行するコマンドライン等はネットで調べた知識とマニュアルで調べた知識のごった煮になっています。あまり参考にならないでしょう。

実行するコマンドライン

最初に、Quartus Primeのインストールが終わったら過去記事を参考にして、Modelsimのディレクトリへパスを張っておきます。これで、カレントディレクトリがどこであってもModelsimを動かすことが出来ます。

実行は、以下のように三つのModelsimコマンドからなります。私はこれらを一つのスクリプト・ファイルにまとめています。

#! /bin/sh
 
# if first time, create a work library.
 
if [ ! -e work ]; then
     vlib work
fi
 
# compile the VHDL source and put the object into the work library.
# -2002 mean, based on the VHDL 2002
 
vcom -explicit -work work -2002 "trial.vhd"
vcom -explicit -work work -2002 "test_bench.vhd"
 
# vsim is modelsim simulator. This command runs the 
# test_bech module of the work library.  
# -c : command line only
# -do : execute given string as command.
 
vsim work.test_bench -c -do "run 1ms; quit"

 

vlib はライブラリを作るためのコマンドです。ライブラリを作るか否かはアプリケーションによるような気がしますが、それはC言語の話です。VHDLでは分割コンパイル時にコンパイル結果をオブジェクト・ファイルではなくライブラリに追加していきます。そのため、どのようなアプリケーションもvlibによって作業用ライブラリを作ります。ライブラリの名前はプログラムからも参照されるので注意が必要です。ここでは慣例に従ってworkとしておきます。なお、ライブラリと同じ名前のディレクトリを作っておきます。

vcom はVHDLソースファイルをコンパイルするコマンドです。-work work オプションで、ワーキング・ライブラリとしてworkを指定します。また、-2002で、VHDL2002に準拠することを示します。-2002は省略可能ですが、ここでは明示しています。なお、-excplicitは調べたのですが、意味が余りよくわかりませんでした。深入りせずにそのまま使っています。

vsim はシミュレーションコマンドです。work.test_bench は、workライブラリのtest_benchモジュールをシミュレートすることを指示します。このモジュールは名前の通り、テストベンチを記述したファイルです。-c オプションはコマンドラインで実行し、GUIを表示しないことを指示します。-do に続く文字列は、シミュレータに与える命令です。ここでは1m秒分のシミュレーションを行い、終了するよう指示しています。

実行したVHDLプログラム

テスト用に簡単なVHDLプログラムを作りました。trial.vhdは1/2デバイダで、test_bench.vhdはtrial用のテストベンチです。名前はきちんとしたものを用意する癖が必要ですね。

trial.vhdでは内部に2ステートを持ち、クロックの立ち上がりでステートに付随する出力の用意とステート遷移を行います。なお、実際の出力は、クロックの立ち下がりで行っています。ビルドの実験なので初期化については省いています。

--------------------------------------------------------------------------------
-- Entity: trial
-- Date:2016-09-10  
-- Author: takemasa     
--
-- Description: 
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity trial is
    port  (
        clk : in std_logic;       -- input clock, xx MHz. 
        q : out std_logic         -- output divided by 2
    );
end trial;


architecture RTL of trial is
    signal state : std_logic := '0';
begin
    -- On rising endge, it changes internal state
    -- On falling edge, it output the state.


    process( clk )  
    begin 
            -- sample the clock and drive the state
        if ( clk = '1' ) then
             -- update state           
            case state is
                when '0' =>
                    state <= '1';
                when others =>
                    state <= '0'; 
            end case;
            
            -- output the internal date on the falling clock
        elsif ( clk = '0' ) then
            -- work on state
            case state is
                when '0' =>
                    q <= '0';                  
                when others =>
                    q <= '1'; 
            end case;
        end if;
                
    end process;    

end RTL;

 

test_bench.vhdではtrialモジュールを読み込んで、これにクロックを与えています。trialの読み込みではコンポーネント宣言ではなく、エンティティの参照を利用しました。コンポーネント宣言はいちいち引数宣言をコピーするため、短気な私の性に合いません。

--------------------------------------------------------------------------------
-- Entity: test_bench
-- Date:2016-09-11  
-- Author: takemasa     
--
-- Description: 
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;
use ieee.std_logic_textio.all;

entity test_bench is
end test_bench;

architecture RTL of test_bench is
    signal clock : std_logic := '0';
    signal Q : std_logic;
    file fo: TEXT open write_mode is "test_out.txt";
    
begin
    dut: entity work.trial port map( clk=>clock, q=>Q );
    
    process 
        variable lo : line; 
    begin
        wait for 100 ns;
        if clock = '0' then
            clock <= '1';
        else
            clock <= '0';
            write( lo, Q );
            writeline( fo, lo );
        end if;
        
    end process;

end RTL;

 

まとめ

非常に荒っぽくはありますが、コマンドラインからVHDLのシミュレーションが出来るようになりました。これで個別モジュールをじっくり開発することが出来ます。

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください