十二 · 2021年11月01日

SpinalHDL—小练习(二)

本系列适合新手在对Scala及SpinalHDL有初步了解后做练手使用。

题目

端口列表:针对多比特输入信号,对其中的比特位分组求异或值。
image.png

参数类:

case class config(bitsPerGroup:Int,
                  dataWidth:Int){
  require(dataWidth%bitsPerGroup==0,"Invalid parameter")
  val sigOutWidth=dataWidth/bitsPerGroup
}

这里将参数放置在一个class中,以便方便使用及统一的参数检查。

实现

case class config(bitsPerGroup:Int,
                  dataWidth:Int){
  require(dataWidth%bitsPerGroup==0,"Invalid parameter")
  val sigOutWidth=dataWidth/bitsPerGroup
}
case class example2(cfg:config) extends Component{
  val io=new Bundle{
    val sigIn=in UInt(cfg.dataWidth bits)
    val sigOut=out UInt(cfg.sigOutWidth bits)
  }
  noIoPrefix()
  val _=new Area{
    io.sigOut:=io.sigIn.subdivideIn(cfg.bitsPerGroup bits).map(_.xorR).asBits().asUInt
  }.setName("")
 }
object example2App extends App{
  val cfg=config(8,32)
  SpinalSystemVerilog(example2(cfg)).printPruned()
}

Key:

  • subdivideIn方法的使用
  • Scala Collection中map函数的使用

进阶一

对每组比特安位取反,随后对每组比特累加求和.考虑到时序问题,在求和前添加一级寄存器

case class config(bitsPerGroup:Int,
                  dataWidth:Int){
  require(dataWidth%bitsPerGroup==0,"Invalid parameter")
  val sigOutWidth=dataWidth/bitsPerGroup
}
case class example2_1(cfg:config) extends Component{
  val io=new Bundle{
    val sigIn=in UInt(cfg.dataWidth bits)
    val sigOut=out UInt(cfg.bitsPerGroup bits)
  }
  noIoPrefix()
  val _=new Area{
    io.sigOut:=(io.sigIn.subdivideIn(cfg.bitsPerGroup bits).map(~_).map(RegNext(_))).reduce(_+_)
  }.setName("")
}
object example2App extends App{
  val cfg=config(8,32)
  SpinalSystemVerilog(example2_1(cfg)).printPruned()
}

Key:

  • Scala Collection中reduce函数的使用

进阶二

在进阶一的基础上,当加法溢出时做饱和处理

case class config(bitsPerGroup:Int,
                  dataWidth:Int){
  require(dataWidth%bitsPerGroup==0,"Invalid parameter")
  val sigOutWidth=dataWidth/bitsPerGroup
}
case class example2_2(cfg:config) extends Component{
  val io=new Bundle{
    val sigIn=in UInt(cfg.dataWidth bits)
    val sigOut=out UInt(cfg.bitsPerGroup bits)
  }
  noIoPrefix()
  val _=new Area{
    io.sigOut:=(io.sigIn.subdivideIn(cfg.bitsPerGroup bits).map(~_).map(RegNext(_))).reduce(_ +| _)
  }.setName("")
}
object example2App extends App{
  val cfg=config(8,32)
  SpinalSystemVerilog(example2_2(cfg)).printPruned()
}

Key:

  • SpinalHDL中UInt/SInt中“+|”操作符使用。

END

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

推荐阅读

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