when-otherwise Statement vs. Mux Statement

Viewed 77

I was wondering whether there are any fundamental differences between using the Mux statement vs. using the when-otherwise statement?

For example:

    when(read){ 
       dataReg := inValue
    }.otherwise{
       dataReg := 0.U
    }

Or

    dataReg := Mux (read, inValue, 0.U)

Should there be any preferences for one of them?

1 Answers

You can think about when-otherwise as a higher-level construct that is lowered to one or more Muxes. Mux is useful for simple cases (especially when you'd like the code to fit on 1 line), but there are a lot of things that are more convenient to express with when-otherwise.

For example, when-otherwise can be used to express bidirectional connections in a convenient way that Mux does not allow.

  val producer_1 = IO(Flipped(Decoupled(UInt(8.W))))
  val producer_2 = IO(Flipped(Decoupled(UInt(8.W))))
  val select = IO(Input(Bool()))
  val consumer = IO(Decoupled(UInt(8.W)))

  when(select) {
    consumer <> producer_1
    producer_2.ready := false.B
  } .otherwise {
    consumer <> producer_2
    producer_1.ready := false.B
  }

This generates:

  assign producer_1_ready = select & consumer_ready;
  assign producer_2_ready = select ? 1'h0 : consumer_ready;
  assign consumer_valid = select ? producer_1_valid : producer_2_valid;
  assign consumer_bits = select ? producer_1_bits : producer_2_bits;

(Executable example link: https://scastie.scala-lang.org/GVH1zA2MTQ2fhm4yENijbg)

In addition, when-otherwise can be used for connections to multiple things at the same time:

  val a   = IO(Input(Bool()))
  val b   = IO(Input(Bool()))
  val foo = IO(Input(UInt(8.W)))
  val bar = IO(Input(UInt(8.W)))
  val out = IO(Output(UInt(8.W)))

  val reg1 = RegInit(0.U(8.W))
  val reg2 = RegInit(0.U(8.W))
  
  out := reg1
  when (a) {
    reg1 := foo
  } .elsewhen (b) {
    reg1 := bar
    reg2 := foo
  } .otherwise {
    out := reg2
  }

(Executable example link: https://scastie.scala-lang.org/q9WNZVDoSpufRCyBeukCEg)

Note that there are connections to reg1, reg2, and out on the different paths, and none even show up in every single path.

Related