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

1 /* 
2 (C) OOMusou 2010 http://oomusou.cnblogs.com

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

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

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

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

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

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

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

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

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

請先把你自己當成simulator,實際模擬一下結果為何。

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

blocking.v

nonblocking.v

你所預期的結果與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,就是一行程式執行完才能執行下一行,所以在clk rising edge時,先將b的值給a,然後再將a的值給a,也就是說,在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

再來討論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)

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

Reference
Clifford E. Cummings 2000, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kills, Sunburst Design, Inc.
夏宇文 2008, Verilog數字系統設計教程, 北京航空航天大學出版社

(原創) 深入探討blocking與nonblocking (SOC) (Verilog)相关推荐

  1. (原創) 如何解決DE2_LCM_CCD上下顛倒左右相反與無法設定曝光值的問題? (SOC) (DE2)...

    AbstractDE2_LCM_CCD是友晶科技為DE2和其130萬像素CMOS與彩色LCD所寫的範例,但官方的範例會造成上下顛倒左右相反與曝光值無法設定的問題,本文提出解決方式. Introduct ...

  2. (原創) 如何使用SignalTap II觀察reg與wire值? (SOC) (Verilog) (Quartus II) (SignalTap II)

    Abstract 撰寫Verilog時,雖然每個module都會先用ModelSim或Quartus II自帶的simulator仿真過,但真的將每個module合併時,一些不可預期的『run-tim ...

  3. signature=ae83778c2aa4dd8b9deb3ee108c1263d,何品達多媒體作品發表會含輔助文件《奎》原創作品與註釋...

    摘要: <奎>為結合樂器現場演出與即時影音處理的多媒體音樂作品,以宗教信仰與藝術的關聯為發想,將台西溪頂明聖宮魁星爺神像於日治時期遭日人查扣焚燒,歷劫歸來的過程,引申為逆境求生之精神並以多 ...

  4. (原創) 如何正確的使用迴圈(使用for_each)? (C/C++) (STL) (template)

    Abstract之前在(原創) 如何使用for_each() algorithm? (C/C++) (STL) 曾經討論過for_each(),不過當時功力尚淺,只談到了皮毛而已,這次看了effect ...

  5. (原創) 如何使用ModelSim-Altera對Nios II仿真? (SOC) (Nios II) (SOPC Builder) (ModelSim) (DE2)...

    Abstract 在剛學習Nios II時,每次在Run As Nios II Hardware下方,看到Run As Nios II ModelSim就覺得很好奇,Nios II明明是嵌入式系統,怎 ...

  6. Chris Hadfield現身《ABS 2020》,各方菁英和THORBOT 雷神量化機器人一同進行深入探討

    雖然新冠肺炎疫情,在 2020 上半年嚴重衝擊了全球的實體經濟,但這同時也是一個向世界展示區塊鏈技術的重要機會.包括實現無現金社會.醫療物資追蹤,乃至於疫情的資訊共享,THORBOT 雷神量化機器人在 ...

  7. (原創) Quartus II安裝新觀念:如何將Quartus II安裝在VirtualBox內? (SOC) (Quartus II) (VirtualBox)...

    Abstract VM並不是什麼新的觀念,透過VM我們可以在一個OS去執行其他OS,若我們將Quartus II也裝在VM中,將可解決一些長久以來Quartus II使用上所遇到的問題. Introd ...

  8. Android 4.3安全機制探討

    http://www.tshopping.com.tw/thread-232697-1-1.html http://loda.hala01.com/2013/08/android-4-3%E5%AE% ...

  9. (原創) 如何將編譯結果,統一放在一個目錄下? (SOC) (Quartus II)

    Abstract Quartus II預設會將所有檔案都放在project的根目錄下,導致根目錄檔案過多,管理不便,若能將編譯的結果統一放到其他目錄下,將有助於日後管理. Introduction 使 ...

最新文章

  1. 深入理解PHP原理之变量(Variables inside PHP)
  2. tomcat源码分析_Tomcat源码分析(一)--Tomcat的初始化
  3. 代码收藏——js+asp 的屏幕滚动脚本
  4. Java SE 7、8、9 –推进Java
  5. pe常用软件_装机不求人之打造自己的全功能PE系统维护优盘
  6. Codevs 1200 同余方程 2012年NOIP全国联赛提高组
  7. 计算机时间校对更改原因,计算机时间校准方法
  8. 《管理学》第十周阶段性回顾
  9. 微信小程序入门(一)微信小程序注册申请
  10. 暑期机器学习小组读书报告----机器学习概述
  11. 使用FFmpeg将一张图片和一段音频转换成视频
  12. Electron中主进程和渲染进程之间的通信
  13. 刘强东的“百亿补贴” 被指“雷”声大雨点小
  14. 中国移动呼叫转移设置
  15. Java最新面试题100道,包含答案示例(1-10题)
  16. ClassDiagram类图举例 明 继承图
  17. 阿里智能语音翻译和科大讯飞(机译)语音翻译的结果对比
  18. DWI图像 从DICOM Tag识别 b value 的方法
  19. 苹果虚拟机装vmware tool
  20. BZOJ 2386: [Ceoi2011]Team

热门文章

  1. Android 抓包的一些命令 及 adb使用的一些注意事项
  2. Windows Phone 8初学者开发—第12部分:改进视图模型和示例数据
  3. 入手一个windows ce系统的可以打电话的HPC,测试在上面发表博客
  4. python简单爬虫程序分析_[Python专题学习]-python开发简单爬虫
  5. 利用SoapUI 测试web service的一些问题总结
  6. Java中PreparedStatement和Statement的用法区别
  7. 我来谈谈PHP和JAVA在web开发上的的区别
  8. PO、BO、VO、DTO、POJO、DAO的区别
  9. Java String,StringBuilder和StringBuffer的区别 StringBuilder StringBuffer String
  10. (转)Vix_API 操作 VMware