Altifigence Academy

15 / 37 · 概念

Nonblocking 指定與同步狀態更新

分開舊值與下一值,正確解讀管線與計數器 RTL。

右側算式以舊狀態求值

時脈驅動的循序區塊中,<= 先計算右側,再於 nonblocking非阻塞賦值(nonblocking)在循序 RTL 中以 <= 表示。它先求右側運算式的值,再排程更新,讓同一邊緣的暫存器都能依據先前狀態計算。 更新階段反映結果。同一邊緣更新多個暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容時,可避免新值因程式行序而一路穿透。

SystemVerilog
always_ff @(posedge clk) begin
  if (rst) begin
    a <= 8'd0;
    b <= 8'd0;
  end else begin
    a <= d;
    b <= a;
  end
end
ak+1=dk,bk+1=aka_{k+1}=d_k,\qquad b_{k+1}=a_k

初始 a=b=0、輸入依序 5、9、2,邊緣後 (a,b) 為 (5,0)、(9,5)、(2,9)。若認為第二行讀到已更新的 a,就等於刪掉一級管線管線以暫存器將計算分為多個階段,讓多筆輸入重疊處理。資料、valid 與控制訊號必須在各階段對齊。 詳細內容。

每欄是一次上升緣上升緣是時脈由 0 變成 1 的瞬間。它與表示整段 CLK=1 期間的高準位不同。 詳細內容的觀察紀錄。輸入為邊緣前值,名稱含「後」的狀態為更新後值。欄位對齊表示取樣順序,並未繪出實體傳播延遲傳播延遲是輸入改變後,輸出穩定至正確值所需的時間。邏輯式是否等價與時間特性是兩個不同問題。 詳細內容。
由 a=b=0 開始。a 儲存新 d 的同時,b 儲存舊 a,因此兩列相差一級。

a 與 b 讀取相同的先前狀態
查看波形資料
波形資料:每個字元表示一個區間;句點保持先前狀態;p 表示一個時脈週期。
訊號波形匯流排值
邊緣234E0 → E1 → E2
d2345 → 9 → 2
a 後2345 → 9 → 2
b 後2340 → 5 → 9

改成 blocking 為何危險

若同一區塊改為 a=d; b=a;,b 的計算可能讀到區塊內已改變的 a。與其他循序區塊的排程也可能產生競爭。基本原則是組合計算用 blocking、狀態儲存用 nonblocking;只有能解釋事件語意時才採用例外。

避免對同一暫存器多次指定

同一程序若對 q 執行多次 nonblocking 指定,最後執行者可能決定結果。不要用多個獨立 if 隱藏優先權,應用 if / else if / else 或明確的 next-state 變數表達功能,也應避免多個區塊驅動同一暫存器。

RTL 審查時,為每個暫存器寫一條下一狀態式很有幫助。若出現兩條式子,或某條件下未定義,就是重新檢查控制優先權的訊號。

自己試試看

初始 a=1、b=4,在同一時脈區塊執行 a<=b; b<=a;,一個與兩個邊緣後的狀態各為何?

查看解說

一個邊緣後 (a,b)=(4,1),兩個後為 (1,4)。各指定都讀取同一份前次狀態,因此互換。若寫 a=b; b=a;,依順序可能都成為舊 b,並非相同功能。

此選擇適用於本瀏覽器,隨時可從頁尾變更。