如何在 Chisel 中将状态机拆分为多个类或特征?

问题描述

我正在尝试将状态机拆分为多个特征,因此每个状态一个特征。 每个状态都有一个子状态机,所以划分会让我的代码更易读。

实际上我在第一个 when 语句中失败了。

我的实际测试代码如下所示:

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

生成 verilog 代码时,它会忽略切换子状态的时间。 所以带有赋值的 verilog“总是”看起来像这样:

  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

我尝试使用状态和子状态 val 的 override 和 protected 修饰符,但它没有任何区别,我不知道如何让它工作。也许 trait 不是正确的构造?

解决方法

好问题。我认为您在构建类的过程中被评估顺序所困扰。在评估惰性值之前执行特征。通过在chisel3 repo 的issues 中搜索可以找到对状态机构造的一些兴趣,你应该在那里闲逛一下。

但为了立即考虑,请查看 This executable example。这是来源,我认为它可能与您要查找的内容很接近。

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