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

spinal.lib.memory.sdram.dfi.function.DfiAlignment.scala Maven / Gradle / Ivy

package spinal.lib.memory.sdram.dfi.function

import spinal.core._
import spinal.lib._
import spinal.lib.memory.sdram.dfi.interface._

case class CAAlignment(config: DfiConfig) extends Component {
  import config._
  val io = new Bundle {
    val cmd = Vec(slave(Flow(DfiCmd(config))), config.frequencyRatio)
    val address = Vec(slave(Flow(DfiAddr(config))), config.frequencyRatio)
    val cke = in Vec (Bits(config.chipSelectNumber bits), config.frequencyRatio)
    val output = master(DfiControlInterface(config))
  }
  // cke,reserN,odt
  // Most DRAMs define CKE as low at reset; some devices, such as LPDDR1, LPDDR2 and LPDDR3, define CKE as high at
  // reset. The default value should adhere to the DRAM definition.
  io.output.cke := io.cke.asBits
  // In general, the dfi_reset_n signal is defined as low at reset; however, in some cases it may be necessary
  // to hold dfi_reset_n high during initialization.
  if (useResetN) io.output.resetN.setAll()
  // The MC generates dfi_odt (dfi_odt_pN in frequency ratio systems) based on the DRAM burst length including
  // CRC data. With CRC enabled, the MC may need to extend ODT.
  if (useOdt) io.output.odt.clearAll()

  // cmd
  if (useAckN) io.output.actN := Bits(widthOf(io.output.actN) bits).setAll()
  io.output.csN := Bits(widthOf(io.output.csN) bits).setAll()
  io.output.rasN := Bits(widthOf(io.output.rasN) bits).setAll()
  io.output.casN := Bits(widthOf(io.output.casN) bits).setAll()
  io.output.weN := Bits(widthOf(io.output.weN) bits).setAll()
  if (useCid) io.output.cid := Bits(widthOf(io.output.cid) bits).clearAll()

  // address
  if (config.useBg) io.output.bg := Bits(widthOf(io.output.bg) bits).assignDontCare()
  io.output.bank := Bits(widthOf(io.output.bank) bits).clearAll()
  io.output.address := Bits(widthOf(io.output.address) bits).clearAll()

  def csN = io.output.csN.subdivideIn(frequencyRatio slices)
  def casN = io.output.casN.subdivideIn(frequencyRatio slices)
  def rasN = io.output.rasN.subdivideIn(frequencyRatio slices)
  def weN = io.output.weN.subdivideIn(frequencyRatio slices)

  for (i <- 0 until (frequencyRatio)) {
    when(io.cmd(i).valid) {
      if (useAckN) io.output.actN.subdivideIn(frequencyRatio slices)(i) := io.cmd(i).actN.asBits
      if (useCid) io.output.cid.subdivideIn(frequencyRatio slices)(i) := io.cmd(i).cid.asBits
      csN(i) := io.cmd(i).csN.asBits
      casN(i) := io.cmd(i).casN.asBits
      rasN(i) := io.cmd(i).rasN.asBits
      weN(i) := io.cmd(i).weN.asBits
    }
    when(io.address(i).valid) {
      if (config.useBg) io.output.bg(i * bankGroupWidth, bankGroupWidth bits) := io.address(i).bg
      io.output.bank(i * bankWidth, bankWidth bits) := io.address(i).bank
      io.output.address(i * addressWidth, addressWidth bits) := io.address(i).address
    }
  }
}

case class RdAlignment(config: DfiConfig) extends Component {
  import config._
  val io = new Bundle {
    val phaseClear = in Bool ()
    val dfiRd = in Vec (DfiRd(config), config.frequencyRatio)
    val dfiRdCs = useRddataCsN generate Vec(out(DfiRdCs(config)), config.frequencyRatio)
    val idfiRd = Vec(master(Stream(Fragment(DfiRdData(config)))), config.frequencyRatio)
    val idfiRdCs = useRddataCsN generate Vec(slave(Flow(DfiReadCs(config))), config.frequencyRatio)
  }

  val rdDataTemp = Vec(Stream(Fragment(DfiRdData(config))), config.frequencyRatio)
  rdDataTemp.foreach(_.last.clear())
  for (i <- 0 until (frequencyRatio)) {
    rdDataTemp(i).valid := io.dfiRd(i).rddataValid
    rdDataTemp(i).rdData.assignDontCare()
  }

  val curPhase = Reg(UInt(log2Up(frequencyRatio) bits)) init (0)
  val rdDataPhase = Reg(UInt(log2Up(frequencyRatio) + 1 bits)) init (0)
  rdDataPhase.clearAll()
  when(io.phaseClear) {
    curPhase := U(0)
  }

  for (i <- 0 until (frequencyRatio)) {
    when(rdDataTemp(i).fire) {
      rdDataTemp(i).rdData := (i + curPhase + frequencyRatio - rdDataPhase)
        .resize(log2Up(frequencyRatio))
        .muxListDc(io.dfiRd.zipWithIndex.map(t => (t._2, t._1)))
        .rddata
      curPhase := (i + 1) % frequencyRatio
      rdDataPhase := (rdDataPhase + i + 1 + frequencyRatio - curPhase).resize(log2Up(frequencyRatio)).resized
    }
  }
  val rdDataFifos = for (i <- 0 until (frequencyRatio)) yield new Area {
    val rdDataFifo = new StreamFifo(Fragment(DfiRdData(config)), config.beatCount + 2)
    rdDataFifo.io.flush.clear()
    rdDataFifo.io.flush.setWhen(io.phaseClear)
  }
  val readyForPop = Mux(rdDataFifos.map(_.rdDataFifo.io.occupancy =/= 0).andR, io.idfiRd.map(_.ready).orR, False)

  for (i <- 0 until (frequencyRatio)) {
    rdDataFifos(i).rdDataFifo.io.push << rdDataTemp(i)
    io.idfiRd(i).valid := rdDataFifos.map(_.rdDataFifo.io.pop.valid).andR
    io.idfiRd(i).payload := rdDataFifos(i).rdDataFifo.io.pop.payload
    rdDataFifos(i).rdDataFifo.io.pop.ready := RegNext(readyForPop)
  }

  if (useRddataCsN) {
    for (i <- 0 until (frequencyRatio)) {
      io.dfiRdCs(i).rddataCsN.setAll()
      when(io.idfiRdCs(i).valid) {
        io.dfiRdCs(i).rddataCsN := io.idfiRdCs(i).rdCs
      }
    }
  }
}

case class WrAlignment(config: DfiConfig) extends Component {
  import config._
  val io = new Bundle {
    val idfiWrCs = useWrdataCsN generate Vec(slave(Flow(DfiWrCs(config))), config.frequencyRatio)
    val idfiWrData = Vec(slave(Flow(DfiWrData(config))), config.frequencyRatio)
    val dfiWr = master(DfiWriteInterface(config))
  }
  for (i <- 0 until (frequencyRatio)) {
    io.dfiWr.wr(i).wrdataEn := io.idfiWrData(i).valid
  }

  val delay = Reg(U(timeConfig.tPhyWrData / frequencyRatio) << 1).init(0)

  when(io.idfiWrData.map(_.valid).orR.rise()) {
    delay := timeConfig.tPhyWrData / frequencyRatio
  }

  val wrdatahistary = Vec(Vec(DfiWrData(config), timeConfig.tPhyWrData / frequencyRatio + 2), frequencyRatio)
  for (i <- 0 until (frequencyRatio)) {
    wrdatahistary(i) := History(io.idfiWrData(i).payload, 0 to timeConfig.tPhyWrData / frequencyRatio + 1)
    io.dfiWr.wr(i).wrdata.assignDontCare()
    io.dfiWr.wr(i).wrdataMask.assignDontCare()
  }

  for (phase <- 0 until (frequencyRatio)) {
    io.dfiWr.wr(phase).wrdata := (if (phase < timeConfig.tPhyWrData % frequencyRatio) delay + 1 else delay)
      .muxListDc(
        wrdatahistary
          .shuffle(t => (t + timeConfig.tPhyWrData % frequencyRatio) % frequencyRatio)(phase)
          .zipWithIndex
          .map(t => (t._2, t._1))
      )
      .wrData
    io.dfiWr.wr(phase).wrdataMask := (if (phase < timeConfig.tPhyWrData % frequencyRatio) delay + 1 else delay)
      .muxListDc(
        wrdatahistary
          .shuffle(t => (t + timeConfig.tPhyWrData % frequencyRatio) % frequencyRatio)(phase)
          .zipWithIndex
          .map(t => (t._2, t._1))
      )
      .wrDataMask
  }

  if (useWrdataCsN) {
    for (i <- 0 until (frequencyRatio)) {
      io.dfiWr.wr(i).wrdataCsN.setAll()
      when(io.idfiWrCs(i).valid) {
        io.dfiWr.wr(i).wrdataCsN := io.idfiWrCs(i).wrCs
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy