Fix TLClockDivider syncronization

This commit is contained in:
Jerry Zhao
2023-05-28 23:35:58 -07:00
parent 0ec98e07d4
commit 1830bbf0e9
2 changed files with 16 additions and 10 deletions

View File

@@ -26,20 +26,26 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit
val sinks = clockNode.out.head._1.member.elements.toSeq val sinks = clockNode.out.head._1.member.elements.toSeq
require (sources.size == sinks.size) require (sources.size == sinks.size)
val nSinks = sinks.size val nSinks = sinks.size
// The implicit clock of this module is the clock of the tilelink bus
// busReset is sync'd to that clock, and will be asserted longer than the
// resets coming in through the clockNode, since the busReset is derived from
// the clockNode resets in downstream PRCI nodes
val busReset = reset
val regs = (0 until nSinks) .map { i => val regs = (0 until nSinks) .map { i =>
val sinkName = sinks(i)._1 val sinkName = sinks(i)._1
val asyncReset = sources(i).reset val asyncReset = sources(i).reset
val reg = withReset (asyncReset) { val reg = Module(new AsyncResetRegVec(w=divBits, init=0))
Module(new AsyncResetRegVec(w=divBits, init=0))
}
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider") println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider")
sinks(i)._2.clock := withClockAndReset(sources(i).clock, asyncReset) { val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl))) divider.io.clockIn := sources(i).clock
divider.io.divisor := reg.io.q // busReset is expected to be high for a long time, since reset will take a while to propagate
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset // to the TL bus. While reset is propagating, make sure we propagate a fast, undivided clock
divider.io.clockOut // by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
} divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
sinks(i)._2.clock := divider.io.clockOut
// Note this is not synchronized to the output clock, which takes time to appear // Note this is not synchronized to the output clock, which takes time to appear
// so this is still asyncreset // so this is still asyncreset