Chisel 在模块中保留值直到新写入
Chisel persist value in module until new write
我创建了一个基本模块,用于表示 Chisel3 中的一个内存单元:
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 MemCellBundle())
val write = Wire(UInt())
write := io.voltageBus
val internalValue = Reg(UInt())
// More than 50% of total voltage in (255).
when(write === 1.U) {
internalValue := io.dataBus
io.cellBus := io.dataBus
} .otherwise {
io.cellBus := internalValue
}
}
我想要的是当write
总线为逻辑低电平时输出internalValue
,并用逻辑高电平改变这个值。我对Chisel的理解是寄存器可以在时钟周期之间持久化这个internalValue
,所以这基本上充当了一个内存单元。
作为一个更大项目的一部分,我正在这样做。但是,在编写单元测试时,我发现 'read-after-write' 场景失败了。
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.write.poke(0.U)
c.io.cellBus.expect(0.U)
// Write
c.io.dataBus.poke(5.U)
c.io.write.poke(1.U)
c.io.cellBus.expect(5.U)
// Verify read-after-write
c.io.dataBus.poke(12.U)
c.io.write.poke(0.U)
c.io.cellBus.expect(5.U)
}
}
}
前两个预期的效果与我预期的一样。但是,当我在写完之后尝试阅读时,cellBus
returns 变成了 0
而不是坚持我之前写的 5
。
test MemCell Success: 0 tests passed in 1 cycles in 0.035654 seconds 28.05 Hz
[info] MemCellTest:
[info] MemCell
[info] - should read and write *** FAILED ***
[info] io_cellBus=0 (0x0) did not equal expected=5 (0x5) (lines in MyTest.scala: 10) (MyTest.scala:21)
显然寄存器没有保存这个值,因此 internalValue
恢复为 0
。但为什么会发生这种情况,我如何才能创造出可以持续存在的价值?
Drakinite 的评论是正确的。您需要确保步进时钟才能看到寄存器锁存值。我调整了您的测试以包括几个步骤并且它按预期工作:
c.io.dataBus.poke(5.U)
c.io.writeBus.poke(0.U)
c.io.cellBus.expect(0.U)
c.clock.step() // Added step
// Write passthrough (same cycle)
c.io.dataBus.poke(5.U)
c.io.writeBus.poke(1.U)
c.io.cellBus.expect(5.U)
c.clock.step() // Added step
// Verify read-after-write
c.io.dataBus.poke(12.U)
c.io.writeBus.poke(0.U)
c.io.cellBus.expect(5.U)
这里是一个可执行示例,显示它有效(使用 chisel3 v3.4.4 和 chiseltest v0.3.4):https://scastie.scala-lang.org/5E1rOEsYSzSUrLXZCvoyNA
我创建了一个基本模块,用于表示 Chisel3 中的一个内存单元:
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 MemCellBundle())
val write = Wire(UInt())
write := io.voltageBus
val internalValue = Reg(UInt())
// More than 50% of total voltage in (255).
when(write === 1.U) {
internalValue := io.dataBus
io.cellBus := io.dataBus
} .otherwise {
io.cellBus := internalValue
}
}
我想要的是当write
总线为逻辑低电平时输出internalValue
,并用逻辑高电平改变这个值。我对Chisel的理解是寄存器可以在时钟周期之间持久化这个internalValue
,所以这基本上充当了一个内存单元。
作为一个更大项目的一部分,我正在这样做。但是,在编写单元测试时,我发现 'read-after-write' 场景失败了。
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.write.poke(0.U)
c.io.cellBus.expect(0.U)
// Write
c.io.dataBus.poke(5.U)
c.io.write.poke(1.U)
c.io.cellBus.expect(5.U)
// Verify read-after-write
c.io.dataBus.poke(12.U)
c.io.write.poke(0.U)
c.io.cellBus.expect(5.U)
}
}
}
前两个预期的效果与我预期的一样。但是,当我在写完之后尝试阅读时,cellBus
returns 变成了 0
而不是坚持我之前写的 5
。
test MemCell Success: 0 tests passed in 1 cycles in 0.035654 seconds 28.05 Hz
[info] MemCellTest:
[info] MemCell
[info] - should read and write *** FAILED ***
[info] io_cellBus=0 (0x0) did not equal expected=5 (0x5) (lines in MyTest.scala: 10) (MyTest.scala:21)
显然寄存器没有保存这个值,因此 internalValue
恢复为 0
。但为什么会发生这种情况,我如何才能创造出可以持续存在的价值?
Drakinite 的评论是正确的。您需要确保步进时钟才能看到寄存器锁存值。我调整了您的测试以包括几个步骤并且它按预期工作:
c.io.dataBus.poke(5.U)
c.io.writeBus.poke(0.U)
c.io.cellBus.expect(0.U)
c.clock.step() // Added step
// Write passthrough (same cycle)
c.io.dataBus.poke(5.U)
c.io.writeBus.poke(1.U)
c.io.cellBus.expect(5.U)
c.clock.step() // Added step
// Verify read-after-write
c.io.dataBus.poke(12.U)
c.io.writeBus.poke(0.U)
c.io.cellBus.expect(5.U)
这里是一个可执行示例,显示它有效(使用 chisel3 v3.4.4 和 chiseltest v0.3.4):https://scastie.scala-lang.org/5E1rOEsYSzSUrLXZCvoyNA