diff --git a/src/main/scala/util/AsyncQueue.scala b/src/main/scala/util/AsyncQueue.scala index 91e5c05d..e0de910d 100644 --- a/src/main/scala/util/AsyncQueue.scala +++ b/src/main/scala/util/AsyncQueue.scala @@ -13,27 +13,12 @@ object GrayCounter { } } -object UIntSyncChain { - def apply(in: UInt, sync: Int, name: String = "gray"): UInt = { - val syncv = List.tabulate(sync) { i => - Module (new AsyncResetRegVec(w = in.getWidth, 0)).suggestName(s"${name}_sync_${i}") - } - syncv.last.io.d := in - syncv.last.io.en := Bool(true) - (syncv.init zip syncv.tail).foreach { case (sink, source) => - sink.io.d := source.io.q - sink.io.en := Bool(true) - } - syncv.head.io.q - } -} - class AsyncValidSync(sync: Int, desc: String) extends Module { val io = new Bundle { val in = Bool(INPUT) val out = Bool(OUTPUT) } - io.out := UIntSyncChain(io.in.asUInt, sync, desc)(0) + io.out := AsyncResetSynchronizerShiftReg(io.in, sync, Some(desc)) } class AsyncQueueSource[T <: Data](gen: T, depth: Int, sync: Int, safe: Boolean = true, narrowData: Boolean = false) extends Module { @@ -55,7 +40,7 @@ class AsyncQueueSource[T <: Data](gen: T, depth: Int, sync: Int, safe: Boolean = val sink_ready = Wire(init = Bool(true)) val mem = Reg(Vec(depth, gen)) // This does NOT need to be reset at all. val widx = GrayCounter(bits+1, io.enq.fire(), !sink_ready, "widx_bin") - val ridx = UIntSyncChain(io.ridx, sync, "ridx_gray") + val ridx = AsyncResetSynchronizerShiftReg(io.ridx, sync, Some("ridx_gray")) val ready = sink_ready && widx =/= (ridx ^ UInt(depth | depth >> 1)) val index = if (depth == 1) UInt(0) else io.widx(bits-1, 0) ^ (io.widx(bits, bits) << (bits-1)) @@ -112,7 +97,7 @@ class AsyncQueueSink[T <: Data](gen: T, depth: Int, sync: Int, safe: Boolean = t val source_ready = Wire(init = Bool(true)) val ridx = GrayCounter(bits+1, io.deq.fire(), !source_ready, "ridx_bin") - val widx = UIntSyncChain(io.widx, sync, "widx_gray") + val widx = AsyncResetSynchronizerShiftReg(io.widx, sync, Some("widx_gray")) val valid = source_ready && ridx =/= widx // The mux is safe because timing analysis ensures ridx has reached the register diff --git a/src/main/scala/util/SynchronizingReg.scala b/src/main/scala/util/SynchronizingReg.scala index 08069c71..8660e051 100644 --- a/src/main/scala/util/SynchronizingReg.scala +++ b/src/main/scala/util/SynchronizingReg.scala @@ -32,9 +32,10 @@ object AbstractSynchronizerReg { def apply [T <: Chisel.Data](gen: (Int, Int) => AbstractSynchronizerReg, in: T, sync: Int = 3, name: Option[String] = None): T = { val sync_chain = Module(gen(in.getWidth, sync)) - name.foreach{ sync_reg.suggestName(_) } - sync_reg.io.d := in.asUInt - (in.chiselCloneType).fromBits(sync_reg.io.q) + name.foreach{ sync_chain.suggestName(_) } + sync_chain.io.d := in.asUInt + + (in.chiselCloneType).fromBits(sync_chain.io.q) } }