日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

(原創) 深入探討blocking與nonblocking (SOC) (Verilog)

發(fā)布時(shí)間:2025/7/14 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (原創) 深入探討blocking與nonblocking (SOC) (Verilog) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Abstract
Verilog雖然是個(gè)語(yǔ)法簡(jiǎn)單的語(yǔ)言,但是blocking與nonblocking卻是大家學(xué)習(xí)Verilog時(shí)永遠(yuǎn)的痛,即時(shí)是很資深的IC Designer,也未必完全搞清楚兩者的差異,本文試著以simulator與synthesizer的角度去探討之。

Introduction
使用環(huán)境:NC-Verilog 5.4 + Debussy 5.4 v9 + Quartus II 7.2

軟體的語(yǔ)言都是一行一行依序執(zhí)行,這與Verilog的blocking觀念一樣,但偏偏Verilog還有個(gè)nonblocking,而且在寫(xiě)同步電路時(shí),還一定得用nonblocking寫(xiě),到底blocking與nonblocking有什麼不同呢?我在(筆記)如何使用blocking與nonblocking assignment? (SOC) (Verilog)這篇討論過(guò)幾個(gè)簡(jiǎn)單的原則,基本上只要依照這幾個(gè)原則去寫(xiě)RTL,就能保證simulation的與synthesis的結(jié)果一致,但當(dāng)時(shí)我並沒(méi)有討論其原因,只是將規(guī)則背下來(lái)而已。

在正式討論之前,請(qǐng)各位先做個(gè)小測(cè)驗(yàn),考驗(yàn)?zāi)挠^念是否正確:

blocking.v / Verilog?

1?/*?
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?

1?/*?
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?

1?/*?
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?

1?/*?
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,其實(shí)真正的差異只有以下兩部份,其他部分完全一樣:

1.在always block使用blocking

always@(posedge clk or?negedge rst_n) begin
?
if (~rst_n) begin
??? a
= a_i;
??? b
= b_i;
?
end
?
else?begin
??? a
= b;
??? b
= a;
?
end
end

2.在always block使用nonblocking?

always@(posedge clk or?negedge rst_n) begin
?
if (~rst_n) begin
??? a
<= a_i;
??? b
<= b_i;
?
end
?
else?begin
??? a
<= b;
??? b
<= a;
?
end
end

請(qǐng)先把你自己當(dāng)成simulator,實(shí)際模擬一下結(jié)果為何。

以下為使用NC-Verilog + Debussy所模擬的結(jié)果:

blocking.v

?

nonblocking.v

你所預(yù)期的結(jié)果與simulator一樣嗎?

以Simulator角度探討blocking與nonblocking

blocking

always@(posedge clk or?negedge rst_n) begin
?
if (~rst_n) begin
??? a
= a_i;
??? b
= b_i;
?
end
?
else?begin
??? a
= b;
??? b
= a;
?
end
end

先討論較好理解的blocking,所謂的blocking,就是一行程式執(zhí)行完才能執(zhí)行下一行,所以在clk rising edge時(shí),先將b的值給a,然後再將a的值給a,也就是說(shuō),在clk rising edge之後,a = b = 0,這與C的觀念一樣。

nonblocking

always@(posedge clk or?negedge rst_n) begin
?
if (~rst_n) begin
??? a
<= a_i;
??? b
<= b_i;
?
end
?
else?begin
??? a
<= b;
??? b
<= a;
?
end
end

再來(lái)討論nonblocking,在clk rising edge時(shí),a <= b,b <= a,這到底要怎麼理解呢?這必須牽涉到simulator的event queue如何處理這些event。

在討論evnet之前,先解釋兩個(gè)專有名詞,RHS與LHS。

RHS:在 =? 或 <= 右邊的運(yùn)算式或變數(shù)

LHS:在 = 或 <= 左邊的運(yùn)算式或變數(shù)

由於電腦軟體本身是依序執(zhí)行(也就是如C一樣程式一行一行的執(zhí)行),但硬體電路卻可併行執(zhí)行,simulator是軟體寫(xiě)的,卻要能夠模擬出硬體電路的的並行執(zhí)行,也就是如在5 ns時(shí),同時(shí)有很多信號(hào)被處理,所以才有event queue的概念,將同一個(gè)time step要處理的信號(hào)放在一個(gè)event queue,simulator再依序處理,處理完後再處理下一個(gè)time step,這樣就能使依序執(zhí)行的simulator可以模擬出並行執(zhí)行的硬體電路。

在IEEE Verilog standard定義了以下的event queue讓simulator廠商實(shí)作,至於該如何實(shí)作是各廠商的商業(yè)機(jī)密。

?

絕大部分的event都會(huì)放在Active Events queue內(nèi),包括blocking assignments、blocking的RHS、continuous assignments、$display()..等,也就是說(shuō)當(dāng)某個(gè)time step到達(dá)時(shí),會(huì)執(zhí)行Active Events queue的event,但Verilog IEEE standard並沒(méi)有保證在Active Events queue內(nèi)event的執(zhí)行順序(所以一些不良的coding style可能會(huì)造成race condition,這又是另外一個(gè)Verilog很惱人的issue,再另闢專文討論),值得注意的是nonblocking的RHS是放在Active Events queue,但沒(méi)有包含nonblocking的LHS。

在IEEE standard有定義演算法介紹其他Event queue如何加進(jìn)Active Events,在這就不多談,這裡的重點(diǎn)是有一個(gè)Nonblocking Events queue專門(mén)放nonblocking的LHS,會(huì)在適當(dāng)?shù)臅r(shí)機(jī)加入Active Events queue執(zhí)行。

所以由此可知,由於RHS of nonblocking放在Active Events,所以會(huì)先執(zhí)行,之後等在Nonblocking Events queue的LHS of nonblocking進(jìn)入Active Events queue後再執(zhí)行。

因此整個(gè)nonblocking可視為兩個(gè)步驟的行為:

1.在clk rising edge的一開(kāi)始執(zhí)行RHS。

2.在clk rising edge快結(jié)束時(shí)執(zhí)行LHS。

所以在 a <= b, b <= a時(shí),clk rising edge一開(kāi)始先執(zhí)行RHS,也就是a = 1,b = 0,然後再執(zhí)行LHS,因此a = 0,b = 1,因此nonblocking不會(huì)如blocking因?yàn)閍已經(jīng)更新了,因而改變了b的值。可以發(fā)現(xiàn),blocking會(huì)因?yàn)槌淌降淖珜?xiě)順序而有不同的值,但nonblocking卻不會(huì)因?yàn)槌淌降淖珜?xiě)順序而有影響,原因是nonblocking的執(zhí)行是2個(gè)步驟,而blocking的執(zhí)行是1個(gè)步驟

以Synthesizer角度探討blocking與nonblocking

寫(xiě)Verilog最擔(dān)心的是simulation時(shí)正常,但synthesis後卻不是你要的,因此我們實(shí)際在Quartus II跑看看,看看經(jīng)過(guò)P&R之後,是否與NC-Verilog的結(jié)果一樣,並使用RTL Viewer看看Quartus II如何synthesis。

blocking.v

?

nonblocking.v

?

除了加上delay外,基本上波形與NC-Verilog所模擬的一樣。

blocking.v

?

雖然在code中宣告了2個(gè)reg,但synthesizer只會(huì)合成出1個(gè)register,也就是a = b, b = a只delay了1個(gè)clk。

nonblocking.v

?

會(huì)合成出2個(gè)register,符合我們的預(yù)期,也就是 a <= b, b <= a會(huì)delay 2個(gè)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的角度同時(shí)去思考,若想得知更完整的資訊,可參考Reference的paper與書(shū)籍。

See Also
(筆記)如何使用blocking與nonblocking assignment? (SOC) (Verilog)
(筆記) Cliff Cummings的paper大全 (SOC) (Verilog)

(筆記) $dispaly()、$strobe()、$monitor() 、$fwrite()與blocking / nonblocking的關(guān)係 (SOC) (Verilog) (Debussy) (Verdi)

Reference
Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.
夏宇文 2008, Verilog數(shù)字系統(tǒng)設(shè)計(jì)教程, 北京航空航天大學(xué)出版社

總結(jié)

以上是生活随笔為你收集整理的(原創) 深入探討blocking與nonblocking (SOC) (Verilog)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。