From 1830bbf0e994eb1f705ff7250e1be54f58b6efd7 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 28 May 2023 23:35:58 -0700 Subject: [PATCH] Fix TLClockDivider syncronization --- .../main/scala/clocking/TLClockDivider.scala | 24 ++++++++++++------- generators/testchipip | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/generators/chipyard/src/main/scala/clocking/TLClockDivider.scala b/generators/chipyard/src/main/scala/clocking/TLClockDivider.scala index bc722799..45f9374d 100644 --- a/generators/chipyard/src/main/scala/clocking/TLClockDivider.scala +++ b/generators/chipyard/src/main/scala/clocking/TLClockDivider.scala @@ -26,20 +26,26 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit val sinks = clockNode.out.head._1.member.elements.toSeq require (sources.size == 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 sinkName = sinks(i)._1 val asyncReset = sources(i).reset - val reg = withReset (asyncReset) { - Module(new AsyncResetRegVec(w=divBits, init=0)) - } + val reg = Module(new AsyncResetRegVec(w=divBits, init=0)) + 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))) - divider.io.divisor := reg.io.q - divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset - divider.io.clockOut - } + val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl))) + divider.io.clockIn := sources(i).clock + // busReset is expected to be high for a long time, since reset will take a while to propagate + // to the TL bus. While reset is propagating, make sure we propagate a fast, undivided clock + // 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 // so this is still asyncreset diff --git a/generators/testchipip b/generators/testchipip index 06e34926..a3e9c1ff 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 06e3492610499dd9a6473466273383ea234ae517 +Subproject commit a3e9c1ffeae8af573831e4ac5fd00a76df0ca7f1