# 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)

# 补充

  1. s2mPipe() is ready to accept new data when the internal data register does not contain valid data.
  2. 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
更新于 阅读次数