Moving on from Chisel


Once upon a time, I worked at a company that heavily contributed to and used Chisel (a Verilog generator using a Scala DSL). Now, roughly 3 years later, I tried to make a fun little hardware design using Chisel. I remembered that the people who were contributing to Chisel liked to break backward compatibility for no reason at all, so I decided to stick with the version of Chisel that I was using back in 2018 (3.2.x).

Unfortunately, even with that safety measure, I didn’t get far before running into trouble. Here’s my simple design:

class N64DevCartMain() extends Module {
    val io = IO(new Bundle {
        val n64adi = Input(UInt(16.W))
        val n64readn = Input(Bool())
        val n64ale_l = Input(Bool())
        val n64ale_h = Input(Bool())
        val n64ado = Output(UInt(16.W))
        val romAddr = Output(UInt(32.W))
        val romData = Input(UInt(16.W))
    })
    val addr = RegInit(0.U(32.W))
    when (!io.n64ale_h && !RegNext(!io.n64ale_h)) { // ALE_H falling edge
        addr := (addr & "hffff".U) | ((io.n64adi & "hffff".U) << 16)
    }.elsewhen (!io.n64ale_l && !RegNext(!io.n64ale_l)) { // ALE_L falling edge
        addr := (addr & "hffff0000".U) | (io.n64adi & "hffff".U)
    }.elsewhen (io.n64readn && RegNext(!io.n64readn)) { // read rising edge
        addr := addr + 2.U
    }
    io.romAddr := addr;
    io.n64ado := io.romData
}

I wrote a small test for this also:

package N64DevCartMainTesters {
    class ReadWords(dut: N64DevCartMain) extends PeekPokeTester(dut) {
        val delay = 3
        // Set initial state
        poke(dut.io.n64adi, 0.U(16.W))
        poke(dut.io.n64readn, true.B)
        poke(dut.io.n64ale_l, true.B)
        poke(dut.io.n64ale_h, true.B)
        poke(dut.io.romData, 0.U(16.W))
        // Check initial output
        expect(dut.io.romAddr, 0.U(16.W))
        // Change address to 0x12345678
        poke(dut.io.n64adi, "h1234".U(16.W))
        poke(dut.io.n64ale_h, false.B)
        step(delay)
        poke(dut.io.n64adi, "h5678".U(16.W))
        poke(dut.io.n64ale_l, false.B)
        step(delay)
        poke(dut.io.n64readn, false.B)
        step(delay)
        expect(dut.io.romAddr, "h12345678".U(32.W))
    }
}

Unfortunately, this test was flaky, somehow. One in three runs of this test would get an incorrect value in romAddr. Why? Who knows.

I tried updating Chisel3 to the latest version, 3.5.1. But, apparently, the API for instantiating tests was deprecated (in a minor version change!). Here was the test instantiation code:

object Main extends App {
  chisel3.Driver.execute("-td chisel_output".split(" +"), () => new N64DevCartMain())
}

So yeah. I don’t have time for this. What should I try next? Bluespec? MyHDL? SpinalHDL? ROHD? Migen? Clash? There are a ton listed on this page, and I just hope that I can find one that is more stable and than Chisel.


Leave a Reply

%d bloggers like this: