來(lái)源:《Verilog數(shù)字系統(tǒng)設(shè)計(jì)(夏宇聞)》
阻塞和非阻塞賦值的語(yǔ)言結(jié)構(gòu)是Verilog 語(yǔ)言中最難理解概念之一。甚至有些很有經(jīng)驗(yàn)的Verilog 設(shè)計(jì)工程師也不能完全正確地理解:何時(shí)使用非阻塞賦值何時(shí)使用阻塞賦值才能設(shè)計(jì)出符合要求的電路。
他們也不完全明白在電路結(jié)構(gòu)的設(shè)計(jì)中,即可綜合風(fēng)格的Verilog模塊的設(shè)計(jì)中,究竟為什么還要用非阻塞賦值,以及符合IEEE 標(biāo)準(zhǔn)的Verilog 仿真器究竟如何來(lái)處理非阻塞賦值的仿真。
本小節(jié)的目的是盡可能地把阻塞和非阻塞賦值的含義詳細(xì)地解釋清楚,并明確地提出可綜合的Verilog模塊編程在使用賦值操作時(shí)應(yīng)注意的要點(diǎn),按照這些要點(diǎn)來(lái)編寫(xiě)代碼就可以避免在Verilog 仿真時(shí)出現(xiàn)冒險(xiǎn)和競(jìng)爭(zhēng)的現(xiàn)象。我們?cè)谇懊嬖岬竭^(guò)下面兩個(gè)要點(diǎn):
在描述組合邏輯的always塊中用阻塞賦值,則綜合成組合邏輯的電路結(jié)構(gòu)。
在描述時(shí)序邏輯的always塊中用非阻塞賦值,則綜合成時(shí)序邏輯的電路結(jié)構(gòu)。
為什么一定要這樣做呢?回答是,這是因?yàn)橐咕C合前仿真和綜合后仿真一致的緣故。如果不按照上面兩個(gè)要點(diǎn)來(lái)編寫(xiě)Verilog代碼,也有可能綜合出正確的邏輯,但前后仿真的結(jié)果就會(huì)不一致。
為了更好地理解上述要點(diǎn),我們需要對(duì)Verilog 語(yǔ)言中的阻塞賦值和非阻塞賦值的功能和執(zhí)行時(shí)間上的差別有深入的了解。為了解釋問(wèn)題方便下面定義兩個(gè)縮寫(xiě)字:
RHS – 方程式右手方向的表達(dá)式或變量可分別縮寫(xiě)為:RHS表達(dá)式或RHS變量。
LHS – 方程式左手方向的表達(dá)式或變量可分別縮寫(xiě)為:LHS表達(dá)式或LHS變量。
IEEE Verilog標(biāo)準(zhǔn)定義了有些語(yǔ)句有確定的執(zhí)行時(shí)間,有些語(yǔ)句沒(méi)有確定的執(zhí)行時(shí)間。若有兩條或兩條以上語(yǔ)句準(zhǔn)備在同一時(shí)刻執(zhí)行,但由于語(yǔ)句的排列次序不同(而這種排列次序的不同是IEEE Verilog標(biāo)準(zhǔn)所允許的), 卻產(chǎn)生了不同的輸出結(jié)果。這就是造成Verilog模塊冒險(xiǎn)和競(jìng)爭(zhēng)現(xiàn)象的原因。為了避免產(chǎn)生競(jìng)爭(zhēng),理解阻塞和非阻塞賦值在執(zhí)行時(shí)間上的差別是至關(guān)重要的。
阻塞賦值阻塞賦值操作符用等號(hào)(即 = )表示。為什么稱這種賦值為阻塞賦值呢?這是因?yàn)樵谫x值時(shí)先計(jì)算等號(hào)右手方向(RHS)部分的值,這時(shí)賦值語(yǔ)句不允許任何別的Verilog語(yǔ)句的干擾,直到現(xiàn)行的賦值完成時(shí)刻,即把RHS賦值給 LHS的時(shí)刻,它才允許別的賦值語(yǔ)句的執(zhí)行。
一般可綜合的阻塞賦值操作在RHS不能設(shè)定有延遲,(即使是零延遲也不允許)。從理論上講,它與后面的賦值語(yǔ)句只有概念上的先后,而無(wú)實(shí)質(zhì)上的延遲。若在RHS 加上延遲,則在延遲期間會(huì)阻止賦值語(yǔ)句的執(zhí)行, 延遲后才執(zhí)行賦值,這種賦值語(yǔ)句是不可綜合的,在需要綜合的模塊設(shè)計(jì)中不可使用這種風(fēng)格的代碼。
阻塞賦值的執(zhí)行可以認(rèn)為是只有一個(gè)步驟的操作:
計(jì)算RHS并更新LHS,此時(shí)不能允許有來(lái)自任何其他Verilog語(yǔ)句的干擾。所謂阻塞的概念是指在同一個(gè)always塊中,其后面的賦值語(yǔ)句從概念上(即使不設(shè)定延遲)是在前一句賦值語(yǔ)句結(jié)束后再開(kāi)始賦值的。
如果在一個(gè)過(guò)程塊中阻塞賦值的RHS變量正好是另一個(gè)過(guò)程塊中阻塞賦值的LHS變量,這兩個(gè)過(guò)程塊又用同一個(gè)時(shí)鐘沿觸發(fā),這時(shí)阻塞賦值操作會(huì)出現(xiàn)問(wèn)題,即如果阻塞賦值的次序安排不好,就會(huì)出現(xiàn)競(jìng)爭(zhēng)。若這兩個(gè)阻塞賦值操作用同一個(gè)時(shí)鐘沿觸發(fā),則執(zhí)行的次序是無(wú)法確定的。下面的例子可以說(shuō)明這個(gè)問(wèn)題:
[例1]。 用阻塞賦值的反饋振蕩器
module fbosc1 (y1, y2, clk, rst);
output y1, y2;
input clk, rst;
reg y1, y2;
always @(posedge clk or posedge rst)
if (rst) y1 = 0; // reset
else y1 = y2;
always @(posedge clk or posedge rst)
if (rst) y2 = 1; // preset
else y2 = y1;
endmodule
按照IEEE Verilog 的標(biāo)準(zhǔn),上例中兩個(gè)always塊是并行執(zhí)行的,與前后次序無(wú)關(guān)。如果前一個(gè)always塊的復(fù)位信號(hào)先到0時(shí)刻,則y1 和y2都會(huì)取1,而如果后一個(gè)always塊的復(fù)位信號(hào)先到0時(shí)刻,則y1 和y2都會(huì)取0。這清楚地說(shuō)明這個(gè)Verilog模塊是不穩(wěn)定的會(huì)產(chǎn)生冒險(xiǎn)和競(jìng)爭(zhēng)的情況。
非阻塞賦值非阻塞賦值操作符用小于等于號(hào) (即 《= )表示。為什么稱這種賦值為非阻塞賦值?這是因?yàn)樵谫x值操作時(shí)刻開(kāi)始時(shí)計(jì)算非阻塞賦值符的RHS表達(dá)式,賦值操作時(shí)刻結(jié)束時(shí)更新LHS。
在計(jì)算非阻塞賦值的RHS表達(dá)式和更新LHS期間,其他的Verilog語(yǔ)句,包括其他的Verilog非阻塞賦值語(yǔ)句都能同時(shí)計(jì)算RHS表達(dá)式和更新LHS。非阻塞賦值允許其他的Verilog語(yǔ)句同時(shí)進(jìn)行操作。非阻塞賦值的操作可以看作為兩個(gè)步驟的過(guò)程:
在賦值時(shí)刻開(kāi)始時(shí),計(jì)算非阻塞賦值RHS表達(dá)式。
在賦值時(shí)刻結(jié)束時(shí),更新非阻塞賦值LHS表達(dá)式。
非阻塞賦值操作只能用于對(duì)寄存器類型變量進(jìn)行賦值,因此只能用在“initial”塊和“always”塊等過(guò)程塊中。非阻塞賦值不允許用于連續(xù)賦值。下面的例子可以說(shuō)明這個(gè)問(wèn)題:
[例2]。 用非阻塞賦值的反饋振蕩器
module fbosc2 (y1, y2, clk, rst);
output y1, y2;
input clk, rst;
reg y1, y2;
always @(posedge clk or posedge rst)
if (rst) y1 《= 0; // reset
else y1 《= y2;
always @(posedge clk or posedge rst)
if (rst) y2 《= 1; // preset
else y2 《= y1;
endmodule
同樣,按照IEEE Verilog 的標(biāo)準(zhǔn),上例中兩個(gè)always塊是并行執(zhí)行的,與前后次序無(wú)關(guān)。無(wú)論哪一個(gè)always塊的復(fù)位信號(hào)先到, 兩個(gè)always塊中的非阻塞賦值都在賦值開(kāi)始時(shí)刻計(jì)算RHS表達(dá)式,而在結(jié)束時(shí)刻才更新LHS表達(dá)式。所以這兩個(gè)always塊在復(fù)位信號(hào)到來(lái)后,在always塊結(jié)束時(shí) y1為0而y2為1是確定的。從用戶的角度看這兩個(gè)非阻塞賦值正好是并行執(zhí)行的。
Verilog模塊編程要點(diǎn):
下面我們還將對(duì)阻塞和非阻塞賦值做進(jìn)一步解釋并將舉更多的例子來(lái)說(shuō)明這個(gè)問(wèn)題。在此之前,掌握可綜合風(fēng)格的Verilog模塊編程的八個(gè)原則會(huì)有很大的幫助。在編寫(xiě)時(shí)牢記這八個(gè)要點(diǎn)可以為絕大多數(shù)的Verilog用戶解決在綜合后仿真中出現(xiàn)的90-100% 的冒險(xiǎn)競(jìng)爭(zhēng)問(wèn)題。
時(shí)序電路建模時(shí),用非阻塞賦值。
鎖存器電路建模時(shí),用非阻塞賦值。
用always塊建立組合邏輯模型時(shí),用阻塞賦值。
在同一個(gè)always塊中建立時(shí)序和組合邏輯電路時(shí),用非阻塞賦值。
在同一個(gè)always塊中不要既用非阻塞賦值又用阻塞賦值。
不要在一個(gè)以上的always塊中為同一個(gè)變量賦值。
用$strobe系統(tǒng)任務(wù)來(lái)顯示用非阻塞賦值的變量值
在賦值時(shí)不要使用 #0 延遲
Verilog的新用戶在徹底搞明白這兩種賦值功能差別之前,一定要牢記這幾條要點(diǎn)。照著要點(diǎn)來(lái)編寫(xiě)Verilog模塊程序,就可省去很多麻煩。
編輯:jq
-
振蕩器
+關(guān)注
關(guān)注
28文章
3966瀏覽量
140404 -
Verilog
+關(guān)注
關(guān)注
28文章
1365瀏覽量
111801 -
阻塞
+關(guān)注
關(guān)注
0文章
24瀏覽量
8245
原文標(biāo)題:【Verilog】深入理解阻塞和非阻塞賦值的不同
文章出處:【微信號(hào):gh_339470469b7d,微信公眾號(hào):FPGA與數(shù)據(jù)通信】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
在testbench中如何使用阻塞賦值和非阻塞賦值

Verilog中阻塞賦值和非阻塞賦值的正確使用
verilog中阻塞賦值和非阻塞賦值
阻塞賦值和非阻塞賦值的用法一篇文章就夠了
IEEE Verilog阻塞賦值和非阻塞賦值的區(qū)別

評(píng)論