在Verilog中有兩種類型的賦值語(yǔ)句:阻塞賦值語(yǔ)句(“=”)和非阻塞賦值語(yǔ)句(“<=”)。正確地使用這兩種賦值語(yǔ)句對(duì)于Verilog的設(shè)計(jì)和仿真非常重要。
Verilog語(yǔ)言中講的阻塞賦值與非阻塞賦值,但從字面意思來(lái)看,阻塞就是執(zhí)行的時(shí)候在某個(gè)地方卡住了,等這個(gè)操作執(zhí)行完在繼續(xù)執(zhí)行下面的語(yǔ)句,而非阻塞就是不管執(zhí)行完沒(méi)有,我不管執(zhí)行的結(jié)果是什么,反正我繼續(xù)下面的事情。而Verilog中的阻塞賦值與非阻塞賦值正好也是這個(gè)意思,通過(guò)執(zhí)行一個(gè)例子,就可以簡(jiǎn)單地明白了:
1、阻塞賦值可以理解為語(yǔ)句的順序執(zhí)行,因此語(yǔ)句的執(zhí)行順序很重要
2、非阻塞賦值可以理解為語(yǔ)句的并行執(zhí)行,所以語(yǔ)句的執(zhí)行不考慮順序
3、在assign的結(jié)構(gòu)中,必須使用的是阻塞賦值
也就是說(shuō):
阻塞:在本語(yǔ)句中“右式計(jì)算”和“左式更新”完全完成之后,才開始執(zhí)行下一條語(yǔ)句;
非阻塞:當(dāng)前語(yǔ)句的執(zhí)行不會(huì)阻塞下一語(yǔ)句的執(zhí)行。
下面給出實(shí)例來(lái)說(shuō)明:
給出相應(yīng)的案例來(lái)幫助理解:
module prj1(in,b,c,d,clk,rst_n);
input in;
input clk;
input rst_n;
output b,c,d;
reg b,c,d;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
b <=0;
c <=0;
d <=0;
end
else begin
b <=in;
c <=b;
d <=c;
end
end
endmodule
這個(gè)目的是為了展示非阻塞賦值過(guò)程中的時(shí)序變化,對(duì)應(yīng)的RTL電路圖和仿真波形如下圖:
從仿真圖可以看書,b,c,d是在每個(gè)時(shí)鐘后依次傳遞的,如果采用阻塞賦值,如果in改變,那么b,c,d立刻改變,這個(gè)就在這里不給出仿真。
阻塞賦值和非阻塞賦值的另外一個(gè)區(qū)別在于綜合的時(shí)候,如果輸出只有d,bc作為中間變量,阻塞賦值在綜合的過(guò)程中會(huì)自動(dòng)省略掉中間過(guò)程。給出如下仿真,理解更為清楚
module prj1(in,b,c,clk,rst_n);
input in;
input clk;
input rst_n;
output b,c;
reg b,c, e,f, m,n;
/* <= */
always @(posedge clk or negedge rst_n) begin
if(!rst_n) b <=0;
else begin
e <=in;
f <=e;
b <=f;
end
end
/* = */
always @(posedge clk or negedge rst_n) begin
if(!rst_n) c=0;
else begin
m = in;
n = m;
c = n;
end
end
endmodule
綜合后結(jié)果如圖,可以看出,采用阻塞賦值,綜合后的邏輯單元只有一個(gè),中間變量m,n直接省去了。
下面我們來(lái)看看兩者代碼之間到底是怎么運(yùn)行的。
(1)對(duì)于阻塞賦值的情況:
always @(posedge clk or negedge rst_n) begin
if(!rst_n) c=0;
else begin
m = in;
n = m;
c = n;
end
end
always語(yǔ)句塊對(duì)Clk的上升沿敏感,當(dāng)發(fā)生Clk 0~1的跳變時(shí),執(zhí)行該always語(yǔ)句。
在begin...end語(yǔ)句塊中所有語(yǔ)句是順序執(zhí)行的,而且最關(guān)鍵的是,阻塞賦值是在本語(yǔ)句中“右式計(jì)算”和“左式更新”完全完成之后,才開始執(zhí)行下一條語(yǔ)句的。
在本例中,in的值賦給m以后,再執(zhí)行n = m;同樣在n的值更新以后,才執(zhí)行c = n。這樣,最終的計(jì)算結(jié)果就是in = c。也就是說(shuō)時(shí)鐘上升沿到來(lái)的時(shí)候,整個(gè)語(yǔ)句塊執(zhí)行完后,in,m,n,c的值都是一樣的,這也就是我們前面說(shuō)的,in變化之后,m,n,c都跟著變化。所有的語(yǔ)句執(zhí)行完以后,該always語(yǔ)句等待Clk的上升沿,從而再一次觸發(fā)begin...end語(yǔ)句。
總結(jié)
完成阻塞賦值的過(guò)程為:首先計(jì)算等號(hào)右邊表達(dá)式的結(jié)果;接著這個(gè)結(jié)果存入仿真系統(tǒng)的內(nèi)部臨時(shí)寄存器中,這個(gè)寄存器也稱為賦值事件隊(duì)列和調(diào)度的臨時(shí)寄存器。如果賦值時(shí)沒(méi)有延遲信息,則這個(gè)事件立即被調(diào)度執(zhí)行。
(2)對(duì)于非阻塞賦值的情況
always @(posedge clk or negedge rst_n) begin
if(!rst_n) b <=0;
else begin
e <=in;
f <=e;
b <=f;
end
end
首先執(zhí)行e <= in,產(chǎn)生一個(gè)更新事件,將in的當(dāng)前值賦給e,但是這個(gè)賦值過(guò)程并沒(méi)有立刻執(zhí)行,而是在事件隊(duì)列中處于等待狀態(tài)。
然后執(zhí)行f <= e,同樣產(chǎn)生一個(gè)更新事件,將e的當(dāng)前值(注意上一語(yǔ)句中將in值賦給e的過(guò)程并沒(méi)有完成,e還是舊值)賦給f,這個(gè)賦值事件也將在事件隊(duì)列中處于等待狀態(tài)。
再執(zhí)行b <= f,產(chǎn)生一個(gè)更新事件,將f的當(dāng)前值賦給b,這個(gè)賦值事件也將在事件隊(duì)列中等待執(zhí)行。
這時(shí)always語(yǔ)句塊執(zhí)行完成,開始對(duì)下一個(gè)Clk上升沿敏感。也就是說(shuō),使用非阻塞賦值方式進(jìn)行賦值時(shí),各個(gè)賦值語(yǔ)句同步執(zhí)行;因此,通常在一個(gè)時(shí)鐘沿對(duì)臨時(shí)變量進(jìn)行賦值,而在另一個(gè)時(shí)鐘沿對(duì)其進(jìn)行采樣。
那么什么時(shí)候才執(zhí)行那3個(gè)在事件隊(duì)列中等待的事件呢?只有當(dāng)當(dāng)前仿真時(shí)間內(nèi)的所有活躍事件和非活躍事件都執(zhí)行完成后,才開始執(zhí)行這些非阻塞賦值的更新事件。這樣就相當(dāng)于將in、e和f的值同時(shí)賦給了e、f和b。
注:
*仿真器首先按照仿真時(shí)間對(duì)事件進(jìn)行排序,然后再在當(dāng)前仿真時(shí)間里按照事件的優(yōu)先級(jí)順序進(jìn)行排序。
*活躍事件是優(yōu)先級(jí)最高的事件。在活躍事件之間,它們的執(zhí)行順序是隨機(jī)的。阻塞賦值(=)、連續(xù)賦值(assign)以及非阻塞賦值的右式計(jì)算等都屬于活躍事件。
總結(jié) :
非阻塞語(yǔ)句的執(zhí)行過(guò)程為:首先,它會(huì)把非阻塞賦值放入調(diào)度隊(duì)列中;接著,仿真工具開始執(zhí)行下一條語(yǔ)句而不等待當(dāng)前這條語(yǔ)句執(zhí)行完畢。也就是說(shuō),先計(jì)算出等號(hào)右邊表達(dá)式的結(jié)果,再把這個(gè)結(jié)果的賦值操作保存在事件隊(duì)列中,等輪到事件被調(diào)度的時(shí)候,把這個(gè)結(jié)果賦值給等號(hào)左邊。如果沒(méi)有指定等號(hào)右邊的延遲,賦值的操作會(huì)發(fā)生在當(dāng)前時(shí)間單位的最后時(shí)刻。
知道了阻塞賦值和非阻塞賦值的區(qū)別之后,大家肯定就會(huì)關(guān)心什么時(shí)候該用阻塞賦值什么時(shí)候該用非阻塞賦值,下面我簡(jiǎn)單的說(shuō)幾句:
賦值的類型的選擇取決于建模的邏輯類型。一般情況是這樣的(也有特殊情況):
(1)在時(shí)序邏輯電路中一般使用非阻塞賦值。
非阻塞賦值在塊結(jié)束后才完成賦值操作,此賦值方式可以避免在仿真出現(xiàn)冒險(xiǎn)和競(jìng)爭(zhēng)現(xiàn)象。
(2)在組合邏輯電路中一般使用阻塞賦值。
使用阻塞方式對(duì)一個(gè)變量進(jìn)行賦值時(shí),此變量的值在在賦值語(yǔ)句執(zhí)行完后就立即改變。
(3)在assign語(yǔ)句中必須使用阻塞賦值語(yǔ)句
希望大家在懂得了阻塞和非阻塞語(yǔ)句的區(qū)別之后,能夠很好的在自己的項(xiàng)目中靈活地運(yùn)用,這也是大家面試的時(shí)候,必須會(huì)面對(duì)的一個(gè)問(wèn)題,希望大家能夠掌握
編輯:jq
-
Verilog
+關(guān)注
關(guān)注
28文章
1352瀏覽量
110425 -
HDL
+關(guān)注
關(guān)注
8文章
328瀏覽量
47475 -
阻塞
+關(guān)注
關(guān)注
0文章
24瀏覽量
8141
原文標(biāo)題:Verilog HDL中阻塞語(yǔ)句和非阻塞語(yǔ)句的區(qū)別
文章出處:【微信號(hào):gh_9d70b445f494,微信公眾號(hào):FPGA設(shè)計(jì)論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
socket編程中的阻塞與非阻塞
socket阻塞和非阻塞的區(qū)別是什么
求助,關(guān)于CyU3PUsbHostEpWaitForCompletion函數(shù)中的阻塞問(wèn)題求解
是否可以使用Aurix中的CCU6模塊,以非阻塞方式在檢測(cè)到GPIO下降沿時(shí)觸發(fā)中斷?
FPGA學(xué)習(xí)筆記---基本語(yǔ)法
請(qǐng)問(wèn)使用lwip創(chuàng)建socket,該如何做到非阻塞的接收發(fā)送數(shù)據(jù)?
關(guān)于Verilog的一些基本語(yǔ)法
鴻蒙TypeScript入門學(xué)習(xí)第6天:【條件語(yǔ)句】
![鴻蒙TypeScript入門學(xué)習(xí)第6天:【條件<b class='flag-5'>語(yǔ)句</b>】](https://file1.elecfans.com/web2/M00/C6/84/wKgZomYKR_aAbRPhAABW3F6g280594.png)
評(píng)論