電子回路わからん日記

にゃーんと言いながら電子回路いじってます

Questa - Intel FPGA Starter Editionでのシミュレーションバッチ実行

どうもです。
毎年恒例のこの時期がやってきました

qiita.com

意外と情報が出てこないな・・・・ということで少し書いてみることにしました。


ModelSim/QuestaのGUI実行って面倒くさい

さて、皆様がFPGAのRTLシミュレーションをするときに何を使用されているでしょうか?

などいろいろありますが、これらの大変なところは「VerilogVHDLを組み合わせたシミュレーションができない」点です(そもそも需要あるのか?という話はさておき・・・)。

混合シミュレーションを実行可能で、無料で入手可能なシミュレータは以下3つになると思います。

  • Questa - Intel FPGA Starter Edition
  • xsim(AMD Vivadoに付属)
  • Aldec Active-HDL Student Edition(学生のみ)

この中でシミュレータを単独起動でき、社会人でも使用可能なものはQuesta - Intel FPGA Starter Editionのみです。

しかし、QuestaやIntelを一からGUIで実行しようとすると

  1. プロジェクトの作成
  2. モジュールとテストベンチのインポート
  3. コンパイル
  4. シミュレーション設定
  5. シミュレーション実行

をマウスを使ってポチポチやる必要があり、結構時間を食います。

www.paltek.co.jp

ということで、効率よくシミュレーションを実行するためにはVerilator等のようにコマンドラインで行うことが欠かせません。


バッチ実行

Questaでシミュレーションを行うにあたりコマンドを一行一行打っても良いのですが、こちらもVerilator等と比較すると手順が多いです。

  1. シミュレーション用ワーキングディレクトリの作成
  2. マッピング
  3. コンパイル
  4. シミュレーション開始
  5. シミュレーション・ログ設定
  6. 実行

ということで、一般的にこれらを一からコマンドで行うことはほとんどなく、バッチファイルを作成して行うことが一般的です。


バッチファイル作成

ということで、ここではざっくりとバッチファイルにまとめるコマンドを紹介します。

詳細な説明は以下リンク先にもありますので、ぜひご参照ください。

www.paltek.co.jp

なお、ここではプロジェクト全体ではなく、比較的小規模なモジュールでのシミュレーションを想定して紹介します。

ディレクトリ作成(vlib)

シミュレーション用のワーキングディレクトリを作成します。
OS標準コマンドでの作成はできませんのでご注意ください。
基本的には「work」という名のディレクトリを作成することが一般的です。

vlib work

マッピング(vmap)

論理ライブラリとワーキングディレクトリをマッピングします。
基本的にライブラリ名とディレクトリ名を合わせておくと混乱は起きないと思います。

vmap work work

コンパイルvlog/vcom)

ここが少し大変です。

VerilogVHDLコンパイルのコマンドが異なったり、言語バージョンによってはコマンドオプションが必要になったりします。

また、複数のディレクトリをvlibおよびvmapで作成している場合は指定して上げる必要があります。

Verilog

オプションを入れない場合、Verolog-2001としてコンパイルされます。

vlog [-vlog95compat|-vlog01compat] hoge.v
SystemVerilog

拡張子svの場合は-svオプションは不要です。

vlog [-sv] fuga.sv
VHDL

オプションを入れない場合はVHDL-2002としてコンパイルされます。

vcom [-87|-97|-2002|-2008] hogefuga.vhd

シミュレーション(vsim)

-cオプションでバッチ実行モードとなります(-cオプションを付けない場合、GUIウィンドウが起動します)。
-tでシミュレーションの単位時間を指定します。
-doの後でシミュレーションの細かい設定を入れておきます。
ここでは"wave.do"というファイルの中身に細かい内容を記載します。

vsim -c -t ns -do "do wave.do; run -all;"

波形確認

vsimを-cオプションと共に実行するとGUIが起動しないため、あとから波形ファイルを開いて確認する場合があります。

その際はvsimコマンドの後に波形ファイル(*.wlf)ファイルを指定すればよいです。基本的には"vsim.wlf"になります。

vsim vsim.wlf

doファイルの中身

doファイルの中身はシミュレーション開始後の設定(波形表示する信号やログを取る信号など)を書いていきます。

add log

観測する信号を指定します。ここに入っていない信号はシミュレーション完了後の波形観測や信号の変化を追跡できません。

add log {/top/module/signal}

-rオプションを付けることで指定した階層以下の全ての信号の観測をすることもできます。大規模なシミュレーションでは実行速度が遅くなりますので注意が必要です。
例えば、以下コマンドでテストベンチ含めた全ての信号を観測できます。

add log -r *

add wave

QuestaをGUI起動する場合はadd waveコマンドで波形表示する信号を指定しておくと良いです。

add wave {/top/module/signal}

実際にやってみる

ここで筆者が普段やってる方法でシミュレーションをやってみます。

簡単なダウンカウンタをテーマにしてみます。
環境はWindowsになります。
Linuxで実行する場合は拡張子".bat"を".sh"にすれば動くと思います。

モジュール本体(CNT_DOWN.sv)

`default_nettype none
module CNT_DOWN #(
    parameter int unsigned BIT_WIDTH = 4
) (
    input  bit CLK_I ,
    input  bit NRST_I,
    output logic signed [BIT_WIDTH - 1:0] CNT
);

    logic signed [BIT_WIDTH - 1:0] CNT_REG = {(BIT_WIDTH){1'b0}};

    always_ff @( posedge CLK_I ) begin: blk_cnt
        if (!NRST_I) begin
            CNT_REG <= {(BIT_WIDTH){1'b0}};
        end else begin
            CNT_REG <= CNT_REG - 1'b1;
        end
    end

    assign CNT = CNT_REG;

endmodule
`default_nettype wire

テストベンチ(CNT_DOWN_tb.sv)

`default_nettype none
`timescale 1ns/1ps
module CNT_DOWN_tb ();

    localparam int unsigned BIT_WIDTH = 4;

    logic CLK_I = 1'b0;
    logic NRST_I = 1'b1;
    logic signed [BIT_WIDTH - 1:0] CNT;

    CNT_DOWN #(
        .BIT_WIDTH(BIT_WIDTH)
    ) u0 (
        .CLK_I(CLK_I),
        .NRST_I(NRST_I),
        .CNT(CNT)
    );

    initial begin
        $dumpfile("CNT_DOWN.vcd");
        $dumpvars(0, CNT_DOWN_tb);

        #23 NRST_I = 1'b0;
        #14 NRST_I = 1'b1;

        #100 $finish();
    end

    always begin: blk_genclk
        #2 CLK_I <= ~CLK_I;
    end

endmodule
`default_nettype wire

バッチファイル(CNT_DOWN.bat)

GUIを出して波形表示までしたいので、vsimに-cオプションは付けていません。
また、最適化オプションやデバッグオプション(-voptargs=+acc、-debugdb=+acc)を付加しています。

vlib work
vmap work work

vlog -sv CNT_DOWN.sv
vlog -sv CNT_DOWN_tb.sv

vsim -t ns -voptargs=+acc -debugdb=+acc work.CNT_DOWN_tb -do "do wave.do; run -all;"

doファイル(wave.do)

add log -r *
 
add wave {/CNT_DOWN_tb/u0/CLK_I}
add wave {/CNT_DOWN_tb/u0/NRST_I}
add wave {/CNT_DOWN_tb/u0/CNT_I}

以上4つのファイルを同一ディレクトリに保存し、バッチファイルを実行してください。

以下のようなメッセージが表示されますが、「いいえ」をクリックしてください。
「はい」を選択するとソフトウェアが終了してしまいます。

すると波形が表示された状態でGUIを操作可能になります。
あとはRadixをいじったり・・・

RTLのブロックを確認したり・・・

自由自在です。個人的にこの「GUIでいろいろ確認できるような状態にするまで」をバッチファイルで自動化すると下準備のほとんどを毎回やる必要がなくなり、非常に便利と思います。