问题描述
我正在尝试将状态机拆分为多个特征,因此每个状态一个特征。 每个状态都有一个子状态机,所以划分会让我的代码更易读。
实际上我在第一个 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))