From 5241ee6442d1be538e17bb646dfe375dc9e60088 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Tue, 16 Feb 2016 21:45:39 -0800 Subject: [PATCH] add multi-width FIFO --- junctions/src/main/scala/util.scala | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/junctions/src/main/scala/util.scala b/junctions/src/main/scala/util.scala index 28d5a470..f03251f1 100644 --- a/junctions/src/main/scala/util.scala +++ b/junctions/src/main/scala/util.scala @@ -219,3 +219,71 @@ class DecoupledHelper(val rvs: Seq[Bool]) { (rvs.filter(_ ne exclude) ++ includes).reduce(_ && _) } } + +class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module { + val io = new Bundle { + val in = Decoupled(Bits(width = inW)).flip + val out = Decoupled(Bits(width = outW)) + } + + if (inW == outW) { + io.out <> Queue(io.in, n) + } else if (inW > outW) { + val nBeats = inW / outW + + require(inW % outW == 0, s"MultiWidthFifo: in: $inW not divisible by out: $outW") + require(n % nBeats == 0, s"Cannot store $n output words when output beats is $nBeats") + + val wdata = Reg(Vec(n / nBeats, Bits(width = inW))) + val rdata = Vec(wdata.flatMap { indat => + (0 until nBeats).map(i => indat(outW * (i + 1) - 1, outW * i)) }) + + val head = Reg(init = UInt(0, log2Up(n / nBeats))) + val tail = Reg(init = UInt(0, log2Up(n))) + val size = Reg(init = UInt(0, log2Up(n + 1))) + + when (io.in.fire()) { + wdata(head) := io.in.bits + head := head + UInt(1) + } + + when (io.out.fire()) { tail := tail + UInt(1) } + + size := MuxCase(size, Seq( + (io.in.fire() && io.out.fire()) -> (size + UInt(nBeats - 1)), + io.in.fire() -> (size + UInt(nBeats)), + io.out.fire() -> (size - UInt(1)))) + + io.out.valid := size > UInt(0) + io.out.bits := rdata(tail) + io.in.ready := size < UInt(n) + } else { + val nBeats = outW / inW + + require(outW % inW == 0, s"MultiWidthFifo: out: $outW not divisible by in: $inW") + + val wdata = Reg(Vec(n * nBeats, Bits(width = inW))) + val rdata = Vec.tabulate(n) { i => + Cat(wdata.slice(i * nBeats, (i + 1) * nBeats).reverse)} + + val head = Reg(init = UInt(0, log2Up(n * nBeats))) + val tail = Reg(init = UInt(0, log2Up(n))) + val size = Reg(init = UInt(0, log2Up(n * nBeats + 1))) + + when (io.in.fire()) { + wdata(head) := io.in.bits + head := head + UInt(1) + } + + when (io.out.fire()) { tail := tail + UInt(1) } + + size := MuxCase(size, Seq( + (io.in.fire() && io.out.fire()) -> (size - UInt(nBeats - 1)), + io.in.fire() -> (size + UInt(1)), + io.out.fire() -> (size - UInt(nBeats)))) + + io.out.valid := size >= UInt(nBeats) + io.out.bits := rdata(tail) + io.in.ready := size < UInt(n * nBeats) + } +}