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
This commit is contained in:
parent
d787bae0d0
commit
8641639873
@ -2,22 +2,28 @@
|
|||||||
|
|
||||||
package junctions
|
package junctions
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import uncore.util.{AsyncResetRegVec, AsyncResetReg}
|
||||||
|
|
||||||
object GrayCounter {
|
object GrayCounter {
|
||||||
def apply(bits: Int, increment: Bool = Bool(true)): UInt = {
|
def apply(bits: Int, increment: Bool = Bool(true)): UInt = {
|
||||||
val binary = RegInit(UInt(0, width = bits))
|
val incremented = Wire(UInt(width=bits))
|
||||||
val incremented = binary + increment.asUInt()
|
val binary = AsyncResetReg(incremented, 0)
|
||||||
binary := incremented
|
incremented := binary + increment.asUInt()
|
||||||
incremented ^ (incremented >> UInt(1))
|
incremented ^ (incremented >> UInt(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AsyncGrayCounter {
|
object AsyncGrayCounter {
|
||||||
def apply(in: UInt, sync: Int): UInt = {
|
def apply(in: UInt, sync: Int): UInt = {
|
||||||
val syncv = RegInit(Vec.fill(sync){UInt(0, width = in.getWidth)})
|
val syncv = List.fill(sync)(Module (new AsyncResetRegVec(w = in.getWidth, 0)))
|
||||||
syncv.last := in
|
syncv.last.io.d := in
|
||||||
(syncv.init zip syncv.tail).foreach { case (sink, source) => sink := source }
|
syncv.last.io.en := Bool(true)
|
||||||
syncv(0)
|
(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 = 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 widx = GrayCounter(bits+1, io.enq.fire())
|
||||||
val ridx = AsyncGrayCounter(io.ridx, sync)
|
val ridx = AsyncGrayCounter(io.ridx, sync)
|
||||||
val ready = widx =/= (ridx ^ UInt(depth | depth >> 1))
|
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))
|
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 }
|
when (io.enq.fire() && !reset) { mem(index) := io.enq.bits }
|
||||||
io.enq.ready := RegNext(ready, Bool(false))
|
val ready_reg = AsyncResetReg(ready, 0)
|
||||||
io.widx := RegNext(widx, UInt(0))
|
io.enq.ready := ready_reg
|
||||||
|
|
||||||
|
val widx_reg = AsyncResetReg(widx, 0)
|
||||||
|
io.widx := widx_reg
|
||||||
|
|
||||||
io.mem := mem
|
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
|
// 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
|
// 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))
|
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)
|
// This register does not NEED to be reset, as its contents will not
|
||||||
io.deq.valid := RegNext(valid, Bool(false))
|
// be considered unless the asynchronously reset deq valid register is set.
|
||||||
io.ridx := RegNext(ridx, UInt(0))
|
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] {
|
class AsyncQueue[T <: Data](gen: T, depth: Int = 8, sync: Int = 3) extends Crossing[T] {
|
||||||
|
Loading…
Reference in New Issue
Block a user