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

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

3天内不再提示

在SpinalHDL中如何像软件调用方法那样优雅地例化端口

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-06-13 10:01 次阅读

在编写Verilog代码时最痛苦的事情便是例化模块时端口的连接,这时候的你我便成了连线工程师,本节就在SpinalHDL中如何像软件调用方法那样优雅地例化端口进行探讨。

前言

习惯了写Verilog的小伙伴们在做大型工程时是否有遇到过连续数天时间化身“连线工程师”去例化模块、为端口赋值连接的场景(关键是这些工作量老板他也不认)。尽管在SystemVerilog中提供了Interface接口的概念,但是从事FPGA的小伙伴都清楚无论是Xilinx的Vivado还是Intel Quartus虽然支持SystemVerilog但远没有做到像软件代码编辑器那般做到自动联想与提示。最近分析一个Intel的大型源码工程其中用到了大量的SystemVerilog中的interface及struct,但自动关联提示做的真是一团糟,导致阅读体验真是差的一匹…… 本文以一个简单的加法器的例子来看如何在SpinalHDL中如何避免成为连线工程师。 加法器端口列表如下所示:
端口名 方向 位宽 说明
valid_in input 1 输入有效标志
data1 input 8 输入数据
data2 input 8 输入数据
sum output 8
sum_valid output 1 和有效标志

初阶

刚开始接触SpinalHDL时这个加法器我们可能会这么来写:


class add(dataWidth:Int) extends Component{  val validIn=in Bool()  val data1=in UInt(dataWidth bits)  val data2=in UInt(dataWidth bits)  val sum=out UInt(dataWidth bits)  val sumValid=out Bool()  sum:=RegNextWhen(data1+data2,validIn)  sumValid:=RegNext(validIn,False)}

这里针对端口的实现形式和我们在Verilog中的方式基本相同。那么当我们在例化这个模块时,我们可能会这么来写:


class addInst(dataWidth:Int) extends Component {  val io=new Bundle{    val validIn_0=in Bool()    val data1_0=in UInt(dataWidth bits)    val data2_0=in UInt(dataWidth bits)    val sum_0=out UInt(dataWidth bits)    val sumValid_0=out Bool()
    val validIn_1=in Bool()    val data1_1=in UInt(dataWidth bits)    val data2_1=in UInt(dataWidth bits)    val sum_1=out UInt(dataWidth bits)    val sumValid_1=out Bool()  }  val add0=new add(dataWidth)  val add1=new add(dataWidth)  add0.validIn<>io.validIn_0  add0.data1<>io.data1_0  add0.data2<>io.data2_0  add0.sum<>io.sum_0  add0.sumValid<>io.sumValid_0    add1.validIn<>io.validIn_1  add1.data1<>io.data1_1  add1.data2<>io.data2_1  add1.sum<>io.sum_1  add1.sumValid<>io.sumValid_1}

这里例化了两个加法器,可以看到,这里如同我们写Verilog代码般一根根连线,当有众多模块需要去例化时还是蛮痛苦的。

中阶

在SystemVerilog中提供了Interface的概念用于封装接口,在SpinalHDL中,我们可以借助软件面向对象的思想把接口给抽象出来:


case class sumPort(dataWidth:Int=8) extends Bundle with IMasterSlave{  case class dataPort(dataWidth:Int=8) extends Bundle{    val data1=UInt(dataWidth bits)    val data2=UInt(dataWidth bits)  }  val dataIn=Flow(dataPort(dataWidth))  val sum=Flow(UInt(dataWidth bits))
  override def asMaster(): Unit = {    master(dataIn)    slave(sum)  }}

这里我们将加法器的端口抽象成sumPort端口。其中包含两个Flow类型:dataIn、sum。并声明当作为master端口时dataIn为master、sum为slave。这样,我们的加法器便可以这么来写:


case class add2(dataWidth:Int=8)extends Component{  val io=new Bundle{    val sumport=slave(sumPort(dataWidth))  }  io.sumport.sum.payload:=RegNextWhen(io.sumport.dataIn.data1+io.sumport.dataIn.data2,io.sumport.dataIn.valid)  io.sumport.sum.valid:=RegNext(io.sumport.dataIn.valid,False)}

而我们在例化时,便可以简洁地例化:


class addInst1(dataWidth:Int) extends Component{  val io=new Bundle{    val sumport0=slave(sumPort(dataWidth))    val sumport1=slave(sumPort(dataWidth))  }  val addInst_0=add2(dataWidth)  val addInst_1=add2(dataWidth)  io.sumport0<>addInst_0.io.sumport  io.sumport1<>addInst_1.io.sumport}

如此我们便能简洁地例化加法器。虽然这里地做法思想和SystemVerilog中地思想基本一致,但好处是我们能够在IDEA中像阅读软件代码那般快速地跳转和定位,相较于厂商工具中那样分析工程地痛苦实在是好太多。

高阶

在中阶例,我们采用了类似SystemVerilog中Interface及struct概念,但可以发现,我们这里依旧存在连线行为。一个模块例化一次要连线一次,要例化N次还是要……

在软件代码中,调用一个方法或者模块往往一行代码了事:声明调用函数并将参数放在括号列表里。那么在这里,我们能否像软件调用那样一行代码搞定呢?

可以的!由于SpinalHDL是基于Scala的,因此我们可以将端口列表当成参数列表来传递。这里我们先为我们的加法器定义一个伴生对象:


object add2{  def apply(dataWidth: Int,port Unit = {    val addInst=new add2(dataWidth)    addInst.io.sumport<>port  }}

这里我们为加法器add2定义了一个伴生对象(伴生对象声明为object,名字与类名相同)。并在其中定义了一个apply方法,传入两个参数:位宽dataWidth及端口port,并在apply实现中完成模块例化及端口连接(一次连线,终身使用)。随后我们在例化时便可以像软件调用方法那样例化模块了:


class addInst1(dataWidth:Int) extends Component{  val io=new Bundle{    val sumport0=slave(sumPort(dataWidth))    val sumport1=slave(sumPort(dataWidth))  }  add2(dataWidth,io.sumport0)  add2(dataWidth,io.sumport0)}

一行代码搞定一个模块的一次例化和端口连接!

审核编辑 :李倩


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

    关注

    6

    文章

    183

    浏览量

    30114
  • 代码
    +关注

    关注

    30

    文章

    4779

    浏览量

    68524
  • 编辑器
    +关注

    关注

    1

    文章

    805

    浏览量

    31163

原文标题:SpinalHDL—像软件调用方法般例化模块

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

收藏 人收藏

    评论

    相关推荐

    Verilog说明

    (或说是调用)。一个FPGA项目工程,其输入、输出端口命名通常在设计前期就已确定下来,
    的头像 发表于 12-17 11:29 91次阅读
    Verilog<b class='flag-5'>例</b><b class='flag-5'>化</b>说明

    三相维也纳电路,是否需要单项那样加一个pfc芯片?

    本人接了一个项目,需要输入端380-525vac输入,但是输出要达到600-800vdc,电流14-17a,想用三相维也纳电路,但现在迷茫如何看电路pf值是否得到了矫正,需不需要单项那样加一个pfc芯片,因为要实现软启动,过
    发表于 10-17 09:31

    ad端口的几种类型

    Altium Designer(简称AD)等电子设计自动(EDA)软件端口(Port)是设计原理图时用于连接和表示信号流动的重要元素
    的头像 发表于 09-29 10:11 1665次阅读

    请问studio可以裸机一样调用定时器中断吗?

    studio可以裸机一样调用定时器中断吗?我调用后显示出错了,使用hal库还需要添加什么吗
    发表于 09-13 08:18

    求助各位关于Verilog当中模块端口与引脚 的问题

    初学者。我刷HDLbits的时候做到了这道题 答案: 答案给的是定义了wire型的信号,并借这个来进行端口连接。而我的疑问在于: 1.模块化时,如果采用按名字的方式进行
    发表于 07-15 20:38

    每次调用espconn_send之前,重新设置远程IP和端口的目的是什么?

    我们初始期间设置remote_ip并remote_port一次,则在每次重复调用此函数之前,remote_ip和remote_port永远不会更改。即使发送方从第三个网络节点到同
    发表于 07-11 07:25

    动态追溯方法:彻底革新软件测试

    动态追溯方法为解决软件开发追溯的挑战提供了创新的解决方案。通过自动和动态地链接需求和测试用,使测试过程显著提高效率和精确度。该方法减少了
    的头像 发表于 07-05 17:40 393次阅读
    动态追溯<b class='flag-5'>方法</b>:彻底革新<b class='flag-5'>软件</b>测试

    STM32的IO口能不能51的IO口那样直接控制Px口输出?

    大家好,STM32的IO口能不能51的IO口那样直接控制Px口输出?比如我要用51控制器段数码管,只要给Px口送十六进制数值就可以了?请问STM32可以吗?
    发表于 04-07 07:59

    浅析SpinalHDLPipeline的复位定制

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

    verilog端口类型有哪三种

    Verilog 端口类型有三种:输入端口(input)、输出端口(output)和双向端口
    的头像 发表于 02-23 10:28 2070次阅读

    verilog调用模块端口对应方式

    Verilog是一种硬件描述语言(HDL),广泛应用于数字电路设计和硬件验证。Verilog,模块是构建电路的基本单元,而模块端口对应方式则用于描述模块之间信号传递的方式。本文将介绍
    的头像 发表于 02-23 10:20 1746次阅读

    优雅停机是什么?SpringBoot+Nacos+k8s实现优雅停机

    优雅停机是什么?网上说的优雅下线、无损下线,都是一个意思。
    的头像 发表于 02-20 10:00 2027次阅读
    <b class='flag-5'>优雅</b>停机是什么?SpringBoot+Nacos+k8s实现<b class='flag-5'>优雅</b>停机

    #2024,立Flag了嘛? #win平台搭建SpinalHDL开发环境

    1、软件下载 首先列出我们需要安装的软件:IDEA(社区版就行,不需要采用特殊的方法去PJ)、JDK17(也是免费的); 2、软件安装 2.1、IntelliJ IDEA安装 其他的按
    发表于 01-21 10:52

    请问如何使用BLE蓝牙串行端口上打印数据?

    让我学习? 以 Ce218137_ble_Proximity_RTOS 为,我可以成功连接并查看 CySmart 的值变化。 但是我想要的是将它们打印串行端口中,然后从调谐器
    发表于 01-18 08:37

    如何在同步的 Rust 方法调用异步代码 | Tokio 使用的几点教训

    同步的 Rust 方法调用异步代码经常会导致一些问题,特别是对于不熟悉异步 Rust runtime 底层原理的初学者。
    的头像 发表于 12-24 16:23 1347次阅读