Flow
规范
数据流接口是一个简单的有效/负载协议,这意味着从端无法终止总线。它可用于表示来自UART控制器的数据、写入片上存储器的请求等。
信号 |
类型 |
驱动 |
描述 |
何时忽略 |
---|---|---|---|---|
valid |
Bool |
Master |
当为高时 => 接口上存在有效负载(payload) |
|
payload |
T |
Master |
传输任务内容 |
valid为低 |
函数
语法 |
描述 |
返回类型 |
延迟 |
---|---|---|---|
Flow(type : Data) |
创建给定类型的流 |
Flow[T] |
|
master/slave Flow(type : Data) |
创建给定类型的流
通过相应的输入/输出设置进行初始化
|
Flow[T] |
|
x.m2sPipe() |
Return a Flow driven by x
通过寄存器,切断valid/payload路径
|
Flow[T] |
1 |
x.stage() |
等价于 x.m2sPipe() |
Flow[T] |
1 |
x << y
y >> x
|
将 y 连接到 x |
0 |
|
x <-< y
y >-> x
|
通过 m2sPipe 将 y 连接到 x |
1 |
|
x.throwWhen(cond : Bool) |
返回连接到 x 的流
当 cond 为高时,放弃传输的事务
|
Flow[T] |
0 |
x.toReg() |
返回一个寄存器,当valid为高时,该寄存器将加载 |
T |
|
x.setIdle() |
将流量设置为闲置状态: |
||
x.push(newPayload: T) |
为流设置新的有效payload。 |
代码示例
case class FlowExample() extends Component {
val io = new Bundle {
val request = slave(Flow(Bits(8 bit)))
val answer = master(Flow(Bits(8 bit)))
}
val storage = Reg(Bits(8 bit))
val fsm = new StateMachine {
io.answer.setIdle()
val idle: State = new State with EntryPoint {
whenIsActive {
when(io.request.valid) {
storage := io.request.payload
goto(sendEcho)
}
}
}
val sendEcho: State = new State {
whenIsActive {
io.answer.push(storage)
goto(idle)
}
}
}
// This StateMachine behaves equivalently to
// io.answer <-< io.request
}
仿真支持
类 |
用法 |
---|---|
FlowMonitor |
用于主端和从端,如果数据流传输数据,则调用带有负载的函数。 |
FlowDriver |
Testbench中主端通过调用函数来应用值(如果可用)以驱动值。如果值可用,则函数必须返回。支持随机的延迟。 |
ScoreboardInOrder |
通常用于比较参考/dut数据 |
package spinaldoc.libraries.flow
import spinal.core._
import spinal.core.sim._
import spinal.lib._
import spinal.lib.sim.{FlowDriver, FlowMonitor, ScoreboardInOrder}
import scala.language.postfixOps
case class SomeDUT() extends Component {
val io = new Bundle {
val input = slave(Flow(UInt(8 bit)))
val output = master(Flow(UInt(8 bit)))
}
io.output <-< io.input
}
object Example extends App {
val dut = SimConfig.withWave.compile(SomeDUT())
dut.doSim("simple test") { dut =>
SimTimeout(10000)
val scoreboard = ScoreboardInOrder[Int]()
// drive random data at random intervals, and add inputted data to scoreboard
FlowDriver(dut.io.input, dut.clockDomain) { payload =>
payload.randomize()
true
}
FlowMonitor(dut.io.input, dut.clockDomain) { payload =>
scoreboard.pushRef(payload.toInt)
}
// add all data coming out of DUT to scoreboard
FlowMonitor(dut.io.output, dut.clockDomain) { payload =>
scoreboard.pushDut(payload.toInt)
}
dut.clockDomain.forkStimulus(10)
dut.clockDomain.waitActiveEdgeWhere(scoreboard.matches == 100)
}
}