質問 1 について。ノンブロッキング割り当ては、必ずしもシーケンシャルな動作を意味するわけではありません。ブロッキング/ノンブロッキング代入はシミュレーション構造です。理解を深めるために、小さな例を見てみましょう。
module some_gate(
input logic a,
input logic b,
output logic c,
output logic d
);
// c is 'a or b'
// d is 'a and c'
endmodule
2 つの入力信号と 2 つの出力信号があります。複合ゲートをモデル化します。
従来の Verilog スタイルでは、次のように記述します。
always @(a or b) begin
c = a || b;
d = a && c;
end
これは、a
またはが変化するたびに、とb
の値を計算することを意味します。に対してブロッキング代入を使用したため、ここで計算した値は の計算に「伝播」されます。これは基本的に、 で記述されたロジックを のロジックの後に連鎖させたことを意味します。c
d
c
d
d
c
これは、小さなテストベンチを使用してテストできます。
module test;
logic a, b, c, d;
some_gate dut(.*);
always @(a or b or c or d)
$display("[%0d] a = %b, b = %b, c = %b, d = %b", $time(), a, b, c, d);
initial begin
#1 a = 1;
#1 b = 1;
#1 a = 0;
#1 $finish();
end
endmodule
これをシミュレートすると、次のようになります。
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
これは、表示プロセスが変数の変更ごとに 1 回トリガーされるためです。は からにa
変更されますが、まだ更新されていません。次に、同じ時間ステップで更新されます。後で、 を変更しますが、これはまたはの変更をトリガーしません。その後、同じタイム スライスで再度変更し、更新されます。x
1
c
c
d
b
c
d
a
d
センシティビティ リストを指定しなければならないのは少し冗長です。なぜなら、組み合わせロジックが必要であることがわかっている場合は、代入の右側にある何かが変更されるたびにプロセスを再トリガーする必要があるからです。これがalways_comb
目的です。
always_comb
センシティビティ リストを削除するだけで、を使用してコードを書き直すことができます。
always_comb begin
c = a || b;
d = a && c;
end
このコードを実行すると、同じ出力が得られます。
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
次に興味深い部分です。always_comb
非ブロッキング割り当てを使用して、まったく同じ回路をモデル化できます。
always_comb begin
c <= a || b;
d <= a && c;
end
ただし、このコードを実行すると、わずかに異なる出力が生成されます。
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
最初のタイム ステップでは、1 つではなく 3 つのプリントがあることに注意してください。ここで何が起こるかを詳しく見てみましょう。まず、 を変更a
しますが、c
まだd
更新されていません。第二に、c
更新されd
ますが、同じままです。これは、 の非ブロッキング代入が原因で、c
のd
「古い」値が「見える」ことになりc
ます。3 番目に、c
公式に更新された後、ツールは更新をスケジュールd
し、最初の時間ステップの最後の印刷を確認します。残りは前の場合と同じです。
always_comb
割り当ての右側で何かが変更されるたびに再トリガーされる前の段落を思い出してください。ここでのトリックは、これalways_comb
が実際には次のように動作することです。
always @(a or b or c) begin
c <= a || b;
d <= a && c;
end
これは非標準の Verilog ですが、同じロジックをモデル化します。c
機密リストに明示的に追加されていることに注意してください。これを省略すると、ラッチを説明することになります。このスタイルは、間違いやすい (つまり、センシティビティ リストに中間ロジック ノードを追加するのを忘れる) ため、お勧めできません。
ここで重要なポイントは、ブロッキング代入またはノンブロッキング代入は、順次ロジックまたは組み合わせロジックを記述しないということです。コードからどの論理回路が推論されるかを制御するのは、コンテキスト全体 (つまり、いつ実行されるかを決定するセンシティビティ リスト) です。
完全なコード例はEDAPlaygroundで入手できます。
質問 2 について。これはツール固有のものであり、これに関するフォーラムではありません。ベンダーの Web サイトでこれを確認する必要があります。