本当に欲しい波形
$displayはテキストを出力します。クイックなsanityチェックには問題ないですが、タイミング問題のあるカウンタや、止まった状態機械をデバッグする瞬間、 絵 が欲しくなります。電圧として時間に渡って描かれたsignal、スクロール可能、ズーム可能、任意の遷移にドロップできるカーソル付き。
その絵が VCDファイル です。「value change dump」、IEEEがオリジナルのVerilog仕様で標準化したテキストフォーマットです。すべてのモダンなシミュレータはこれを書け、すべてのモダンな波形ビューアは読めます。生成するコストはtestbench内の2行です。
2行
initialブロック内(通常刺激を持つ同じもの)に追加します:
$dumpfile("dump.vcd");
$dumpvars(0, test);
$dumpfileは出力ファイルに名前を付けます。任意のパスを渡してください。ディレクトリがなければシミュレータの作業ディレクトリに着地します。$dumpvars(0, test)は「testスコープとすべてのサブスコープのすべてのsignalを、無制限の深さで、再帰的に記録する」と言います。
それがセットアップの全部です。シミュレーションを実行すると、GTKWaveまたはブラウザエディタのWaveformタブで開けるdump.vcdができます。
完全な例
実行してください。Waveformタブに3つのsignal(clk、reset、count)が、シミュレーション全時間に渡って描かれます。任意の点にカーソルをドロップして、その時間のsignal値を読めます。1クロックサイクルを調査するためにドラッグズームできます。
$dumpvarsの最初の引数が何をするか
$dumpvars(depth, scope)はscopeとそれが含むすべてのサブインスタンスを歩き、depthレベル深くまでsignalを記録します。depth値:
0- 無制限。scopeとすべてのネストされたサブmoduleのすべてのsignalが記録される。1-scope内に直接宣言されたsignalのみ。サブmoduleは記録されない。2-scopeプラス1レベルのサブmodule。N-scopeプラスN-1レベルのサブmodule。
実際には、$dumpvars(0, test)がほぼすべてのtestbenchが使うものです。すべてを捕捉するのは安価(VCDは遷移だけを保存し、安定stateを保存しない)で、デバッグの途中で必要なsignalがダンプされていないことを発見したくありません。
非常に大きな設計があってVCDが大きすぎる場合、選択的にダンプできます:
$dumpvars(0, dut.inner_module); // 興味深いサブmoduleだけ
$dumpvars(0, dut.regs); // レジスタファイルだけ
$dumpvarsを複数回呼び出してスコープを蓄積できます。
特定のsignalをダンプ
$dumpvarsはスコープ全体ではなく特定のsignalのリストを取ることもできます:
$dumpvars(0, test.clk, test.reset, dut.count);
これは3つのsignalだけを記録します。設計が巨大で、ほんの一握りのsignalしか気にしないときに有用です。小さな設計では、すべてをダンプする方がシンプルです。
シミュレーション中のダンプ制御
$dumpvarsとペアになる2つのタスク:
$dumpoff- ダンプを一時停止。それ以上の変化はVCDに入らない。$dumpon- ダンプを再開。
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... 興味深い領域 ...
#1000 $dumpoff;
// ... VCDに入れたくない長い退屈な領域 ...
#5000 $dumpon;
// ... 別の興味深い領域 ...
end
長いテストの「100万サイクル実行する」退屈な部分をスキップして、5GBのVCDファイルを生成しないようにする方法です。
結果を見る
主な方法は2つ:
ブラウザエディタで
このページのエディタはVCDをインラインでレンダリングします。シミュレーションを実行し、Waveformタブに切り替えると、signalが左側に階層付きで、右側にドラッグ可能なカーソル付きで現れます。トレースの任意の場所をクリックしてカーソルをドロップすると、その時間のsignal値がsignal名の横に小さなピルとして表示されます。
GTKWaveで
シミュレーションをローカルで実行した(iverilog -o sim test.vしてからvvp sim)場合、結果のVCDを開きます:
gtkwave dump.vcd
GTKWaveはファイルをロードし、左にスコープtreeを表示し、右の波形エリアにsignalをドラッグするのを待ちます。マルチビットsignalを右クリックして表示フォーマット(バイナリ、16進、10進、アナログ)を変更します。下部の検索ボックスを使って特定の時間やsignal遷移にジャンプします。
一般的なパターン
小さなtestbenchヘルパー
ほとんどのtestbenchファイルはこの正確なブロックで始まります。すべてを1つのinitialにまとめて短く保てます:
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... 刺激 ...
$finish;
end
条件付きダンプ
失敗テストのみVCD出力が欲しいテスト環境で:
initial begin
if (DUMP_VCD) begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
end
// ... 刺激 ...
end
DUMP_VCDはコマンドラインから設定するか、テストモードに応じて定義するparameterです。リグレッションスイートでディスク容量を節約します。
メモリダンプ
メモリ(unpacked配列)はデフォルトでは$dumpvarsによってダンプされません。巨大になりうるからです。欲しい場合は明示的に$dumpvars(0, dut.memory)を使うか、一部のシミュレータでは$dumpmemを使ってください。
よくある間違い
空のVCDファイル。 $dumpfileまたは$dumpvarsを忘れたか、signalが変わる前にシミュレーションが$finishを呼びました。セットアップ後少なくとも数時間単位は実行してください。
波形にsignalが見当たらない。 渡したスコープがそれらを含みませんでした。$dumpvars(0, dut)はdut内のものだけを記録します。testbenchがtestレベルでsignalを駆動しているなら、それらは現れません。常にtestbenchスコープからダンプしてください:$dumpvars(0, test)。
VCDファイルが巨大。 急速に変化する幅広いsignalを持つ長いシミュレーションは多くのVCD行を生成します。3つの修正:より狭いスコープをダンプする、退屈な部分の周りで$dumpoff/$dumponを使う、FST(iverilogとGTKWaveの両方が-fstフラグでサポート)のようなよりコンパクトなフォーマットに切り替える。
次に読むもの
この章の最後のドキュメントTimescale and Delaysは、`timescaleディレクティブと#delayが実際に壁時計時間にどうマップされるかを説明します。それが終わると、ドキュメントを最初から最後まで完了したことになります。
よくある質問
VerilogのVCDファイルとは?
VCDはValue Change Dumpの略で、シミュレーション中のすべてのsignal遷移を記録するテキストフォーマットです。シミュレータは時刻0で各signalの初期値を書き込み、その後すべての変化をタイムスタンプ付きで書き込みます。GTKWaveのような波形ビューアがファイルを読み、スクロール・ズーム可能なグラフィカルタイミング図としてレンダリングします。
VerilogでVCDファイルを生成するには?
testbenchのinitialブロック内に2つのシステムタスクを追加します。$dumpfile("dump.vcd");は出力ファイルに名前を付け、$dumpvars(0, top_module);はtop_module以下のすべてのsignalを記録します。シミュレーション終了後に、任意の波形ビューアで開けるdump.vcdファイルができます。
Verilogの$dumpvars(0, ...)の意味は?
$dumpvars(depth, instance)はinstanceから開始し、depthレベル深く再帰しsignalを記録します。$dumpvars(0, test)は「testスコープとすべてのサブスコープのすべてのsignalを再帰的に」を意味します。深さ0は特別で、無制限を意味します。$dumpvars(1, test)はtest内のsignalだけを記録し、インスタンス化されたサブmoduleは記録しません。
VerilogのVCDファイルが空になるのはなぜ?
3つの可能性のある原因:$dumpfile/$dumpvarsをまったく呼ばなかった。signalが変わる前にシミュレーションが$finishに当たった(dump呼び出し後少なくとも数時間単位は実行してください)。$dumpvarsに渡したスコープが実際の階層と一致しない。動作する最小シーケンスは$dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;です。