非阻塞賦值 (<=
) 是“并行”的,但是代碼順序會影響結果?”這正是 Verilog 的硬件描述本質 vs 行為語義之間的微妙之處。
💡1. 非阻塞賦值真的并行嗎?
是的!非阻塞賦值 <=
從行為上是并行的,也就是說:
always @(posedge clk) begina <= b;b <= c;
end
這段代碼的意思是:
-
在同一個時鐘沿上
-
a
會接收到舊的b
-
b
會接收到舊的c
這叫做非阻塞(non-blocking),等價于這樣寫的“并行賦值邏輯”:
臨時保存所有右邊值:tmp_a = btmp_b = c
時鐘來臨,一起賦值:a <= tmp_ab <= tmp_b
所以你說它“并行”是對的!💯
🧠2. 那為啥還說“順序會影響結果”?
重點來了!
“并行”只適用于賦值的“時間點”,不適用于你寫代碼時的“表達順序”
來看下面這個例子,關鍵點是多個 if 控制同一個變量的場景:
always @(posedge clk) beginif (a)x <= 1;if (b)x <= 2;
end
?? 雖然都是非阻塞 <=
,但表達的是兩個賦值行為的意圖
當 a=1
且 b=1
,你是想:
-
讓
x
同時變成 1 和 2?硬件無法這么干,它只能接收一個值 -
所以編譯器按照你寫的順序,理解為你希望用最后一個賦值為準
即使兩個賦值語句都在非阻塞、在行為上并行,它們還是描述了兩個競爭的硬件連接,Verilog 編譯器不可能自動幫你“合并”這兩個賦值。
所以順序不是運行時的順序,而是你代碼“行為邏輯優先級”的順序
🏗?3. 抽象層級理解:Verilog的三層視角
層級 | 你寫的代碼意義 | 實際電路含義 | 是否考慮順序 |
---|---|---|---|
行為級 (Behavioral) | 多個 if 判斷 | 多個觸發條件 | 順序決定優先級(誰“最后”賦值) |
RTL級 (Register Transfer Level) | 每一條賦值對應電路 | 描述寄存器、組合邏輯 | 并行,但賦值沖突要人為控制 |
門級 (Gate Level) | 最終邏輯門實現 | 真正并行門電路 | 無代碼順序,純邏輯表達 |
🔄4. 非阻塞賦值 ≠ 萬能同步魔法
非阻塞賦值只是告訴 Verilog 在時鐘沿后一起更新,它不會自動解決你邏輯寫法上的沖突或覆蓋問題。
如果你寫多個 x <= xxx;
,就相當于你拉了好多根線同時往一個寄存器塞值,編譯器只能“按你寫的順序取最后那個”。
?小結:關鍵點匯總
問題 | 回答 |
---|---|
非阻塞賦值是并行的嗎? | ? 是的,更新在時鐘沿后同時發生 |
那為什么順序會影響? | 因為你可能給一個變量多次賦值,Verilog 會保留最后一次賦值(前面的等于白費) |
所以 Verilog 是并行的嗎? | ? 硬件層面是并行的,但行為描述上,賦值意圖仍體現為“誰優先、誰覆蓋” |
怎么避免這種順序沖突? | - 同一變量賦值最好統一用 if-else - 先算中間變量,最后只賦一次 - 多個模塊分開處理不同變量 |
【verilog】多個 if 控制同一個變量 是否不是標準的語言規范,標準的語言規范應該如何寫?