1. 程式人生 > >阻塞(=)和非阻塞賦值(

阻塞(=)和非阻塞賦值(

就知道在Verilog HDL中阻塞賦值"="非阻塞賦值"<="有著很大的不同。

  對於我這樣的初學者而言,首先要掌握可綜合風格的Verilog模組程式設計的7個原則,並且牢記,才能在綜合佈局佈線的模擬中避免出現競爭冒險現象。

  (1)  時序電路建模時,用非阻塞賦值。

  (2)  鎖存器電路建模時,用非阻塞賦值。

  (3)  用always塊建立組合邏輯模型時,用阻塞賦值。

  (4)  在同一個always塊中建立時序和組合邏輯電路時,用非阻塞賦值。

  (5)  在同一個always塊中不要既用非阻塞賦值又用阻塞賦值。

  (6)  不要在一個以上的always塊中為同一個變數賦值。

  (7)  在賦值時不要使用 #0延時。

  這樣做的目的是為了使綜合前模擬綜合後模擬一致。在很多時候,用"="或者是"<="實際上對應的是不同的硬體電路,這點一定要十分清楚。

  阻塞賦值(=):

  我們先做下面定義:RHS—賦值等號右邊的表示式,LHS—賦值等號左邊的表示式。在序列語句塊中,阻塞賦值語句按照它們在塊中的排列順序依次執行,即前一條語句沒有完成賦值之前,後面的語句不可能被執行,換言之,後面的語句被阻塞了。阻塞賦值的執行可以認為只有一個步驟的操作,即計算RHS並更新LHS,此時不允許有來自任何其他Verilog語句的干擾。所謂阻塞的概念是指在同一個always塊中,其後面的賦值語句從概念上是在前一條賦值語句結束後開始賦值的。有句話我一直沒讀懂:從理論上講,它與後面的賦值語句只有概念上的先後,而無實質上的延時。

  例如:

  begin

    B = A;

    C = B + 1;

  end

  首先第一條語句執行,將A的值賦給B,接著執行第二條語句,將B+1(即A加1),並賦給C。也就是說C = A + 1。

  非阻塞賦值(<=):

  非阻塞語句的執行過程是:首先計算語句塊內部所有右邊表示式(RHS)的值,然後完成對左邊暫存器變數的賦值操作,例如,下面兩條非阻塞賦值語句的執行過程是:先計算右邊表示式的值並暫存在一個暫存器中,A的值被儲存在一個暫存器中,而B+1的值被儲存在另一個暫存器中,在begin和end之間所有語句的右邊表示式都被計算並存儲完後,對左邊的暫存器變數的賦值才會進行。這樣C得到的是B的原始值而不是A加一。

  begin

    B <= A;

    C <= B +1;

  end

  如果我們想讓兩個最基本的D觸發器串聯,我們用阻塞和非阻塞賦值看看結果有什麼不同

  阻塞和非阻塞的不同造成了電路上巨大的不同,因此他們的差別應該牢記。

  我們在從模擬(Simulation)的角度去看一下,在輸出結果上有造成什麼樣的不同,我們有同樣的的testbench。

程式碼

  模擬波形如下:

  可以看到,在阻塞賦值的情況下當時鐘上升沿來的時候讀取輸入iD的值,並且輸出oQA和oQB的值應該是一樣的,從波形中我們可以看出輸出oQA和oQB的波形是完全一樣的。

  在非阻塞賦值的情況下,它是先計算 iD 和 oQA的值,開始 iD的值為1, oQA的值是不定的,所以oQA被賦為1, 而oQB還是被賦為不定值,兩者的波形不一致。

  阻塞和非阻塞的學習隨著以後的深入還得深刻理解,在用時要遵循規則,避免麻煩。

----------------------------------------------------------------------------------------------------------

總結一下,

在verilog中,阻塞賦值是按照時間邏輯進行的,即,逐步進行,每一個語句,等到上一個語句賦值結束後再進行賦值。

而在同一個always模組中,所有的非阻塞賦值都是同時賦值的,無所謂時間先後。及,並行結構。也正因如此,非阻塞賦值能根據輸入逐步賦值。

這裡還找到一個很好的例子:

[例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 的標準,上例中兩個always塊是並行執行的,與前後次序無關。如果前一個always塊的復位訊號先到0時刻,則y1 和y2都會取1,而如果後一個always塊的復位訊號先到0時刻,則y1 和y2都會取0。這清楚地說明這個Verilog模組是不穩定的會產生冒險和競爭的情況。這樣一個模組的波形圖是這樣的:

[例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 的標準,上例中兩個always塊是並行執行的,與前後次序無關。無論哪一個always塊的復位訊號先到, 兩個always塊中的非阻塞賦值都在賦值開始時刻計算RHS表示式,,而在結束時刻才更新LHS表示式。所以這兩個always塊在復位訊號到來後,在always塊結束時 y1為0而y2為1是確定的。從使用者的角度看這兩個非阻塞賦值正好是並行執行的。這樣的一個模組的波形圖就是: