Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Split a State Machine in multiple Classes or Traits in Chisel?

Tags:

scala

chisel

I'm trying to split a state machine into several traits, so one trait per state. Each state has a substate machine, so the division would make the code more readable for me.

Actually I'm failing at the first when statement.

My actual Test Code looks like this:

class A extends Module with B{
    val io = IO(
        new Bundle{
            val state = Output(UInt(2.W))
            val substate = Output(UInt(2.W))
        }
    )

    lazy val state = RegInit(0.U(2.W))
    lazy val substate = RegInit(0.U(2.W))
    io.state := state
    io.substate := substate
}

trait B{
    def state : UInt
    def substate : UInt

    when(state === 0.U){
        state := 1.U
        substate := ~substate
    }
}

When generating the verilog code it ignores the when for the toggling of the substate. So the verilog "always" with the assignments looks like this:

  assign _T_7 = state == 2'h0; // @[traittest.scala 25:16:@9.4]
  assign _T_11 = ~ substate; // @[traittest.scala 27:21:@13.6]
  always @(posedge clock) begin
    if (reset) begin
      state <= 2'h0;
    end else begin
      if (_T_7) begin
        state <= 2'h1;
      end
    end
    if (reset) begin
      substate <= 2'h0;
    end else begin
      substate <= _T_11;
    end
  end

I tried it with the override and protected modifiers for the state and substate val's but it doesn't make a difference and I have no other idea how to get it working. Perhaps traits aren't the right constructs for that?

like image 605
julian Avatar asked Nov 20 '25 23:11

julian


1 Answers

Good question. I think you are being bitten by order of evaluation during the construction of your classes. The traits get executed before the lazy vals are evaluated. There has been some interest in state machine construction that can be found by searching in the issues of the chisel3 repo, you should poke around there a little.

But for immediate consideration take a look at This executable example. This is the source, I think it might be close to what you are looking for.

import chisel3._
import chisel3.stage.ChiselStage
import chiseltest._
import chiseltest.experimental.ChiselTestShell

trait State {
  def state: UInt
  def substate: UInt
}

class A extends Module with State {
    val io = IO(
        new Bundle{
            val state = Output(UInt(2.W))
            val substate = Output(UInt(2.W))
        }
    )

    val state = RegInit(0.U(2.W))
    val substate = RegInit(0.U(2.W))
  
    new B(state, substate)
    new C(state, substate)
  
    io.state := state
    io.substate := substate
}

class B(val state: UInt, val substate: UInt) extends State {
    when(state === 0.U){
        state := 1.U
        substate := ~substate
    }
}

class C(val state: UInt, val substate: UInt) extends State {
    when(state === 1.U){
        state := 2.U
        substate := substate + 1.U
    }
}

println((new ChiselStage()).emitVerilog(new A))
like image 139
Chick Markley Avatar answered Nov 23 '25 08:11

Chick Markley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!