diff --git a/src/main/scala/uncore/tilelink2/RationalCrossing.scala b/src/main/scala/uncore/tilelink2/RationalCrossing.scala index fcec6f45..6d3b70fd 100644 --- a/src/main/scala/uncore/tilelink2/RationalCrossing.scala +++ b/src/main/scala/uncore/tilelink2/RationalCrossing.scala @@ -1,5 +1,12 @@ // See LICENSE.SiFive for license details. +// If you know two clocks are related with a N:1 or 1:N relationship, you +// can cross the clock domains with lower latency than an AsyncQueue. +// This clock crossing behaves almost identically to a TLBuffer(2): +// - It adds one cycle latency to each clock domain. +// - All outputs of TLRational are registers (bits, valid, and ready). +// - It costs 3*bits registers as opposed to 2*bits in a TLBuffer(2) + package uncore.tilelink2 import Chisel._ diff --git a/src/main/scala/util/RationalCrossing.scala b/src/main/scala/util/RationalCrossing.scala index 64a1b01e..8a0f5448 100644 --- a/src/main/scala/util/RationalCrossing.scala +++ b/src/main/scala/util/RationalCrossing.scala @@ -1,5 +1,9 @@ // See LICENSE.SiFive for license details. +// If you know two clocks are related with a N:1 or 1:N relationship, you +// can cross the clock domains with lower latency than an AsyncQueue. This +// crossing adds 1 cycle in the target clock domain. + package util import Chisel._ @@ -34,7 +38,7 @@ class RationalCrossingSource[T <: Data](gen: T) extends Module deq.valid := enq.valid deq.source := count - deq.bits := Mux(equal, enq.bits, RegEnable(enq.bits, equal && enq.valid)) + deq.bits := Mux(equal, enq.bits, RegEnable(enq.bits, equal)) enq.ready := Mux(equal, deq.ready, count(1) =/= deq.sink(0)) when (enq.fire()) { count := Cat(count(0), !count(1)) }