Muxes and Input Selection

Selecting inputs is very useful in hardware description, and therefore Chisel provides several built-in generic input-selection implementations.


The first one is Mux. This is a 2-input selector. Unlike the Mux2 example which was presented previously, the built-in Mux allows the inputs (in0 and in1) to be any datatype as long as they are the same subclass of Data.

By using the functional module creation feature presented in the previous section, we can create multi-input selector in a simple way:

Mux(c1, a, Mux(c2, b, Mux(..., default)))


The nested Mux is not necessary since Chisel also provides the built-in MuxCase, which implements that exact feature. MuxCase is an n-way Mux, which can be used as follows:

MuxCase(default, Array(c1 -> a, c2 -> b, ...))

Where each selection dependency is represented as a tuple in a Scala array [ condition -> selected_input_port ].


Chisel also provides MuxLookup which is an n-way indexed multiplexer:

MuxLookup(idx, default,
          Array(0.U -> a, 1.U -> b, ...))

This is the same as a MuxCase, where the conditions are all index based selection:

        Array((idx === 0.U) -> a,
              (idx === 1.U) -> b, ...))

Note that the conditions/cases/selectors (eg. c1, c2) must be in parentheses.


Another Mux utility is the one-hot mux, Mux1H. It takes a sequence of selectors and values and returns the value associated with the one selector that is set. If zero or multiple selectors are set the behavior is undefined. For example:

  val hotValue = chisel3.util.Mux1H(Seq(
    io.selector(0) -> 2.U,
    io.selector(1) -> 4.U,
    io.selector(2) -> 8.U,
    io.selector(4) -> 11.U,

Mux1H whenever possible generates Firrtl that is readily optimizable as low depth and/or tree. This optimization is not possible when the values are of type FixedPoint or an aggregate type that contains FixedPoints and results instead as a simple Mux tree. This behavior could be sub-optimal. As FixedPoint is still experimental this behavior may change in the future.