This post is about getting started with Chisel which is scala based design library.

Scala Hello world Link to heading

First we need to install some packages. Most important one is probably java.

sudo apt install openjdk-8-jdk git make gtkwave

I found the apt scala version is too old and it fails on Mint 12. So i got the binaries for scala. Now, we can run hello world

scala hello.scala

Similar to installing scala, sbt binaries needs to be installed and added to path.

First, we need to project with scala3.g8 with name ex

$ sbt new

 b) typelevel/toolkit.local           - Toolkit to start building Typelevel apps
 c) sbt/cross-platform.local          - A cross-JVM/JS/Native project
 d) scala/scala3.g8                   - Scala 3 seed template
 e) scala/scala-seed.g8               - Scala 2 seed template
 f) playframework/play-scala-seed.g8  - A Play project in Scala
 g) playframework/play-java-seed.g8   - A Play project in Java
 i) softwaremill/tapir.g8             - A tapir project using Netty
 m) scala-js/vite.g8                  - A Scala.JS + Vite project
 n) holdenk/sparkProjectTemplate.g8   - A Scala Spark project
 o) spotify/scio.g8                   - A Scio project
 p) disneystreaming/smithy4s.g8       - A Smithy4s project
 q) quit
Select a template: d

A template to demonstrate a minimal Scala 3 application 

name [Scala 3 Project Template]: ex  

$ cd ex

To run the sbt project

sbt run

The output as follows

[info] running hello 
Hello world!
I was compiled by Scala 3. :)
[success] Total time: 2 s, completed 3 Apr 2025, 23:02:49

Chisel Hello world Link to heading

I am using older version of chisel 3.6.1. So, I had cryptic messages that pointed to firtool 1.37.0 we need to install firtool in PATH.

The directory structure should look like this:

├── build.sbt
├── Makefile
└── src
    └── main
        └── scala
            └── blinky
                └── Blinky.scala

So, we need to create build.sbt to point to chisel

$ more build.sbt 
scalaVersion := "2.13.14"
val chiselVersion = "3.6.1"
addCompilerPlugin("edu.berkeley.cs" %% "chisel3-plugin" % chiselVersion cross CrossVersion.full)
libraryDependencies += "edu.berkeley.cs" %% "chisel3" % chiselVersion
libraryDependencies += "edu.berkeley.cs" %% "chiseltest" % "0.6.2"

To confirm things work, we can run sbt in console mode and import chisel

sbt console
scala> import chisel3._
import chisel3._

scala> Bits
val res0: chisel3.Bits.type = chisel3.package$Bits$@185a2b97

Then, Blinky Modules can be defined as follows:

$ more src/main/scala/blinky/Blinky.scala 
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")
    )
  )
}

Finally, we have generated verilog. That was easy.

// 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