前言:阻塞與非阻塞賦值是Verilog語言中最基本的部分,也是讓大部分Verilog新手最困惑的地方。關於阻塞與非阻塞的著做文章可謂汗牛充棟,這些文章對阻塞與非阻塞賦值的原理進行了很是詳細的講解,但新手讀了以後依然有種似懂非懂的感受,編碼過程當中一如既往的犯錯。因此,本文的目的立足於提供一種實用化的解決方案,用最簡單的語言和形象的類比讓新手可以一目瞭然的明白正確的編碼方式以及相應的電路行爲邏輯,關於仿真細節的講解不是本文重點,須要瞭解更多細節的朋友能夠參考文後列舉的參考文獻。併發
本文共分爲三部分,第一部分是正確使用阻塞與非阻塞賦值的基本原則。第二部分是阻塞與非阻塞賦值對應電路的行爲邏輯。第三部分是阻塞與非阻塞賦值的原理簡介。編碼
一.Golden Ruleblog
編碼原則不少,就阻塞非阻塞賦值而言,新手最須要牢記的是其中三條:變量
1) 時序邏輯必定用非阻塞賦值」<=」,一旦看到敏感列表有posedge就用」<=」。原理
2) 組合邏輯必定用」=」,一旦敏感列表沒有posedge就用」=」,一旦看到assign就用」=」。sed
3) 時序邏輯和組合邏輯分紅不一樣的模塊,即一個always模塊裏面只能出現非阻塞賦值」<=」或者」=」。若是發現兩種賦值並存,一個字」改」,心存僥倖可能會給後續工做帶來更多麻煩。coding
以上三條,對新手而言沒必要追求爲何,須要的就是條件反射的照章辦事。最後說一句,新手可能記不住哪一個符號是阻塞賦值,哪一個是非阻塞賦值,你們能夠數數,」非阻塞賦值」一共5個字,「阻塞賦值「4個字,因此非阻塞用的符號」<=」比阻塞賦值用的符號」=」長。反射
二.電路行爲邏輯。im
第一節給出了三條最基本的編碼原則,有個朋友可能會想,按照這三條編碼原則寫出來的代碼會按怎樣的邏輯工做呢?這一節就是回答這個問題。新手
首先解釋一下阻塞賦值與非阻塞賦值的含義。所謂的阻塞賦值」=」就是說,在這個語句沒有執行完以前,後面的語句是不執行的。這裏執行的含義是指完成變量值的更新。非阻塞賦值」<=」是指,全部的語句能夠併發執行,而前面的值是否執行完畢不會影響後面的語句,換句話說,語句的順序是可有可無的。
舉個例子,假設一個模塊,有2個寄存器,b和c,初值都是1。a爲輸入信號線。在某個時刻,由於某種緣由,模塊被觸發執行。對於組合邏輯而言,通常是輸入信號值變了,對於時序邏輯而言,通常是時鐘沿到了。
首先看組合邏輯:假設輸入a = 2;
always@(a)
begin
b = a;
c = b;
end
因爲是阻塞賦值,因此首先執行完第一句b=a,執行完成以後b=2。接着執行c=b,執行完成後c=2,一次仿真結束後 b=c=2;
對於時序邏輯而言,依然假設a =2;
always@(posedge clk)
begin
b <= a;
c <= b;
end
因爲是非阻塞賦值,首先執行第一句b<=a,這時候a = 2,可是尚未執行完第一句的時候,第二句c<=b也執行了,因爲第一句沒有執行完,b的值仍是1,這時候賦值給c的值也是1。執行完畢的結果就是c=1,b=2.等到模塊再次被觸發的時候c的值更新爲2。有個朋友可能就會問了,憑啥第一句執行到一半就該第二句執行呢?究竟是第一句先完成賦值呢仍是第二句先完成賦值?答案是,誰先完成賦值都不要緊,結果是同樣的。
爲何說結果同樣呢?由於兩種賦值方式分別是按照下面的順序執行的。阻塞賦值,就跟C語言同樣,嚴格按照代碼書寫的前後順序執行,全部值都是當即更新,而且在下面的語句中按照新值執行。而時序電路就不同了,你們能夠這麼理解時序邏輯的代碼行爲,一次執行分爲兩輪:第一輪是全部的左值都先賦給臨時變量,第二輪用輸入值以及和右值同名的臨時變量值去更新左值。好比上面的例子,第一輪,賦給臨時變量:tempc=c;tempb=b。第二輪,臨時變量更新左值,b = a;c = tempb;output = tempc。從上面的分析也能夠看出,組合邏輯的結果與代碼順序直接相關,而時序邏輯與代碼順序沒有關係。這就是所謂的順序執行(組合邏輯)與併發執行(時序邏輯)。
爲了進一步理解這兩種賦值方式的行爲,下面用對應的電路進行說明,之前面的代碼爲例。你們首先閉上眼睛想一想,對應的電路是什麼樣子的呢?
其實答案很簡單,對於阻塞賦值來講,如圖一所示,綜合的結果就是一根導線,固然,可能有反相器,buf什麼的,反正仍是能夠看做一根線。
圖一
到這裏,應該就很容易理解順序執行的行爲方式了。
有細心的朋友可能會問,若是換種寫法呢?
always@(a)
begin
c = b;
b = a;
end
很顯然,這種電路的行爲跟以前是不同的,從邏輯來看會產生相似於非阻塞賦值的結果,但很顯然不知足非阻塞賦值併發執行的特色。若是把輸入電平a觸發改爲時鐘邊沿觸發posedge clk,出來的就是寄存器,但這違反了時序邏輯不用阻塞賦值的原則,因此嚴重不推薦。至於這種組合邏輯描述方式出來的電路是啥我也不知道,你們能夠本身綜合看看,或者哪位高人補上~~應該注意的是,若是想象不出這種怪異的coding方式會產生何種電路,就不要這麼寫,由於實現這種邏輯最好的辦法是採用非阻塞方式描述。
而對於非阻塞賦值而言,如圖二所示,綜合出來的結果就是2個寄存器。對b,c賦值的過程就是寄存器輸入採樣的過程,很顯然兩個採樣是同時進行的,並且一次時鐘沿只會採樣一次,因此輸入值a會首先被採樣到b,再在下一個時鐘被採樣到c。
圖二
總結一下,關於兩種賦值方式,首先講述了代碼執行的過程,而後用直連線和寄存器分別對應了兩種描述方式。應該指出的是,非阻塞賦值用寄存器的類比是徹底準確的,而阻塞賦值用直連線的類比卻未必準確,只不過由於通常認爲直連線是從輸入到輸出依次更新的,並且沒有傳輸之外的延遲,因此這種類比有助於新人理解,雖然不夠嚴密。你們熟悉了以後就應該按照更嚴謹的方式去理解。
三.仿真原理。
待續。。。