// See LICENSE for license details. package uncore.util import Chisel._ import uncore.tilelink._ class FlowThroughSerializer[T <: Bundle with HasTileLinkData](gen: T, n: Int) extends Module { val io = new Bundle { val in = Decoupled(gen).flip val out = Decoupled(gen) val cnt = UInt(OUTPUT, log2Up(n)) val done = Bool(OUTPUT) } val narrowWidth = io.in.bits.data.getWidth / n require(io.in.bits.data.getWidth % narrowWidth == 0) if(n == 1) { io.out <> io.in io.cnt := UInt(0) io.done := Bool(true) } else { val cnt = Reg(init=UInt(0, width = log2Up(n))) val wrap = cnt === UInt(n-1) val rbits = Reg{io.in.bits} val active = Reg(init=Bool(false)) val shifter = Wire(Vec(n, Bits(width = narrowWidth))) (0 until n).foreach { i => shifter(i) := rbits.data((i+1)*narrowWidth-1,i*narrowWidth) } io.done := Bool(false) io.cnt := cnt io.in.ready := !active io.out.valid := active || io.in.valid io.out.bits := io.in.bits when(!active && io.in.valid) { when(io.in.bits.hasData()) { cnt := Mux(io.out.ready, UInt(1), UInt(0)) rbits := io.in.bits active := Bool(true) } io.done := !io.in.bits.hasData() } when(active) { io.out.bits := rbits io.out.bits.data := shifter(cnt) when(io.out.ready) { cnt := cnt + UInt(1) when(wrap) { cnt := UInt(0) io.done := Bool(true) active := Bool(false) } } } } } object FlowThroughSerializer { def apply[T <: Bundle with HasTileLinkData](in: DecoupledIO[T], n: Int): DecoupledIO[T] = { val fs = Module(new FlowThroughSerializer(in.bits, n)) fs.io.in.valid := in.valid fs.io.in.bits := in.bits in.ready := fs.io.in.ready fs.io.out } }