chisel.lib.dclib.DCAsyncFifo.scala Maven / Gradle / Ivy
The newest version!
package chisel.lib.dclib
import chisel3._
import chisel3.util._
/**
* Asynchronous FIFO with Decoupled interfaces
*
* Implements a clock-domain crossing FIFO with synchronized pointers. The FIFO must be a natural power of 2
* in depth, and should be at least 8 words deep for full performance. Internally uses a 1-bit larger pointer
* value to track empty vs. full.
*
* @param data Data type for FIFO
* @param depth Depth of FIFO, must be power of 2
* @param doubleSync Generator function to create a double-synchronized version of input
*/
class DCAsyncFifo[D <: Data](data: D, depth: Int, doubleSync: (UInt) => UInt = defaultDoubleSync) extends RawModule {
val io = IO(new Bundle {
val enqClock = Input(Clock())
val enqReset = Input(Reset())
val deqClock = Input(Clock())
val deqReset = Input(Reset())
val enq = Flipped(new DecoupledIO(data.cloneType))
val deq = new DecoupledIO(data.cloneType)
})
// Async FIFO must be power of two for pointer sync to work correctly
val asz = log2Ceil(depth)
require(depth == 1 << asz)
val mem = withClockAndReset(io.enqClock, io.enqReset) {
Reg(Vec(depth, data))
}
val wrptr_enq = withClockAndReset(io.enqClock, io.enqReset) {
RegInit(init = 0.U((asz + 1).W))
}
val wrptr_grey_enq = BinaryToGray(wrptr_enq)
val wrptr_grey_deq = withClockAndReset(io.deqClock, io.deqReset) {
doubleSync(wrptr_grey_enq)
}
val rdptr_deq = withClockAndReset(io.deqClock, io.deqReset) {
RegInit(init = 0.U((asz + 1).W))
}
val rdptr_grey_deq = BinaryToGray(rdptr_deq)
val rdptr_grey_enq = withClockAndReset(io.enqClock, io.enqReset) {
doubleSync(rdptr_grey_deq)
}
val full_enq =
wrptr_grey_enq(asz - 1, 0) === rdptr_grey_enq(asz - 1, 0) & (wrptr_grey_enq(asz) =/= rdptr_grey_enq(asz))
val empty_deq = wrptr_grey_deq === rdptr_grey_deq
io.enq.ready := !full_enq
when(io.enq.fire) {
wrptr_enq := wrptr_enq + 1.U
withClockAndReset(io.enqClock, io.enqReset) {
mem(wrptr_enq(asz - 1, 0)) := io.enq.bits
}
}
io.deq.valid := !empty_deq
when(io.deq.fire) {
rdptr_deq := rdptr_deq + 1.U
}
io.deq.bits := mem(rdptr_deq(asz - 1, 0))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy