聊一聊SpinalHDL 1.9.4版本中的PackedBundle、PackedWordBundle的使用
位域的提取與封裝 在邏輯設計里,但凡牽涉到協(xié)議,一般都避免不了協(xié)議字段的提取。以下面的一個簡單協(xié)議為例:
這里256bit輸入數(shù)據(jù),包含了五個協(xié)議字段:
host_addr:64 bits
card_addr:64 bits
length:14 bits
sop:1 bits
eop:1 bits
在進行協(xié)議解析時,我們可能會定義如下數(shù)據(jù)類型:
caseclassDescriptor() extendsBundle{ val host_addr=UInt(64bits) val card_addr=UInt(64bits) val length=UInt(14bits) val sop=Bool() val eop=Bool() override defassignFromBits(data:Bits)={ host_addr.assignFromBits(data(0,64bits)) card_addr.assignFromBits(data(64,64bits)) length.assignFromBits(data(128,14bits)) sop:=data(144) eop:=data(145) } override defasBits():Bits={ eop##sop##B(0,2 bits)##length##card_addr##host_addr } }
在Descriptor中,我們重寫了assignFromBits()和asBits用于協(xié)議字段的提取與數(shù)據(jù)流的的封裝.如此,我們在使用時即可在代碼使用時使代碼里盡可能的簡潔明了:
在一個大型工程里,往往可能存在許多的協(xié)議定義,那么協(xié)議的提取與數(shù)據(jù)流封裝就往往需要許多這種assignFromBits()和asBits的重寫了,“繁重的”體力勞動。
在SpinalHDL 1.9.4版本中,引入了PackedBundle、PackedWordBundle兩個組件(之前的版本略有bug)。從而能夠避免這種重復的體力活。像上面的結構中,可以直接這么定義Descriptor數(shù)據(jù)類型:
caseclassDescriptor() extends PackedBundle { val host_addr=UInt(64bits).packFrom(0) val card_addr=UInt(64bits).packFrom(64) val length=UInt(14bits) //根據(jù)當前已使用的位域推斷其對應的位域 val sop=Bool().packFrom(128+16) val eop=Bool().packFrom(128+16+1) }
我們無需再override任何函數(shù),僅需定義數(shù)據(jù)類型即可。在使用時:
通過unpack,可以從data_in中提取協(xié)議字段,通過packed方法,可以將協(xié)議字段按照位域封裝成數(shù)據(jù)流。
》PackedBundle
在PackedBundle中,為SpinalHDL中的基礎數(shù)據(jù)類型隱式擴展了DataPositionEnrich類。為其定義了用于位域綁定的函數(shù):
def pack(range: Range)
def pack(range: Range, endianness: Endianness = LITTLE)
def packFrom(pos: Int)
def packTo(pos: Int)
通過這幾個函數(shù),我們可以在使用時對定義的字段綁定位域。這里面在使用時更傾向于后面兩種方式。對于packTo與packFrom,下面的Descriptor描述方式和上面的Descriptor是等效的:
caseclassDescriptor() extends PackedBundle { val host_addr=UInt(64bits).packTo(63) val card_addr=UInt(64bits).packTo(127) val length=UInt(14bits) val sop=Bool().packFrom(128+16) val eop=Bool().packFrom(128+16+1) }
而通過PackedBundle中所提供的pack方法,可以用于將我們定義的數(shù)據(jù)類型封裝成數(shù)據(jù)流:
def packed: Bits
而對于從數(shù)據(jù)流中提取協(xié)議字段,則可以通過unpack方法:
def unpack(bits: Bits)
def unpack(bits: Bits, hi: Int, lo: Int)
第二個方法使用場景可能相對較少,感興趣的可以去看源代碼。
》PackedWordBundle
PackedWordBundle是在PackedBundle的基礎上擴展而來,從而能夠按照Word進行位域綁定,使用相對簡單,不再做額外贅述,參考例子:
》使用注意
對于PackedBundle、PackedWordBundle,其有種C語言位域結構體的味道,可以方便的定義位域,減少重復性的開發(fā)工作。不過其中有一點是其允許位域重復,如下所示:
caseclassDescriptor() extends PackedBundle { val host_addr=UInt(64bits).packTo(63) val card_addr=UInt(64bits).packTo(63) val length=UInt(14bits) val sop=Bool().packFrom(128+16) val eop=Bool().packFrom(128+16+1) }
將card_addr與host_addr綁定到相同的位置是允許的,在進行pack時由于Last Valid Assignment Win,host_addr將不會被使用。故在使用時需注意別重復綁定。
審核編輯:彭菁
-
數(shù)據(jù)
+關注
關注
8文章
7233瀏覽量
90736 -
封裝
+關注
關注
128文章
8363瀏覽量
144443 -
代碼
+關注
關注
30文章
4880瀏覽量
70000
原文標題:位域一鍵提取/封裝
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
如何實現(xiàn)SpinalHDL 環(huán)境搭建

在SpinalHDL中如何快速地實現(xiàn)總線連接
spinalhdl轉Verilog可讀性 SpinalHDL開發(fā)流程

TortoiseSVN-1.9.4.27285-x64-svn-1.9.4
聊一聊SpinalHDL 1.6.1引入的blackbox inline功能
在SpinalHDL中關于casez的使用
如何在SpinalHDL里啟動一個仿真
SpinalHDL設計錯誤總結相關資料分享
基于Windows系統(tǒng)的SpinalHDL開發(fā)環(huán)境搭建步驟
看下在SpinalHDL中常見的位拼接符的使用
SpinalHDL中的SpiMasterCtrl模塊做使用說明詳解
在SpinalHDL中的對應關系及聲明形式
SpinalHDL中Bundle數(shù)據(jù)類型的轉換
SpinalHDL BlackBox時鐘與復位

評論