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