Issues with creating an n-to-1 multiplexer in Chisel

67 Views Asked by At

I am currently working on creating an n-to-1 multiplexer using Chisel, where nr_m equals 2. I have written some code, but I am encountering issues when trying to generate Verilog. Here is the code I have written:

import chisel3._
import chisel3.util._

class AXIIN extends Bundle {
  val arvalid = Input(Bool())
  val araddr  = Input(UInt(32.W))

  val rready  = Input(Bool())

  val awaddr  = Input(UInt(32.W))
  val awvalid = Input(Bool())

  val wdata   = Input(UInt(32.W))
  val wstrb   = Input(UInt(8.W))
  val wvalid  = Input(Bool())

  val bready  = Input(Bool())
}

class MasterOutMuxIO(nr_m: Int) extends Bundle {
  val in = Vec(nr_m, new AXIIN)

  val selector = Input(UInt(nr_m.W)) // The selector is a one-hot code.

  val out = Flipped(new AXIIN)
}

class MasterOutMux(nr_m: Int) extends Module {
  val io = IO(new MasterOutMuxIO(2))
  val sel = io.selector
  
  val defaultOut = Wire(new AXIIN)
  for (enty <- defaultOut.getElements) {
    enty := 0.U
  }
  io.out := MuxLookup(io.selector, defaultOut)(
              (0 until nr_m).map(i => ((1.U << i) -> io.in(i))))

}

When I run this code, I receive the following error message:

Exception in thread "main" circt.stage.phases.Exceptions$FirtoolNonZeroExitCode: firtool returned a non-zero exit code. Note that this version of Chisel (5.0.0) was published against firtool version 1.40.0.
------------------------------------------------------------------------------
ExitCode:
1
STDOUT:

STDERR:
<stdin>:43:5: error: Node cannot be analog and must be passive or passive under a flip '!firrtl.bundle<arvalid flip: uint<1>, araddr flip: uint<32>, rready flip: uint<1>, awaddr flip: uint<32>, awvalid flip: uint<1>, wdata flip: uint<32>, wstrb flip: uint<8>, wvalid flip: uint<1>, bready flip: uint<1>>'
    node _io_out_T_3 = mux(_io_out_T_2, io.in[0], defaultOut) @[playground/src/device/AXI/MasterOutMux.scala 36:47]
    ^

------------------------------------------------------------------------------
1 targets failed
playground.test.runMain subprocess failed

I have tried writing the contents of MuxLookup myself, but I still encounter the same issue:

  io.out := MuxLookup(io.selector, io.in(1)) (
    List(
      (1.U << 0) -> io.in(0),
      (1.U << 1) -> io.in(1)
    )
  )

I hope it can successfully compile into Verilog code. If you could provide any clues, I would be very grateful.

1

There are 1 best solutions below

0
Jack Koenig On

I see you asked this question on the Chisel repo, I apologize for not noticing it there.

TLDR: Avoid using direction specifiers inside of Bundles when all fields go the same direction, instead use them outside.

The basic problem is that muxes do not allow flipped values, and if you use Input inside of the definition of a Bundle, you are flipping that field.

Try removing all Input from AXIIn, then flip val in in MasterOutMuxIO and unflip val out.

Here is your code with those fixes applied using the ScalaCLI chisel-template as suggested by the new Install page on the Chisel website:

//> using scala "2.13.12"
//> using lib "org.chipsalliance::chisel::6.0.0"
//> using plugin "org.chipsalliance:::chisel-plugin::6.0.0"
//> using options "-unchecked", "-deprecation", "-language:reflectiveCalls", "-feature", "-Xcheckinit", "-Xfatal-warnings", "-Ywarn-dead-code", "-Ywarn-unused", "-Ymacro-annotations"

import circt.stage.ChiselStage
import chisel3._
import chisel3.util._

class AXIIN extends Bundle {
  val arvalid = Bool()
  val araddr  = UInt(32.W)

  val rready  = Bool()

  val awaddr  = UInt(32.W)
  val awvalid = Bool()

  val wdata   = UInt(32.W)
  val wstrb   = UInt(8.W)
  val wvalid  = Bool()

  val bready  = Bool()
}

class MasterOutMuxIO(nr_m: Int) extends Bundle {
  val in = Flipped(Vec(nr_m, new AXIIN))

  val selector = Input(UInt(nr_m.W)) // The selector is a one-hot code.

  val out = new AXIIN
}

class MasterOutMux(nr_m: Int) extends Module {
  val io = IO(new MasterOutMuxIO(2))
  val sel = io.selector
  
  val defaultOut = Wire(new AXIIN)
  for (enty <- defaultOut.getElements) {
    enty := 0.U
  }
  io.out := MuxLookup(io.selector, defaultOut)(
              (0 until nr_m).map(i => ((1.U << i) -> io.in(i))))

}

object Main extends App {
  println(
    ChiselStage.emitSystemVerilog(
      gen = new MasterOutMux(2),
      firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info")
    )
  )
}