阻塞賦值與非阻塞賦值的差異:求值時機、順序、使用場合比較
兩者都是在 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 區塊之間 | 在同一個邊緣動作的區塊之間,容易發生結果隨執行順序而改變的競爭 | 右邊的求值會先完成,因此不易發生競爭 |
| 用錯時 | 用於循序電路時,結果會受區塊的執行順序左右,有時與合成後電路的動作不一致 | 用於組合電路時,中間值會以舊值被讀取,模擬可能與合成後的電路不一致,或被多餘地重新執行 |
數值為具代表性的大致參考值,會因世代或產品而異。