49 lines
1.7 KiB
Scala
49 lines
1.7 KiB
Scala
|
// See LICENSE.SiFive for license details.
|
||
|
|
||
|
package uncore.apb
|
||
|
|
||
|
import Chisel._
|
||
|
import config._
|
||
|
import diplomacy._
|
||
|
|
||
|
class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||
|
{
|
||
|
val node = APBSlaveNode(APBSlavePortParameters(
|
||
|
Seq(APBSlaveParameters(
|
||
|
address = List(address),
|
||
|
regionType = RegionType.UNCACHED,
|
||
|
executable = executable,
|
||
|
supportsRead = true,
|
||
|
supportsWrite = true)),
|
||
|
beatBytes = beatBytes))
|
||
|
|
||
|
// We require the address range to include an entire beat (for the write mask)
|
||
|
require ((address.mask & (beatBytes-1)) == beatBytes-1)
|
||
|
|
||
|
lazy val module = new LazyModuleImp(this) {
|
||
|
val io = new Bundle {
|
||
|
val in = node.bundleIn
|
||
|
}
|
||
|
|
||
|
val in = io.in(0)
|
||
|
|
||
|
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
|
||
|
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
|
||
|
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
|
||
|
val paddr = Cat((mask zip (in.paddr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse)
|
||
|
|
||
|
// Use single-ported memory with byte-write enable
|
||
|
val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8)))
|
||
|
def holdUnless[T <: Data](in : T, enable: Bool): T = Mux(!enable, RegEnable(in, enable), in)
|
||
|
|
||
|
val read = in.psel && !in.penable && !in.pwrite
|
||
|
when (in.psel && !in.penable && in.pwrite) {
|
||
|
mem.write(paddr, Vec.tabulate(beatBytes) { i => in.pwdata(8*(i+1)-1, 8*i) }, in.pstrb.toBools)
|
||
|
}
|
||
|
|
||
|
in.pready := Bool(true)
|
||
|
in.pslverr := Bool(false)
|
||
|
in.prdata := holdUnless(mem.read(paddr, read).asUInt, RegNext(read))
|
||
|
}
|
||
|
}
|