對于VerilogHDL語言中,經(jīng)常在always模塊中,面臨兩種賦值方式:阻塞賦值和非阻塞賦值。對于初學者,往往非常迷惑這兩種賦值方式的用法,本章節(jié)主要介紹這兩種文章的用法。其實,有時候概念稍微不清楚,Bug就會找到我們,下面一文掃清阻塞賦值和非阻塞賦值所有的障礙。
基本概念
阻塞賦值(Blocking Assignment)
阻塞賦值的基本描述格式為:
[變量] = [邏輯表達式];
阻塞賦值在執(zhí)行的時候,右端表達式執(zhí)行并賦值到左邊變量,不會受任何情況打斷。所以在本次賦值結束之前他“阻塞”了當前其他的賦值任務,阻塞賦值的操作和C語言中的變量賦值非常相似。
非阻塞賦值(Nonblocking assignment)
非阻塞賦值的基本描述格式為:
[變量] 《= [邏輯表達式];
非阻塞賦值行為有些細微之處比較難以理解。我們最好從硬件角度來理解,always模塊可以被認為是純硬件模塊,當always模塊被激活時,非阻塞賦值的右側表達式就開始執(zhí)行;當always模塊所有表達式執(zhí)行結束之后,所有執(zhí)行結果才賦值到左側變量當中。之所以稱為“非阻塞”就是在本條賦值語句執(zhí)行的過程中,其他賦值語句也可以執(zhí)行。
金規(guī)
1. 在組合邏輯電路描述中采用阻塞賦值
阻塞賦值和非阻塞賦值雖然都可以用來描述同一電路,以1位比較器舉例來解釋這種差別。
阻塞賦值實現(xiàn)1bit比較器
module eq1_block
(
input wire i0, i1,
output reg eq
);
reg p0, p1;
always @(i0,i1) // i0 和i1 在敏感量列表當中
// 語句描述的順序非常關鍵
begin
p0 = ~i0 & ~i1;
p1 = i0 & i1;
eq = p0 | p1;
end
endmodule
分析:程序中,敏感量列表中包含i0和i1,只要這兩個變量有一個發(fā)生改變,都會激活always語句,那么p0、p1和eq就會順序賦值,最終eq賦值就會被更新,所以這三條語句的描述順序非常關鍵,假如將最后一條語句提前:
always @(i0,i1)
begin
eq = p0 | p1;
p0 = ~i0 & ~i1;
p1 = i0 & i1;
end
在第一條描述中,由于p0和p1還沒有被賦予新值,所以p0和p1依然保持原來的賦值,這樣得到的最終結果顯然是錯誤的。
非阻塞賦值實現(xiàn)1bit比較器
module eq1_non_block
(
input wire i0, i1,
output reg eq
);
reg p0, p1;
always @(i0,i1,p0,p1) // p0, p1依然在敏感量列表中
// 描述順序無關緊要
begin
p0 《= ~i0 & ~i1;
p1 《= i0 & i1;
eq 《= p0 | p1;
end
endmodule
分析:p0和p1包含在敏感量列表當中,當i0 或者 i1有所變化,always模塊被激活,p0和p1在第一個時鐘節(jié)拍結束時賦值,由于eq值為基于p0和p1原來保持值的賦值,所以eq不變,當前賦值結束時,always模塊重新被激活,由于p0和p1被改變(這就是p0和p1放在敏感量列表中的原因),eq變量在第二個時鐘節(jié)拍賦予了新值。從以上分析,即使將以上語句的順序發(fā)生改變,也不會影響最終結果,因為eq的賦值以及always模塊的激活與這些語句的順序并沒關系。
總結:雖然兩種描述方法都可以描述同一電路,但是兩個電路的結果是有區(qū)別的,采用非阻塞賦值法描述仿真的時候花的時間更長一些,電路輸出結果在時序上也有微弱差別,鑒于此,我們有這么一條原則“在組合邏輯電路描述中采用阻塞賦值”。
2. 時序邏輯描述,采用非阻塞賦值方式賦值
就單獨一個寄存器來說,阻塞賦值和非阻塞賦值都可以描述存儲單元,如DFF可以描述為
always@(posedge clk)
q 《= d;
也可以描述為
always@(posedge clk)
q = d;
但是當設計中存在多個寄存器描述單元的時候,就會有細微的查別,假設有兩個寄存器在每個時鐘的上升沿進行數(shù)據(jù)交換,采用阻塞賦值描述如下:
always@(posedge clk)
a = b;
always@(posedge clk)
b = a;
在時鐘的上升沿,兩個always語句同時被激活并且并行執(zhí)行,一個時鐘節(jié)拍后兩條語句執(zhí)行結束,按照verilog語法標準,兩個always語句執(zhí)行結果時間順序上誰都有可能在前面,這樣一來,如果第一個always語句執(zhí)行在前面,由于阻塞賦值,所以變量a立即得到b的賦值,那么當?shù)诙€always塊執(zhí)行之后,變量b得到a的賦值,由于剛才第一個always執(zhí)行的時候b值賦予了a,所以現(xiàn)在b的值會維持不變,還是原來的值。
同樣的道理,如果第二個always模塊先執(zhí)行了,那么a就會保持自身值不變,從Verilog語法角度來看,兩種結果都是有效的。但是從數(shù)字電路的角度來說,明顯引起了競爭。
下面我們將阻塞賦值修改為非阻塞賦值,以上代碼修改為:
always@(posedge clk)
a 《= b;
always@(posedge clk)
b 《= a;
采用非阻塞賦值,由于原始信號在賦值語句中使用,所以a和b都會得到正確的值,而與順序沒有關系。所以在時序邏輯描述中,阻塞賦值往往會引起條件競爭,所以要采用非阻塞賦值方式賦值。
總結一下
① 在組合邏輯電路描述中采用阻塞賦值
② 時序邏輯描述,采用非阻塞賦值方式賦值
-
阻塞賦值
+關注
關注
0文章
9瀏覽量
9153 -
VerilogHDL
+關注
關注
2文章
39瀏覽量
19067
發(fā)布評論請先 登錄
相關推薦
評論