RationalCrossing: clock crossing between related clock domains
This commit is contained in:
parent
1285fa909f
commit
5cf4b0632d
97
src/main/scala/util/RationalCrossing.scala
Normal file
97
src/main/scala/util/RationalCrossing.scala
Normal file
@ -0,0 +1,97 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package util
|
||||
import Chisel._
|
||||
|
||||
final class RationalIO[T <: Data](gen: T) extends Bundle
|
||||
{
|
||||
val bits = gen.chiselCloneType
|
||||
val valid = Bool()
|
||||
val source = UInt(width = 2)
|
||||
val ready = Bool().flip
|
||||
val sink = UInt(width = 2).flip
|
||||
|
||||
override def cloneType: this.type = new RationalIO(gen).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
object RationalIO
|
||||
{
|
||||
def apply[T <: Data](gen: T) = new RationalIO(gen)
|
||||
}
|
||||
|
||||
class RationalCrossingSource[T <: Data](gen: T) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val enq = DecoupledIO(gen).flip
|
||||
val deq = RationalIO(gen)
|
||||
}
|
||||
|
||||
val enq = Queue(io.enq, 1, flow=true)
|
||||
val deq = io.deq
|
||||
|
||||
val count = RegInit(UInt(0, width = 2))
|
||||
val equal = count === deq.sink
|
||||
|
||||
deq.valid := enq.valid
|
||||
deq.source := count
|
||||
deq.bits := Mux(equal, enq.bits, RegEnable(enq.bits, equal && enq.valid))
|
||||
enq.ready := Mux(equal, deq.ready, count(1) =/= deq.sink(0))
|
||||
|
||||
when (enq.fire()) { count := Cat(count(0), !count(1)) }
|
||||
}
|
||||
|
||||
class RationalCrossingSink[T <: Data](gen: T) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val enq = RationalIO(gen).flip
|
||||
val deq = DecoupledIO(gen)
|
||||
}
|
||||
|
||||
val enq = io.enq
|
||||
val deq = Wire(io.deq)
|
||||
io.deq <> Queue(deq, 1, pipe=true)
|
||||
|
||||
val count = RegInit(UInt(0, width = 2))
|
||||
val equal = count === enq.source
|
||||
|
||||
enq.ready := deq.ready
|
||||
enq.sink := count
|
||||
deq.bits := enq.bits
|
||||
deq.valid := Mux(equal, enq.valid, count(1) =/= enq.source(0))
|
||||
|
||||
when (deq.fire()) { count := Cat(count(0), !count(1)) }
|
||||
}
|
||||
|
||||
class RationalCrossing[T <: Data](gen: T) extends Module
|
||||
{
|
||||
val io = new CrossingIO(gen)
|
||||
|
||||
val source = Module(new RationalCrossingSource(gen))
|
||||
val sink = Module(new RationalCrossingSink(gen))
|
||||
|
||||
source.clock := io.enq_clock
|
||||
source.reset := io.enq_reset
|
||||
sink .clock := io.deq_clock
|
||||
sink .reset := io.deq_reset
|
||||
|
||||
source.io.enq <> io.enq
|
||||
io.deq <> sink.io.deq
|
||||
}
|
||||
|
||||
object ToRational
|
||||
{
|
||||
def apply[T <: Data](x: DecoupledIO[T]): RationalIO[T] = {
|
||||
val source = Module(new RationalCrossingSource(x.bits))
|
||||
source.io.enq <> x
|
||||
source.io.deq
|
||||
}
|
||||
}
|
||||
|
||||
object FromRational
|
||||
{
|
||||
def apply[T <: Data](x: RationalIO[T]): DecoupledIO[T] = {
|
||||
val sink = Module(new RationalCrossingSink(x.bits))
|
||||
sink.io.enq <> x
|
||||
sink.io.deq
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user