私はVerilogにまったく慣れていないので、我慢してください。
Verilogにassertステートメントがあるかどうか疑問に思います。私のテストベンチでは、モジュールの出力が特定の値に等しいことを表明できるようにしたいと思います。
例えば、
mymodule m(in, out);
assert(out == 1'b1);
グーグルは私に いくつかのリンク を与えました、しかしそれらは複雑すぎるか、私が望んでいたものではなかったようです。
[〜#〜] ovl [〜#〜] と呼ばれるアサーション用のオープンソースライブラリがあります。しかし、それはかなり重いです。私がそこからニックネームを付けた1つのトリックは、アサーションを実行するモジュールを作成することです。
module assert(input clk, input test);
always @(posedge clk)
begin
if (test !== 1)
begin
$display("ASSERTION FAILED in %m");
$finish;
end
end
endmodule
これで、シグナルをチェックしたいときはいつでも、次のようにモジュールでアサーションをインスタンス化するだけです。
module my_cool_module(input clk, ...);
...
assert a0(.clk(clk), .test(some_signal && some_other_signal));
...
endmodule
アサーションが失敗すると、次のようなメッセージが表示されます。
ASSERTION FAILED in my_cool_module.a0
Displayステートメントの%mは、問題のあるアサーションの階層全体を表示します。これは、大規模なプロジェクトにこれらが多数ある場合に便利です。
なぜ私が時計の端をチェックするのか不思議に思うかもしれません。これは微妙ですが重要です。上記の式のsome_signalとsome_other_signalが異なるalwaysブロックに割り当てられている場合、Verilogシミュレーターがブロックをスケジュールする順序によっては、式が短時間falseになる可能性があります(ロジックが完全に有効であったとしても)。これはあなたに偽陰性を与えるでしょう。
上記のもう1つの注意点は、!==を使用することです。これにより、テスト値がXまたはZの場合にアサーションが失敗します。通常の!=を使用すると、場合によってはサイレントに誤検知が発生する可能性があります。
上記をマクロと組み合わせると、私にとってはうまくいきます。
`define assert(signal, value) \
if (signal !== value) begin \
$display("ASSERTION FAILED in %m: signal != value"); \
$finish; \
end
その後、私のテストモジュールで:
initial begin // assertions
#32 `assert(q, 16'hF0CB)
end
テストの失敗例として:
ASSERTION FAILED in test_shift_register: q != 16'hF0CB
シミュレーターがSystemVerilog構文をサポートしている場合は、必要な処理を実行するassert
キーワードがあります。
あなたはこのように書くことができます
if(!(out==1'b1)) $finish;
Verilogはアサーションをサポートしていません。一部のツールは、アサーションをコメントに配置するPSLをサポートしていますが、これは非標準です。代わりに、テストベンチからの階層参照の使用を検討する必要があります。そうしないと、各アサーションをプロセスに配置する必要があり、面倒になります。
Cのようなアサーションを模倣する最も簡単な方法は、おそらく「定義」です。これにより、アサーションがグローバルになります。
`define assert(condition) if(condition) begin $finish(1); end
例のような非手続き型のコンテキストでシグナルをチェックするには、条件シグナルを作成し、そのシグナルのテストイベントをトリガーする別のマクロが必要になります。
`define assert_always(condition) generate if(1) begin wire test = condition; always @(test) `assert(condition) end endgenerate
上記の生成により、変数テストの新しいスコープが作成されるため、複数のインスタンスが機能するはずです。
手続き型のより良い方法は、別のファイルにタスクを作成し、それを任意のモジュール宣言に含めることです。
task assert(input condition);
if(!condition)
$finish(2);
endtask
非手続き型コンテキストの場合、プロセスを含むモジュールを作成し、そのモジュールをインスタンス化する必要があります。これには、生成ブロックに配置しない限り、インスタンスごとに一意の名前が必要になります。