仿真过程中访问信号
读写信号
顶层模块的每个接口信号都可以从 Scala 程序中读写:
语法 |
描述 |
---|---|
|
将硬件 |
|
将硬件 |
|
将硬件 |
|
将硬件中的 |
|
将硬件中的 |
|
将 Scala 的 |
|
将 Scala 的 |
|
将 Scala 的 |
|
将 Scala 的 |
|
将 Scala 的 |
|
将随机值赋值给 SpinalHDL 硬件信号。 |
dut.io.a #= 42
dut.io.a #= 42l
dut.io.a #= BigInt("101010", 2)
dut.io.a #= BigInt("0123456789ABCDEF", 16)
println(dut.io.b.toInt)
访问组件层次结构内部的信号
要访问组件层次结构内部的信号,您必须首先将给定信号设置为 simPublic
。
您可以直接在硬件描述中添加此 simPublic
标签:
object SimAccessSubSignal {
import spinal.core.sim._
class TopLevel extends Component {
val counter = Reg(UInt(8 bits)) init(0) simPublic() // Here we add the simPublic tag on the counter register to make it visible
counter := counter + 1
}
def main(args: Array[String]) {
SimConfig.compile(new TopLevel).doSim{dut =>
dut.clockDomain.forkStimulus(10)
for(i <- 0 to 3) {
dut.clockDomain.waitSampling()
println(dut.counter.toInt)
}
}
}
}
或者您可以稍后在实例化仿真的顶层文件中添加它:
object SimAccessSubSignal {
import spinal.core.sim._
class TopLevel extends Component {
val counter = Reg(UInt(8 bits)) init(0)
counter := counter + 1
}
def main(args: Array[String]) {
SimConfig.compile {
val dut = new TopLevel
dut.counter.simPublic() // Call simPublic() here
dut
}.doSim{dut =>
dut.clockDomain.forkStimulus(10)
for(i <- 0 to 3) {
dut.clockDomain.waitSampling()
println(dut.counter.toInt)
}
}
}
}
仿真中内存的加载和存储
可以在仿真中修改 Mem
硬件接口组件的内容。 data 参数应该是一个字的位宽的值,address 是访问的字的地址。
没有 API 可以将地址和/或单个数据位转换为自然的字位宽以外的单位。
没有 API 可以用仿真中的 `X`(未定义)状态来标记任何内存位置。
语法 |
描述 |
---|---|
|
从仿真器的对应地址处读取一个字。 |
|
在地址处向仿真器内的存储器写入一个字。 |
这是一个简单的使用内存的示例:
case class MemoryExample() extends Component {
val wordCount = 64
val io = new Bundle {
val address = in port UInt(log2Up(wordCount) bit)
val i = in port Bits(8 bit)
val o = out port Bits(8 bit)
val we = in port Bool()
}
val mem = Mem(Bits(8 bit), wordCount=wordCount)
io.o := mem(io.address)
when(io.we) {
mem(io.address) := io.i
}
}
设置仿真环境后,我们可以这样访问内存:
SimConfig.withVcdWave.compile {
val d = MemoryExample()
// make memory accessible during simulation
d.mem.simPublic()
d
}.doSim("example") { dut =>
我们可以在仿真期间读取数据,但必须注意确保数据可用(由于仿真器是事件驱动的,这可能会造成一个周期的延迟):
// do a write
dut.io.we #= true
dut.io.address #= 10
dut.io.i #= 0xaf
dut.clockDomain.waitSampling(2)
// check written data is there
assert(dut.mem.getBigInt(10) == 0xaf)
并且可以像这样写入内存:
// set some data in memory
dut.mem.setBigInt(15, 0xfe)
// do a read to check if it's there
dut.io.address #= 15
dut.clockDomain.waitSampling(1)
assert(dut.io.o.toBigInt == 0xfe)
必须注意的是,由于仿真器是事件驱动的,例如上面描述的读取操作必须延迟到该值在内存中实际可用后进行。