Welcome to the Chisel cookbook. This cookbook is still in early stages. If you have any requests or examples to share, please file an issue and let us know!

Please note that these examples make use of Chisel’s scala-style printing.

Converting Chisel Types to/from UInt

How do I create a UInt from an instance of a Bundle?

Call asUInt on the Bundle instance.

import chisel3._

class MyBundle extends Bundle {
  val foo = UInt(4.W)
  val bar = UInt(4.W)
}

class Foo extends RawModule {
  val bundle = Wire(new MyBundle)
  bundle.foo := 0xc.U
  bundle.bar := 0x3.U
  val uint = bundle.asUInt
}

How do I create a Bundle from a UInt?

Use the asTypeOf method to reinterpret the UInt as the type of the Bundle.

import chisel3._

class MyBundle extends Bundle {
  val foo = UInt(4.W)
  val bar = UInt(4.W)
}

class Foo extends RawModule {
  val uint = 0xb4.U
  val bundle = uint.asTypeOf(new MyBundle)
}

How do I create a Vec of Bools from a UInt?

Use VecInit given a Seq[Bool] generated using the asBools method.

import chisel3._

class Foo extends RawModule {
  val uint = 0xc.U
  val vec = VecInit(uint.asBools)
}

How do I create a UInt from a Vec of Bool?

Use the builtin function asUInt

import chisel3._

class Foo extends RawModule {
  val vec = VecInit(true.B, false.B, true.B, true.B)
  val uint = vec.asUInt
}

Vectors and Registers

How do I create a Vector of Registers?

Rule! Use Reg of Vec not Vec of Reg!

You create a Reg of type Vec. Because Vecs are a type (like UInt, Bool) rather than a value, we must bind the Vec to some concrete value.

How do I create a Reg of type Vec?

For more information, the API Documentation for Vec provides more information.

import chisel3._

class Foo extends RawModule {
  val regOfVec = Reg(Vec(4, UInt(32.W))) // Register of 32-bit UInts
  regOfVec(0) := 123.U                   // Assignments to elements of the Vec
  regOfVec(1) := 456.U
  regOfVec(2) := 789.U
  regOfVec(3) := regOfVec(0)

  // Reg of Vec of 32-bit UInts initialized to zero
  //   Note that Seq.fill constructs 4 32-bit UInt literals with the value 0
  //   VecInit(...) then constructs a Wire of these literals
  //   The Reg is then initialized to the value of the Wire (which gives it the same type)
  val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W))))
}

How do I create a finite state machine (FSM)?

The advised way is to use ChiselEnum to construct enumerated types representing the state of the FSM. State transitions are then handled with switch/is and when/.elsewhen/.otherwise.

import chisel3._
import chisel3.util._
import chisel3.experimental.ChiselEnum

object DetectTwoOnes {
  object State extends ChiselEnum {
    val sNone, sOne1, sTwo1s = Value
  }
}

/* This FSM detects two 1's one after the other */
class DetectTwoOnes extends Module {
  import DetectTwoOnes.State
  import DetectTwoOnes.State._

  val io = IO(new Bundle {
    val in = Input(Bool())
    val out = Output(Bool())
    val state = Output(State())
  })

  val state = RegInit(sNone)

  io.out := (state === sTwo1s)
  io.state := state

  switch (state) {
    is (sNone) {
      when (io.in) {
        state := sOne1
      }
    }
    is (sOne1) {
      when (io.in) {
        state := sTwo1s
      } .otherwise {
        state := sNone
      }
    }
    is (sTwo1s) {
      when (!io.in) {
        state := sNone
      }
    }
  }
}

Note: the is statement can take multiple conditions e.g. is (sTwo1s, sOne1) { ... }.

How do I unpack a value (“reverse concatenation”) like in Verilog?

In Verilog, you can do something like the following which will unpack a the value z:

wire [1:0] a;
wire [3:0] b;
wire [2:0] c;
wire [8:0] z = [...];
assign {a,b,c} = z;

Unpacking often corresponds to reinterpreting an unstructured data type as a structured data type. Frequently, this structured type is used prolifically in the design, and has been declared as in the following example:

import chisel3._

class MyBundle extends Bundle {
  val a = UInt(2.W)
  val b = UInt(4.W)
  val c = UInt(3.W)
}

The easiest way to accomplish this in Chisel would be:

class Foo extends RawModule {
  val z = Wire(UInt(9.W))
  z := DontCare // This is a dummy connection
  val unpacked = z.asTypeOf(new MyBundle)
  unpacked.a
  unpacked.b
  unpacked.c
}

If you really need to do this for a one-off case (Think thrice! It is likely you can better structure the code using bundles), then rocket-chip has a Split utility which can accomplish this.

How do I do subword assignment (assign to some bits in a UInt)?

You may try to do something like the following where you want to assign only some bits of a Chisel type. Below, the left-hand side connection to io.out(0) is not allowed.

import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}

class Foo extends Module {
  val io = IO(new Bundle {
    val bit = Input(Bool())
    val out = Output(UInt(10.W))
  })
  io.out(0) := io.bit
}

If you try to compile this, you will get an error.

(new ChiselStage).execute(Array("-X", "verilog"), Seq(new ChiselGeneratorAnnotation(() => new Foo)))
// firrtl.options.StageError: 
// 	at chisel3.stage.ChiselStage.run(ChiselStage.scala:47)
// 	at firrtl.options.Stage$$anon$1.transform(Stage.scala:43)
// 	at firrtl.options.Stage$$anon$1.transform(Stage.scala:43)
// 	at firrtl.options.phases.DeletedWrapper.internalTransform(DeletedWrapper.scala:32)
// 	at firrtl.options.phases.DeletedWrapper.internalTransform(DeletedWrapper.scala:15)
// 	at firrtl.options.Translator.transform(Phase.scala:140)
// 	at firrtl.options.Translator.transform$(Phase.scala:140)
// 	at firrtl.options.phases.DeletedWrapper.transform(DeletedWrapper.scala:15)
// 	at firrtl.options.Stage.$anonfun$transform$5(Stage.scala:46)
// 	at scala.collection.LinearSeqOptimized.foldLeft(LinearSeqOptimized.scala:122)
// 	at scala.collection.LinearSeqOptimized.foldLeft$(LinearSeqOptimized.scala:118)
// 	at scala.collection.immutable.List.foldLeft(List.scala:86)
// 	at firrtl.options.Stage.$anonfun$transform$3(Stage.scala:46)
// 	at logger.Logger$.$anonfun$makeScope$2(Logger.scala:168)
// 	at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
// 	at logger.Logger$.makeScope(Logger.scala:166)
// 	at firrtl.options.Stage.transform(Stage.scala:46)
// 	at firrtl.options.Stage.execute(Stage.scala:57)
// 	at repl.Session$App7$$anonfun$12.apply(cookbook.md:216)
// 	at repl.Session$App7$$anonfun$12.apply(cookbook.md:216)

Chisel3 does not support subword assignment. The reason for this is that subword assignment generally hints at a better abstraction with an aggregate/structured types, i.e., a Bundle or a Vec.

If you must express it this way, one approach is to blast your UInt to a Vec of Bool and back:

import chisel3._

class Foo extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(10.W))
    val bit = Input(Bool())
    val out = Output(UInt(10.W))
  })
  val bools = VecInit(io.in.asBools)
  bools(0) := io.bit
  io.out := bools.asUInt
}

How can I dynamically set/parametrize the name of a module?

You can override the desiredName function. This works with normal Chisel modules and BlackBoxes. Example:

import chisel3._

class Coffee extends BlackBox {
    val io = IO(new Bundle {
        val I = Input(UInt(32.W))
        val O = Output(UInt(32.W))
    })
    override def desiredName = "Tea"
}

class Salt extends Module {
    val io = IO(new Bundle {})
    val drink = Module(new Coffee)
    override def desiredName = "SodiumMonochloride"
}

Elaborating the Chisel module Salt yields our “desire name” for Salt and Coffee in the output Verilog:

[info] [0.000] Elaborating design… [info] [0.059] Done elaborating.

module SodiumMonochloride(
  input   clock,
  input   reset
);
  wire [31:0] drink_I; // @[cookbook.md 261:23]
  wire [31:0] drink_O; // @[cookbook.md 261:23]
  Tea drink ( // @[cookbook.md 261:23]
    .I(drink_I),
    .O(drink_O)
  );
  assign drink_I = 32'h0;
endmodule

How do I create an optional I/O?

The following example is a module which includes the optional port out2 only if the given parameter is true.

import chisel3._

class ModuleWithOptionalIOs(flag: Boolean) extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(12.W))
    val out = Output(UInt(12.W))
    val out2 = if (flag) Some(Output(UInt(12.W))) else None
  })

  io.out := io.in
  if (flag) {
    io.out2.get := io.in
  }
}

How do I get Chisel to name signals properly in blocks like when/withClockAndReset?

To get Chisel to name signals (wires and registers) declared inside of blocks like when, withClockAndReset, etc, use the @chiselName annotation as shown below:

import chisel3._
import chisel3.experimental.chiselName

@chiselName
class TestMod extends Module {
  val io = IO(new Bundle {
    val a = Input(Bool())
    val b = Output(UInt(4.W))
  })
  when (io.a) {
    val innerReg = RegInit(5.U(4.W))
    innerReg := innerReg + 1.U
    io.b := innerReg
  } .otherwise {
    io.b := 10.U
  }
}

Note that you will need to add the following line to your project’s build.sbt file.

addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)

If we compile this module without @chiselName, Chisel is not able to name innerReg correctly (notice the _T):

[info] [0.000] Elaborating design… [info] [0.049] Done elaborating.

module TestMod(
  input        clock,
  input        reset,
  input        io_a,
  output [3:0] io_b
);
  reg [3:0] _T; // @[cookbook.md 356:27]
  reg [31:0] _RAND_0;
  wire [3:0] _T_2; // @[cookbook.md 357:26]
  assign _T_2 = _T + 4'h1; // @[cookbook.md 357:26]
  assign io_b = io_a ? _T : 4'ha; // @[cookbook.md 358:10 cookbook.md 360:10]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
  integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{`RANDOM}};
  _T = _RAND_0[3:0];
  `endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock) begin
    if (reset) begin
      _T <= 4'h5;
    end else begin
      _T <= _T_2;
    end
  end
endmodule

However, if we use @chiselName then the register previously called _T is now innerReg:

[info] [0.001] Elaborating design… [info] [0.034] Done elaborating.

module TestMod(
  input        clock,
  input        reset,
  input        io_a,
  output [3:0] io_b
);
  reg [3:0] innerReg; // @[cookbook.md 328:27]
  reg [31:0] _RAND_0;
  wire [3:0] _T_1; // @[cookbook.md 329:26]
  assign _T_1 = innerReg + 4'h1; // @[cookbook.md 329:26]
  assign io_b = io_a ? innerReg : 4'ha; // @[cookbook.md 330:10 cookbook.md 332:10]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
  integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
  `ifdef RANDOMIZE
    `ifdef INIT_RANDOM
      `INIT_RANDOM
    `endif
    `ifndef VERILATOR
      `ifdef RANDOMIZE_DELAY
        #`RANDOMIZE_DELAY begin end
      `else
        #0.002 begin end
      `endif
    `endif
  `ifdef RANDOMIZE_REG_INIT
  _RAND_0 = {1{`RANDOM}};
  innerReg = _RAND_0[3:0];
  `endif // RANDOMIZE_REG_INIT
  `endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
  always @(posedge clock) begin
    if (reset) begin
      innerReg <= 4'h5;
    end else begin
      innerReg <= _T_1;
    end
  end
endmodule