RationalCrossing: clock crossing between related clock domains
This commit is contained in:
		
							
								
								
									
										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 | ||||||
|  |   } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user