數(shù)字硬件建模SystemVerilog(十三)-枚舉數(shù)據(jù)類型
上一節(jié)介紹了已經(jīng)被淘汰的$unit聲明空間,今天我們來看看一種重要的數(shù)據(jù)類型-枚舉數(shù)據(jù)類型。
枚舉數(shù)據(jù)類型提供了一種聲明變量的方法,該變量可以包含有效值的特定列表。每個值都與一個標(biāo)簽(確定的用戶自定義名宇)相關(guān)聯(lián)。枚舉變量用enum關(guān)鍵字聲明,后面是用大括號({})括起來的逗號分隔的標(biāo)簽列表。
在下面的示例中,變量rgb的值可以是RED GREEN BLUE
枚舉列表中的標(biāo)簽是常量,類似于localparam常量。標(biāo)簽可以是任何名稱。本系列使用大寫字母作為常量的慣例。
枚舉數(shù)據(jù)類型聲明語法
枚舉數(shù)據(jù)類型有一個底層數(shù)據(jù)類型,稱為基類型,可以是任何SystemVerilog內(nèi)置數(shù)據(jù)類型或用戶自定義類型。枚舉列表中的每個標(biāo)簽都有一個與該標(biāo)簽關(guān)聯(lián)的邏輯值。
SystemVerilog提供了兩種用于聲明枚舉數(shù)據(jù)類型的樣式:隱式樣式和顯式樣式。
隱式樣式枚舉聲明
隱式樣式枚舉聲明使用基類型和標(biāo)簽值的默認(rèn)值。默認(rèn)的基本類型是int。標(biāo)簽的默認(rèn)值是列表中的第一個標(biāo)簽的值為0,并且每個后續(xù)標(biāo)簽的值遞增一。
在以下隱式樣式枚舉聲明中:
enum{WAITE,LOAD,READY}states_e;
states_e是int數(shù)據(jù)類型的變量,是32位有符號數(shù)據(jù)類型。這意味著枚舉列表最多可以有2147483648(2^(32-1))個標(biāo)簽。
列表中的第一個標(biāo)簽WAITE的值為0,LOAD為l,READY為2。(標(biāo)簽WAITE故意在末尾拼寫為“E”,以避免與SystemVerilog中保留的關(guān)鍵字wait產(chǎn)生混淆或沖突。)
這些默認(rèn)設(shè)置很少適用于硬件建模。基類型int是2-state類型,這意味著在仿真期間導(dǎo)致X的任何設(shè)計問題都不能反映在枚舉變量中。基類型int的寬度為32位,通常比所表示的硬件所需的向量大得多。標(biāo)簽值(如0、1和2)不能代表很多其他類型的硬件設(shè)計中使用的編碼,例如獨熱碼值、格雷碼或約翰遜計數(shù)。
顯式樣式枚舉聲明
顯式樣式枚舉聲明指定基類型和標(biāo)簽值。以下聲明表示使用一種獨熱編碼的3位寬狀態(tài)變量:
顯式樣式枚舉聲明強制使用了幾個語法規(guī)則,可以幫助防止編碼錯誤:
基類型的向量寬度和標(biāo)簽值的顯式寬度必須相同。允許使用大小不一的文字值(例如WAITE = 1)
每個標(biāo)簽的值必須是唯一的;兩個標(biāo)簽不能具有相同的值。
標(biāo)簽的數(shù)量不能超過基本類型的向量寬度所能代表的數(shù)量。
無需指定枚舉列表中每個標(biāo)簽的值。
如果未指定值,則該值將從上一個標(biāo)簽增加1。在下一個例子中,標(biāo)簽A顯式地給出了一個值l,B自動給出了遞增為值2,C給出了遞增的值3。D被明確定義為具有13的值,E和F分別被賦予14和15的遞增值。
如果兩個標(biāo)簽的值相同,則會導(dǎo)致錯誤。以下示例將產(chǎn)生一個錯誤,因為c和D的值相同,都為3:
最佳實踐指南4-3 |
---|
在RTL模型中使用顯式樣式枚舉數(shù)據(jù)類型聲明,在RTL模型中,基類型和標(biāo)簽值是指定的,而不是推斷的。 |
指定基本類型和標(biāo)簽值有幾個優(yōu)點:它記錄了設(shè)計工程師的意圖;它可以更準(zhǔn)確地仿真門級行為,并允許更準(zhǔn)確的RTL到門級邏輯等價性檢查。
自定義和匿名枚舉數(shù)據(jù)類型
可以使用typedef將枚舉數(shù)據(jù)類型聲明為用戶自定義類型,這為使用相同的枚舉值集聲明多個變量或網(wǎng)絡(luò)提供了一種便捷的方法。
使用typedef聲明的枚舉數(shù)據(jù)類型稱為自定義枚舉數(shù)據(jù)類型。如果未使用typedef,則枚舉數(shù)據(jù)類型稱為匿名枚舉數(shù)據(jù)類型。
枚舉數(shù)據(jù)類型標(biāo)簽序列
有兩種快捷方式可以指定枚舉數(shù)據(jù)類型列表中具有相似名稱的多個標(biāo)簽。
COUNT_[4] 快捷方式將生成四個標(biāo)簽,分別為COUNT_0、COUNT_1、COUNT_2和COUNT_3。與COUNT_0關(guān)聯(lián)的值將默認(rèn)為0,隨后每個標(biāo)簽的值將增加一。
第二個快捷方式:指定一系列標(biāo)簽。
COUNT_[8:11]簡寫符號將生成四個標(biāo)簽,分別為COUNT_8、COUNT_9、COUNT_10和COUNT_11。與COUNT_8關(guān)聯(lián)的值被明確定義為8,后續(xù)標(biāo)簽的值將增加1。
如果范圍中的第一個值小于第二個值,如在COUNT_[8:11]中,則序列將從第一個數(shù)字遞增到最后一個數(shù)字。如果范圍內(nèi)的第一個值大于第二個值,如COUNT_[11: 8]中所示,序列將從第一個數(shù)字遞減到最后一個數(shù)字。
枚舉數(shù)據(jù)類型標(biāo)簽作用域
枚舉數(shù)據(jù)類型列表中的標(biāo)簽在聲明和使用標(biāo)簽的范圍內(nèi)必須是唯一的。可以包含枚舉數(shù)據(jù)類型聲明的RTL建模范圍是模塊、接口、包、begin-end塊、任務(wù)、函數(shù)和$unit聲明空間。
以下代碼片段將導(dǎo)致錯誤,因為枚舉標(biāo)簽 GO在同一模塊范圍內(nèi)使用兩次:
可以通過將至少一個枚舉數(shù)據(jù)類型聲明放在具有自己的名稱范圍的begin-end塊中來糾正上例中的錯誤。
如上圖所示為begin-end塊命名不是必需的,但有助于記錄代碼的可讀性和維護(hù)性。
從包中導(dǎo)入枚舉數(shù)據(jù)類型
自定義枚舉數(shù)據(jù)類型可以在一個包中定義,它允許多個設(shè)計塊和驗證代碼使用相同的定義。
筆記 |
---|
枚舉數(shù)據(jù)類型定義的顯式導(dǎo)入不會導(dǎo)入該定義中使用的標(biāo)簽。 |
使用包的通配符導(dǎo)入是解決此限制的最簡單方法 。通配符導(dǎo)入使包中的所有內(nèi)容都可用。
從包導(dǎo)入自定義枚舉數(shù)據(jù)類型定義時,只導(dǎo)入自定義名稱。枚舉列表中的值標(biāo)簽不會自動導(dǎo)入,并在導(dǎo)入枚舉數(shù)據(jù)類型名稱的名稱空間中顯示。下面的代碼片段將不起作用。
為了同時導(dǎo)入枚舉數(shù)據(jù)類型標(biāo)簽,必須顯式導(dǎo)入每個標(biāo)簽,或者必須通配符導(dǎo)入包-通配符導(dǎo)入將使枚舉數(shù)據(jù)類型名稱和枚舉標(biāo)簽在import語句的范圍內(nèi)可見。下面的部分示例顯示了通配符導(dǎo)入的使用。
從多個包進(jìn)行通配符導(dǎo)入時必須小心。如果在多個包中定義了標(biāo)識符(名稱),并且兩個包都使用通配符導(dǎo)入,則會發(fā)生編譯或細(xì)化錯誤。對于這種情況,要使用的標(biāo)識符必須顯式導(dǎo)入或直接導(dǎo)入。SV包定義中討論了如何使用多個軟件包。
枚舉數(shù)據(jù)類型分配規(guī)則
大多數(shù)SystemVerilog變量類型都是弱類型的,這意味著任何數(shù)據(jù)類型的值都可以分配給變量,該值將使用SystemVerilog標(biāo)準(zhǔn)中指定的轉(zhuǎn)換規(guī)則轉(zhuǎn)換為變量類型。
枚舉類型不在 SV的這個一般原則內(nèi)。枚舉數(shù)據(jù)類型變量是半強類型的,這意味著只能為該變量指定特定的數(shù)據(jù)類型。
只能為枚舉數(shù)據(jù)類型變量賦值:
枚舉數(shù)據(jù)類型列表中的標(biāo)簽。
同一類型的另一個枚舉數(shù)據(jù)類型變量。也就是說,這兩個變量都是使用相同的自定義或匿名枚舉數(shù)據(jù)類型定義聲明的。
轉(zhuǎn)換為自定義枚舉數(shù)據(jù)類型的值,
使用以下定義和枚舉變量舉例說明這些規(guī)則:
如下所述,state 和 next_state分配枚舉變量既是合法的也是非法的:
筆記 |
---|
枚舉數(shù)據(jù)類型的強類型規(guī)則僅適用于對枚舉變量的賦值。存儲在枚舉變量中的值只是一個值,在表達(dá)式(如比較和數(shù)學(xué)運算)中不受限制地使用。 |
對枚舉數(shù)據(jù)類型值的操作。對枚舉數(shù)據(jù)類型變量執(zhí)行操作時,枚舉變量的值將轉(zhuǎn)換為枚舉數(shù)據(jù)類型定義的基類型。操作的結(jié)果不再是枚舉數(shù)據(jù)類型,結(jié)果可以分配給常規(guī)的、弱類型的變量,但不能分配回枚舉變量。
logic[2:0]temp;//非枚舉變量 temp = next_state + 1;//合規(guī)的:temp是弱類型的 state = next_state + 1;//非法的:next_state + 1不是枚舉表達(dá)式 state++;//非法的:++的結(jié)果不是枚舉表達(dá)式 state += next_state;//非法的:+=的結(jié)果不是枚舉表達(dá)式
將表達(dá)式強制轉(zhuǎn)換為枚舉數(shù)據(jù)類型。任何值都可以強制轉(zhuǎn)換為自定義枚舉數(shù)據(jù)類型,然后分配給該枚舉數(shù)據(jù)類型的變量,即使該值與枚舉定義的某個標(biāo)簽不匹配,
在RTL建模中,有時需要將非枚舉表達(dá)式強制轉(zhuǎn)換為枚舉數(shù)據(jù)類型。然而,使用cast運算符(后面將詳細(xì)討論)時必須小心。將一個值強制放入不在枚舉列表中的枚舉變量可能會導(dǎo)致錯誤行為;無論是在仿真還是在綜合中。使用強制轉(zhuǎn)換會給設(shè)計工程師帶來負(fù)擔(dān),因為要確保枚舉變量中只強制輸入有效值。這與弱類型的正則變量沒有什么不同,設(shè)計工程師需要確保指定的值是有效的。
SystemVerilog還有一個cast系統(tǒng)功能,可以自動驗證cast操作的結(jié)果。不幸的是,對于RTL設(shè)計人員來說,cast不受一些主要綜合編譯器的支持,cast在驗證測試臺上很有用,但不被認(rèn)為是可綜合的結(jié)構(gòu)體。
枚舉類型的專用系統(tǒng)任務(wù)和方法
枚舉數(shù)據(jù)類型有幾個內(nèi)置函數(shù),稱為方法methods,用于遍歷枚舉數(shù)據(jù)類型列表中的值。這些方法會自動處理枚舉數(shù)據(jù)類型的半強類型性質(zhì),這樣做很容易,比如遞增到枚舉數(shù)據(jù)類型列表中的下一個值,以及跳到列表的開頭或結(jié)尾。使用這些方法,不需要知道標(biāo)簽名稱。
筆記 |
---|
在撰寫本文時,一些綜合編譯器支持枚舉數(shù)據(jù)類型方法,但并非所有綜合編譯器都普遍支持。 |
枚舉數(shù)據(jù)類型方法對硬件行為建模的用處有限。它們只能通過賦值語句實現(xiàn)的快捷方式。由于枚舉數(shù)據(jù)類型方法的綜合限制,本文僅簡要介紹了這些方法,并給出了一個簡單的示例。
調(diào)用枚舉方法的方法是將方法名附加到枚舉數(shù)據(jù)類型變量名的末尾,并以句點(.)作為分隔符。這些方法是:
<枚舉變量名>.first-返回指定變量的枚舉列表中第一個成員的值。
<枚舉變量名>.last-返回枚舉列表中最后一個成員的值。
<枚舉變量名>.next(N)-返回枚舉列表中下—個成員的值。可以用一個整數(shù)值作為 next 的參數(shù)。在這種情況下, 從枚舉變量的當(dāng)前位置算起, 返回后面第 N 個成員的值。如果到達(dá)了枚舉列表的末尾, 則會返回到列表的開頭。如果枚舉變量的當(dāng)前值不在枚舉列表中, 則返回列表中第一個成員的值。
<枚舉變量名>.prev(N))-返回枚舉列表中前一個成員的值。同 ne*t 的方法一樣.可以給 prev 指定一個整數(shù)參數(shù) 。在這種情況下, 從枚舉變量的當(dāng)前位S算起, 返回前面第 N 個成員的值。如果到達(dá)枚舉列表的開頭, 則會返冋到列表的末尾。如果枚舉變量 當(dāng)前值不在枚舉列表中 , 則返回列表中敁后一個成員的值。
<枚舉變量名>.num-返回變量枚舉列表中的標(biāo)簽個數(shù)。
<枚舉變量名>.name-返回枚舉變里中代表這個值的字符串。如果這個值不在枚舉變M列表中, 則返回一個空字符串。
打印枚舉數(shù)據(jù)類型。枚舉數(shù)據(jù)類型值可以打印為標(biāo)簽的實際值,也可以打印為標(biāo)簽的名稱。直接打印枚舉數(shù)據(jù)類型變量將打印枚舉數(shù)據(jù)類型變量的當(dāng)前實際邏輯值。使用name方法可以打印表示當(dāng)前值而不是實際值的標(biāo)簽。
舉一個使用枚舉方法的例子,這個例子演示了如何使用其中一些枚舉數(shù)據(jù)類型方法來建模狀態(tài)機(jī)序列器。該模型是一個狀態(tài)機(jī),可以設(shè)置或清除數(shù)據(jù)同步標(biāo)志。如果數(shù)據(jù)匹配輸入在至少8個連續(xù)時鐘周期內(nèi)為真,則設(shè)置數(shù)據(jù)同步標(biāo)志;如果數(shù)據(jù)匹配輸入在多個連續(xù)時鐘周期內(nèi)為假,則清除數(shù)據(jù)同步標(biāo)志,清除數(shù)據(jù)同步標(biāo)志所需的連續(xù)假數(shù)據(jù)匹配數(shù)取決于有多少連續(xù)周期數(shù)據(jù)匹配為真,
圖4-1顯示了該狀態(tài)機(jī)的狀態(tài)流。狀態(tài)機(jī)可以遞增或遞減的計數(shù)器。計數(shù)器統(tǒng)計已發(fā)生的連續(xù)數(shù)據(jù)匹配數(shù),最多為16。請注意,對于大多數(shù)狀態(tài),計數(shù)器要么遞增1,要么遞減2。next和prev枚舉數(shù)據(jù)類型方法可以非常簡潔地仿真這種遞增或遞減行為,但某些綜合編譯器可能不支持這種方法。
圖4-1:置信計數(shù)器(confidence counter))狀態(tài)機(jī)的狀態(tài)圖 示例4-5:對置信計數(shù)器狀態(tài)機(jī)使用枚舉數(shù)據(jù)類型方法
// //Book,"RTLModelingwithSystemVerilogforASICandFPGADesign" //byStuartSutherland // //Statemachinemodelforaconfidencecountermodeledusing //enumeratedtypemethods. // //Copyright2016,StuartSutherland.Allrightsreserved. // //Version1.0 // `begin_keywords"1800-2012"http://useSystemVerilog-2012keywords moduleconfidence_counter (inputlogicdata_matches,compare_en,rstN,clk, outputlogicdata_synched ); timeunit1ns/1ns; typedefenumlogic[3:0]{COUNT[0:15]}states_enum_t; states_enum_tCurState,NextState; //sequentialblock always_ff@(posedgeclk,negedgerstN) if(!rstN)CurState<=?COUNT0; ????else???????CurState?<=?NextState; ??//?next?state?combination?logic?block ??always_comb?begin ????if?(!compare_en) ??????NextState?=?CurState;??//?not?comparing?(no?state?change) ????else?if?(data_matches)???//?compare_en?&&?data_matches ??????case?(CurState) ????????COUNT15?:?;?//?can't?increment?past?15 ????????default:?NextState?=?CurState.next;??//?increment?by?1 ??????endcase ????else?????????????????????//?compare_en?&&?!data_matches ??????case?(CurState) ????????COUNT0?:?;?//?can't?decrement?below?0 ????????COUNT1?:?NextState?=?CurState.prev(1);??//?decrement?by?1 ????????default:?NextState?=?CurState.prev(2);??//?decrement?by?2 ??????endcase ??end ??//?register?output?block ??always_ff?@(posedge?clk,?negedge?rstN) ????if?(!rstN) ??????data_synched?<=?0; ????else ??????begin ????????if?(CurState?==?COUNT8) ??????????data_synched?<=?1; ????????else?if?(CurState?==?COUNT0) ??????????data_synched?<=?0; ??????end endmodule:?confidence_counter `end_keywords
沒有枚舉數(shù)據(jù)類型的傳統(tǒng)Verilog編碼風(fēng)格
Verilog語言在成為SystemVerilog之前沒有枚舉數(shù)據(jù)類型。要為數(shù)據(jù)值創(chuàng)建標(biāo)簽,必須定義一個parameter或localparam常量來表示每個值,并為該常量指定一個值。或者,可以使用'define宏定義一組宏名稱,每個名稱都有特定的值。
使用parameter創(chuàng)建標(biāo)簽的一些示例如下:
請注意,在使用parameters時,state和nex_state變量是reg類型的通用變量,而不是枚舉變量。這些通用變量是弱類型的,這意味著任何值都可以分配給變量。使用弱類型的賦值規(guī)則,以下賦值語句是合法賦值,但屬于功能性錯誤:
這種編碼錯誤可能是枚舉數(shù)據(jù)類型變量的語法錯誤。使用傳統(tǒng)的Verilog風(fēng)格的參數(shù)和通用變量類型并不能防止像這樣的意外編碼錯誤。
SystemVerilog(十二)-$unit聲明空間
SystemVerilog(十一)-SystemVerilog 包
原文標(biāo)題:SystemVerilog(十三)-枚舉數(shù)據(jù)類型
文章出處:【微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7079瀏覽量
89166 -
硬件
+關(guān)注
關(guān)注
11文章
3345瀏覽量
66288 -
軟件包
+關(guān)注
關(guān)注
0文章
104瀏覽量
11613
原文標(biāo)題:SystemVerilog(十三)-枚舉數(shù)據(jù)類型
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論