(原創) 深入探討blocking與nonblocking (SOC) (Verilog)
Abstract
Verilog雖然是個語法簡單的語言,但是blocking與nonblocking卻是大家學習Verilog時永遠的痛,即時是很資深的IC Designer,也未必完全搞清楚兩者的差異,本文試著以simulator與synthesizer的角度去探討之。
Introduction
使用環境:NC-Verilog 5.4 + Debussy 5.4 v9 + Quartus II 7.2
軟體的語言都是一行一行依序執行,這與Verilog的blocking觀念一樣,但偏偏Verilog還有個nonblocking,而且在寫同步電路時,還一定得用nonblocking寫,到底blocking與nonblocking有什麼不同呢?我在(筆記)如何使用blocking與nonblocking assignment? (SOC) (Verilog)這篇討論過幾個簡單的原則,基本上只要依照這幾個原則去寫RTL,就能保證simulation的與synthesis的結果一致,但當時我並沒有討論其原因,只是將規則背下來而已。
在正式討論之前,請各位先做個小測驗,考驗您的觀念是否正確:
blocking.v / Verilog
2 (C) OOMusou 2010 http://oomusou.cnblogs.com
3
4 Filename : blocking.v
5 Simulator : NC-Verilog 5.4
6 Description : blocking assignment in always block
7 Release : Jul/30/2010 1.0
8 */
9
10 module blocking (
11 clk,
12 rst_n,
13 a_i,
14 b_i,
15 a_o,
16 b_o
17 );
18
19 input clk;
20 input rst_n;
21 input a_i;
22 input b_i;
23 output a_o;
24 output b_o;
25
26 reg a;
27 reg b;
28
29 assign a_o = a;
30 assign b_o = b;
31
32 always@(posedge clk or negedge rst_n) begin
33 if (~rst_n) begin
34 a = a_i;
35 b = b_i;
36 end
37 else begin
38 a = b;
39 b = a;
40 end
41 end
42
43 endmodule
blocking_tb.v / Verilog
2 (C) OOMusou 2010 http://oomusou.cnblogs.com
3
4 Filename : blocking_tb.v
5 Simulator : NC-Verilog 5.4
6 Description : testbench of blocking assignment in always block
7 Release : Jul/30/2010 1.0
8 */
9
10 `include "blocking.v"
11
12 module blocking_tb;
13
14 reg clk;
15 reg rst_n;
16 reg a_i;
17 reg b_i;
18 wire a_o;
19 wire b_o;
20
21 initial begin
22 clk = 1'b0;
23 rst_n = 1'b0;
24 a_i = 1'b1;
25 b_i = 1'b0;
26 #5;
27 rst_n = 1'b1;
28 #100;
29 $finish;
30 end
31
32 always #10 clk = ~clk;
33
34 initial begin
35 $fsdbDumpfile("blocking.fsdb");
36 $fsdbDumpvars(0, blocking_tb);
37 end
38
39 blocking blocking_0 (
40 .clk(clk),
41 .rst_n(rst_n),
42 .a_i(a_i),
43 .b_i(b_i),
44 .a_o(a_o),
45 .b_o(b_o)
46 );
47
48 endmodule
nonblocking.v / Verilog
2 (C) OOMusou 2010 http://oomusou.cnblogs.com
3
4 Filename : nonblocking.v
5 Simulator : NC-Verilog 5.4
6 Description : nonblocking assignment in always block
7 Release : Jul/30/2010 1.0
8 */
9
10 module nonblocking (
11 clk,
12 rst_n,
13 a_i,
14 b_i,
15 a_o,
16 b_o
17 );
18
19 input clk;
20 input rst_n;
21 input a_i;
22 input b_i;
23 output a_o;
24 output b_o;
25
26 reg a;
27 reg b;
28
29 assign a_o = a;
30 assign b_o = b;
31
32 always@(posedge clk or negedge rst_n) begin
33 if (~rst_n) begin
34 a <= a_i;
35 b <= b_i;
36 end
37 else begin
38 a <= b;
39 b <= a;
40 end
41 end
42
43 endmodule
nonblocking_tb.v / Verilog
2 (C) OOMusou 2010 http://oomusou.cnblogs.com
3
4 Filename : nonblocking_tb.v
5 Simulator : NC-Verilog 5.4
6 Description : testbench of nonblocking assignment in always block
7 Release : Jul/30/2010 1.0
8 */
9
10 `include "nonblocking.v"
11
12 module nonblocking_tb;
13
14 reg clk;
15 reg rst_n;
16 reg a_i;
17 reg b_i;
18 wire a_o;
19 wire b_o;
20
21 initial begin
22 clk = 1'b0;
23 rst_n = 1'b0;
24 a_i = 1'b1;
25 b_i = 1'b0;
26 #5;
27 rst_n = 1'b1;
28 #100;
29 $finish;
30 end
31
32 always #10 clk = ~clk;
33
34 initial begin
35 $fsdbDumpfile("nonblocking.fsdb");
36 $fsdbDumpvars(0, nonblocking_tb);
37 end
38
39 nonblocking nonblocking_0 (
40 .clk(clk),
41 .rst_n(rst_n),
42 .a_i(a_i),
43 .b_i(b_i),
44 .a_o(a_o),
45 .b_o(b_o)
46 );
47
48 endmodule
以上為完整的RTL與testbench,其實真正的差異只有以下兩部份,其他部分完全一樣:
1.在always block使用blocking
if (~rst_n) begin
a = a_i;
b = b_i;
end
else begin
a = b;
b = a;
end
end
2.在always block使用nonblocking
if (~rst_n) begin
a <= a_i;
b <= b_i;
end
else begin
a <= b;
b <= a;
end
end
請先把你自己當成simulator,實際模擬一下結果為何。
以下為使用NC-Verilog + Debussy所模擬的結果:
blocking.v
nonblocking.v
你所預期的結果與simulator一樣嗎?
以Simulator角度探討blocking與nonblocking
blocking
if (~rst_n) begin
a = a_i;
b = b_i;
end
else begin
a = b;
b = a;
end
end
先討論較好理解的blocking,所謂的blocking,就是一行程式執行完才能執行下一行,所以在clk rising edge時,先將b的值給a,然後再將a的值給a,也就是說,在clk rising edge之後,a = b = 0,這與C的觀念一樣。
nonblocking
if (~rst_n) begin
a <= a_i;
b <= b_i;
end
else begin
a <= b;
b <= a;
end
end
再來討論nonblocking,在clk rising edge時,a <= b,b <= a,這到底要怎麼理解呢?這必須牽涉到simulator的event queue如何處理這些event。
在討論evnet之前,先解釋兩個專有名詞,RHS與LHS。
RHS:在 = 或 <= 右邊的運算式或變數
LHS:在 = 或 <= 左邊的運算式或變數
由於電腦軟體本身是依序執行(也就是如C一樣程式一行一行的執行),但硬體電路卻可併行執行,simulator是軟體寫的,卻要能夠模擬出硬體電路的的並行執行,也就是如在5 ns時,同時有很多信號被處理,所以才有event queue的概念,將同一個time step要處理的信號放在一個event queue,simulator再依序處理,處理完後再處理下一個time step,這樣就能使依序執行的simulator可以模擬出並行執行的硬體電路。
在IEEE Verilog standard定義了以下的event queue讓simulator廠商實作,至於該如何實作是各廠商的商業機密。
絕大部分的event都會放在Active Events queue內,包括blocking assignments、blocking的RHS、continuous assignments、$display()..等,也就是說當某個time step到達時,會執行Active Events queue的event,但Verilog IEEE standard並沒有保證在Active Events queue內event的執行順序(所以一些不良的coding style可能會造成race condition,這又是另外一個Verilog很惱人的issue,再另闢專文討論),值得注意的是nonblocking的RHS是放在Active Events queue,但沒有包含nonblocking的LHS。
在IEEE standard有定義演算法介紹其他Event queue如何加進Active Events,在這就不多談,這裡的重點是有一個Nonblocking Events queue專門放nonblocking的LHS,會在適當的時機加入Active Events queue執行。
所以由此可知,由於RHS of nonblocking放在Active Events,所以會先執行,之後等在Nonblocking Events queue的LHS of nonblocking進入Active Events queue後再執行。
因此整個nonblocking可視為兩個步驟的行為:
1.在clk rising edge的一開始執行RHS。
2.在clk rising edge快結束時執行LHS。
所以在 a <= b, b <= a時,clk rising edge一開始先執行RHS,也就是a = 1,b = 0,然後再執行LHS,因此a = 0,b = 1,因此nonblocking不會如blocking因為a已經更新了,因而改變了b的值。可以發現,blocking會因為程式的撰寫順序而有不同的值,但nonblocking卻不會因為程式的撰寫順序而有影響,原因是nonblocking的執行是2個步驟,而blocking的執行是1個步驟。
以Synthesizer角度探討blocking與nonblocking
寫Verilog最擔心的是simulation時正常,但synthesis後卻不是你要的,因此我們實際在Quartus II跑看看,看看經過P&R之後,是否與NC-Verilog的結果一樣,並使用RTL Viewer看看Quartus II如何synthesis。
blocking.v
nonblocking.v
除了加上delay外,基本上波形與NC-Verilog所模擬的一樣。
blocking.v
雖然在code中宣告了2個reg,但synthesizer只會合成出1個register,也就是a = b, b = a只delay了1個clk。
nonblocking.v
會合成出2個register,符合我們的預期,也就是 a <= b, b <= a會delay 2個clk。
完整程式碼下載
blocking.7z (NC-Verilog + Debussy)
blocking_quartus_ii.7z (Quartus II)
nonblocking.7z (NC-Verilog + Debussy)
nonblocking_quartus_ii.7z (Quartus II)
Conclusion
本文試著用最淺顯易懂的方式解釋blocking與nonblocking的差異,並從simulator與synthesizer的角度同時去思考,若想得知更完整的資訊,可參考Reference的paper與書籍。
See Also
(筆記)如何使用blocking與nonblocking assignment? (SOC) (Verilog)
(筆記) Cliff Cummings的paper大全 (SOC) (Verilog)
Reference
Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.
夏宇文 2008, Verilog數字系統設計教程, 北京航空航天大學出版社