對(duì)于VerilogHDL語(yǔ)言中,經(jīng)常在always模塊中,面臨兩種賦值方式:阻塞賦值和非阻塞賦值。對(duì)于初學(xué)者,往往非常迷惑這兩種賦值方式的用法,本章節(jié)主要介紹這兩種文章的用法。其實(shí),有時(shí)候概念稍微不清楚,Bug就會(huì)找到我們,下面一文掃清阻塞賦值和非阻塞賦值所有的障礙。
基本概念
阻塞賦值(Blocking Assignment)
阻塞賦值的基本描述格式為:
[變量] = [邏輯表達(dá)式];
阻塞賦值在執(zhí)行的時(shí)候,右端表達(dá)式執(zhí)行并賦值到左邊變量,不會(huì)受任何情況打斷。所以在本次賦值結(jié)束之前他“阻塞”了當(dāng)前其他的賦值任務(wù),阻塞賦值的操作和C語(yǔ)言中的變量賦值非常相似。
1.非阻塞賦值(Nonblocking assignment)
非阻塞賦值的基本描述格式為:
[變量] <= ?[邏輯表達(dá)式];
非阻塞賦值行為有些細(xì)微之處比較難以理解。我們最好從硬件角度來(lái)理解,always模塊可以被認(rèn)為是純硬件模塊,當(dāng)always模塊被激活時(shí),非阻塞賦值的右側(cè)表達(dá)式就開(kāi)始執(zhí)行;當(dāng)always模塊所有表達(dá)式執(zhí)行結(jié)束之后,所有執(zhí)行結(jié)果才賦值到左側(cè)變量當(dāng)中。之所以稱(chēng)為“非阻塞”就是在本條賦值語(yǔ)句執(zhí)行的過(guò)程中,其他賦值語(yǔ)句也可以執(zhí)行。
1金規(guī)
在組合邏輯電路描述中采用阻塞賦值
阻塞賦值和非阻塞賦值雖然都可以用來(lái)描述同一電路,以1位比較器舉例來(lái)解釋這種差別。
阻塞賦值實(shí)現(xiàn)1bit比較器
moduleeq1_block
(
inputwirei0, i1,
outputregeq
);
regp0, p1;
always@(i0,i1) // i0 和i1 在敏感量列表當(dāng)中
// 語(yǔ)句描述的順序非常關(guān)鍵
begin
p0 = ~i0 & ~i1;
p1 = i0 & i1;
eq = p0 | p1;
end
endmodule
分析:程序中,敏感量列表中包含i0和i1,只要這兩個(gè)變量有一個(gè)發(fā)生改變,都會(huì)激活always語(yǔ)句,那么p0、p1和eq就會(huì)順序賦值,最終eq賦值就會(huì)被更新,所以這三條語(yǔ)句的描述順序非常關(guān)鍵,假如將最后一條語(yǔ)句提前:
always@(i0,i1)
begin
eq = p0 | p1;
p0 = ~i0 & ~i1;
p1 = i0 & i1;
end
在第一條描述中,由于p0和p1還沒(méi)有被賦予新值,所以p0和p1依然保持原來(lái)的賦值,這樣得到的最終結(jié)果顯然是錯(cuò)誤的。
非阻塞賦值實(shí)現(xiàn)1bit比較器
moduleeq1_non_block
(
inputwirei0, i1,
outputregeq
);
regp0, p1;
always@(i0,i1,p0,p1) // p0, p1依然在敏感量列表中
// 描述順序無(wú)關(guān)緊要
begin
p0 <= ~i0 & ~i1;
p1 <= i0 & i1; ?
eq <= p0 | p1; ??
end
endmodule
分析:p0和p1包含在敏感量列表當(dāng)中,當(dāng)i0 或者 i1有所變化,always模塊被激活,p0和p1在第一個(gè)時(shí)鐘節(jié)拍結(jié)束時(shí)賦值,由于eq值為基于p0和p1原來(lái)保持值的賦值,所以eq不變,當(dāng)前賦值結(jié)束時(shí),always模塊重新被激活,由于p0和p1被改變(這就是p0和p1放在敏感量列表中的原因),eq變量在第二個(gè)時(shí)鐘節(jié)拍賦予了新值。從以上分析,即使將以上語(yǔ)句的順序發(fā)生改變,也不會(huì)影響最終結(jié)果,因?yàn)閑q的賦值以及always模塊的激活與這些語(yǔ)句的順序并沒(méi)關(guān)系。
總結(jié):雖然兩種描述方法都可以描述同一電路,但是兩個(gè)電路的結(jié)果是有區(qū)別的,采用非阻塞賦值法描述仿真的時(shí)候花的時(shí)間更長(zhǎng)一些,電路輸出結(jié)果在時(shí)序上也有微弱差別,鑒于此,我們有這么一條原則“在組合邏輯電路描述中采用阻塞賦值”。
2時(shí)序邏輯描述,采用非阻塞賦值方式賦值
就單獨(dú)一個(gè)寄存器來(lái)說(shuō),阻塞賦值和非阻塞賦值都可以描述存儲(chǔ)單元,如DFF可以描述為
always@(posedgeclk)
q <= d;
也可以描述為
always@(posedgeclk)
q = d;
但是當(dāng)設(shè)計(jì)中存在多個(gè)寄存器描述單元的時(shí)候,就會(huì)有細(xì)微的查別,假設(shè)有兩個(gè)寄存器在每個(gè)時(shí)鐘的上升沿進(jìn)行數(shù)據(jù)交換,采用阻塞賦值描述如下:
always@(posedgeclk)
a = b;
always@(posedgeclk)
b = a;
在時(shí)鐘的上升沿,兩個(gè)always語(yǔ)句同時(shí)被激活并且并行執(zhí)行,一個(gè)時(shí)鐘節(jié)拍后兩條語(yǔ)句執(zhí)行結(jié)束,按照verilog語(yǔ)法標(biāo)準(zhǔn),兩個(gè)always語(yǔ)句執(zhí)行結(jié)果時(shí)間順序上誰(shuí)都有可能在前面,這樣一來(lái),如果第一個(gè)always語(yǔ)句執(zhí)行在前面,由于阻塞賦值,所以變量a立即得到b的賦值,那么當(dāng)?shù)诙€(gè)always塊執(zhí)行之后,變量b得到a的賦值,由于剛才第一個(gè)always執(zhí)行的時(shí)候b值賦予了a,所以現(xiàn)在b的值會(huì)維持不變,還是原來(lái)的值。
同樣的道理,如果第二個(gè)always模塊先執(zhí)行了,那么a就會(huì)保持自身值不變,從Verilog語(yǔ)法角度來(lái)看,兩種結(jié)果都是有效的。但是從數(shù)字電路的角度來(lái)說(shuō),明顯引起了競(jìng)爭(zhēng)。
下面我們將阻塞賦值修改為非阻塞賦值,以上代碼修改為:
always@(posedgeclk)
a <= b;
always@(posedgeclk)
b <= a;
采用非阻塞賦值,由于原始信號(hào)在賦值語(yǔ)句中使用,所以a和b都會(huì)得到正確的值,而與順序沒(méi)有關(guān)系。所以在時(shí)序邏輯描述中,阻塞賦值往往會(huì)引起條件競(jìng)爭(zhēng),所以要采用非阻塞賦值方式賦值。
總結(jié)一下
在組合邏輯電路描述中采用阻塞賦值
時(shí)序邏輯描述,采用非阻塞賦值方式賦值
審核編輯:湯梓紅
-
模塊
+關(guān)注
關(guān)注
7文章
2655瀏覽量
47292 -
Verilog
+關(guān)注
關(guān)注
28文章
1343瀏覽量
109925 -
HDL
+關(guān)注
關(guān)注
8文章
326瀏覽量
47307 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7594瀏覽量
135856 -
時(shí)序邏輯
+關(guān)注
關(guān)注
0文章
39瀏覽量
9134
原文標(biāo)題:【干貨分享】Verilog中阻塞和非阻塞賦值金規(guī)
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論