Search code examples
scalahdlchisel

Vec of Bundle as a Module parameter


I'm writing a Wishbone Intercon module to make the address decoding automatically. I have two Bundle classes that describe Wishbone master and Wishbone slave interface.

class WbMaster (val dwidth: Int,
                val awidth: Int) extends Bundle {
    val adr_o = Output(UInt(awidth.W))
//...
    val cyc_o = Output(Bool())
}

// Wishbone slave interface
class WbSlave (val dwidth: Int,
               val awidth: Int) extends Bundle {
  val adr_i = Input(UInt(awidth.W))
//...
  val cyc_i = Input(Bool())
}

I want to pass these Bundle as parameter to my module Wishbone like following:

class WbInterconOneMaster(val awbm: WbMaster,
                          val awbs: Vec(WbSlave)) extends Module {
    val io = IO(new Bundle{
      val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth))
      val wbs = Vec(?)
    })
}

The objective is to permit a variable number of wishbone slaves and let the module doing the plumbing. Like following:

  val spi2Wb = Module(new Spi2Wb(dwidth, awidth))
  val wbMdio1 = Module(new MdioWb(mainFreq, targetFreq))
  val wbMdio2 = Module(new MdioWb(mainFreq, targetFreq))

  val slavesVec = Vec(Seq(wbMdio1, wbMdio2))

  val wbIntercon = Module(new WbIntercon(spi2Wb.io.wbm, slavesVec))

The question is multiple:

  • is it the right way to do it ?
  • How to declare the Vec() in module parameters ?

I tryied this but does not work:

// Wishbone Intercone with one master and several slaves
// data bus is same size as master
class WbInterconOneMaster(val awbm: WbMaster,
                          val awbs: Vec[Seq[WbSlave]]) extends Module {
    val io = IO(new Bundle{
      val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth))
      val wbs = Vec.fill(awbs.size){awbs.map(_.cloneType())}
    })
}

Solution

  • I found a solution with MixedVec (experimental) module. I simply pass a Seq of WbSlave Bundle as a module parameter and I made a MixedVec (WbSlave can have different parameters in fact):

    class WbInterconOneMaster(val awbm: WbMaster,
                              val awbs: Seq[WbSlave]) extends Module {
        val io = IO(new Bundle{
          val wbm = Flipped(new WbMaster(awbm.dwidth, awbm.awidth))
          val wbs = MixedVec(awbs.map{i => new WbSlave(i.dwidth, i.awidth)})
        })
    
        io.wbm.dat_i := 0.U
        io.wbm.ack_i := 0.U
        for(i <- 0 until io.wbs.size){
          io.wbs(i).dat_o := 0.U
          io.wbs(i).ack_o := 0.U
        }
    }
    

    That compile in the testbench.