# s2mPipe
# 关键点
self.ready 为 s2mPipe.ready 打一拍,rValid 和 rData 用于寄存输入 valid 和 payload 避免气泡。
# 开敲
如果有寄存数据,输出寄存数据;如果没有寄存数据,寄存数据 or 直接输出(视输出 ready 决定)
val rData = RegNextWhen(self.payload, self.fire & ~s2mPipe.fire) | |
val rValid = RegInit(False) setWhen(self.fire) clearWhen(s2mPipe.fire) | |
val rReady = RegInit(True) setWhen(s2mPipe.ready) clearWhen(~s2mPipe.ready | rValid) | |
self.ready := rReady | |
s2mPipe.valid := self.valid | rValid | |
s2mPipe.payload := Mux(rValid, rData, self.payload) |
修正 1:rData 只有在 rValid 拉高时才用到,而 rValid 只有 self.fire 时才为高,因此
val rData = RegNextWhen(self.payload, self.fire) |
修正 2:rValid 说明是否包含寄存数据,rValid 为高时说明无法再接收新寄存数据,这要求 self.ready 拉低,因为只能寄存 - 消化 - 直通 or 寄存 - 消化 - 寄存 - 消化 or 直通,即有寄存数据后只能消化,不能消化的同时寄存(因为 rValid 在消化的时候拉低了,就算寄存了 rValid 也为低,这与前面说法相违背,或者说这种情况应该是 m2sPipe,因为 payload 和 valid 有一拍延时),因此实际上 self.ready 只在没有寄存数据的时候才能为高,即
self.ready := ~rValid |
修正 3:self.ready 依赖于 rValid,而 rValid 依赖 self.fire,这形成了环路,存在问题。实际上,rValid 为高时,s2mPipe.valid 为高,因此拉低条件 s2mPipe.fire 可以退化成 s2mPipe.ready;而拉高条件 self.fire & ~s2mPipe.ready 是为了说明有数据寄存且没有消化,则原来的 rValid 为低,self.ready 为高(self.ready := ~rValid),因此拉高条件退化为 self.valid & ~s2mPipe.ready,则
val rValid = RegInit(False) setWhen (self.valid) clearWhen(s2mPipe.ready) |
修正 4:rData 的寄存条件 self.fire 较为严格,因为实际输出依赖 rValid 选择 payload,而 rValid 是在 self.valid 时拉高,因此寄存条件 self.fire = self.valid & self.ready 可以退化为 self.ready,则
val rData = RegNextWhen(self.payload, self.ready) |
# 完整代码
val rData = RegNextWhen(self.payload, self.ready) | |
val rValid = RegInit(False) setWhen(self.valid) clearWhen(s2mPipe.ready) | |
self.ready := ~rValid | |
s2mPipe.valid := self.valid | rValid | |
s2mPipe.payload := Mux(rValid, rData, self.payload) |
# 补充
- s2mPipe() is ready to accept new data when the internal data register does not contain valid data.
- The ready becomes valid when rData is free, thus when it does not contain valid data already.
# m2sPipe
# 关键点
rValid 和 rData 寄存输入 valid 和 payload, self.ready 处理气泡拼接。
# 开敲
val rData = RegNextWhen(self.payload, self.ready) | |
val rValid = RegNextWhen(self.valid, self.ready) init(False) | |
self.ready := m2sPipe.ready | ~m2sPipe.valid // m2sPipe.isFree | |
m2sPipe.valid := rValid | |
m2sPipe.payload := rData |