1. 程式人生 > >關於veriolg中阻塞與非阻塞賦值問題

關於veriolg中阻塞與非阻塞賦值問題

觸發 改變 希望 到來 決定 工作 執行 為什麽 個人

在一開始學到阻塞和非阻塞的時候,所被告知的兩者的區別就在於阻塞是串行的,非阻塞是並行的。但是雖然知道這個不同點,有些時候還是很難真正區分用兩者電路的區別,在這就通過幾個例子來解釋一下。

以一個簡單的串行流水線寄存器為例:d-q1-q2-q3.

1,采用阻塞賦值

代碼:always @ (posedge clk) begin q1=d; q2=q1; q3=q2; end

這樣的代碼將會導致每一個寄存器輸出都是d,即d將無延時的傳送給q3(即q3=d)。因為采用的是阻塞賦值,當時鐘上升沿到來時,先執行q1=d,再執行q2=q1。以此類推,最後所以寄存器的值都變成了d.反映到電路中的結果就是一個單獨的直接從d到q3的寄存器,不符合流水線要求。

2,依然采用阻塞賦值,但是賦值順序有變化

代碼:always @ (posedge clk) begin q3=q2; q2=q1; q1=d; end

當我們改變賦值順序後,綜合的電路是符合要求的。當上升沿到來,先執行q3=q2,則q3的值是上一個時鐘沿時q2的值。類似的,當上升沿到來後,每個寄存器的值都往後移動了一位,也就實現了預期的流水線結構。但是這樣的缺點就在於我們要仔細的安排賦值的順序,容易出錯,且增加工作量。

3,采用非阻塞賦值

代碼:always @ (posedge clk) begin q1<=d; q2<=q1; q3<=q2; end

由於非阻塞賦值是並發執行的,當時鐘沿到來時,每個寄存器更新的值都是賦值寄存器在上一個時鐘沿所被賦予的值,也就真正實現了流水線的結構。而且采用非阻塞賦值的好處在於,不用想阻塞賦值一樣需要考慮賦值順序問題。

另外一個問題是,為什麽在組合邏輯中需要使用阻塞賦值?

在大多數情況下,都應該使用非阻塞賦值,這也比較符合電路並發執行的特點。但是在組合邏輯中並不一定。

例如:

always @ (a or b or c or d) begin

temp1<=a & b;

temp2<=c & d;

y<=temp1 | temp2;

end

在這個組合邏輯中,我們希望實現的是先將ab相與,cd相與,再將產生的temp1,temp2相或。但由於采用的是非阻塞賦值,是並發執行的。當執行y<=temp1 | temp2時,temp1,temp2的值並未更新,也就是說y輸出的是上一個觸發時temp1 | temp2的值,即延後了一次觸發。

而如果此時采用阻塞賦值的話,則能正確實現電路。

不過對於這個問題,我還是覺得並不是說組合邏輯導致要使用阻塞賦值,而是說電路功能決定到底使用哪種。即便上面的例子是時序電路,如果要實現相同的邏輯,則依然要用阻塞賦值。而如果你是使用類似之前提到的移位的功能,則即便用的是組合邏輯,也需要用非阻塞賦值。

至於為什麽會有組合電路用阻塞的說法,應該是大部分時候組合邏輯功能需要阻塞賦值,且這是一個規範吧,畢竟規範有時候不是很好解釋,但是卻在工作中大有裨益。當然,這只是我個人觀點,有不同意見者希望不吝指教。

關於veriolg中阻塞與非阻塞賦值問題