Chisel3存储单元模块寄存器值不持久化、写后读测试失败问题排查
问题原因
你遇到的问题由以下几个错误共同导致:
- 信号名不匹配:你在接口
MemristorCellBundle中定义的写控制信号名为writeBus,但模块内部错误引用了不存在的io.voltageBus,测试代码中也错误调用了c.io.write,命名不一致属于低级笔误。 - 未明确指定位宽:中间信号
write、寄存器internalValue定义时都没有指定位宽,Chisel自动推断位宽可能出现不符合预期的结果。 - 最核心问题:测试未触发时钟沿:Chisel中
Reg类型是时钟沿触发的寄存器,只有时钟发生跳变时,组合逻辑的赋值才会写入寄存器的存储单元。你的测试代码所有操作都在同一个时钟周期内完成,写入5的操作没有触发时钟沿,寄存器internalValue的值从来没有被真正更新,一直保持初始的0值。
修复方案
首先修正模块代码的命名、位宽问题,可选给寄存器添加复位初始值保证初始状态可控:
class MemristorCellBundle() extends Bundle { val writeBus = Input(UInt(1.W)) val dataBus = Input(UInt(8.W)) val cellBus = Output(UInt(8.W)) } class MemCell() extends Module { val io = IO(new MemristorCellBundle()) // 修正信号名,明确指定位宽 val write = Wire(UInt(1.W)) write := io.writeBus // 明确寄存器位宽,设置复位初始值为0 val internalValue = RegInit(UInt(8.W), 0.U) when(write === 1.U) { internalValue := io.dataBus io.cellBus := io.dataBus } .otherwise { io.cellBus := internalValue } }
然后修改测试代码,写入操作后步进一个时钟周期,触发寄存器更新:
class MemCellTest extends FlatSpec with ChiselScalatestTester with Matchers { behavior of "MemCell" it should "read and write" in { test(new MemCell()) { c => c.io.dataBus.poke(5.U) c.io.writeBus.poke(0.U) c.io.cellBus.expect(0.U) // 写入操作 c.io.dataBus.poke(5.U) c.io.writeBus.poke(1.U) c.io.cellBus.expect(5.U) // 步进一个时钟,触发寄存器把5写入存储单元 c.clock.step(1) // 验证写后读 c.io.dataBus.poke(12.U) c.io.writeBus.poke(0.U) c.io.cellBus.expect(5.U) } } }
如果你的场景不需要复位逻辑,也可以用Reg(UInt(8.W))定义寄存器,但必须保证寄存器被使用前至少完成一次有效写入,否则初始值为未定义状态,仿真可能出现随机值。
内容的提问来源于stack exchange,提问作者Nick Felker
相关产品推荐
相关产品推荐

