ブロッキング代入とノンブロッキング代入の違い:評価のタイミング・順序・使う場所を比較
どちらもVerilogのalwaysブロックの中で使う代入ですが、左辺が書き換わるタイミングが違います。ブロッキング代入(=)は、その行を実行した時点で左辺を更新し、次の行では新しい値が使われます。ノンブロッキング代入(<=)は、同じタイミングのすべての右辺を先に評価し、そのあとでまとめて左辺を更新します。クロックで動く順序回路には<=、組み合わせ回路のalwaysには=、というのが基本のガイドラインです。
| 項目 | ブロッキング代入(=) | ノンブロッキング代入(<=) |
|---|---|---|
| 書き方 | a = b; | a <= b; |
| 左辺を更新するタイミング | その行を実行したとき、すぐに更新する | 同じタイミングの右辺をすべて評価した後、まとめて更新する |
| 次の行から見える値 | 更新後の新しい値 | 更新前の古い値 |
| 記述の順序への依存 | あり。行の順番を入れ替えると結果が変わる | ほぼなし。ただし同じ変数に2回代入すると、後の代入が残る |
| 対応する回路の動き | 上から順に途中の値を計算していく組み合わせ回路 | クロックのエッジで一斉に値を取り込むフリップフロップ |
| 主に使う場所 | 組み合わせ回路のalways @(*)、テストベンチの手続き | クロックで動く順序回路のalways @(posedge clk) |
| 2段のシフトレジスタ(クロックで動くブロック) | q1 = d; q2 = q1; では、q2にも同じエッジでdが入り、1段しか遅れない | q1 <= d; q2 <= q1; では、q2にエッジの前のq1が入り、2段になる |
| 値の入れ替え(クロックで動くブロック) | a = b; b = a; では、aとbが同じ値になる | a <= b; b <= a; では、aとbが入れ替わる |
| 複数のalwaysブロックの間 | 同じエッジで動くブロックどうしで、実行の順番によって結果が変わるレースが起きやすい | 右辺の評価が先にそろうので、レースが起きにくい |
| 使い方を誤ったとき | 順序回路に使うと、結果がブロックの実行順に左右され、合成した回路と動きが食い違うことがある | 組み合わせ回路に使うと、途中の値が古いまま読まれ、シミュレーションが合成した回路と食い違ったり、余分に再実行されたりする |
数値は代表的な目安で、世代や製品によって異なります。