Chisel
Chisel: A Modern Hardware Design Language
Install / Use
/learn @chipsalliance/ChiselREADME
The Constructing Hardware in a Scala Embedded Language (Chisel) is an open-source hardware description language (HDL) used to describe digital electronics and circuits at the register-transfer level that facilitates advanced circuit generation and design reuse for both ASIC and FPGA digital logic designs.
Chisel adds hardware construction primitives to the Scala programming language, providing designers with the power of a modern programming language to write complex, parameterizable circuit generators that produce synthesizable Verilog. This generator methodology enables the creation of re-usable components and libraries, such as the FIFO queue and arbiters in the Chisel Standard Library, raising the level of abstraction in design while retaining fine-grained control.
For more information on the benefits of Chisel see: "What benefits does Chisel offer over classic Hardware Description Languages?"
Chisel is powered by FIRRTL (Flexible Intermediate Representation for RTL), a hardware compiler framework implemented by LLVM CIRCT.
Chisel is permissively licensed (Apache 2.0) under the guidance of CHIPS Alliance.
What does Chisel code look like?
LED blink
import chisel3._
import chisel3.util.Counter
import circt.stage.ChiselStage
class Blinky(freq: Int, startOn: Boolean = false) extends Module {
val io = IO(new Bundle {
val led0 = Output(Bool())
})
// Blink LED every second using Chisel built-in util.Counter
val led = RegInit(startOn.B)
val (_, counterWrap) = Counter(true.B, freq / 2)
when(counterWrap) {
led := ~led
}
io.led0 := led
}
object Main extends App {
// These lines generate the Verilog output
println(
ChiselStage.emitSystemVerilog(
new Blinky(1000),
firtoolOpts = Array("-disable-all-randomization", "-strip-debug-info")
)
)
}
Should output the following Verilog:
<!-- Note that you can regenerate the HTML below by using VSCode with extensions: * Markdown All in One: https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one * Verilog-HDL/SystemVerilog/Bluespec SystemVerilog: https://marketplace.visualstudio.com/items?itemName=mshr-h.VerilogHDL You then generate the Verilog and place it in a syntax highlighted code block in this file, eg. ```verilog ... ``` You can then run the command: > Markdown All in One: Print current document to HTML Then you can open the generated HTML and copy-paste --> <details> <summary>Click to expand!</summary></code></pre>
<pre><code class="language-verilog"><span class="hljs-comment">// Generated by CIRCT firtool-1.37.0</span> <span class="hljs-keyword">module</span> Blinky( <span class="hljs-keyword">input</span> clock, reset, <span class="hljs-keyword">output</span> io_led0 ); <span class="hljs-keyword">reg</span> led; <span class="hljs-keyword">reg</span> [<span class="hljs-number">8</span>:<span class="hljs-number">0</span>] counterWrap_c_value; <span class="hljs-keyword">always</span> @(<span class="hljs-keyword">posedge</span> clock) <span class="hljs-keyword">begin</span> <span class="hljs-keyword">if</span> (reset) <span class="hljs-keyword">begin</span> led <= <span class="hljs-number">1'h0</span>; counterWrap_c_value <= <span class="hljs-number">9'h0</span>; <span class="hljs-keyword">end</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">begin</span> <span class="hljs-keyword">automatic</span> <span class="hljs-keyword">logic</span> counterWrap = counterWrap_c_value == <span class="hljs-number">9'h1F3</span>; led <= counterWrap ^ led; <span class="hljs-keyword">if</span> (counterWrap) counterWrap_c_value <= <span class="hljs-number">9'h0</span>; <span class="hljs-keyword">else</span> counterWrap_c_value <= counterWrap_c_value + <span class="hljs-number">9'h1</span>; <span class="hljs-keyword">end</span> <span class="hljs-keyword">end</span> <span class="hljs-comment">// always @(posedge)</span> <span class="hljs-keyword">assign</span> io_led0 = led; <span class="hljs-keyword">endmodule</span> </code></pre> </details>FIR Filter
Consider an FIR filter that implements a convolution operation, as depicted in this block diagram:
<img src="https://raw.githubusercontent.com/chipsalliance/chisel/main/docs/src/images/fir_filter.svg?sanitize=true" width="512" />While Chisel provides similar base primitives as synthesizable Verilog, and could be used as such:
// 3-point moving sum implemented in the style of a FIR filter
class MovingSum3(bitWidth: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(bitWidth.W))
val out = Output(UInt(bitWidth.W))
})
val z1 = RegNext(io.in)
val z2 = RegNext(z1)
io.out := (io.in * 1.U) + (z1 * 1.U) + (z2 * 1.U)
}
the power of Chisel comes from the ability to create generators, such as an FIR filter that is defined by the list of coefficients:
// Generalized FIR filter parameterized by the convolution coefficients
class FirFilter(bitWidth: Int, coeffs: Seq[UInt]) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(bitWidth.W))
val out = Output(UInt(bitWidth.W))
})
// Create the serial-in, parallel-out shift register
val zs = Reg(Vec(coeffs.length, UInt(bitWidth.W)))
zs(0) := io.in
for (i <- 1 until coeffs.length) {
zs(i) := zs(i-1)
}
// Do the multiplies
val products = VecInit.tabulate(coeffs.length)(i => zs(i) * coeffs(i))
// Sum up the products
io.out := products.reduce(_ + _)
}
and use and re-use them across designs:
val movingSum3Filter = Module(new FirFilter(8, Seq(1.U, 1.U, 1.U))) // same 3-point moving sum filter as before
val delayFilter = Module(new FirFilter(8, Seq(0.U, 1.U))) // 1-cycle delay as a FIR filter
val triangleFilter = Module(new FirFilter(8, Seq(1.U, 2.U, 3.U, 2.U, 1.U))) // 5-point FIR filter with a triangle impulse response
The above can be converted to Verilog using ChiselStage:
import chisel3.stage.ChiselGeneratorAnnotation
import circt.stage.{ChiselStage, FirtoolOption}
(new ChiselStage).execute(
Array("--target", "systemverilog"),
Seq(ChiselGeneratorAnnotation(() => new FirFilter(8, Seq(1.U, 1.U, 1.U))),
FirtoolOption("--disable-all-randomization"))
)
Alternatively, you may generate some Verilog directly for inspection:
val verilogString = chisel3.getVerilogString(new FirFilter(8, Seq(0.U, 1.U)))
println(verilogString)
Getting Started
Bootcamp Interactive Tutorial
The online Chisel Bootcamp is the recommended way to get started with and learn Chisel. No setup is required (it runs in the browser), nor does it assume any prior knowledge of Scala.
The classic Chisel tutorial contains small exercises and runs on your computer.
A Textbook on Chisel
If you like a textbook to learn Chisel and also a bit of digital design in general, you may be interested in reading Digital Design with Chisel. It is available in English, Chi
