私は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
あなたはこのように書くことができます
if(!(out==1'b1)) $finish;
シミュレーターが SystemVerilog 構文をサポートしている場合、必要な機能を実行するassert
キーワードがあります。
Verilog はアサーションをサポートしていません。一部のツールは、アサーションをコメントに配置する PSL をサポートしていますが、これは標準ではありません。代わりに、テストベンチから階層参照を使用することを検討する必要があります。そうしないと、各アサーションをプロセスに配置する必要があり、面倒になります。
C ライクなアサーションを模倣する最も簡単な方法は、おそらく `define です。これにより、アサーションがグローバルになります。
`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
非手続き型のコンテキストでは、プロセスを含むモジュールを作成し、そのモジュールをインスタンス化する必要があります。これには、生成ブロックに配置しない限り、各インスタンスに一意の名前が必要です。