过了一遍chisel bookchisel tutorial的内容,学了chisel基本搭电路的语法,能把verilog的代码翻译成chisel,但在翻译的过程中发现仅有这些基本技能还不够,完全没有发挥出scala这种高级语言的优势,知乎看到一篇用Chisel快速搭建FFT流水线电路,发现好多方便的操作,总结下来有以下几点:

  • local parameter
  • 同类线网Bundle
  • 实例化模块

一、局部变量local parameter

verilog 经常会有局部变量,有些定义位宽,有些定义循环次数,chisel里也能用val 定义变量,但总感觉“不干净”,而且不好复用,有什么办法呢?scala的trait很好用!

可以在Config.scala里定义参数:

package FFT

trait HasDataConfig {
  val DataWidth = 32
  val BinaryPoint = 16
}

trait HasElaborateConfig {
  val FFTLength = 512
  val useGauss = false
  val supportIFFT = false
}

然后定义时,在需要这些局部变量的模块加上with就可以访问,非常方便:

//用with增加局部变量
class MyComplex extends Bundle with HasDataConfig {  
  val re = FixedPoint(DataWidth.W, BinaryPoint.BP)
  val im = FixedPoint(DataWidth.W, BinaryPoint.BP)
}

二、Bundle线网

实际电路的输入输出其实会分数据线和控制线,还有一些信号属于同类型的,但verilog只能一视同仁,只能在命名上加以区分,但chisel里的Bundle类可以把相同的信号“绑”在一起,既便于阅读,也便于调用。

先定义一个复数的Bundle,然后在Switch模块里就可以直接调用MyComplex,而无需再定义实部虚部,更加简洁。

//Bundle“绑定”相同类型的信号
class MyComplex extends Bundle with HasDataConfig { 
  val re = FixedPoint(DataWidth.W, BinaryPoint.BP)
  val im = FixedPoint(DataWidth.W, BinaryPoint.BP)
}

class Switch extends Module {
  val io = IO(new Bundle{
    val in1 = Input(new MyComplex)
    val in2 = Input(new MyComplex)
    val sel = Input(Bool())
    val out1 = Output(new MyComplex)
    val out2 = Output(new MyComplex)
  })
  io.out1 := Mux(io.sel, io.in2, io.in1)
  io.out2 := Mux(io.sel, io.in1, io.in2)
}

三、伴生对象之工厂方法

别被这个名词唬了,verilog调用子模块时,都需要再连线,很繁琐,代码又长又臭。chisel伴生对象的工厂方法可以很好解决这个问题。

class Switch extends Module {
  val io = IO(new Bundle{
    val in1 = Input(new MyComplex)
    val in2 = Input(new MyComplex)
    val sel = Input(Bool())
    val out1 = Output(new MyComplex)
    val out2 = Output(new MyComplex)
  })
  io.out1 := Mux(io.sel, io.in2, io.in1)
  io.out2 := Mux(io.sel, io.in1, io.in2)
}
//定义伴生对象,apply方法
object Switch {
  def apply(in1: MyComplex, in2: MyComplex, sel: Bool): (MyComplex, MyComplex) = {
    val inst = Module(new Switch)
    inst.io.in1 := in1
    inst.io.in2 := in2
    inst.io.sel := sel
    (inst.io.out1, inst.io.out2)
  }
}

这样就可以很方便例化模型,不需要再连线,元素访问也很简单:

//不需要再连线
val sw12 = Switch(in1,in2,swCtrl)
//元素访问
val out1 = sw12._1
val out2 = sw12._2

除此之外,用map生成正弦余弦rom,scala测试代码中还有一些高效操作,还没有完全掌握,得慢慢消化。

标签: chisel, fft

添加新评论