Constructing Hardware in a Scala Embedded Language

Get Started View on GitHub

Chisel is an open-source hardware construction language developed at UC Berkeley that supports advanced hardware design using highly parameterized generators and layered domain-specific hardware languages.

  • Hardware construction language (not C to Gates)
  • Embedded in the Scala programming language
  • Algebraic construction and wiring
  • Abstract data types and interfaces
  • Bulk connections
  • Hierarchical + object oriented + functional construction
  • Highly parameterizable using metaprogramming in Scala
  • Supports layering of domain specific languages
  • Sizeable standard library including floating-point units
  • Multiple clock domains
  • Generates low-level Verilog designed to pass on to standard ASIC or FPGA tools
  • Open source on github with modified BSD license
  • Complete set of docs
  • Growing community of adopters

You can find code examples on the Berkeley EECS Berkeley Architecture Research (BAR) github page. Chisel-tutorial is a set of sample circuits with supporting Sodor is a set of educational processors written in Chisel by Christopher Celio, a PhD student at UC Berkeley. Sodor implements the RISC-V Instruction Set Architecture designed in the BAR group and described on riscv.org.

import chisel3._

class GCD extends Module {
  val io = IO(new Bundle {
    val a  = Input(UInt.width(32))
    val b  = Input(UInt.width(32))
    val e  = Input(Bool())
    val z  = Output(UInt.width(32))
    val v  = Output(Bool())
  })
  val x = Reg(UInt.width( 32))
  val y = Reg(UInt.width( 32))
  when (x > y)   { x := x -% y }
  .otherwise     { y := y -% x }
  when (io.e) { x := io.a; y := io.b }
  io.z := x
  io.v := y === 0.U
}
    
import chisel3._

class MaxN(val n: Int, val w: Int) extends Module {

  private def Max2(x: UInt, y: UInt) = Mux(x > y, x, y)

  val io = IO(new Bundle {
    val ins = Input(Vec(n, UInt(width = w)))
    val out = Output(UInt(width = w))
  })
  io.out := io.ins.reduceLeft(Max2)
}

                                
import chisel3._
import scala.collection.mutable.ArrayBuffer

/** Four-by-four multiply using a look-up table.
*/
class Mul extends Module {
  val io = IO(new Bundle {
    val x   = Input(UInt(width = 4))
    val y   = Input(UInt(width = 4))
    val z   = Output(UInt(width = 8))
  })
  val muls = new ArrayBuffer[UInt]()

  // -------------------------------- \\
  // Calculate io.z = io.x * io.y by
  // building filling out muls
  // -------------------------------- \\

  for (i <- 0 until 16)
    for (j <- 0 until 16)
      muls += UInt(i * j, width = 8)
  val tbl = Vec(muls)
  io.z := tbl((io.x << 4.U) | io.y)
}

                                
import chisel3._
import chisel3.util._

//A n-bit adder with carry in and carry out
class Adder(val n:Int) extends Module {
  val io = IO(new Bundle {
    val A    = Input(UInt(width=n))
    val B    = Input(UInt(width=n))
    val Cin  = Input(UInt(width=1))
    val Sum  = Output(UInt(width=n))
    val Cout = Output(UInt(width=1))
  })
  //create a vector of FullAdders
  val FAs   = Vec.fill(n)(Module(new FullAdder()).io)
  val carry = Wire(Vec(n+1, UInt(width = 1)))
  val sum   = Wire(Vec(n, Bool()))

  //first carry is the top level carry in
  carry(0) := io.Cin

  //wire up the ports of the full adders
  for (i <- 0 until n) {
    FAs(i).a := io.A(i)
    FAs(i).b := io.B(i)
    FAs(i).cin := carry(i)
    carry(i+1) := FAs(i).cout
    sum(i) := FAs(i).sum.toBool()
  }
  io.Sum := Cat(sum.reverse)
  io.Cout := carry(n)
}

Getting started with Chisel is easy. Its DSL is built on familiar concepts. Boilerplate verilog often directly maps to Chisel one-liners. Integration with the Scala language simplifies the expression of complicated circuits.

Chisel is released as a collection of JARs file published through the official Maven repo. Clone the Chisel Tutorial repo and be running Chisel right away.

Chisel uses the Scala Language