1
0

Apply "async_queue: Give names to all the registers which show up in the queue (#390)"

Adjusted to include names for the new registers.
Changes to RegisterCrossing were discarded.
This commit is contained in:
Wesley W. Terpstra 2016-10-08 20:25:19 -07:00
parent ffb734ac0e
commit 52b8121e68

View File

@ -4,17 +4,19 @@ package util
import Chisel._
object GrayCounter {
def apply(bits: Int, increment: Bool = Bool(true), clear: Bool = Bool(false)): UInt = {
def apply(bits: Int, increment: Bool = Bool(true), clear: Bool = Bool(false), name: String = "binary"): UInt = {
val incremented = Wire(UInt(width=bits))
val binary = AsyncResetReg(incremented)
val binary = AsyncResetReg(incremented, name)
incremented := Mux(clear, UInt(0), binary + increment.asUInt())
incremented ^ (incremented >> UInt(1))
}
}
object AsyncGrayCounter {
def apply(in: UInt, sync: Int): UInt = {
val syncv = List.fill(sync)(Module (new AsyncResetRegVec(w = in.getWidth, 0)))
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) =>
@ -39,22 +41,22 @@ class AsyncQueueSource[T <: Data](gen: T, depth: Int, sync: Int) extends Module
}
// extend the sink reset to a full cycle (assertion latency <= 1 cycle)
val catch_reset_n = AsyncResetReg(Bool(true), clock, !io.sink_reset_n)
val catch_reset_n = AsyncResetReg(Bool(true), clock, !io.sink_reset_n, "catch_sink_reset_n")
// reset_n has a 1 cycle shorter path to ready than ridx does
val sink_reset_n = AsyncGrayCounter(catch_reset_n.asUInt, sync)(0)
val sink_reset_n = AsyncGrayCounter(catch_reset_n.asUInt, sync, "sink_reset_n")(0)
val mem = Reg(Vec(depth, gen)) //This does NOT need to be asynchronously reset.
val widx = GrayCounter(bits+1, io.enq.fire(), !sink_reset_n)
val ridx = AsyncGrayCounter(io.ridx, sync)
val widx = GrayCounter(bits+1, io.enq.fire(), !sink_reset_n, "widx_bin")
val ridx = AsyncGrayCounter(io.ridx, sync, "ridx_gray")
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()) { mem(index) := io.enq.bits }
val ready_reg = AsyncResetReg(ready.asUInt)(0)
val ready_reg = AsyncResetReg(ready.asUInt, "ready")(0)
io.enq.ready := ready_reg && sink_reset_n
val widx_reg = AsyncResetReg(widx)
val widx_reg = AsyncResetReg(widx, "widx_gray")
io.widx := widx_reg
io.mem := mem
@ -77,12 +79,12 @@ class AsyncQueueSink[T <: Data](gen: T, depth: Int, sync: Int) extends Module {
}
// extend the source reset to a full cycle (assertion latency <= 1 cycle)
val catch_reset_n = AsyncResetReg(Bool(true), clock, !io.source_reset_n)
val catch_reset_n = AsyncResetReg(Bool(true), clock, !io.source_reset_n, "catch_source_reset_n")
// reset_n has a 1 cycle shorter path to valid than widx does
val source_reset_n = AsyncGrayCounter(catch_reset_n.asUInt, sync)(0)
val source_reset_n = AsyncGrayCounter(catch_reset_n.asUInt, sync, "source_reset_n")(0)
val ridx = GrayCounter(bits+1, io.deq.fire(), !source_reset_n)
val widx = AsyncGrayCounter(io.widx, sync)
val ridx = GrayCounter(bits+1, io.deq.fire(), !source_reset_n, "ridx_bin")
val widx = AsyncGrayCounter(io.widx, sync, "widx_gray")
val valid = ridx =/= widx
// The mux is safe because timing analysis ensures ridx has reached the register
@ -96,10 +98,10 @@ class AsyncQueueSink[T <: Data](gen: T, depth: Int, sync: Int) extends Module {
// This is safe, because isolation gates brought mem low before the zeroed widx reached us
io.deq.bits := RegEnable(io.mem(index), valid)
val valid_reg = AsyncResetReg(valid.asUInt)(0)
val valid_reg = AsyncResetReg(valid.asUInt, "valid_reg")(0)
io.deq.valid := valid_reg && source_reset_n
val ridx_reg = AsyncResetReg(ridx)
val ridx_reg = AsyncResetReg(ridx, "ridx_gray")
io.ridx := ridx_reg
// It is a fatal error to reset half a Queue while it still has data