crossing: refactor AsyncDecoupled to provide AsyncDecoupledCrossing with no clock domain
This commit is contained in:
		| @@ -1,13 +1,13 @@ | ||||
| package junctions | ||||
| import Chisel._ | ||||
|  | ||||
| class Crossing[T <: Data](gen: T, enq_sync: Boolean, deq_sync: Boolean) extends Bundle { | ||||
| class Crossing[T <: Data](gen: T) extends Bundle { | ||||
|     val enq = Decoupled(gen).flip() | ||||
|     val deq = Decoupled(gen) | ||||
|     val enq_clock = if (enq_sync) Some(Clock(INPUT)) else None | ||||
|     val deq_clock = if (deq_sync) Some(Clock(INPUT)) else None | ||||
|     val enq_reset = if (enq_sync) Some(Bool(INPUT))  else None | ||||
|     val deq_reset = if (deq_sync) Some(Bool(INPUT))  else None | ||||
|     val enq_clock = Clock(INPUT) | ||||
|     val deq_clock = Clock(INPUT) | ||||
|     val enq_reset = Bool(INPUT) | ||||
|     val deq_reset = Bool(INPUT) | ||||
| } | ||||
|  | ||||
| // Output is 1 for one cycle after any edge of 'in' | ||||
| @@ -87,11 +87,11 @@ class AsyncHandshakeSink[T <: Data](gen: T, sync: Int, clock: Clock, reset: Bool | ||||
| } | ||||
|  | ||||
| class AsyncHandshake[T <: Data](gen: T, sync: Int = 2) extends Module { | ||||
|   val io = new Crossing(gen, true, true) | ||||
|   val io = new Crossing(gen) | ||||
|   require (sync >= 2) | ||||
|  | ||||
|   val source = Module(new AsyncHandshakeSource(gen, sync, io.enq_clock.get, io.enq_reset.get)) | ||||
|   val sink   = Module(new AsyncHandshakeSink  (gen, sync, io.deq_clock.get, io.deq_reset.get)) | ||||
|   val source = Module(new AsyncHandshakeSource(gen, sync, io.enq_clock, io.enq_reset)) | ||||
|   val sink   = Module(new AsyncHandshakeSink  (gen, sync, io.deq_clock, io.deq_reset)) | ||||
|  | ||||
|   source.io.enq <> io.enq | ||||
|   io.deq <> sink.io.deq | ||||
| @@ -101,50 +101,38 @@ class AsyncHandshake[T <: Data](gen: T, sync: Int = 2) extends Module { | ||||
|   source.io.pop := sink.io.pop | ||||
| } | ||||
|  | ||||
| class AsyncDecoupledTo[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module { | ||||
|   val io = new Crossing(gen, false, true) | ||||
| class AsyncScope extends Module { val io = new Bundle } | ||||
| object AsyncScope { def apply() = Module(new AsyncScope) } | ||||
|  | ||||
|   // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } | ||||
|   val crossing = Module(new AsyncHandshake(gen, sync)).io | ||||
|   crossing.enq_clock.get := clock | ||||
|   crossing.enq_reset.get := reset | ||||
|   crossing.enq <> io.enq | ||||
|   crossing.deq_clock.get := io.deq_clock.get | ||||
|   crossing.deq_reset.get := io.deq_reset.get | ||||
|   io.deq <> crossing.deq | ||||
| } | ||||
|  | ||||
| object AsyncDecoupledTo { | ||||
|   // source is in our clock domain, output is in the 'to' clock domain | ||||
|   def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 0, sync: Int = 2): DecoupledIO[T] = { | ||||
|     val to = Module(new AsyncDecoupledTo(source.bits, depth, sync)) | ||||
|     to.io.deq_clock.get := to_clock | ||||
|     to.io.deq_reset.get := to_reset | ||||
|     to.io.enq <> source | ||||
|     to.io.deq | ||||
| object AsyncDecoupledCrossing | ||||
| { | ||||
|   // takes from_source from the 'from' clock domain and puts it into the 'to' clock domain | ||||
|   def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { | ||||
|     // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } | ||||
|     val crossing = Module(new AsyncHandshake(from_source.bits, sync)).io | ||||
|     crossing.enq_clock := from_clock | ||||
|     crossing.enq_reset := from_reset | ||||
|     crossing.enq       <> from_source | ||||
|     crossing.deq_clock := to_clock | ||||
|     crossing.deq_reset := to_reset | ||||
|     crossing.deq | ||||
|   } | ||||
| } | ||||
|  | ||||
| class AsyncDecoupledFrom[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module { | ||||
|   val io = new Crossing(gen, true, false) | ||||
|  | ||||
|   // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } | ||||
|   val crossing = Module(new AsyncHandshake(gen, sync)).io | ||||
|   crossing.enq_clock.get := io.enq_clock.get | ||||
|   crossing.enq_reset.get := io.enq_reset.get | ||||
|   crossing.enq <> io.enq | ||||
|   crossing.deq_clock.get := clock | ||||
|   crossing.deq_reset.get := reset | ||||
|   io.deq <> crossing.deq | ||||
| } | ||||
|  | ||||
| object AsyncDecoupledFrom { | ||||
|   // source is in the 'from' clock domain, output is in our clock domain | ||||
|   def apply[T <: Data](from_clock: Clock, from_reset: Bool, source: DecoupledIO[T], depth: Int = 0, sync: Int = 2): DecoupledIO[T] = { | ||||
|     val from = Module(new AsyncDecoupledFrom(source.bits, depth, sync)) | ||||
|     from.io.enq_clock.get := from_clock | ||||
|     from.io.enq_reset.get := from_reset | ||||
|     from.io.enq <> source | ||||
|     from.io.deq | ||||
| object AsyncDecoupledTo | ||||
| { | ||||
|   // takes source from your clock domain and puts it into the 'to' clock domain | ||||
|   def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncDecoupledCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncDecoupledFrom | ||||
| { | ||||
|   // takes from_source from the 'from' clock domain and puts it into your clock domain | ||||
|   def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -706,32 +706,33 @@ class NastiMemoryDemux(nRoutes: Int)(implicit p: Parameters) extends NastiModule | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncNastiCrossing { | ||||
|   // takes from_source from the 'from' clock domain to the 'to' clock domain | ||||
|   def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2) = { | ||||
|     val to_sink = Wire(new NastiIO()(from_source.p)) | ||||
|  | ||||
|     to_sink.aw <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.aw, to_clock, to_reset, depth, sync) | ||||
|     to_sink.ar <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.ar, to_clock, to_reset, depth, sync) | ||||
|     to_sink.w  <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.w,  to_clock, to_reset, depth, sync) | ||||
|     from_source.b <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.b, from_clock, from_reset, depth, sync) | ||||
|     from_source.r <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.r, from_clock, from_reset, depth, sync) | ||||
|  | ||||
|     to_sink // is now to_source | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncNastiTo { | ||||
|   // source(master) is in our clock domain, output is in the 'to' clock domain | ||||
|   def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = { | ||||
|     val sink = Wire(new NastiIO) | ||||
|  | ||||
|     sink.aw <> AsyncDecoupledTo(to_clock, to_reset, source.aw, depth, sync) | ||||
|     sink.ar <> AsyncDecoupledTo(to_clock, to_reset, source.ar, depth, sync) | ||||
|     sink.w  <> AsyncDecoupledTo(to_clock, to_reset, source.w,  depth, sync) | ||||
|     source.b <> AsyncDecoupledFrom(to_clock, to_reset, sink.b, depth, sync) | ||||
|     source.r <> AsyncDecoupledFrom(to_clock, to_reset, sink.r, depth, sync) | ||||
|  | ||||
|     sink | ||||
|   // takes source from your clock domain and puts it into the 'to' clock domain | ||||
|   def apply(to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncNastiCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncNastiFrom { | ||||
|   // source(master) is in the 'from' clock domain, output is in our clock domain | ||||
|   def apply[T <: Data](from_clock: Clock, from_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = { | ||||
|     val sink = Wire(new NastiIO) | ||||
|  | ||||
|     sink.aw <> AsyncDecoupledFrom(from_clock, from_reset, source.aw, depth, sync) | ||||
|     sink.ar <> AsyncDecoupledFrom(from_clock, from_reset, source.ar, depth, sync) | ||||
|     sink.w  <> AsyncDecoupledFrom(from_clock, from_reset, source.w,  depth, sync) | ||||
|     source.b <> AsyncDecoupledTo(from_clock, from_reset, sink.b, depth, sync) | ||||
|     source.r <> AsyncDecoupledTo(from_clock, from_reset, sink.r, depth, sync) | ||||
|  | ||||
|     sink | ||||
|   // takes from_source from the 'from' clock domain and puts it into your clock domain | ||||
|   def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncNastiCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -86,19 +86,19 @@ class JtagDTMWithSync(implicit val p: Parameters) extends Module { | ||||
|   } else { | ||||
|     val req_sync  = Module (new AsyncMailbox()) | ||||
|     val resp_sync = Module (new AsyncMailbox()) | ||||
|     req_sync.io.enq             := jtag_dtm.io.dtm_req | ||||
|     req_sync.io.enq_clock.get   := io.jtag.TCK | ||||
|     req_sync.io.enq_reset.get   := io.jtag.TRST | ||||
|     req_sync.io.deq_clock.get   := clock | ||||
|     req_sync.io.deq_reset.get   := reset | ||||
|     dtm_req                     := req_sync.io.deq | ||||
|     req_sync.io.enq         := jtag_dtm.io.dtm_req | ||||
|     req_sync.io.enq_clock   := io.jtag.TCK | ||||
|     req_sync.io.enq_reset   := io.jtag.TRST | ||||
|     req_sync.io.deq_clock   := clock | ||||
|     req_sync.io.deq_reset   := reset | ||||
|     dtm_req                 := req_sync.io.deq | ||||
|  | ||||
|     jtag_dtm.io.dtm_resp        := resp_sync.io.deq | ||||
|     resp_sync.io.deq_clock.get  := io.jtag.TCK | ||||
|     resp_sync.io.deq_reset.get  := io.jtag.TRST | ||||
|     resp_sync.io.enq_clock.get  := clock | ||||
|     resp_sync.io.enq_reset.get  := reset | ||||
|     resp_sync.io.enq            := dtm_resp | ||||
|     jtag_dtm.io.dtm_resp    := resp_sync.io.deq | ||||
|     resp_sync.io.deq_clock  := io.jtag.TCK | ||||
|     resp_sync.io.deq_reset  := io.jtag.TRST | ||||
|     resp_sync.io.enq_clock  := clock | ||||
|     resp_sync.io.enq_reset  := reset | ||||
|     resp_sync.io.enq        := dtm_resp | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -121,6 +121,5 @@ class AsyncMailbox extends BlackBox { | ||||
|   // this mailbox just has a fixed width of 64 bits, which is enough | ||||
|   // for our specific purpose here. | ||||
|  | ||||
|   val io = new Crossing(UInt(width=64), true, true) | ||||
|  | ||||
|   val io = new Crossing(UInt(width=64)) | ||||
| } | ||||
|   | ||||
| @@ -982,22 +982,28 @@ class DebugModule ()(implicit val p:cde.Parameters) | ||||
|  | ||||
| } | ||||
|  | ||||
| object AsyncDebugBusCrossing { | ||||
|   // takes from_source from the 'from' clock domain to the 'to' clock domain | ||||
|   def apply(from_clock: Clock, from_reset: Bool, from_source: DebugBusIO, to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2) = { | ||||
|     val to_sink = Wire(new DebugBusIO()(from_source.p)) | ||||
|     to_sink.req <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.req, to_clock, to_reset, depth, sync) | ||||
|     from_source.resp <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.resp, from_clock, from_reset, depth, sync) | ||||
|     to_sink // is now to_source | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncDebugBusFrom { // OutsideClockDomain | ||||
|   def apply(from_clock: Clock, from_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = { | ||||
|     val sink = Wire(new DebugBusIO) | ||||
|     sink.req <> AsyncDecoupledFrom(from_clock, from_reset, source.req) | ||||
|     source.resp <> AsyncDecoupledTo(from_clock, from_reset, sink.resp) | ||||
|     sink | ||||
|   // takes from_source from the 'from' clock domain and puts it into your clock domain | ||||
|   def apply(from_clock: Clock, from_reset: Bool, from_source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncDebugBusCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AsyncDebugBusTo { // OutsideClockDomain | ||||
|   def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = { | ||||
|     val sink = Wire(new DebugBusIO) | ||||
|     sink.req <> AsyncDecoupledTo(to_clock, to_reset, source.req) | ||||
|     source.resp <> AsyncDecoupledFrom(to_clock, to_reset, sink.resp) | ||||
|     sink | ||||
|   // takes source from your clock domain and puts it into the 'to' clock domain | ||||
|   def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = { | ||||
|     val scope = AsyncScope() | ||||
|     AsyncDebugBusCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user