All Downloads are FREE. Search and download functionalities are using the official Maven repository.

chisel.lib.fifo.MemFifo.scala Maven / Gradle / Ivy

The newest version!
// Author: Martin Schoeberl ([email protected])
// License: this code is released into the public domain, see README.md and http://unlicense.org/

package chisel.lib.fifo

import chisel3._
import chisel3.util._

/**
  * FIFO with memory and read and write pointers.
  * Extra shadow register to handle the one cycle latency of the synchronous memory.
  */
class MemFifo[T <: Data](gen: T, depth: Int) extends Fifo(gen: T, depth: Int) {

  def counter(depth: Int, incr: Bool): (UInt, UInt) = {
    val cntReg = RegInit(0.U(log2Ceil(depth).W))
    val nextVal = Mux(cntReg === (depth - 1).U, 0.U, cntReg + 1.U)
    when(incr) {
      cntReg := nextVal
    }
    (cntReg, nextVal)
  }

  val mem = SyncReadMem(depth, gen, SyncReadMem.WriteFirst)

  val incrRead = WireInit(false.B)
  val incrWrite = WireInit(false.B)
  val (readPtr, nextRead) = counter(depth, incrRead)
  val (writePtr, nextWrite) = counter(depth, incrWrite)

  val emptyReg = RegInit(true.B)
  val fullReg = RegInit(false.B)

  val outputReg = Reg(gen)
  val outputValidReg = RegInit(false.B)
  val read = WireDefault(false.B)

  io.deq.valid := outputValidReg
  io.enq.ready := !fullReg

  val doWrite = WireDefault(false.B)
  val data = Wire(gen)
  data := mem.read(readPtr)
  io.deq.bits := data
  when(doWrite) {
    mem.write(writePtr, io.enq.bits)
  }

  val readCond =
    !outputValidReg && ((readPtr =/= writePtr) || fullReg) // should add optimization when downstream is ready for pipielining
  when(readCond) {
    read := true.B
    incrRead := true.B
    outputReg := data
    outputValidReg := true.B
    emptyReg := nextRead === writePtr
    fullReg := false.B // no concurrent read when full (at the moment)
  }
  when(io.deq.fire) {
    outputValidReg := false.B
  }
  io.deq.bits := outputReg

  when(io.enq.fire) {
    emptyReg := false.B
    fullReg := (nextWrite === readPtr) & !read
    incrWrite := true.B
    doWrite := true.B
  }

  // some assertions
  val fullNr = Mux(fullReg, depth.U, 0.U)
  val number = writePtr - readPtr + fullNr
  assert(number >= 0.U)
  assert(number < (depth + 1).U)

  assert(!(emptyReg && fullReg))

  when(readPtr =/= writePtr) {
    assert(emptyReg === false.B)
    assert(fullReg === false.B)
  }

  when(fullReg) {
    assert(readPtr === writePtr)
  }

  when(emptyReg) {
    assert(readPtr === writePtr)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy