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

    浏览量

    31233
  • 代码
    +关注

    关注

    30

    文章

    4941

    浏览量

    73146
  • 编辑器
    +关注

    关注

    1

    文章

    826

    浏览量

    32648

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    连载|开发工具,易安卓让系统功能调用写应用逻辑一样简单

    通过自研系统封装库,易安卓将复杂的系统控制能力以接口形式开放给开发者,让系统功能调用写应用逻辑一样简单。
    的头像 发表于 11-27 11:40 87次阅读
    连载|开发工具,易安卓让系统功能<b class='flag-5'>调用</b><b class='flag-5'>像</b>写应用逻辑一样简单

    API接口调用的网络异常及解决方案

    不可达(Connection Refused/Timeout) 服务器IP/端口错误:配置的API域名解析错误、端口号填写错误(如将HTTPS默认的443端口写成80)。 服务器离线或过载:API服务器宕机、维护
    的头像 发表于 11-17 09:22 315次阅读

    Python调用API教程

    两个不同系统之间的信息交互。在这篇文章,我们将详细介绍Python调用API的方法和技巧。 一、用Requests库发送HTTP请求 使用Python调用API的第一步是发送HTTP
    的头像 发表于 11-03 09:15 324次阅读

    E203外设的与编译配置

    e203_subsys_perips层与icb总线进⾏连接。e203_subsys_perips同样e203_subsys_main
    发表于 10-24 07:14

    Xilinx BRAM IP核配置及其

    )的,所以通过合理分配BRAM的大小,可以提高片上block的利用率。 完成以后,进行综合,可以通过report utilization来查看资源消耗情况 可以看到使用的板子
    发表于 10-24 06:10

    上海控安:基于模型的测试用生成

    的测试用生成(Model-Based Test Case Generation)作为一种新兴且高效的测试方法,正逐渐成为解决这一问题的重要手段。 01 引 言 传统的软件测试过程
    的头像 发表于 08-28 14:30 514次阅读
    上海控安:基于模型的测试用<b class='flag-5'>例</b>生成

    请问有没有什么方法可以通过PSoC5LP将配置数据编程到BCR plus?

    有没有什么方法可以通过 PSoC5LP 将配置数据编程到 BCR plus? 我们希望通过 PC 使用 BCR plus 将配置二进制数据编程到原型板。但是,该主板没有CY4534那样
    发表于 08-15 06:42

    如何CanMV IDE预览哪样可以Windows上读到实时图像?

    在做一个产品,需要将识别到的人脸及标注一同显示自己用c#开发的MIS软件,请教方法CanMV IDE
    发表于 08-01 06:29

    cyusb3014插入usb2.0接口后,软件调用cyapi.lib的哪些函数完成初始、读写操作?

    cyusb3014,插入usb2.0接口后,软件调用cyapi.lib的哪些函数完成初始、读写操作?
    发表于 05-29 07:14

    研发排查问题的利器:一款方法调用栈跟踪工具

    作者:京东物流 郭忠强 导语 本文从日常值班问题排查痛点出发,分析方法复用的调用链路和上下文业务逻辑,通过思考分析,借助栈帧开发了一个方法调用栈的链式跟踪工具,便于展示一次请求的
    的头像 发表于 05-06 17:24 3011次阅读
    研发排查问题的利器:一款<b class='flag-5'>方法</b><b class='flag-5'>调用</b>栈跟踪工具

    stm32的pcrop安全系数高不高,是否会普通flash读保护那样被人家破解?

    问题1,stm32的pcrop安全系数高不高,是否会普通flash读保护那样被人家破解?能否起到代码保护作用不被解密 2,哪些stm32型号具备pcrop功能?希望具体一点。
    发表于 03-13 06:09

    Linux下安装软件有哪些方法

    Linux下安装软件,可以有哪些方法? 首先是最简单的,使用软件包管理工具。 如果是ubuntu或者debian系统,可以使用apt;如果是红帽或者centos,可以使用yum。 所
    的头像 发表于 02-08 09:41 1020次阅读

    ShiMetaOS | 怎样调用ShiMeta信息发布软件快速打造数字标牌产品

    发布软件无缝集成于ShiMetaOS系统,无需额外授权即可使用,极大地降低了使用成本,为用户提供了一款高性价比的解决方案。二、怎样调用ShiMetaOS的信息发
    的头像 发表于 02-05 17:10 1048次阅读
    ShiMetaOS  | 怎样<b class='flag-5'>调用</b>ShiMeta信息发布<b class='flag-5'>软件</b>快速打造数字标牌产品

    请问ADS1256能ADS1271那样级联吗?

    项目要做多了同步采集,ADS1256的精度较ADS1271高,所以,选用ADS1256,请问:ADS1256能ADS1271那样级联吗?
    发表于 12-24 07:32

    Verilog说明

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