SystemVerilog の 2012 ルール 4.7 がどのように実装されているかについて、私はまだ少し混乱しています。規則では、次のような状況で次のように規定されています。
module test;
logic a;
integer cnt;
initial begin
cnt = 0;
#100;
a <= 0;
a <= 1;
a <= 0;
a <= 1;
a <= 0;
end
always @(posedge a)
begin
cnt <= cnt + 1;
end
endmodule
すべての割り当ては非ブロッキング割り当てキューでスケジュールされ、順番に実行する必要があります。最後の値が勝ちます。ここまでは、すべてクリアです。
次に何が起こるかは、すべてのシミュレーターで同じではありません。iverilog および Modelsim (少なくとも Vivado 2016/3 エディション) は、'a' に1 つのイベントを作成し、これにより cnt がインクリメントされます。これは、カミングス氏が SNUG 2000 で示した動作とも一致しているようです。
ただし、VCS は中間値を除外し、最後の値のみを適用します。ちなみに、これは実際のフリップフロップの動作方法でもあります。
この場合、これは純粋に仮説的な議論ではなく、シミュレーション結果が異なります。また、iverilog/modelsim の動作がバグを引き起こす可能性があり、フロップはトグルしますが、波形に値の変化は見られないため、検出が非常に困難です。
もう 1 つのポイントは次のとおりです。iverilog/modelsim が正しい場合、なぜ2 つではなく1 つのイベントを作成するのでしょうか?
編集:追加のメモ。
上記の例は、実際にはあまり意味がありません。より現実的なケースは
always @(posedge clk)
begin
clk2 <= 1'b1;
if (somecondition)
clk2 <= 1'b0;
end
always @(posedge clk2, negedge rst_n)
begin
if (!rst_n)
q <= 1'b0;
else
q <= ~q;
end
これは完全に合法であり、実際のハードウェアではグリッチは発生しません。最初の always は実際には論理的に同一です
always @(posedge clk)
begin
if (somecondition)
clk2 <= 1'b0;
else
clk2 <= 1'b1;
end
ただし、ModelSim で最初のバージョンをシミュレートすると、q が clk2 定数 0 で喜んでトグルすることがわかります。これはデバッグの悪夢です。