From 864163987303f8f978dd8acd76f3d62be0cd9e9c Mon Sep 17 00:00:00 2001 From: mwachs5 Date: Mon, 26 Sep 2016 11:08:38 -0700 Subject: [PATCH] Async rst async queue (#336) * crossing: use async reset * crossings: asyncqueue needs Asynchronous reset. * crossing: Actually enable the head of the synchronizer flop chain * crossing: remove reset from logic. This flop will no longer be written during reset because valid will be low. * crossing: Tidy up code & comments --- src/main/scala/junctions/asyncqueue.scala | 40 +++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/scala/junctions/asyncqueue.scala b/src/main/scala/junctions/asyncqueue.scala index 585fa9e9..f5533472 100644 --- a/src/main/scala/junctions/asyncqueue.scala +++ b/src/main/scala/junctions/asyncqueue.scala @@ -2,22 +2,28 @@ package junctions import Chisel._ +import uncore.util.{AsyncResetRegVec, AsyncResetReg} object GrayCounter { def apply(bits: Int, increment: Bool = Bool(true)): UInt = { - val binary = RegInit(UInt(0, width = bits)) - val incremented = binary + increment.asUInt() - binary := incremented + val incremented = Wire(UInt(width=bits)) + val binary = AsyncResetReg(incremented, 0) + incremented := binary + increment.asUInt() incremented ^ (incremented >> UInt(1)) } } object AsyncGrayCounter { def apply(in: UInt, sync: Int): UInt = { - val syncv = RegInit(Vec.fill(sync){UInt(0, width = in.getWidth)}) - syncv.last := in - (syncv.init zip syncv.tail).foreach { case (sink, source) => sink := source } - syncv(0) + val syncv = List.fill(sync)(Module (new AsyncResetRegVec(w = in.getWidth, 0))) + 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(0).io.d } } @@ -33,15 +39,19 @@ class AsyncQueueSource[T <: Data](gen: T, depth: Int, sync: Int, clockIn: Clock, val mem = Vec(depth, gen).asOutput } - val mem = Reg(Vec(depth, gen)) + val mem = Reg(Vec(depth, gen)) //This does NOT need to be asynchronously reset. val widx = GrayCounter(bits+1, io.enq.fire()) val ridx = AsyncGrayCounter(io.ridx, sync) val 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)) when (io.enq.fire() && !reset) { mem(index) := io.enq.bits } - io.enq.ready := RegNext(ready, Bool(false)) - io.widx := RegNext(widx, UInt(0)) + val ready_reg = AsyncResetReg(ready, 0) + io.enq.ready := ready_reg + + val widx_reg = AsyncResetReg(widx, 0) + io.widx := widx_reg + io.mem := mem } @@ -66,9 +76,13 @@ class AsyncQueueSink[T <: Data](gen: T, depth: Int, sync: Int, clockIn: Clock, r // On an FPGA, only one input changes at a time => mem updates don't cause glitches // The register only latches when the selected valued is not being written val index = if (depth == 1) UInt(0) else ridx(bits-1, 0) ^ (ridx(bits, bits) << (bits-1)) - io.deq.bits := RegEnable(io.mem(index), valid && !reset) - io.deq.valid := RegNext(valid, Bool(false)) - io.ridx := RegNext(ridx, UInt(0)) + // This register does not NEED to be reset, as its contents will not + // be considered unless the asynchronously reset deq valid register is set. + io.deq.bits := RegEnable(io.mem(index), valid) + + io.deq.valid := AsyncResetReg(valid, 0) + + io.ridx := AsyncResetReg(ridx, 0) } class AsyncQueue[T <: Data](gen: T, depth: Int = 8, sync: Int = 3) extends Crossing[T] {