十二 · 2021年11月09日

你刚写完接口,我已经把功能实现了

三两行代码实现一个模块,让工作轻松一点儿不好么。

小伙伴的问题

下午微信群里有个小伙伴问了这么一道题:

  • 将一个为UInt(128 bits)的Stream接口连接到一个UInt(32 bits)的StreamFiFo上,在SpinalHDL里有没有什么好的方式实现。

熟悉数字逻辑电路的小伙伴想必都不陌生,其本质上是一个接口位宽转换,在实现时无非用位宽转换FIFO或者自己在入口做一个简单的位宽转换,进来一拍有效数据分成4拍放入FIFO里~

若自己的工作里遇到这个需求,熟悉Verilog的小伙伴们是否已经迫不及待的开始动手写了呢~

你先写着,我让子弹飞一会儿.

84feabe5ea763bd32cafcb06d8fa7f7c.jpg

三行代码实现一个功能

这个需求在SpinalHDL里只需要三行代码(接口的声明不算~):

case class example5() extends Component{
  val io=new Bundle{
    val dataIn=slave(Stream(UInt(128 bits)))
    val dataOut=master(Stream(UInt(32 bits)))
  }
  val dataAdapt=Stream(UInt(32 bits))
  StreamWidthAdapter(io.dataIn,dataAdapt)
  io.dataOut<>dataAdapt.queue(512)
}

仿真波形:

3779e8e6d084af904c6f745332b470bb.png

这里的实现调用了两个库函数:StreamWidthAdapter,queue。而你的接口列表写完了否?

StreamWidthAdapter

StreamWidthAdapter,顾名思义,其用途是进行Stream接口的位宽转换。看下其源代码:

dc904047ca4b90fd999d1e1be1137d8b.pngdc904047ca4b90fd999d1e1be1137d8b.png

其输入参数列表为

  • input:输入Stream接口
  • output:输出Stream接口
  • endianness:选择转换方式为大尾端还是小尾端(LITTLE,BIG)
  • padding:当输入输出端口位宽不是整数倍时进行数据填充(默认为false,但如果位宽不能整除则要设置为true)。

其内部设计实现思路并不难,位宽匹配时输入输出直接相连,不匹配时则通过增加一个counter来实现接口时序调整和数据填充。

除此之外,StreamWidthAdapter还提供了一个make方法:

def make[T <: Data, T2 <: Data](input : Stream[T], outputPayloadType : HardType[T2], endianness: Endianness = LITTLE, padding : Boolean = false) : Stream[T2] = {
    val ret = Stream(outputPayloadType())
    StreamWidthAdapter(input,ret,endianness,padding)
    ret
  }

可以看出,其内部封装了对StreamWidthAdapter的实现并返回一个Stream接口,通过这个函数,我们上面的代码甚至可以简化为一行:

case class example5() extends Component{
  val io=new Bundle{
    val dataIn=slave(Stream(UInt(128 bits)))
    val dataOut=master(Stream(UInt(32 bits)))
  }
  io.dataOut<>StreamWidthAdapter.make(io.dataIn,UInt(32 bits)).queue(512)
}

queue

SpinalHDL在Stream里提供了一个queue方法:

/** Connect this to a fifo and return its pop stream
  */
  def queue(size: Int): Stream[T] = {
    val fifo = new StreamFifo(payloadType, size).setCompositeName(this,"queue", true)
    fifo.setPartialName(this,"fifo")
    fifo.io.push << this
    fifo.io.pop
  }

注释很明晰:将Stream接口连接到FIFO上,并返回FIFO的POP端口。

小结

SpinalHDL本质上和我们写Verilog并无差别,只不过借助于Scala语言及将常见基础组件封装起来便于快捷的调用。当然我们在使用的同时还是要去仔细分析下其源代码,理解设计的本质。

☆ END ☆

作者:玉骐
原文链接:https://mp.weixin.qq.com/s/MAxApMnOM2WmyjyJTkykpQ
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注Spinal FPGA专栏。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息