記住:阻塞賦值就是它運行時,別人就不能運行,並且直接賦值到底
非阻塞賦值就是它運行時,不阻礙別人的運行,這里說不清(你懂的就OK)
num<=num+1;//是代表只有在時鍾結束的時候右邊的數據才賦值給左邊的寄存器。
一、設計原則
1、在描述組合邏輯的always塊中用阻塞賦值,則綜合成組合邏輯的電路結構;
2、在描述時序邏輯的always塊中用非阻塞賦值,則綜合成時序邏輯的電路結構;
二、語句排列先后的缺點
1、語句的排列有時候是決定了語句的執行順序。當幾個語句在同一時刻執行時,但是由於排列的不同就會造成先后執行,就會出現競爭冒險。
三、什么叫阻塞賦值?
1、阻塞賦值操作符”=“
2、為什么叫阻塞賦值呢?
即阻止其他語句執行的賦值語句。因為在賦值時,先計算等號右邊部分的值,此時賦值語句就不允許任何別的語句的執行,直到現在的賦值完成,即左邊等於右邊的時候,才允許別的語句執行。
3、阻塞賦值缺點舉例說明:
1)always@(posedge clk or posedge rst)
if(rst) y1=0;
else y1=y2;
2)always@(posedge clk or posedge rst)
if(rst) y2=1;
else y2=y1;
在同一個時鍾沿到來時,我們兩者的兩個always塊在硬件上是不可能同步的,中間會差個幾皮秒的相隔時間。
如果1)先執行,那么y1和y2都是1。
如果2)先執行,那么y1和y2都是0。
這說明這個verilog模塊是不穩定的,必定會產生冒險和競爭。
四、非阻塞賦值
1、為什么叫非阻塞賦值?
因為在整個右邊語句計算和左邊語句被賦值的過程中,其他語句依然可以運行。
2、非阻塞賦值操作過程:
1)在賦值開始時刻,計算非阻塞賦值右邊表達式。
2)在賦值結束時刻,更新非阻塞賦值左邊表達式。
五、verilog模塊編程要點
記住以下8點,才能在綜合布局布線后的方陣中避免出現冒險競爭現象。
1、時序電路建模時,用非阻塞賦值。
2、鎖存器電路建模時,用非阻塞賦值。
3、用always塊建立組合邏輯模型時,用阻塞賦值。
4、在同一個always塊中,建立時序和組合邏輯電路時,用非阻塞賦值。
5、在同一個always塊中不要即使用非阻塞賦值又使用阻塞賦值。
6、嚴禁在多個always塊中對同一個變量賦值。易產生競爭冒險。
7、用$strobe系統任務來顯示用非阻塞賦值的變量值。
8、在復制時不要使用#0延遲。
六、verilog的層次化事件隊列
這里我沒有看懂,就是感覺有一個點:非阻塞賦值LHS變量的更新是安排在非阻塞賦值更新事件隊列中,而剩余的其他隊列是被安排在另外的一個隊列事件中。
七、實例講解
1、使用阻塞賦值,不能自行觸發的振盪器,不建議
initial #10 clk=0;//--------------------------(1)
always@(clk) //-----------------------------(2)
#10 clk=~clk;//------------------------(3)
這里使用的是阻塞賦值,在(1)中,我們的clk變化成0,觸發了always塊,延遲10ns,clk變成1
注意在由0->1的過度期間,我們是不允許任何其他程序執行的,所以always塊沒有檢測到變化,也就是always塊並沒有因為第二次的clk變化而被觸發。
2、采用非阻塞賦值,自觸發振盪器,不建議
initial #10 clk=0;//--------------------------(1)
always@(clk) //-----------------------------(2)
#10 clk<=~clk;//-----------------------(3)
這里always塊第一次觸發后~clk便被計算出來,並賦值給LHS的事件並被安排在更新事件隊列中。在非阻塞賦值更新事件隊列被激活之前,又遇到@(clk)語句。當clk發生變化時,always塊便被觸發。這里看來延遲10ns是有必要的。
3、移位寄存器模型
當阻塞賦值時,在並行的always塊中,我們雖說是並行的,當是他們開始的時間是有先后的,這樣就可能造成競爭現象,所以我們不建議在用阻塞賦值。但是我們使用非阻塞賦值時,就不會出現競爭現象,因為他不是阻塞的,也不會立即就會變化的。這樣很好,你懂的。。。。
摘自:verilog數字系統設計教程(夏宇聞)