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.
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:
// Generated by CIRCT firtool-1.37.0
module Blinky(
input clock,
reset,
output io_led0
);
reg led;
reg [8:0] counterWrap_c_value;
always @(posedge clock) begin
if (reset) begin
led <= 1'h0;
counterWrap_c_value <= 9'h0;
end
else begin
automatic logic counterWrap = counterWrap_c_value == 9'h1F3;
led <= counterWrap ^ led;
if (counterWrap)
counterWrap_c_value <= 9'h0;
else
counterWrap_c_value <= counterWrap_c_value + 9'h1;
end
end // always @(posedge)
assign io_led0 = led;
endmodule
Consider an FIR filter that implements a convolution operation, as depicted in this block diagram:
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)
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.
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, Chinese, Japanese, and Vietnamese.
Please see the Installation page of the Chisel website for information about how to use Chisel locally.
When you're ready to build your own circuits in Chisel, we recommend starting from the Chisel Template repository, which provides a pre-configured project, example design, and testbench. Follow the chisel-template README to get started.
If you insist on setting up your own project from scratch, your project needs to depend on both the chisel-plugin (Scalac plugin) and the chisel library. For example, in SBT this could be expressed as:
// build.sbt
scalaVersion := "2.13.12"
val chiselVersion = "6.0.0"
addCompilerPlugin("org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full)
libraryDependencies += "org.chipsalliance" %% "chisel" % chiselVersion
For Chisel prior to v5.0.0, Chisel was published using a different artifact name:
// build.sbt
scalaVersion := "2.13.10"
addCompilerPlugin("edu.berkeley.cs" % "chisel3-plugin" % "3.6.0" cross CrossVersion.full)
libraryDependencies += "edu.berkeley.cs" %% "chisel3" % "3.6.0"
// We also recommend using chiseltest for writing unit tests
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.6.0" % "test"
If you are trying to make a contribution to this project, please read CONTRIBUTING.md.
These simulation-based verification tools are available for Chisel:
fork
and join
with internal and Verilator integration for simulations.If you are migrating from Chisel2, see the migration guide.
Chisel/FIRRTL development meetings happen every Monday from 9:00-10:00 am PT.
Call-in info and meeting notes are available here.
These are the base data types for defining circuit components:
This section describes how to get started contributing to Chisel itself, including how to test your version locally against other projects that pull in Chisel using sbt's managed dependencies.
The Useful Resources for users are also helpful for contributors.
You must first install required dependencies to build Chisel locally, please see the installation instructions.
Clone and build the Chisel library:
git clone https://github.com/chipsalliance/chisel.git
cd chisel
sbt compile
In order to run the following unit tests, you will need several tools on your PATH
, namely
verilator,
yosys,
and espresso.
Check that each is installed on your PATH
by running which verilator
and so on.
If the compilation succeeded and the dependencies noted above are installed, you can then run the included unit tests by invoking:
sbt test
To use the development version of Chisel (main
branch), you will need to build from source and publish locally.
The repository version can be found by running sbt version
.
As of the time of writing it was: 6.0.0+1-8d92842c-SNAPSHOT
.
To publish your version of Chisel to the local Ivy (sbt's dependency manager) repository, run:
sbt "unipublish / publishLocal"
The compiled version gets placed in ~/.ivy2/local/org.chipsalliance/
.
If you need to un-publish your local copy of Chisel, remove the directory generated in ~/.ivy2/local/org.chipsalliance/
.
In order to have your projects use this version of Chisel, you should update the libraryDependencies
setting in your project's build.sbt file to use the current version, for example:
val chiselVersion = "6.0.0+1-8d92842c-SNAPSHOT"
addCompilerPlugin("org.chipsalliance" % "chisel-plugin" % chiselVersion cross CrossVersion.full)
libraryDependencies += "org.chipsalliance" %% "chisel" % chiselVersion
The Chisel compiler consists of these main parts:
chisel3.*
, which is the publicly visible "API" of Chisel and what is used in Chisel RTL. These just add data to the...chisel3.internal.Builder
, which maintains global state (like the currently open Module) and contains commands, generating...chisel3.firrtl.*
, which are syntactically very similar to Firrtl. Once the entire circuit has been elaborated, the top-level object (a Circuit
) is then passed to...chisel3.firrtl.Emitter
, which turns the intermediate data structures into a string that can be written out into a Firrtl file for further processing.Also included is:
chisel3.util.*
. These contain commonly used interfaces and constructors (like Decoupled
, which wraps a signal with a ready-valid pair) as well as fully parameterizable circuit generators (like arbiters and multiplexors).chisel3.stage.*
, which contains compilation and test functions that are invoked in the standard Verilog generation and simulation testing infrastructure. These can also be used as part of custom flows.Chisel consists of several Scala projects; each is its own separate compilation unit:
core
is the bulk of the source code of Chisel, depends on firrtl
, svsim
, and macros
firrtl
is the vestigial remains of the old Scala FIRRTL compiler, much if it will likely be absorbed into core
macros
is most of the macros used in Chisel, no internal dependenciesplugin
is the compiler plugin, no internal dependenciessrc/main
is the "main" that brings it all together and includes a util
library, which depends on core
svsim
is a low-level library for compiling and controlling SystemVerilog simulations, currently targeting Verilator and VCS as backendsCode that touches lots of APIs that are private to the chisel3
package should belong in core
, while code that is pure Chisel should belong in src/main
.
We encourage Chisel users (as opposed to Chisel developers), to use the latest release version of Chisel. This chisel-template repository is kept up-to-date, depending on the most recent version of Chisel. The recommended version is also captured near the top of this README, and in the Github releases section of this repo. If you encounter an issue with a released version of Chisel, please file an issue on GitHub mentioning the Chisel version and provide a simple test case (if possible). Try to reproduce the issue with the associated latest minor release (to verify that the issue hasn't been addressed).
For more information on our versioning policy and what versions of the various Chisel ecosystem projects work together, see Chisel Project Versioning.
If you're developing a Chisel library (or chisel3
itself), you'll probably want to work closer to the tip of the development trunk.
By default, the main branch of the chisel repository is configured to build and publish its version of the code as <version>+<n>-<commit hash>-SNAPSHOT
.
Updated SNAPSHOTs are publised on every push to main.
You are encouraged to do your development against the latest SNAPSHOT, but note that neither API nor ABI compatibility is guaranteed so your code may break at any time.
See Roadmap.