xref: /XiangShan/src/main/scala/device/AXI4RAM.scala (revision aa38aa4ddfa6ad6dd8ed11cb4ed01eac263efc7d)
1// See LICENSE.SiFive for license details.
2
3package device
4
5import chisel3._
6import chisel3.util._
7import chisel3.util.experimental.loadMemoryFromFile
8
9import bus.axi4._
10import utils._
11
12class RAMHelper(memByte: Int) extends BlackBox {
13  val io = IO(new Bundle {
14    val clk = Input(Clock())
15    val rIdx = Input(UInt(64.W))
16    val rdata = Output(UInt(64.W))
17    val wIdx = Input(UInt(64.W))
18    val wdata = Input(UInt(64.W))
19    val wmask = Input(UInt(64.W))
20    val wen = Input(Bool())
21  })
22}
23
24class AXI4RAM[T <: AXI4Lite](_type: T = new AXI4, memByte: Int, beatBytes: Int = 8,
25  useBlackBox: Boolean = false) extends AXI4SlaveModule(_type) {
26
27  val offsetBits = log2Up(memByte)
28  val offsetMask = (1 << offsetBits) - 1
29  def index(addr: UInt) = (addr & offsetMask.U) >> log2Ceil(beatBytes)
30  def inRange(idx: UInt) = idx < (memByte / 8).U
31
32  val wIdx = index(waddr) + writeBeatCnt
33  val rIdx = index(raddr) + readBeatCnt
34  val wen = in.w.fire() && inRange(wIdx)
35
36  val rdata = if (useBlackBox) {
37    val mem = Module(new RAMHelper(memByte))
38    mem.io.clk := clock
39    mem.io.rIdx := rIdx
40    mem.io.wIdx := wIdx
41    mem.io.wdata := in.w.bits.data
42    mem.io.wmask := Cat(in.w.bits.strb.asBools.map(Mux(_, 0xff.U, 0.U)).reverse)
43    mem.io.wen := wen
44    mem.io.rdata
45  } else {
46    val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W)))
47
48    val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8*(i+1)-1, 8*i) }
49    when (wen) { mem.write(wIdx, wdata, in.w.bits.strb.asBools) }
50
51    Cat(mem.read(rIdx).reverse)
52  }
53
54  in.r.bits.data := RegEnable(rdata, ren)
55}
56