0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SpinalHDL 1.9.4版本中的PackedBundle、PackedWordBundle的使用

Spinal FPGA 来源:Spinal FPGA 2023-11-11 15:35 次阅读

聊一聊SpinalHDL 1.9.4版本中的PackedBundle、PackedWordBundle的使用

位域的提取与封装 在逻辑设计里,但凡牵涉到协议,一般都避免不了协议字段的提取。以下面的一个简单协议为例:

c8b275ac-8042-11ee-939d-92fbcf53809c.jpg

这里256bit输入数据,包含了五个协议字段:

host_addr:64 bits

card_addr:64 bits

length:14 bits

sop:1 bits

eop:1 bits

在进行协议解析时,我们可能会定义如下数据类型:

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用于协议字段的提取与数据流的的封装.如此,我们在使用时即可在代码使用时使代码里尽可能的简洁明了:

c8d6d5aa-8042-11ee-939d-92fbcf53809c.png

在一个大型工程里,往往可能存在许多的协议定义,那么协议的提取与数据流封装就往往需要许多这种assignFromBits()和asBits的重写了,“繁重的”体力劳动。

在SpinalHDL 1.9.4版本中,引入了PackedBundle、PackedWordBundle两个组件(之前的版本略有bug)。从而能够避免这种重复的体力活。像上面的结构中,可以直接这么定义Descriptor数据类型:

caseclassDescriptor() extends PackedBundle {
val host_addr=UInt(64bits).packFrom(0)
val card_addr=UInt(64bits).packFrom(64)
val length=UInt(14bits) //根据当前已使用的位域推断其对应的位域
val sop=Bool().packFrom(128+16)
val eop=Bool().packFrom(128+16+1)
}

我们无需再override任何函数,仅需定义数据类型即可。在使用时:

c8fbd63e-8042-11ee-939d-92fbcf53809c.png

通过unpack,可以从data_in中提取协议字段,通过packed方法,可以将协议字段按照位域封装成数据流。

》PackedBundle

在PackedBundle中,为SpinalHDL中的基础数据类型隐式扩展了DataPositionEnrich类。为其定义了用于位域绑定的函数:

def pack(range: Range)

def pack(range: Range, endianness: Endianness = LITTLE)

def packFrom(pos: Int)

def packTo(pos: Int)

通过这几个函数,我们可以在使用时对定义的字段绑定位域。这里面在使用时更倾向于后面两种方式。对于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方法,可以用于将我们定义的数据类型封装成数据流:

def packed: Bits

而对于从数据流中提取协议字段,则可以通过unpack方法:

def unpack(bits: Bits)

def unpack(bits: Bits, hi: Int, lo: Int)

第二个方法使用场景可能相对较少,感兴趣的可以去看源代码。

》PackedWordBundle

PackedWordBundle是在PackedBundle的基础上扩展而来,从而能够按照Word进行位域绑定,使用相对简单,不再做额外赘述,参考例子:

c925974e-8042-11ee-939d-92fbcf53809c.png

》使用注意

对于PackedBundle、PackedWordBundle,其有种C语言位域结构体的味道,可以方便的定义位域,减少重复性的开发工作。不过其中有一点是其允许位域重复,如下所示:

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将不会被使用。故在使用时需注意别重复绑定。

审核编辑:彭菁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6926

    浏览量

    88867
  • 封装
    +关注

    关注

    126

    文章

    7814

    浏览量

    142781
  • 代码
    +关注

    关注

    30

    文章

    4762

    浏览量

    68408

原文标题:位域一键提取/封装

文章出处:【微信号:Spinal FPGA,微信公众号:Spinal FPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何实现SpinalHDL 环境搭建

    SpinalHDL可以不用IDE的运行。教学文档说需要安装的软件如下 也就是需要安装java SDK 1.8,Scala建议采用2.11.12版本 https://www.scala-lang.org
    的头像 发表于 08-24 14:43 8620次阅读
    如何实现<b class='flag-5'>SpinalHDL</b> 环境搭建

    SpinalHDL如何快速地实现总线连接

    教你在SpinalHDL总线连接时针对总线的部分信号位宽不同时的如何快速地实现总线连接。
    发表于 11-28 15:48 830次阅读

    spinalhdl转Verilog可读性 SpinalHDL开发流程

    是比较陡峭的。另外在团队协作,你可以要求你的同伴对Verilog,VHDL语言进行掌握,但是不能要求他们也掌握SpinalHDL,Chisel这些语言,所以你的代码怎么安排别人接手也是一个问题。但是这并不妨碍我们采用SpinalHDL
    的头像 发表于 07-27 09:29 2108次阅读
    <b class='flag-5'>spinalhdl</b>转Verilog可读性 <b class='flag-5'>SpinalHDL</b>开发流程

    TortoiseSVN-1.9.4.27285-x64-svn-1.9.4

    TortoiseSVN-1.9.4.27285-x64-svn-1.9.4svn客户端
    发表于 06-13 11:49

    聊一聊SpinalHDL 1.6.1引入的blackbox inline功能

    1.6.1版本,提供了一个inline功能,用于将blackbox“真的”封装进SpinalHDL。setInlineVerilog在BlackBox的定义里,新增了两个方法:其
    发表于 06-29 16:02

    SpinalHDL关于casez的使用

    SpinalHDL的switch在之前的文章中曾提到过SpinalHDLswitch的使用:通常情况下,switch对应着我们日常Verilog代码
    发表于 07-06 10:59

    如何在SpinalHDL里启动一个仿真

    前言在安装完成Verilator、GtkWave后,我们即可在IDEA里通过SpinalHDL提供的仿真接口来对我们的设计进行仿真。在《SpinalHDL—仿真环境》一文已提到SpinalH
    发表于 07-26 16:59

    SpinalHDL设计错误总结相关资料分享

    1、SpinalHDL设计错误  SpinalHDL编译器会做很多设计检查,来确保生成的VHDL/Verilog是可仿真的可综合的。基本上,SpinalHDL不会生成破损的VHDL/Verilog
    发表于 10-24 15:37

    基于Windows系统的SpinalHDL开发环境搭建步骤

    1 所有软件安装在C:\\SpinalHDL根目录下即可2 所有软件安装过程,把path选项都勾选上3 仿真需要使用GTKWave+Verilator,安装MSYS2软件之后,打开用户终端输入如下
    发表于 10-24 15:40

    看下在SpinalHDL中常见的位拼接符的使用

    在之前写Verilog时,位拼接符是一个很常见的东西,今天来看下在SpinalHDL中常见的位拼接符的使用。建议SpinalHDL 版本不低于1.7.1(1.7.1版本Bug较多,再往
    发表于 11-18 15:21

    SpinalHDL的SpiMasterCtrl模块做使用说明详解

    最近偶尔需要用到SPI模块。正巧看到SpinalHDL中所提供的SPI-Master设计。看完之后尤为佩服如此简洁而又全面的设计方式。本篇不对SPI协议进行讲解,仅针对SpinalHDL的SpiMasterCtrl模块做使用说
    的头像 发表于 04-19 09:58 3689次阅读

    SpinalHDL的对应关系及声明形式

    针对SpinalHDL的两大类型Reg、Wire,来梳理下在SpinalHDL的对应关系及声明形式。
    的头像 发表于 07-03 11:02 1538次阅读

    SpinalHDLBundle数据类型的转换

    SpinalHDLBundle与SystemVerilog的packed struct很像,在某些场景下,与普通数据类型之间的连接赋值可以通过asBits,assignFromBits来实现。
    的头像 发表于 10-17 09:51 1294次阅读

    SpinalHDL BlackBox时钟与复位

    SpinalHDL中使用之前已有的Verilog等代码的时候需要将这些代码包在一个BlackBox里面,但是如果这些代码里面有时钟和复位,我们需要怎么将时钟和复位端口和SpinalHDL已有的时钟域连接起来呢?
    的头像 发表于 05-04 11:13 782次阅读
    <b class='flag-5'>SpinalHDL</b> BlackBox时钟与复位

    浅析SpinalHDLPipeline的复位定制

    之前有系列文章介绍了SpinalHDLPipeline的使用,最近在一个功能模块真实的使用了这个lib。
    的头像 发表于 03-17 17:31 1007次阅读
    浅析<b class='flag-5'>SpinalHDL</b><b class='flag-5'>中</b>Pipeline<b class='flag-5'>中</b>的复位定制