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

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

3天内不再提示

在SpinalHDL中如何优雅地例化端口?

FPGA之家 来源:Spinal FPGA 作者:Spinal FPGA 2021-06-16 17:19 次阅读

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

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

valid_ininput1输入有效标志

data1input8输入数据

data2input8输入数据

sumoutput8和

sum_validoutput1和有效标志

初阶

刚开始接触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)}

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

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

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

责任编辑:haq

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

    关注

    67

    文章

    4348

    浏览量

    85622
  • Verilog
    +关注

    关注

    28

    文章

    1326

    浏览量

    109302

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

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

收藏 人收藏

    评论

    相关推荐

    浅析SpinalHDL中Pipeline中的复位定制

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

    什么是5V/3.3V可切换焊盘?这些端口AURIX™ MCU 吗?

    你好, 什么是 5 V / 3.3 V 可切换焊盘? 这些端口AURIX™ MCU 吗?
    发表于 03-05 07:54

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

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

    TC334ADC配置启用adcGroupConfig.disablePostC alibration时,端口浮动电压变大的原因?

    测试 TC334 时发现了一个奇怪的问题,使用 AURIX 的 ADC 例程,端口浮动时的电压为 0.3V,而当我 ADC 配置
    发表于 01-30 07:40

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

    ,这个一步需要勾选红框的这一项; 对应的IDEA的插件安装Scala和SBT: Scala插件安装: SBT插件安装 2.2、JDK安装 直接到JDK官网下载安装包下载即可: JDK的安装没有
    发表于 01-21 10:52

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

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

    #2024,立Flag了嘛? # 开年之疑问重重

    选择SpinalHDL、chisel还是verilog HDL作为开发语言,上周FPGA大佬跟几个IC设计公司的同学吃饭后,聊了一下发现对应的行业标杆的公司导入了spinalHDL作为开发语言
    发表于 01-13 09:18

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

        聊一聊SpinalHDL 1.9.4版本中的PackedBundle、PackedWordBundle的使用 位域的提取与封装     在逻辑设计里,但凡牵涉到协议,一般都避免不了协议字段
    的头像 发表于 11-11 15:35 830次阅读
    <b class='flag-5'>SpinalHDL</b> 1.9.4版本中的PackedBundle、PackedWordBundle的使用

    Tokio 模块的优雅停机机制

    在进行高并发、网络编程时,优雅停机是一个非常重要的问题。在 Rust 语言中,Tokio 是一个非常流行的异步编程框架,它提供了一些优雅停机的机制,本文将围绕 Tokio 模块的优雅停机进行详细
    的头像 发表于 09-19 15:26 305次阅读

    SpinalHDL Simulation性能提升测试

    昨晚看SpinalHDL的Issues,其中有一个关于性能提升的case 吸引到了我,尝试实验到深夜,测试下在SpinalHDL以及cocotb下的性能优化手段。
    的头像 发表于 08-06 17:10 419次阅读
    <b class='flag-5'>SpinalHDL</b> Simulation性能提升测试

    spinalhdl转Verilog可读性 SpinalHDL开发流程

    SpinalHDL是基于Scala全新的硬件描述语言,解决了不少Verilog等传统HDL语言的痛点,可以快速的完成某些IP的开发,和完美的融入现有的开发流程。 诚然SpinalHDL的学习路线
    的头像 发表于 07-27 09:29 862次阅读
    <b class='flag-5'>spinalhdl</b>转Verilog可读性 <b class='flag-5'>SpinalHDL</b>开发流程

    原来SpinalHDL中BlackBox封装数组接口如此简单

    当在SpinalHDL中调用别人的RTL代码时,需要采用BlackBox进行封装。对于大多数场景,想必小伙伴们都已轻车熟路。今天着重来看下当RTL代码的接口中存在数组形式的接口时如何处理。
    的头像 发表于 05-22 10:04 447次阅读
    原来<b class='flag-5'>SpinalHDL</b>中BlackBox封装数组接口如此简单

    IMXRT1176-EVK上同时运行两个USB端口可行吗?

    ,s1_cdcVcom; 我也处理程序部分进行了修改。 请查收附件。 Q2:初始后,USB OTG-2 App init 不工作。它在此函数返回错误(USB_DeviceAllocateHandle(controllerI
    发表于 05-09 06:55

    SpinalHDL语法之Bool类型

    作为SpinalHDL语法篇的第一节,我们也从最简单的开始。 Bool类型定义
    的头像 发表于 05-05 16:01 391次阅读

    SpinalHDL BlackBox时钟与复位

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