WSL2上でのSimulation環境構築
Windows上でのSimulation環境構築
- Verilog-HDLは、Hardware Description Languageの一つです。この言語で回路設計を行うために、まずは環境構築(ツールの準備)から始めたいと思います。Verilog-HDLを扱う際に最低限必要なツールは下記3種です。
+ テキストエディタ
+ シミュレータ
+ 波形表示ツール
- テキストエディタは、特に説明の必要無いですね。好きなものを使っていただければ良いと思います。次にシミュレータですが、無償かつ複数環境で動かしやすいものとして「Icarus Verilog」を使用します。最後に波形表示ツールですが、シミュレータ同様の理由で「GTKWave」を選びました。
- では早速Windows版Icarus Verilogの入手から始めます。しかしながらIcarus Verilog本家サイト(iverilog.icarus.com)ではWindows版の配布が止まっており(*1)、別のWindows版Icarus Verilogサイト「bleyer.org/icarus」からダウンロードします。現時点での最新安定版は
iverilog-0.9.7_setup.exe (latest stable release) [10.5MB]
です。
- 尚上記で入手できる「Windows版Icarus Verilog 0.9.7」には「GTKWave」も入っています。なのでIcarus Verilogをインストールすると、GTKWaveも使用できるようになります(*2)。インストールは通常のWindows用ツールと同様なので特に説明しませんが、1点注意があります。メッセージでも出てきますが、インストール先のディレクトリ/フォルダ名にスペースを入れてはいけないという制限です。具体的には
NG : C:\Program Files\iVerilog
OK : C:\iVerilog
OK : C:\Tools\iVerilog
のように考えて下さい。2byte系文字が入るのも避けたほうが無難でしょう。
- インストールが終了したら、起動のみ確認してみます。コマンドプロンプトを開いて「iverilog」とコマンド入力して下さい。下記のようにusageが出てくればOKです。
C:>iverilog ← コマンド入力
iverilog: no source files.
Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
[-g1995|-g2001|-g2005] [-g]
[-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
[-N file] [-o filename] [-p flag=value]
[-s topmodule] [-t target] [-T min|typ|max]
[-W class] [-y dir] [-Y suf] source_file(s)
|
- 次はGTKWaveですが、これも先と同様にコマンドプロンプトを開いて「gtkwave」とコマンド入力してください。下図のようなGUIが起動すればOKです。尚、Help→Wave Versionを確認すると「GTKWave Analyzer v3.3.48(w)1999-2013 BSI」になっています。
サンプルのRTL
- ここではIcarus Verilog と GTKWave を用いたSimulationと波形取得について説明します。初めにSimulationで使用するRTLを示します。これは10bitのPRPG(Pseudo Random Pattern Generator)です。微妙(*3)にVerilog HDL 2001の記述方式を混ぜています。
`timescale 1ns/1ps
module Prpg10
#( // parameters
parameter Prpg10_UD = 1 // Unit Delay
)
( // ports
input wire Clk, // Clock
input wire ResetB, // Reset
input wire PrpgUpld, // Seed upload
input wire PrpgStart, // PRPG start
input wire [9:0] PrpgSeed, // Seed input
output wire [9:0] PrpgOut // PRPG data output
);
reg [9:0] PrpgReg;
wire [9:0] PrpgRegIn;
reg PrpgStartReg;
always @(posedge Clk, negedge ResetB) begin
if (ResetB==1'b0) begin // Asynronous reset
PrpgReg <= #Prpg10_UD 10'b00_0000_0000;
PrpgStartReg <= #Prpg10_UD 1'b0;
end
else begin // Function
PrpgReg <= #Prpg10_UD PrpgRegIn;
PrpgStartReg <= #Prpg10_UD PrpgStart;
end
end
assign PrpgRegIn =
(PrpgStartReg)? {PrpgReg[8:0],(PrpgReg[9]^PrpgReg[2])} : // x^10+ x^3 + 1
(PrpgUpld)? PrpgSeed :
PrpgReg ;
assign PrpgOut = PrpgReg & {10{PrpgStartReg}};
endmodule
|
- 次は上記リストのRTLを図示しました。prpg_polyの部分には、10bit PRPGのPrimitive Polynomial(x^10 + x^3 + 1)(*4)が入ります。リストの青字部分に相当しています。
- この回路を動作させる手順ですが、所望のクロック(Clk)が入り続けているとして下記になります。
[1]ResetBを'0'にして、全Registerを初期化します。
[2]ResetB解除前に、入力ポートの値を確定します(全て'0'にします)。
[3]ResetBを解除('1'に)します。
[4]PrpgSeed[9:0]に乱数発生器のSeed値(All'0'以外の値)をセットします。
[5]PrpgUpldを1cyc以上'1'にした後'0'に戻します→PrpgReg[9:0]にSeed値が入ります。
[6]PrpgStartを'1'にすると、次のClkのPositive EdgeからPRPGが動作開始(ランダムパターン出力)します。
[7]PrpgStartを'0'に戻すと、次のClkのPositive EdgeでPRPGが動作停止します。(PrpgOutはAll'0'出力)
- この回路は10bitのPRPGなので、All'0'以外の1023種の値をランダムに生成します。Seed値が再度出力されるのはPRPG起動後の1023cyc後です。
サンプルのテストベンチ
- 回路を動作させるためのテストベンチを示します。各動作のstepがどのステートメントに相当するかコメントを入れてありますので参考にして下さい。またinitial文のすぐ下に、VCDダンプのステートメントも入れてあります。
`timescale 1ns/1ps
module tb_Prpg10;
reg Clk, ResetB, PrpgUpld, PrpgStart;
reg [9:0] PrpgSeed;
wire [9:0] PrpgOut;
parameter CYC = 100;
always #(CYC/2) Clk = ~Clk;
Prpg10 dut ( // Prpg10のInstance
.Clk (Clk),
.ResetB (ResetB),
.PrpgUpld (PrpgUpld),
.PrpgStart (PrpgStart),
.PrpgSeed (PrpgSeed),
.PrpgOut (PrpgOut)
);
initial begin
$dumpfile("tb_Prpg10.vcd"); // vcd file name
$dumpvars(0,tb_Prpg10); // dump targetは「全部」
// Initilai value
#(CYC* 0) Clk=0; ResetB=1; PrpgUpld=0;
PrpgStart=0; PrpgSeed=0; // step[2]の印加値は最初から入れている
// Reset
#(CYC*10) ResetB=0; // step[1]
#(CYC*10) ResetB=1; // step[3](step[2]は実施済み)
// Set seed
#(CYC*10) PrpgSeed=10'b00_0000_0001; // step[4]
#(CYC*10) PrpgUpld=1; // step[5]1にして
#(CYC* 1) PrpgUpld=0; // step[5]0に戻す
// Start PRPG
#(CYC*10) PrpgStart=1; // step[6]
// Stop PRPG after 1024 cyc
#(CYC*1024) PrpgStart=0; // (return to start 00_0000_0001) step[7]
// Stop simulation
#(CYC*10) $finish;
end
endmodule
|
コンパイルと実行
- かなり前置き長くなってしまいましたが、ようやくコンパイルです。現在PRPGの本体である Prpg10.v と テストベンチの tb_Prpg10.v の二つのファイルがあります。これらをIcarus Verilogで下記のようにコンパイルします。
iverilog Prpg10.v tb_Prpg10.v -o tb_Prpg10.o
- オプション -o は、コンパイルオブジェクトのファイル名指定です。未指定時は a.out になります。記述ミスがあるとエラーになりますので、まずはここでデバッグをすることになります(*5)。その他にもdefine指定や、Include Path指定などいろいろなオプションがあります。詳しくはインストールディレクトリの iverilog.pdf を参照して下さい。
- コンパイルが終了したら、次はいよいよSimulation実行です。上記リストのテストベンチは、特にメッセージで判定結果を出さずに「まずは波形を見よう」という感じになっています。Simulationの実行には vvp コマンドを使います。
vvp tb_Prpg10.o
...えっと...これだけです(^^;。今回のサンプルを実行すると「VCD info: dumpfile tb_Prpg10.vcd opened for output.」といったメッセージが出てきます。実際vcdファイル(tb_Prpg10.vcd)が生成されているはずです。
- vvp コマンドにも、ログファイルの指定などいくつかオプションがあります。詳しくは先と同様にインストールディレクトリのvvp.pdf を参照下さい。
波形の観測
- 作成したvcdファイルをGTKWaveで観測します。引数にvcdファイル名を指定してgtkwave(*6)を起動します。ちなみにvcdファイルはGTKWave起動後にメニューからロードすることもできます。
gtkwave tb_Prpg10.vcd
- GTKWaveはGUIツールなので直感的に使い方はわかると思いますが簡単に説明すると、左上のSST window内で観測したいInstanceを選ぶと、その下にwire/registerの一覧が表示されます。その中から観測したい信号を横のSignals windowにドラッグ&ドロップするか、下部のAppend/Insert/Replaceボタンを使って信号波形を表示させていきます。
- 実際に実行結果を表示させて見ました。PRPG動作スタートまでの表示になります。クリックすると別Window(又はタブ)に拡大画像を表示します。
- 作業の流れとしては以上になります。最近ではXilinx, AlteraといったFPGA系ツールでも同様なことができるようになってきていますので、そのあたりもいずれ扱いたいと思います。
|