數(shù)字硬件建模SystemVerilog(十三)-枚舉數(shù)據(jù)類型
上一節(jié)介紹了已經(jīng)被淘汰的$unit聲明空間,今天我們來看看一種重要的數(shù)據(jù)類型-枚舉數(shù)據(jù)類型。
枚舉數(shù)據(jù)類型提供了一種聲明變量的方法,該變量可以包含有效值的特定列表。每個(gè)值都與一個(gè)標(biāo)簽(確定的用戶自定義名宇)相關(guān)聯(lián)。枚舉變量用enum關(guān)鍵字聲明,后面是用大括號(hào)({})括起來的逗號(hào)分隔的標(biāo)簽列表。
在下面的示例中,變量rgb的值可以是RED GREEN BLUE
枚舉列表中的標(biāo)簽是常量,類似于localparam常量。標(biāo)簽可以是任何名稱。本系列使用大寫字母作為常量的慣例。
枚舉數(shù)據(jù)類型聲明語法
枚舉數(shù)據(jù)類型有一個(gè)底層數(shù)據(jù)類型,稱為基類型,可以是任何SystemVerilog內(nèi)置數(shù)據(jù)類型或用戶自定義類型。枚舉列表中的每個(gè)標(biāo)簽都有一個(gè)與該標(biāo)簽關(guān)聯(lián)的邏輯值。
SystemVerilog提供了兩種用于聲明枚舉數(shù)據(jù)類型的樣式:隱式樣式和顯式樣式。
隱式樣式枚舉聲明
隱式樣式枚舉聲明使用基類型和標(biāo)簽值的默認(rèn)值。默認(rèn)的基本類型是int。標(biāo)簽的默認(rèn)值是列表中的第一個(gè)標(biāo)簽的值為0,并且每個(gè)后續(xù)標(biāo)簽的值遞增一。
在以下隱式樣式枚舉聲明中:
enum{WAITE,LOAD,READY}states_e;
states_e是int數(shù)據(jù)類型的變量,是32位有符號(hào)數(shù)據(jù)類型。這意味著枚舉列表最多可以有2147483648(2^(32-1))個(gè)標(biāo)簽。
列表中的第一個(gè)標(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è)計(jì)問題都不能反映在枚舉變量中?;愋蚷nt的寬度為32位,通常比所表示的硬件所需的向量大得多。標(biāo)簽值(如0、1和2)不能代表很多其他類型的硬件設(shè)計(jì)中使用的編碼,例如獨(dú)熱碼值、格雷碼或約翰遜計(jì)數(shù)。
顯式樣式枚舉聲明
顯式樣式枚舉聲明指定基類型和標(biāo)簽值。以下聲明表示使用一種獨(dú)熱編碼的3位寬狀態(tài)變量:
顯式樣式枚舉聲明強(qiáng)制使用了幾個(gè)語法規(guī)則,可以幫助防止編碼錯(cuò)誤:
基類型的向量寬度和標(biāo)簽值的顯式寬度必須相同。允許使用大小不一的文字值(例如WAITE = 1)
每個(gè)標(biāo)簽的值必須是唯一的;兩個(gè)標(biāo)簽不能具有相同的值。
標(biāo)簽的數(shù)量不能超過基本類型的向量寬度所能代表的數(shù)量。
無需指定枚舉列表中每個(gè)標(biāo)簽的值。
如果未指定值,則該值將從上一個(gè)標(biāo)簽增加1。在下一個(gè)例子中,標(biāo)簽A顯式地給出了一個(gè)值l,B自動(dòng)給出了遞增為值2,C給出了遞增的值3。D被明確定義為具有13的值,E和F分別被賦予14和15的遞增值。
如果兩個(gè)標(biāo)簽的值相同,則會(huì)導(dǎo)致錯(cuò)誤。以下示例將產(chǎn)生一個(gè)錯(cuò)誤,因?yàn)閏和D的值相同,都為3:
最佳實(shí)踐指南4-3 |
---|
在RTL模型中使用顯式樣式枚舉數(shù)據(jù)類型聲明,在RTL模型中,基類型和標(biāo)簽值是指定的,而不是推斷的。 |
指定基本類型和標(biāo)簽值有幾個(gè)優(yōu)點(diǎn):它記錄了設(shè)計(jì)工程師的意圖;它可以更準(zhǔn)確地仿真門級(jí)行為,并允許更準(zhǔn)確的RTL到門級(jí)邏輯等價(jià)性檢查。
自定義和匿名枚舉數(shù)據(jù)類型
可以使用typedef將枚舉數(shù)據(jù)類型聲明為用戶自定義類型,這為使用相同的枚舉值集聲明多個(gè)變量或網(wǎng)絡(luò)提供了一種便捷的方法。
使用typedef聲明的枚舉數(shù)據(jù)類型稱為自定義枚舉數(shù)據(jù)類型。如果未使用typedef,則枚舉數(shù)據(jù)類型稱為匿名枚舉數(shù)據(jù)類型。
枚舉數(shù)據(jù)類型標(biāo)簽序列
有兩種快捷方式可以指定枚舉數(shù)據(jù)類型列表中具有相似名稱的多個(gè)標(biāo)簽。
COUNT_[4] 快捷方式將生成四個(gè)標(biāo)簽,分別為COUNT_0、COUNT_1、COUNT_2和COUNT_3。與COUNT_0關(guān)聯(lián)的值將默認(rèn)為0,隨后每個(gè)標(biāo)簽的值將增加一。
第二個(gè)快捷方式:指定一系列標(biāo)簽。
COUNT_[8:11]簡寫符號(hào)將生成四個(gè)標(biāo)簽,分別為COUNT_8、COUNT_9、COUNT_10和COUNT_11。與COUNT_8關(guān)聯(lián)的值被明確定義為8,后續(xù)標(biāo)簽的值將增加1。
如果范圍中的第一個(gè)值小于第二個(gè)值,如在COUNT_[8:11]中,則序列將從第一個(gè)數(shù)字遞增到最后一個(gè)數(shù)字。如果范圍內(nèi)的第一個(gè)值大于第二個(gè)值,如COUNT_[11: 8]中所示,序列將從第一個(gè)數(shù)字遞減到最后一個(gè)數(shù)字。
枚舉數(shù)據(jù)類型標(biāo)簽作用域
枚舉數(shù)據(jù)類型列表中的標(biāo)簽在聲明和使用標(biāo)簽的范圍內(nèi)必須是唯一的??梢园杜e數(shù)據(jù)類型聲明的RTL建模范圍是模塊、接口、包、begin-end塊、任務(wù)、函數(shù)和$unit聲明空間。
以下代碼片段將導(dǎo)致錯(cuò)誤,因?yàn)槊杜e標(biāo)簽 GO在同一模塊范圍內(nèi)使用兩次:
可以通過將至少一個(gè)枚舉數(shù)據(jù)類型聲明放在具有自己的名稱范圍的begin-end塊中來糾正上例中的錯(cuò)誤。
如上圖所示為begin-end塊命名不是必需的,但有助于記錄代碼的可讀性和維護(hù)性。
從包中導(dǎo)入枚舉數(shù)據(jù)類型
自定義枚舉數(shù)據(jù)類型可以在一個(gè)包中定義,它允許多個(gè)設(shè)計(jì)塊和驗(yàn)證代碼使用相同的定義。
筆記 |
---|
枚舉數(shù)據(jù)類型定義的顯式導(dǎo)入不會(huì)導(dǎo)入該定義中使用的標(biāo)簽。 |
使用包的通配符導(dǎo)入是解決此限制的最簡單方法 。通配符導(dǎo)入使包中的所有內(nèi)容都可用。
從包導(dǎo)入自定義枚舉數(shù)據(jù)類型定義時(shí),只導(dǎo)入自定義名稱。枚舉列表中的值標(biāo)簽不會(huì)自動(dòng)導(dǎo)入,并在導(dǎo)入枚舉數(shù)據(jù)類型名稱的名稱空間中顯示。下面的代碼片段將不起作用。
為了同時(shí)導(dǎo)入枚舉數(shù)據(jù)類型標(biāo)簽,必須顯式導(dǎo)入每個(gè)標(biāo)簽,或者必須通配符導(dǎo)入包-通配符導(dǎo)入將使枚舉數(shù)據(jù)類型名稱和枚舉標(biāo)簽在import語句的范圍內(nèi)可見。下面的部分示例顯示了通配符導(dǎo)入的使用。
從多個(gè)包進(jìn)行通配符導(dǎo)入時(shí)必須小心。如果在多個(gè)包中定義了標(biāo)識(shí)符(名稱),并且兩個(gè)包都使用通配符導(dǎo)入,則會(huì)發(fā)生編譯或細(xì)化錯(cuò)誤。對(duì)于這種情況,要使用的標(biāo)識(shí)符必須顯式導(dǎo)入或直接導(dǎo)入。SV包定義中討論了如何使用多個(gè)軟件包。
枚舉數(shù)據(jù)類型分配規(guī)則
大多數(shù)SystemVerilog變量類型都是弱類型的,這意味著任何數(shù)據(jù)類型的值都可以分配給變量,該值將使用SystemVerilog標(biāo)準(zhǔn)中指定的轉(zhuǎn)換規(guī)則轉(zhuǎn)換為變量類型。
枚舉類型不在 SV的這個(gè)一般原則內(nèi)。枚舉數(shù)據(jù)類型變量是半強(qiáng)類型的,這意味著只能為該變量指定特定的數(shù)據(jù)類型。
只能為枚舉數(shù)據(jù)類型變量賦值:
枚舉數(shù)據(jù)類型列表中的標(biāo)簽。
同一類型的另一個(gè)枚舉數(shù)據(jù)類型變量。也就是說,這兩個(gè)變量都是使用相同的自定義或匿名枚舉數(shù)據(jù)類型定義聲明的。
轉(zhuǎn)換為自定義枚舉數(shù)據(jù)類型的值,
使用以下定義和枚舉變量舉例說明這些規(guī)則:
如下所述,state 和 next_state分配枚舉變量既是合法的也是非法的:
筆記 |
---|
枚舉數(shù)據(jù)類型的強(qiáng)類型規(guī)則僅適用于對(duì)枚舉變量的賦值。存儲(chǔ)在枚舉變量中的值只是一個(gè)值,在表達(dá)式(如比較和數(shù)學(xué)運(yùn)算)中不受限制地使用。 |
對(duì)枚舉數(shù)據(jù)類型值的操作。對(duì)枚舉數(shù)據(jù)類型變量執(zhí)行操作時(shí),枚舉變量的值將轉(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á)式強(qiáng)制轉(zhuǎn)換為枚舉數(shù)據(jù)類型。任何值都可以強(qiáng)制轉(zhuǎn)換為自定義枚舉數(shù)據(jù)類型,然后分配給該枚舉數(shù)據(jù)類型的變量,即使該值與枚舉定義的某個(gè)標(biāo)簽不匹配,
在RTL建模中,有時(shí)需要將非枚舉表達(dá)式強(qiáng)制轉(zhuǎn)換為枚舉數(shù)據(jù)類型。然而,使用cast運(yùn)算符(后面將詳細(xì)討論)時(shí)必須小心。將一個(gè)值強(qiáng)制放入不在枚舉列表中的枚舉變量可能會(huì)導(dǎo)致錯(cuò)誤行為;無論是在仿真還是在綜合中。使用強(qiáng)制轉(zhuǎn)換會(huì)給設(shè)計(jì)工程師帶來負(fù)擔(dān),因?yàn)橐_保枚舉變量中只強(qiáng)制輸入有效值。這與弱類型的正則變量沒有什么不同,設(shè)計(jì)工程師需要確保指定的值是有效的。
SystemVerilog還有一個(gè)cast系統(tǒng)功能,可以自動(dòng)驗(yàn)證cast操作的結(jié)果。不幸的是,對(duì)于RTL設(shè)計(jì)人員來說,cast不受一些主要綜合編譯器的支持,cast在驗(yàn)證測(cè)試臺(tái)上很有用,但不被認(rèn)為是可綜合的結(jié)構(gòu)體。
枚舉類型的專用系統(tǒng)任務(wù)和方法
枚舉數(shù)據(jù)類型有幾個(gè)內(nèi)置函數(shù),稱為方法methods,用于遍歷枚舉數(shù)據(jù)類型列表中的值。這些方法會(huì)自動(dòng)處理枚舉數(shù)據(jù)類型的半強(qiáng)類型性質(zhì),這樣做很容易,比如遞增到枚舉數(shù)據(jù)類型列表中的下一個(gè)值,以及跳到列表的開頭或結(jié)尾。使用這些方法,不需要知道標(biāo)簽名稱。
筆記 |
---|
在撰寫本文時(shí),一些綜合編譯器支持枚舉數(shù)據(jù)類型方法,但并非所有綜合編譯器都普遍支持。 |
枚舉數(shù)據(jù)類型方法對(duì)硬件行為建模的用處有限。它們只能通過賦值語句實(shí)現(xiàn)的快捷方式。由于枚舉數(shù)據(jù)類型方法的綜合限制,本文僅簡要介紹了這些方法,并給出了一個(gè)簡單的示例。
調(diào)用枚舉方法的方法是將方法名附加到枚舉數(shù)據(jù)類型變量名的末尾,并以句點(diǎn)(.)作為分隔符。這些方法是:
<枚舉變量名>.first-返回指定變量的枚舉列表中第一個(gè)成員的值。
<枚舉變量名>.last-返回枚舉列表中最后一個(gè)成員的值。
<枚舉變量名>.next(N)-返回枚舉列表中下—個(gè)成員的值??梢杂靡粋€(gè)整數(shù)值作為 next 的參數(shù)。在這種情況下, 從枚舉變量的當(dāng)前位置算起, 返回后面第 N 個(gè)成員的值。如果到達(dá)了枚舉列表的末尾, 則會(huì)返回到列表的開頭。如果枚舉變量的當(dāng)前值不在枚舉列表中, 則返回列表中第一個(gè)成員的值。
<枚舉變量名>.prev(N))-返回枚舉列表中前一個(gè)成員的值。同 ne*t 的方法一樣.可以給 prev 指定一個(gè)整數(shù)參數(shù) 。在這種情況下, 從枚舉變量的當(dāng)前位S算起, 返回前面第 N 個(gè)成員的值。如果到達(dá)枚舉列表的開頭, 則會(huì)返冋到列表的末尾。如果枚舉變量 當(dāng)前值不在枚舉列表中 , 則返回列表中敁后一個(gè)成員的值。
<枚舉變量名>.num-返回變量枚舉列表中的標(biāo)簽個(gè)數(shù)。
<枚舉變量名>.name-返回枚舉變里中代表這個(gè)值的字符串。如果這個(gè)值不在枚舉變M列表中, 則返回一個(gè)空字符串。
打印枚舉數(shù)據(jù)類型。枚舉數(shù)據(jù)類型值可以打印為標(biāo)簽的實(shí)際值,也可以打印為標(biāo)簽的名稱。直接打印枚舉數(shù)據(jù)類型變量將打印枚舉數(shù)據(jù)類型變量的當(dāng)前實(shí)際邏輯值。使用name方法可以打印表示當(dāng)前值而不是實(shí)際值的標(biāo)簽。
舉一個(gè)使用枚舉方法的例子,這個(gè)例子演示了如何使用其中一些枚舉數(shù)據(jù)類型方法來建模狀態(tài)機(jī)序列器。該模型是一個(gè)狀態(tài)機(jī),可以設(shè)置或清除數(shù)據(jù)同步標(biāo)志。如果數(shù)據(jù)匹配輸入在至少8個(gè)連續(xù)時(shí)鐘周期內(nèi)為真,則設(shè)置數(shù)據(jù)同步標(biāo)志;如果數(shù)據(jù)匹配輸入在多個(gè)連續(xù)時(shí)鐘周期內(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ī)可以遞增或遞減的計(jì)數(shù)器。計(jì)數(shù)器統(tǒng)計(jì)已發(fā)生的連續(xù)數(shù)據(jù)匹配數(shù),最多為16。請(qǐng)注意,對(duì)于大多數(shù)狀態(tài),計(jì)數(shù)器要么遞增1,要么遞減2。next和prev枚舉數(shù)據(jù)類型方法可以非常簡潔地仿真這種遞增或遞減行為,但某些綜合編譯器可能不支持這種方法。
圖4-1:置信計(jì)數(shù)器(confidence counter))狀態(tài)機(jī)的狀態(tài)圖 示例4-5:對(duì)置信計(jì)數(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)簽,必須定義一個(gè)parameter或localparam常量來表示每個(gè)值,并為該常量指定一個(gè)值?;蛘?,可以使用'define宏定義一組宏名稱,每個(gè)名稱都有特定的值。
使用parameter創(chuàng)建標(biāo)簽的一些示例如下:
請(qǐng)注意,在使用parameters時(shí),state和nex_state變量是reg類型的通用變量,而不是枚舉變量。這些通用變量是弱類型的,這意味著任何值都可以分配給變量。使用弱類型的賦值規(guī)則,以下賦值語句是合法賦值,但屬于功能性錯(cuò)誤:
這種編碼錯(cuò)誤可能是枚舉數(shù)據(jù)類型變量的語法錯(cuò)誤。使用傳統(tǒng)的Verilog風(fēng)格的參數(shù)和通用變量類型并不能防止像這樣的意外編碼錯(cuò)誤。
SystemVerilog(十二)-$unit聲明空間
SystemVerilog(十一)-SystemVerilog 包
原文標(biāo)題:SystemVerilog(十三)-枚舉數(shù)據(jù)類型
文章出處:【微信公眾號(hào):OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7166瀏覽量
89679 -
硬件
+關(guān)注
關(guān)注
11文章
3401瀏覽量
66490 -
軟件包
+關(guān)注
關(guān)注
0文章
104瀏覽量
11662
原文標(biāo)題:SystemVerilog(十三)-枚舉數(shù)據(jù)類型
文章出處:【微信號(hào):Open_FPGA,微信公眾號(hào):OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
淺析System Verilog中的整數(shù)數(shù)據(jù)類型
數(shù)字硬件建模SystemVerilog-歸約運(yùn)算符
vhdl數(shù)據(jù)類型
go語言枚舉類型怎么用
SystemVerilog對(duì)硬件功能如何進(jìn)行建模
數(shù)字硬件建模SystemVerilog-網(wǎng)絡(luò)
數(shù)字硬件建模SystemVerilog-結(jié)構(gòu)體
SystemVerilog中枚舉類型的使用建議
SpinalHDL中Bundle數(shù)據(jù)類型的轉(zhuǎn)換
關(guān)于有符號(hào)數(shù)據(jù)類型的示例
SystemVerilog中至關(guān)重要的的數(shù)據(jù)類型
![<b class='flag-5'>SystemVerilog</b>中至關(guān)重要的的<b class='flag-5'>數(shù)據(jù)類型</b>](https://file.elecfans.com/web2/M00/89/2E/poYBAGO35PWAEGKBAAkL9OC8J-c957.jpg)
SystemVerilog-網(wǎng)絡(luò)
![<b class='flag-5'>SystemVerilog-</b>網(wǎng)絡(luò)](https://file.elecfans.com/web2/M00/8F/FF/pYYBAGPkjzmANUN3AAbOhWXY4Rw507.jpg)
S71500 硬件數(shù)據(jù)類型的常量
![S71500 <b class='flag-5'>硬件數(shù)據(jù)類型</b>的常量](https://file1.elecfans.com/web2/M00/82/CC/wKgZomRi22iALNKWAAAs4PMqdH0309.png)
評(píng)論