crossing: refactor AsyncDecoupled to provide AsyncDecoupledCrossing with no clock domain
This commit is contained in:
parent
33a05786db
commit
ecdfb528c5
@ -1,13 +1,13 @@
|
|||||||
package junctions
|
package junctions
|
||||||
import Chisel._
|
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 enq = Decoupled(gen).flip()
|
||||||
val deq = Decoupled(gen)
|
val deq = Decoupled(gen)
|
||||||
val enq_clock = if (enq_sync) Some(Clock(INPUT)) else None
|
val enq_clock = Clock(INPUT)
|
||||||
val deq_clock = if (deq_sync) Some(Clock(INPUT)) else None
|
val deq_clock = Clock(INPUT)
|
||||||
val enq_reset = if (enq_sync) Some(Bool(INPUT)) else None
|
val enq_reset = Bool(INPUT)
|
||||||
val deq_reset = if (deq_sync) Some(Bool(INPUT)) else None
|
val deq_reset = Bool(INPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output is 1 for one cycle after any edge of 'in'
|
// 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 {
|
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)
|
require (sync >= 2)
|
||||||
|
|
||||||
val source = Module(new AsyncHandshakeSource(gen, sync, io.enq_clock.get, io.enq_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.get, io.deq_reset.get))
|
val sink = Module(new AsyncHandshakeSink (gen, sync, io.deq_clock, io.deq_reset))
|
||||||
|
|
||||||
source.io.enq <> io.enq
|
source.io.enq <> io.enq
|
||||||
io.deq <> sink.io.deq
|
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
|
source.io.pop := sink.io.pop
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncDecoupledTo[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module {
|
class AsyncScope extends Module { val io = new Bundle }
|
||||||
val io = new Crossing(gen, false, true)
|
object AsyncScope { def apply() = Module(new AsyncScope) }
|
||||||
|
|
||||||
|
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 }
|
// !!! if depth == 0 { use Handshake } else { use AsyncFIFO }
|
||||||
val crossing = Module(new AsyncHandshake(gen, sync)).io
|
val crossing = Module(new AsyncHandshake(from_source.bits, sync)).io
|
||||||
crossing.enq_clock.get := clock
|
crossing.enq_clock := from_clock
|
||||||
crossing.enq_reset.get := reset
|
crossing.enq_reset := from_reset
|
||||||
crossing.enq <> io.enq
|
crossing.enq <> from_source
|
||||||
crossing.deq_clock.get := io.deq_clock.get
|
crossing.deq_clock := to_clock
|
||||||
crossing.deq_reset.get := io.deq_reset.get
|
crossing.deq_reset := to_reset
|
||||||
io.deq <> crossing.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncDecoupledFrom[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module {
|
object AsyncDecoupledTo
|
||||||
val io = new Crossing(gen, true, false)
|
{
|
||||||
|
// takes source from your clock domain and puts it into the 'to' clock domain
|
||||||
// !!! if depth == 0 { use Handshake } else { use AsyncFIFO }
|
def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = {
|
||||||
val crossing = Module(new AsyncHandshake(gen, sync)).io
|
val scope = AsyncScope()
|
||||||
crossing.enq_clock.get := io.enq_clock.get
|
AsyncDecoupledCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync)
|
||||||
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 {
|
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] = {
|
// takes from_source from the 'from' clock domain and puts it into your clock domain
|
||||||
val from = Module(new AsyncDecoupledFrom(source.bits, depth, sync))
|
def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = {
|
||||||
from.io.enq_clock.get := from_clock
|
val scope = AsyncScope()
|
||||||
from.io.enq_reset.get := from_reset
|
AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync)
|
||||||
from.io.enq <> source
|
|
||||||
from.io.deq
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
object AsyncNastiTo {
|
||||||
// source(master) is in our clock domain, output is in the 'to' clock domain
|
// 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: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = {
|
def apply(to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = {
|
||||||
val sink = Wire(new NastiIO)
|
val scope = AsyncScope()
|
||||||
|
AsyncNastiCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AsyncNastiFrom {
|
object AsyncNastiFrom {
|
||||||
// source(master) is in the 'from' clock domain, output is in our clock domain
|
// 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, source: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = {
|
def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = {
|
||||||
val sink = Wire(new NastiIO)
|
val scope = AsyncScope()
|
||||||
|
AsyncNastiCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,17 +87,17 @@ class JtagDTMWithSync(implicit val p: Parameters) extends Module {
|
|||||||
val req_sync = Module (new AsyncMailbox())
|
val req_sync = Module (new AsyncMailbox())
|
||||||
val resp_sync = Module (new AsyncMailbox())
|
val resp_sync = Module (new AsyncMailbox())
|
||||||
req_sync.io.enq := jtag_dtm.io.dtm_req
|
req_sync.io.enq := jtag_dtm.io.dtm_req
|
||||||
req_sync.io.enq_clock.get := io.jtag.TCK
|
req_sync.io.enq_clock := io.jtag.TCK
|
||||||
req_sync.io.enq_reset.get := io.jtag.TRST
|
req_sync.io.enq_reset := io.jtag.TRST
|
||||||
req_sync.io.deq_clock.get := clock
|
req_sync.io.deq_clock := clock
|
||||||
req_sync.io.deq_reset.get := reset
|
req_sync.io.deq_reset := reset
|
||||||
dtm_req := req_sync.io.deq
|
dtm_req := req_sync.io.deq
|
||||||
|
|
||||||
jtag_dtm.io.dtm_resp := resp_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_clock := io.jtag.TCK
|
||||||
resp_sync.io.deq_reset.get := io.jtag.TRST
|
resp_sync.io.deq_reset := io.jtag.TRST
|
||||||
resp_sync.io.enq_clock.get := clock
|
resp_sync.io.enq_clock := clock
|
||||||
resp_sync.io.enq_reset.get := reset
|
resp_sync.io.enq_reset := reset
|
||||||
resp_sync.io.enq := dtm_resp
|
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
|
// this mailbox just has a fixed width of 64 bits, which is enough
|
||||||
// for our specific purpose here.
|
// 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
|
object AsyncDebugBusFrom { // OutsideClockDomain
|
||||||
def apply(from_clock: Clock, from_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = {
|
// takes from_source from the 'from' clock domain and puts it into your clock domain
|
||||||
val sink = Wire(new DebugBusIO)
|
def apply(from_clock: Clock, from_reset: Bool, from_source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = {
|
||||||
sink.req <> AsyncDecoupledFrom(from_clock, from_reset, source.req)
|
val scope = AsyncScope()
|
||||||
source.resp <> AsyncDecoupledTo(from_clock, from_reset, sink.resp)
|
AsyncDebugBusCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync)
|
||||||
sink
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AsyncDebugBusTo { // OutsideClockDomain
|
object AsyncDebugBusTo { // OutsideClockDomain
|
||||||
def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = {
|
// takes source from your clock domain and puts it into the 'to' clock domain
|
||||||
val sink = Wire(new DebugBusIO)
|
def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = {
|
||||||
sink.req <> AsyncDecoupledTo(to_clock, to_reset, source.req)
|
val scope = AsyncScope()
|
||||||
source.resp <> AsyncDecoupledFrom(to_clock, to_reset, sink.resp)
|
AsyncDebugBusCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync)
|
||||||
sink
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user