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 12sealed abstract class RAM[T <: AXI4Lite](_type: T, 13 memByte: Int, beatBytes: Int = 4, dataFile: String = "") extends Module { 14 val io = IO(new Bundle{ 15 val in = Flipped(_type) 16 }) 17 18 val in = io.in 19 val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W))) 20 if (dataFile != "") loadMemoryFromFile(mem, dataFile) 21 22 def index(addr: UInt) = addr >> log2Ceil(beatBytes) 23 24 val w_full = BoolStopWatch(in.aw.fire(), in.b.fire(), startHighPriority = true) 25 val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8*(i+1)-1, 8*i) } 26 when (in.aw.fire()) { 27 mem.write(index(in.ar.bits.addr), wdata, in.w.bits.strb.toBools) 28 } 29 30 in. b.valid := w_full 31 in.aw.ready := in. w.valid && (in.b.ready || !w_full) 32 in. w.ready := in.aw.valid && (in.b.ready || !w_full) 33 in.b.bits.resp := AXI4Parameters.RESP_OKAY 34 35 def holdUnless[T <: Data](x: T, enable: Bool): T = Mux(enable, x, RegEnable(x, enable)) 36 37 val r_full = BoolStopWatch(in.ar.fire(), in.r.fire(), startHighPriority = true) 38 val ren = in.ar.fire() 39 val rdata = RegEnable(mem.read(index(in.ar.bits.addr)), ren) 40 41 in. r.valid := r_full 42 in.ar.ready := in.r.ready || !r_full 43 in.r.bits.resp := AXI4Parameters.RESP_OKAY 44 in.r.bits.data := Cat(rdata.reverse) 45} 46 47class AXI4LiteRAM(memByte: Int, beatBytes: Int = 4, dataFile: String = "") 48 extends RAM(new AXI4Lite, memByte, beatBytes, dataFile) 49 50class AXI4RAM(memByte: Int, beatBytes: Int = 4, dataFile: String = "") 51 extends RAM(new AXI4, memByte, beatBytes, dataFile) { 52 53 in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire()) 54 in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire()) 55 in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire()) 56 in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire()) 57 in.r.bits.last := true.B 58} 59