數(shù)字門級(jí)電路可分為兩大類:組合邏輯和時(shí)序邏輯。鎖存器是組合邏輯和時(shí)序邏輯的一個(gè)交叉點(diǎn),在后面會(huì)作為單獨(dú)的主題處理。
組合邏輯描述了門級(jí)電路,其中邏輯塊的輸出直接反映到該塊的輸入值的組合,例如,雙輸入AND門的輸出是兩個(gè)輸入的邏輯與。如果輸入值發(fā)生變化,輸出值將反映這一變化,組合邏輯的RTL模型需要反映這種門級(jí)行為,這意味著邏輯塊的輸出必須始終反映該邏輯塊當(dāng)前輸入值的組合。
SystemVerilog有三種在可綜合RTL級(jí)別表示組合邏輯的方法:連續(xù)賦值語(yǔ)句、always程序塊和函數(shù)。接下來幾篇文章將探討每種編碼風(fēng)格,并推薦最佳實(shí)踐編碼風(fēng)格。
always和always_comb程序
組合邏輯的主要RTL建模構(gòu)造是always過程,使用通用always關(guān)鍵字或RTL專用的always_comb關(guān)鍵字。這些always程序可以利用之前討論的強(qiáng)大的運(yùn)算符編程語(yǔ)句,而連續(xù)賦值語(yǔ)句僅限于使用SystemVerilog運(yùn)算符。一個(gè)簡(jiǎn)單的組合邏輯加法器被建模為always程序和always_comb程序的例子如下:
可綜合組合邏輯的always程序
綜合編譯器支持always和always_comb程序。
當(dāng)使用通用always程序時(shí),綜合編譯器會(huì)施加一些編碼限制,RTL設(shè)計(jì)工程師必須了解并遵守這些限制。這些限制包括:
程序敏感列表應(yīng)包括每個(gè)信號(hào),其值可能影響組合邏輯的輸出。下一節(jié)詳細(xì)討論了敏感列表。
程序敏感列表必須對(duì)每個(gè)信號(hào)的所有可能值變化敏感。它不能包含限制對(duì)特定變化敏感性的posedge或negedge關(guān)鍵字。
程序應(yīng)在零仿真時(shí)間內(nèi)執(zhí)行,并且不應(yīng)包含任何形式的傳播延遲(包括使用#,@或者wait等控制語(yǔ)句)。
在組合邏輯程序中賦值的變量不應(yīng)被任何其他程序或連續(xù)賦值語(yǔ)句所賦值。(允許在同一程序中進(jìn)行多次賦值。)
對(duì)所有RTL組合邏輯進(jìn)行零延遲建模。 |
最佳實(shí)踐指南7-3 |
---|
綜合器不允許@或wait等時(shí)間控制延遲,并將忽略#延遲。忽略#延遲可能會(huì)導(dǎo)致在仿真中驗(yàn)證的RTL模型與綜合中忽略的門級(jí)實(shí)現(xiàn)不匹配。
使用通用always程序建模
使用RTL專用的always_comb程序?qū)M合邏輯進(jìn)行建模。不要在RTL模型中使用通用的always程序。 |
最佳實(shí)踐指南7-4 |
---|
RTL專用的always_comb會(huì)自動(dòng)執(zhí)行上面列出的編碼限制。敏感列表是推斷出來的,不允許@或wait時(shí)間控制,并且在always_comb程序中賦值的變量不能由其他程序或連續(xù)賦值。
雖然不推薦always程序用于RTL建模,但本文中討論了如何正確使用通用always程序?qū)M合邏輯進(jìn)行建模,因?yàn)檫@種通用程序在傳統(tǒng)的Verilog模型中很常見。
組合邏輯敏感列表。通用always程序需要一個(gè)敏感列表,以告知仿真器何時(shí)處理程序中的編程語(yǔ)句。敏感列表使用@(信號(hào)列表)形式指定,如下例所示:
敏感列表中的每個(gè)信號(hào)用逗號(hào)(,)分隔,如上例所示,或用or關(guān)鍵字分隔,如@(a or b or mode)。使用逗號(hào)(,)與或關(guān)鍵字or相比,沒有任何優(yōu)點(diǎn)或缺點(diǎn)。一些工程師更喜歡逗號(hào)(,)分隔的列表,因?yàn)閛r關(guān)鍵字可能會(huì)被誤認(rèn)為是邏輯or操作,而不僅僅是列表中信號(hào)之間的分隔符。
完整的敏感列表。對(duì)于組合邏輯,組合塊的輸出是該塊輸入的當(dāng)前值的直接反映,為了對(duì)這種行為進(jìn)行建模,當(dāng)任何信號(hào)的值發(fā)生變化而影響程序輸出的值時(shí),always程序需要執(zhí)行其編程語(yǔ)句。組合always程序的輸入是程序中的語(yǔ)句讀取值的任何信號(hào),在上面的加法器示例中,程序的輸入——程序中讀取的信號(hào)為:a、b和mode。
程序輸入與模塊輸入。組合邏輯程序的輸入可能與包含該程序的模塊的輸入端口不一致。模塊可能包含多個(gè)程序塊和連續(xù)賦值語(yǔ)句,因此,每個(gè)程序塊都有輸入端口。模塊也可能包含內(nèi)部信號(hào),在程序塊或連續(xù)賦值語(yǔ)句之間傳遞數(shù)值。這些內(nèi)部信號(hào)將不包括在模塊端口列表中。
不完整的敏感列表-一個(gè)建模故障。
gotcha是一個(gè)編程術(shù)語(yǔ),用于描述語(yǔ)法合法但性能不符合預(yù)期的代碼。一般的always程序允許犯這種類型的編碼錯(cuò)誤。如果組合邏輯程序的一個(gè)或多個(gè)輸入被無意中從敏感列表中忽略,RTL模型也將被編譯,甚至可能看起來是正確的仿真。然而,完整的驗(yàn)證表明,組合邏輯塊的輸出在一定時(shí)間段內(nèi)不反映當(dāng)前輸入值的組合??紤]下面的代碼片段:
如果mode改變,result的輸出將不會(huì)更新為新的操作結(jié)果,直到a或b改變值。在mode更改和a或b更改之間的時(shí)間內(nèi),result值不正確。
這種編碼錯(cuò)誤在只讀取少數(shù)信號(hào)值的小型組合邏輯塊中是很明顯的,但對(duì)于更大、更復(fù)雜的邏輯塊來說,讀取10、20甚至幾十個(gè)信號(hào)并不罕見。當(dāng)涉及這么多信號(hào)時(shí),很容易在不經(jīng)意間忽略敏感列表中的一個(gè)信號(hào)。在設(shè)計(jì)開發(fā)過程中修改always塊也很常見,比如在邏輯中添加另一個(gè)信號(hào),但忘記將其添加到敏感列表中。這種編碼錯(cuò)誤的一個(gè)嚴(yán)重危害是,許多綜合編譯器仍將這種不正確的RTL模型實(shí)現(xiàn)為門級(jí)組合邏輯,可能帶有一條容易忽略的警告消息,盡管綜合編譯器的實(shí)現(xiàn)可能是設(shè)計(jì)者的意圖,但他并不是RTL仿真期間所驗(yàn)證的設(shè)計(jì)功能。因此,設(shè)計(jì)功能沒有被充分驗(yàn)證,這可能會(huì)導(dǎo)致實(shí)際ASIC或FPGA運(yùn)行時(shí)會(huì)出現(xiàn)錯(cuò)誤。
過時(shí)的always@ 程序。IEEE 1364-2001標(biāo)準(zhǔn)(通常稱為Verilog-2001)試圖通過添加特殊標(biāo)記來解決不完整敏感度列表的問題,該標(biāo)記將自動(dòng)推斷出完整的敏感列表,例如:
也可以用括號(hào)括起來,如@( )。與在組合邏輯敏感列表中顯式列出信號(hào)相比,@ 標(biāo)記提供了更好的編碼風(fēng)格。然而,這個(gè)標(biāo)記有兩個(gè)問題。首先,綜合編譯器對(duì)組合邏輯建模施加了一些限制。使用@ 可以推斷出一個(gè)敏感度列表,但不強(qiáng)制執(zhí)行用于組合邏輯建模的其他綜合規(guī)則。@ 的第二個(gè)問題是沒有推斷出完整的敏感度列表。如果一個(gè)組合邏輯程序調(diào)用一個(gè)函數(shù),但沒有將函數(shù)中使用的所有信號(hào)作為函數(shù)參數(shù)傳入,則會(huì)推斷出一個(gè)不完整的敏感列表。
使用SystemVerilog中專用的always_comb程序自動(dòng)推斷正確的組合邏輯敏感列表。不要使用過時(shí)的@*推斷敏感列表。 |
最佳實(shí)踐指南7-5 |
---|
Always_comb程序?qū)⑼茢喑鰷?zhǔn)確的敏感列表,而不存在顯式列表的危害,或者@ 的推斷問題。always_comb過程也會(huì)強(qiáng)制執(zhí)行綜合編譯器精確建模組合邏輯行為所需的編碼限制。
在20世紀(jì)80年代推出的最初的Verilog語(yǔ)言只有通用的always程序。雖然非常有用,但當(dāng)用于RTL建模時(shí),該過程的通用性有嚴(yán)重的局限性。作為一個(gè)通用程序,always可用于仿真組合邏輯、時(shí)序邏輯、鎖存邏輯和各種驗(yàn)證過程。當(dāng)綜合編譯器遇到always過程時(shí),編譯器無法知道設(shè)計(jì)工程師打算對(duì)哪種類型的功能進(jìn)行建模。相反,綜合編譯器必須分析過程的內(nèi)容,并試圖推斷設(shè)計(jì)者的意圖。綜合很可能推斷出不同于工程師預(yù)期的功能類型。
通用always程序的另一個(gè)限制是,它不強(qiáng)制執(zhí)行綜合編譯器為表示組合邏輯行為所需的RTL編碼規(guī)則。使用通用always程序的模型可能看起來仿真正確,但可能無法綜合成預(yù)期的功能,因此在綜合模型之前,必須重寫RTL模型并在仿真中重新驗(yàn)證功能,從而導(dǎo)致工程時(shí)間損失。
使用RTL專用的always_comb程序建模
SystemVerilog引入了RTL專用的always程序,如always_comb,以解決通用always程序的局限性。下面的示例對(duì)前面顯示的算術(shù)邏輯單元功能進(jìn)行建模,但使用always_comb而不是always,
在編寫RTL模型時(shí),always_comb程序有很多好處:
自動(dòng)推斷出完整的敏感列表。該列表是完全完整的,避免了@*推斷不完整敏感列表的極端情況。
不允許在always_comb過程中使用#、@或wait等延遲語(yǔ)句的執(zhí)行,這是對(duì)使用零延遲程序的綜合指南的強(qiáng)制。在always comb中使用這些時(shí)間控件是一個(gè)錯(cuò)誤,在RTL模型的編譯和布線過程中會(huì)發(fā)現(xiàn)這一錯(cuò)誤。
在“always_comb”程序中賦值的任何變量都不能從另一個(gè)程序或連續(xù)賦值語(yǔ)句中賦值,這是綜合編譯器要求的限制。在RTL模型的編譯和布線過程中,會(huì)發(fā)現(xiàn)違反此綜合規(guī)則的編碼錯(cuò)誤。
Always_comb的語(yǔ)義規(guī)則符合綜合編譯器對(duì)組合邏輯RTL模型的編碼限制。這些規(guī)則有助于確保因?yàn)轵?yàn)證無法綜合的設(shè)計(jì)而浪費(fèi)工程時(shí)間。
在仿真開始時(shí)自動(dòng)評(píng)估。always_comb過程還有一個(gè)語(yǔ)義規(guī)則,是專門針對(duì)仿真使用。組合邏輯的行為是,輸出值代表該邏輯塊的輸入值的組合。對(duì)于通用always程序,為了觸發(fā)程序內(nèi)賦值語(yǔ)句的執(zhí)行,敏感列表中的信號(hào)必須發(fā)生值更改。如果敏感列表中的信號(hào)在仿真開始時(shí)均未改變值,則組合邏輯程序的輸出不會(huì)更新,以匹配該過程的輸入值。組合邏輯程序?qū)⒗^續(xù)具有不正確的輸出值,直到敏感列表中的信號(hào)改變值。這個(gè)問題是一個(gè)RTL仿真故障,門級(jí)實(shí)現(xiàn)不會(huì)有這個(gè)問題。
RTL專用的always_comb程序解決了這個(gè)仿真故障。always_comb程序?qū)⒃诜抡骈_始時(shí)自動(dòng)觸發(fā)一次,以確保程序中分配的所有變量準(zhǔn)確反映仿真時(shí)間零點(diǎn)時(shí)程序輸入的值。
使用阻塞(組合邏輯)賦值
在為組合邏輯建模時(shí),只使用阻塞賦值(=)。 |
最佳實(shí)踐指南7-6 |
---|
SystemVerilog有兩種形式的賦值運(yùn)算符:阻塞賦值(=)和非阻塞賦值(<=)。這些賦值類型影響仿真更新賦值語(yǔ)句左側(cè)值的順序,相對(duì)于仿真時(shí)那一刻的任何其他仿真活動(dòng)。阻塞賦值(=)立即更新左側(cè)的變量,使新值可供begin-end語(yǔ)句組中的后續(xù)語(yǔ)句使用?!凹磿r(shí)更新”有效地仿真了組合邏輯數(shù)據(jù)流中的值傳播行為。
下面的代碼片段演示了通過組合邏輯程序塊中的多個(gè)賦值的組合邏輯數(shù)據(jù)流。
在這個(gè)過程中,變量sum立即更新為a+b的運(yùn)算結(jié)果。sum的這個(gè)新值流到下一個(gè)語(yǔ)句,在那里新值被用于計(jì)算prod的新值。prod的這個(gè)新值然后流到下一行代碼,并用于計(jì)算result的值。
賦值語(yǔ)句的阻塞行為對(duì)于該數(shù)據(jù)流在零延遲RTL模型中正確仿真至關(guān)重要。每行代碼中的阻塞賦值都會(huì)阻塞下一行的求值,直到當(dāng)前行用新值更新其左側(cè)變量,對(duì)后續(xù)每行求值代碼的阻塞才能確保每一行使用前一行分配的新變量值。
如果在上面的代碼段中不適當(dāng)?shù)厥褂昧朔亲枞x值,在這些變量被更新為新值之前,則每個(gè)賦值都會(huì)使用其右側(cè)變量的先前值 。顯然這不是組合邏輯行為!然而,當(dāng)使用非阻塞賦值時(shí),綜合編譯器仍可能創(chuàng)建組合邏輯,導(dǎo)致在RTL仿真中驗(yàn)證的行為與綜合后的實(shí)際門級(jí)行為不匹配。
避免組合邏輯程序中的意外鎖存
RTL建模中的一個(gè)常見問題是推斷代碼中的鎖存行為。SystemVerilog語(yǔ)言規(guī)則要求過程賦值的左側(cè)必須是某種類型的變量,Net(網(wǎng)絡(luò))數(shù)據(jù)類型不允許出現(xiàn)在程序賦值的左側(cè)。這種對(duì)使用變量的要求可能會(huì)導(dǎo)致無意的鎖存,這是純組合邏輯的目的。當(dāng)觸發(fā)非時(shí)鐘always程序(即組合邏輯程序)且不對(duì)該程序使用的變量進(jìn)行賦值時(shí),就會(huì)發(fā)生鎖存行為。最常見的兩種情況是:
1.決策語(yǔ)句分配給每個(gè)分支中的不同變量,如下面的代碼段所示,
2.決策語(yǔ)句不會(huì)對(duì)決策表達(dá)式的每個(gè)可能值執(zhí)行分支。下面的代碼片段說明了這個(gè)問題。
在仿真中,這個(gè)簡(jiǎn)單的例子似乎正確地仿真組合邏輯加法器、減法器和乘法器。但是,如果操作碼輸入的值應(yīng)為2’b11,則本例不會(huì)對(duì)result變量進(jìn)行任何賦值。因?yàn)閞esult是一個(gè)變量,所以它會(huì)保留其以前的值,保留值的行為就像鎖存器一樣,盡管其目的是讓always_comb程序表現(xiàn)為組合邏輯。
即使使用always_comb程序,也會(huì)推斷出鎖存器。然而,綜合編譯器和lint checker將報(bào)告一個(gè)警告或非致命錯(cuò)誤,即在always_comb程序中推斷出了鎖存器。此警告是always_comb優(yōu)于常規(guī)always程序的幾個(gè)優(yōu)點(diǎn)之一。always-comb程序記錄了設(shè)計(jì)工程師的意圖,當(dāng)程序中的代碼與該意圖不一致時(shí),軟件工具可以報(bào)告這一不匹配意圖。
審核編輯:郭婷
-
編程
+關(guān)注
關(guān)注
88文章
3565瀏覽量
93536 -
鎖存器
+關(guān)注
關(guān)注
8文章
904瀏覽量
41420 -
RTL
+關(guān)注
關(guān)注
1文章
385瀏覽量
59665 -
編譯器
+關(guān)注
關(guān)注
1文章
1617瀏覽量
49015 -
and
+關(guān)注
關(guān)注
0文章
32瀏覽量
7231
原文標(biāo)題:避免組合邏輯程序中的意外鎖存
文章出處:【微信號(hào):Open_FPGA,微信公眾號(hào):OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論