VerilogHDL中,有兩種過(guò)程賦值方式,即阻塞賦值(blocking)和非阻塞賦值(nonblocking)。阻塞賦值執行時(shí),RHS(righthandstatement)估值與更新LHS(lefthandstatement)值一次執行完成,計算完畢,立即更新。在執行時(shí)阻塞同塊中的其他語(yǔ)句的執行。阻塞式(blocking)的操作符為“=”。它的執行很像傳統程序設計語(yǔ)言。非阻塞賦值RHS估值與更新LHS值分兩步執行。在單位仿真周期開(kāi)始時(shí)RHS估值,在同一單位仿真周期末更新LHS值,不阻塞同塊中其他語(yǔ)句的執行。非阻塞式(non-blocking)的操作符為“<=”,它的執行更像并行電路,使描述電路更自然。阻塞賦值與非阻塞賦值是VerilogHDL程序設計的難點(diǎn),它們既有共同點(diǎn),也有差異,深入剖析其異同,對于硬件程序的開(kāi)發(fā)具有重大意義。 1Verilog事件處理機制 層積事件列(TheStratifiedEventQueue)是一個(gè)事件管理概念模型,而非硬件邏輯。模型內事件的具體實(shí)現與EDA軟件生產(chǎn)商的算法策略有關(guān)。在IEEE-2001中,Verilog把事件分為5個(gè)不同部分,按照時(shí)間順序如圖1所示。 ![]() 觸發(fā)的任何事件可以加入到這5個(gè)事件列中的任何事件列中,但只能從活躍事件列中移出。即上面的5個(gè)事件列中的事件最后都將被激活而放入活躍事件列中。層積事件列是層次模型,層積事件列的執行順序是按優(yōu)先級排列的。任何EDA軟件都只能執行活躍事件。其他事件列都按優(yōu)先級級別依次激活本列事件以供執行。 1.1活躍事件列 由圖1可見(jiàn),大部分事件都被放入活躍事件列;钴S事件列里包括非阻塞賦值RHS估值。但是,非阻塞賦值的更新不是在活躍事件列,它被列成獨立的非阻塞更新事件列;钴S事件列是仿真的執行源,從一開(kāi)始執行活躍事件列到活躍事件列執行完畢稱(chēng)為一個(gè)仿真周期;钴S事件列中的事件可以觸發(fā)活躍或非活躍等其他事件。當活躍事件列中的所有事件執行完后,EDA軟件會(huì )按優(yōu)先級依次觸發(fā)其余事件列以供仿真執行。但在當前活躍事件列中的事件執行順序是不確定的。 1.2非活躍事件列 發(fā)生在當前仿真時(shí)間里并且在活躍事件列執行完后執行的事件列,即非活躍事件列執行優(yōu)先級僅次于活躍事件列。如帶PLI例程的回調過(guò)程(tf_synchronize()、vpi_register_cb(cb_readwrite))。非活躍事件列中的事件亦可以觸發(fā)其他事件。如果觸發(fā)了優(yōu)先級更高的活躍事件,非活躍事件列中的其余事件執行后移。 1.3非阻塞賦值更新事件列 活躍事件列中的每個(gè)非阻塞賦值RHS估值,都會(huì )觸發(fā)一個(gè)與之對應的非阻塞賦值更新事件,這些事件被放在非阻塞賦值更新事件列中,執行優(yōu)先級次于活躍與非活躍事件列。非阻塞賦值更新事件亦可以觸發(fā)其他事件。若在非阻塞賦值更新事件列中,存在多個(gè)對同一變量的先后賦值,只有最后一個(gè)有效,其余值將被覆蓋。 1.4監控事件列 監控事件列被放在非阻塞賦值更新事件列后。由此可見(jiàn),用監控事件列中的監控命令監控得到的值都是賦值后的值,活躍事件列$display系統命令則可以查看非阻塞更新前的值。 1.5未來(lái)事件列 在執行事件時(shí),如果事件含有延時(shí),為不阻礙仿真的繼續執行,該事件將被掛起而放入未來(lái)事件列。未來(lái)事件包含未來(lái)非活躍事件和未來(lái)非阻塞賦值更新事件。 理解阻塞與非阻塞賦值就需要深入理解層積事件列,層積事件列反應了Verilog事件處理機制。 2應用及分析 通常非阻塞賦值產(chǎn)生寄存器等存儲元件,對應的物理器件是帶存貯功能的元件,如寄存器、觸發(fā)器等。阻塞賦值則對應網(wǎng)線(xiàn)(wire)類(lèi)型,通常與物理連線(xiàn)對應。這是兩種賦值方式的最明顯的差異,也是時(shí)序邏輯用非阻塞、組合邏輯用阻塞的重要原因。但這并不是絕對的,事實(shí)上阻塞賦值對應網(wǎng)線(xiàn)(wire)型,亦可對應寄存器(reg)型;阻塞賦值也能生成存貯元件,因此不能片面理解。在組合邏輯里,鎖存器可能引發(fā)測試問(wèn)題,帶來(lái)隱患。說(shuō)明在建模時(shí),首先要從硬件出發(fā)來(lái)考慮問(wèn)題,應先在頭腦中形成電路結構,由于賦值方式的不同,綜合結果差異甚大,運用不當很可能會(huì )導致建模失敗。阻塞賦值在時(shí)序邏輯中亦有著(zhù)重要應用,在需要實(shí)時(shí)更新的組合邏輯中只有阻塞賦值能滿(mǎn)足要求。 以下示例代碼的功能是計算傳送過(guò)來(lái)的data中1和0的個(gè)數。 reg[5:0]count0,count1; always@(posedgeclk,negedgeRst_n) begin if(!Rst_n) ... else begin count0=0;//語(yǔ)句1 count1=0;//語(yǔ)句2 for(i=0;i<=11;i=i+1) begin if(data==1) count1=count1+1;//語(yǔ)句3 elseif(data==0) count0=count0-1;//語(yǔ)句4 else count0=count0+0;//防止生成鎖存器 end end end 在這段代碼里,count0、count1的值必須在每次計數之前被清零,count0、count1必須實(shí)時(shí)更新。顯然,只有阻塞賦值能滿(mǎn)足要求。非阻塞賦值分兩步完成,所有的更新事件在單位仿真周期末同時(shí)執行,只有最后一個(gè)值有效,所以非阻塞賦值無(wú)法完成計數任務(wù)。阻塞賦值卻能很好地勝任,因為阻塞賦值估值和更新一次性完成。 事件上,在時(shí)序邏輯中經(jīng)常碰到上述實(shí)時(shí)更新問(wèn)題,非阻塞賦值往往無(wú)法實(shí)現,如用阻塞賦值則可很好地解決問(wèn)題。 正如阻塞賦值在時(shí)序邏輯中有重要應用一樣,非阻塞賦值在組合邏輯中亦有不可替代的應用。在組合邏輯中用非阻塞賦值可以把組合邏輯改造成流水線(xiàn)?蓤绦腥缦滤炯兘M合邏輯代碼,將生成純組合邏輯,綜合結果如圖2所示。 ![]() inputa,b,c,clk,sel; outputout; regout,temp; always@(posedgeclk) begin temp=a&b;//語(yǔ)句1 if(sel) out=temp|c;//語(yǔ)句2 else out=c;//語(yǔ)句3 end 若把上面代碼中語(yǔ)句1、語(yǔ)句2、語(yǔ)句3阻塞賦值("=")改為非阻塞賦值("<="),則綜合結果如圖3所示。 ![]() 流水線(xiàn)設計方法在高性能、需經(jīng)常進(jìn)行大規模運算的組合邏輯中可以到廣泛運用。 在組合邏輯中,如在begin、end塊中同時(shí)有許多非阻塞賦值,則它們的賦值順序是并發(fā)的。實(shí)際上它們賦予的都是上一個(gè)時(shí)鐘送入寄存器的值。這與使用同一時(shí)鐘沿觸發(fā)的許多在同一個(gè)使能控制信號下賦值完全一致,并且這種賦值因為數據保存在寄存器中,當時(shí)鐘沿到來(lái)時(shí)都已穩定,所以存入的數值是可靠的。用這種方法可以避免由組合邏輯產(chǎn)生的競爭冒險[2]。 在相關(guān)應用中,非阻塞賦值能較好地解決零時(shí)刻競爭冒險問(wèn)題。因為非阻塞賦值分兩步完成,非阻塞賦值更新事件是在所有活躍與非活躍事件執行完之后執行,能確保所有敏感變量值在零時(shí)刻都被觸發(fā)[3]。 在同一always塊混合使用阻塞賦值與非阻塞賦值,利弊共存,混合使用的結果可能事半功倍,亦可能功虧一簣。只有了解其處理機制,深刻理解阻塞與非阻塞賦值底層實(shí)現的異同,方可靈活運用。 本文通過(guò)Verilog事件處理機制,詳細討論了阻塞與非阻塞賦值的區別、聯(lián)系及其應用示例。由本文可知,阻塞與非阻塞賦值靈活多變,底層實(shí)現也差異甚大。因而在數字電路設計時(shí),依據預期功能,從硬件實(shí)現出發(fā),斟酌差異,仔細選用阻塞與非阻塞賦值才能有效避免出錯,縮短開(kāi)發(fā)周期。 Author: Source:EDN |