Clean Murax toplevel by extracting integrated Area into dedicated components located in MuraxUtiles.scala
This commit is contained in:
parent
0cf278b04f
commit
a72c7fd0d1
|
@ -2,15 +2,15 @@ package vexriscv.demo
|
|||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba3.apb.{Apb3SlaveFactory, Apb3Decoder, Apb3Gpio, Apb3}
|
||||
import spinal.lib.bus.amba3.apb._
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
import spinal.lib.com.jtag.Jtag
|
||||
import spinal.lib.com.uart._
|
||||
import spinal.lib.io.TriStateArray
|
||||
import spinal.lib.misc.{InterruptCtrl, Timer, Prescaler}
|
||||
import spinal.lib.soc.pinsec.{PinsecTimerCtrlExternal, PinsecTimerCtrl}
|
||||
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
||||
import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{plugin, VexRiscvConfig, VexRiscv}
|
||||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
@ -132,31 +132,10 @@ object MuraxConfig{
|
|||
}
|
||||
}
|
||||
|
||||
case class SimpleBusCmd() extends Bundle{
|
||||
val wr = Bool
|
||||
val address = UInt(32 bits)
|
||||
val data = Bits(32 bit)
|
||||
val mask = Bits(4 bit)
|
||||
}
|
||||
|
||||
case class SimpleBusRsp() extends Bundle{
|
||||
val data = Bits(32 bit)
|
||||
}
|
||||
|
||||
|
||||
case class SimpleBus() extends Bundle with IMasterSlave {
|
||||
val cmd = Stream(SimpleBusCmd())
|
||||
val rsp = Flow(SimpleBusRsp())
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
master(cmd)
|
||||
slave(rsp)
|
||||
}
|
||||
}
|
||||
|
||||
case class Murax(config : MuraxConfig) extends Component{
|
||||
import config._
|
||||
|
||||
|
||||
val io = new Bundle {
|
||||
//Clocks / reset
|
||||
val asyncReset = in Bool
|
||||
|
@ -203,14 +182,22 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
reset = resetCtrl.systemReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
|
||||
val debugClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.mainClkReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
|
||||
val system = new ClockingArea(systemClockDomain) {
|
||||
val simpleBusConfig = SimpleBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
||||
//Priority to dBus, !! cmd transactions can change on the fly !!
|
||||
val mainBusArbiter = new MuraxMasterArbiter(simpleBusConfig)
|
||||
|
||||
//Instanciate the CPU
|
||||
val cpu = new VexRiscv(
|
||||
|
@ -222,18 +209,14 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
//Checkout plugins used to instanciate the CPU to connect them to the SoC
|
||||
val timerInterrupt = False
|
||||
val externalInterrupt = False
|
||||
var iBus : IBusSimpleBus = null
|
||||
var dBus : DBusSimpleBus = null
|
||||
var debugBus : DebugExtensionBus = null
|
||||
for(plugin <- cpu.plugins) plugin match{
|
||||
case plugin : IBusSimplePlugin => iBus = plugin.iBus
|
||||
case plugin : IBusSimplePlugin => mainBusArbiter.io.iBus <> plugin.iBus
|
||||
case plugin : DBusSimplePlugin => {
|
||||
if(!pipelineDBus)
|
||||
dBus = plugin.dBus
|
||||
mainBusArbiter.io.dBus <> plugin.dBus
|
||||
else {
|
||||
dBus = cloneOf(plugin.dBus)
|
||||
dBus.cmd << plugin.dBus.cmd.halfPipe()
|
||||
dBus.rsp <> plugin.dBus.rsp
|
||||
mainBusArbiter.io.dBus.cmd << plugin.dBus.cmd.halfPipe()
|
||||
mainBusArbiter.io.dBus.rsp <> plugin.dBus.rsp
|
||||
}
|
||||
}
|
||||
case plugin : CsrPlugin => {
|
||||
|
@ -248,218 +231,58 @@ case class Murax(config : MuraxConfig) extends Component{
|
|||
}
|
||||
|
||||
|
||||
val mainBus = SimpleBus()
|
||||
|
||||
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
||||
//Priority to dBus, !! cmd transactions can change on the fly !!
|
||||
val mainBusArbiter = new Area{
|
||||
mainBus.cmd.valid := iBus.cmd.valid || dBus.cmd.valid
|
||||
mainBus.cmd.wr := dBus.cmd.valid && dBus.cmd.wr
|
||||
mainBus.cmd.address := dBus.cmd.valid ? dBus.cmd.address | iBus.cmd.pc
|
||||
mainBus.cmd.data := dBus.cmd.data
|
||||
mainBus.cmd.mask := dBus.cmd.size.mux(
|
||||
0 -> B"0001",
|
||||
1 -> B"0011",
|
||||
default -> B"1111"
|
||||
) |<< dBus.cmd.address(1 downto 0)
|
||||
iBus.cmd.ready := mainBus.cmd.ready && !dBus.cmd.valid
|
||||
dBus.cmd.ready := mainBus.cmd.ready
|
||||
|
||||
|
||||
val rspPending = RegInit(False) clearWhen(mainBus.rsp.valid)
|
||||
val rspTarget = RegInit(False)
|
||||
when(mainBus.cmd.fire && !mainBus.cmd.wr){
|
||||
rspTarget := dBus.cmd.valid
|
||||
rspPending := True
|
||||
}
|
||||
|
||||
when(rspPending && !mainBus.rsp.valid){
|
||||
iBus.cmd.ready := False
|
||||
dBus.cmd.ready := False
|
||||
mainBus.cmd.valid := False
|
||||
}
|
||||
|
||||
iBus.rsp.ready := mainBus.rsp.valid && !rspTarget
|
||||
iBus.rsp.inst := mainBus.rsp.data
|
||||
iBus.rsp.error := False
|
||||
|
||||
dBus.rsp.ready := mainBus.rsp.valid && rspTarget
|
||||
dBus.rsp.data := mainBus.rsp.data
|
||||
dBus.rsp.error := False
|
||||
}
|
||||
|
||||
//Create an SimpleBus mapped RAM
|
||||
val ram = new Area{
|
||||
val bus = SimpleBus()
|
||||
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
||||
bus.rsp.valid := RegNext(bus.cmd.fire && !bus.cmd.wr) init(False)
|
||||
bus.rsp.data := ram.readWriteSync(
|
||||
address = (bus.cmd.address >> 2).resized,
|
||||
data = bus.cmd.data,
|
||||
enable = bus.cmd.valid,
|
||||
write = bus.cmd.wr,
|
||||
mask = bus.cmd.mask
|
||||
)
|
||||
bus.cmd.ready := True
|
||||
|
||||
if(onChipRamHexFile != null){
|
||||
def readHexFile(path : String, callback : (Int, Int) => Unit): Unit ={
|
||||
import scala.io.Source
|
||||
def hToI(that : String, start : Int, size : Int) = Integer.parseInt(that.substring(start,start + size), 16)
|
||||
|
||||
var offset = 0
|
||||
for (line <- Source.fromFile(path).getLines) {
|
||||
if (line.charAt(0) == ':'){
|
||||
val byteCount = hToI(line, 1, 2)
|
||||
val nextAddr = hToI(line, 3, 4) + offset
|
||||
val key = hToI(line, 7, 2)
|
||||
key match {
|
||||
case 0 =>
|
||||
for(i <- 0 until byteCount){
|
||||
callback(nextAddr + i, hToI(line, 9 + i * 2, 2))
|
||||
}
|
||||
case 2 =>
|
||||
offset = hToI(line, 9, 4) << 4
|
||||
case 4 =>
|
||||
offset = hToI(line, 9, 4) << 16
|
||||
case 3 =>
|
||||
case 1 =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val initContent = Array.fill[BigInt](ram.wordCount)(0)
|
||||
readHexFile(onChipRamHexFile,(address,data) => {
|
||||
initContent(address >> 2) |= BigInt(data) << ((address & 3)*8)
|
||||
})
|
||||
ram.initBigInt(initContent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Bridge simpleBus to apb
|
||||
val apbBridge = new Area{
|
||||
val simpleBus = SimpleBus()
|
||||
val apb = Apb3(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
)
|
||||
val simpleBusStage = SimpleBus()
|
||||
simpleBusStage.cmd << (if(pipelineApbBridge) simpleBus.cmd.halfPipe() else simpleBus.cmd)
|
||||
simpleBusStage.rsp >-> simpleBus.rsp
|
||||
|
||||
val state = RegInit(False)
|
||||
simpleBusStage.cmd.ready := False
|
||||
|
||||
apb.PSEL(0) := simpleBusStage.cmd.valid
|
||||
apb.PENABLE := state
|
||||
apb.PWRITE := simpleBusStage.cmd.wr
|
||||
apb.PADDR := simpleBusStage.cmd.address.resized
|
||||
apb.PWDATA := simpleBusStage.cmd.data
|
||||
|
||||
simpleBusStage.rsp.valid := False
|
||||
simpleBusStage.rsp.data := apb.PRDATA
|
||||
when(!state){
|
||||
state := simpleBusStage.cmd.valid
|
||||
} otherwise{
|
||||
when(apb.PREADY){
|
||||
state := False
|
||||
simpleBusStage.rsp.valid := !simpleBusStage.cmd.wr
|
||||
simpleBusStage.cmd.ready := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Connect the mainBus to all slaves (ram, apbBridge)
|
||||
val mainBusDecoder = new Area {
|
||||
val masterBus = SimpleBus()
|
||||
if(!pipelineMainBus) {
|
||||
masterBus.cmd << mainBus.cmd
|
||||
masterBus.rsp >> mainBus.rsp
|
||||
} else {
|
||||
masterBus.cmd <-< mainBus.cmd
|
||||
masterBus.rsp >> mainBus.rsp
|
||||
}
|
||||
|
||||
val specification = List[(SimpleBus,SizeMapping)](
|
||||
ram.bus -> (0x00000000l, onChipRamSize kB),
|
||||
apbBridge.simpleBus -> (0xF0000000l, 1 MB)
|
||||
)
|
||||
|
||||
val slaveBuses = specification.map(_._1)
|
||||
val memorySpaces = specification.map(_._2)
|
||||
|
||||
val hits = for((slaveBus, memorySpace) <- specification) yield {
|
||||
val hit = memorySpace.hit(masterBus.cmd.address)
|
||||
slaveBus.cmd.valid := masterBus.cmd.valid && hit
|
||||
slaveBus.cmd.payload := masterBus.cmd.payload
|
||||
hit
|
||||
}
|
||||
val noHit = !hits.orR
|
||||
masterBus.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR || noHit
|
||||
|
||||
val rspPending = RegInit(False) clearWhen(masterBus.rsp.valid) setWhen(masterBus.cmd.fire && !masterBus.cmd.wr)
|
||||
val rspNoHit = RegNext(False) init(False) setWhen(noHit)
|
||||
val rspSourceId = RegNextWhen(OHToUInt(hits), masterBus.cmd.fire)
|
||||
masterBus.rsp.valid := slaveBuses.map(_.rsp.valid).orR || (rspPending && rspNoHit)
|
||||
masterBus.rsp.payload := slaveBuses.map(_.rsp.payload).read(rspSourceId)
|
||||
|
||||
when(rspPending && !masterBus.rsp.valid) { //Only one pending read request is allowed
|
||||
masterBus.cmd.ready := False
|
||||
slaveBuses.foreach(_.cmd.valid := False)
|
||||
}
|
||||
}
|
||||
|
||||
val gpioACtrl = Apb3Gpio(
|
||||
gpioWidth = gpioWidth
|
||||
//****** MainBus slaves ********
|
||||
val ram = new MuraxSimpleBusRam(
|
||||
onChipRamSize = onChipRamSize,
|
||||
onChipRamHexFile = onChipRamHexFile,
|
||||
simpleBusConfig = simpleBusConfig
|
||||
)
|
||||
|
||||
val apbBridge = new MuraxSimpleBusToApbBridge(
|
||||
apb3Config = Apb3Config(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
),
|
||||
pipelineBridge = pipelineApbBridge,
|
||||
simpleBusConfig = simpleBusConfig
|
||||
)
|
||||
|
||||
|
||||
|
||||
//******** APB peripherals *********
|
||||
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth)
|
||||
io.gpioA <> gpioACtrl.io.gpio
|
||||
|
||||
val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
|
||||
uartCtrl.io.uart <> io.uart
|
||||
externalInterrupt setWhen(uartCtrl.io.interrupt)
|
||||
|
||||
val timer = new Area{
|
||||
val apb = Apb3(
|
||||
addressWidth = 8,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
val prescaler = Prescaler(16)
|
||||
val timerA,timerB = Timer(16)
|
||||
|
||||
val busCtrl = Apb3SlaveFactory(apb)
|
||||
val prescalerBridge = prescaler.driveFrom(busCtrl,0x00)
|
||||
|
||||
val timerABridge = timerA.driveFrom(busCtrl,0x40)(
|
||||
ticks = List(True, prescaler.io.overflow),
|
||||
clears = List(timerA.io.full)
|
||||
)
|
||||
|
||||
val timerBBridge = timerB.driveFrom(busCtrl,0x50)(
|
||||
ticks = List(True, prescaler.io.overflow),
|
||||
clears = List(timerB.io.full)
|
||||
)
|
||||
|
||||
val interruptCtrl = InterruptCtrl(2)
|
||||
val interruptCtrlBridge = interruptCtrl.driveFrom(busCtrl,0x10)
|
||||
interruptCtrl.io.inputs(0) := timerA.io.full
|
||||
interruptCtrl.io.inputs(1) := timerB.io.full
|
||||
timerInterrupt setWhen(interruptCtrl.io.pendings.orR)
|
||||
}
|
||||
val timer = new MuraxApb3Timer()
|
||||
timerInterrupt setWhen(timer.io.interrupt)
|
||||
|
||||
|
||||
|
||||
//******** Memory mappings *********
|
||||
val apbDecoder = Apb3Decoder(
|
||||
master = apbBridge.apb,
|
||||
master = apbBridge.io.apb,
|
||||
slaves = List(
|
||||
gpioACtrl.io.apb -> (0x00000, 4 kB),
|
||||
uartCtrl.io.apb -> (0x10000, 4 kB),
|
||||
timer.apb -> (0x20000, 4 kB)
|
||||
timer.io.apb -> (0x20000, 4 kB)
|
||||
)
|
||||
)
|
||||
|
||||
val mainBusDecoder = new Area {
|
||||
val logic = new MuraxSimpleBusDecoder(
|
||||
master = mainBusArbiter.io.masterBus,
|
||||
specification = List[(SimpleBus,SizeMapping)](
|
||||
ram.io.bus -> (0x00000000l, onChipRamSize kB),
|
||||
apbBridge.io.simpleBus -> (0xF0000000l, 1 MB)
|
||||
),
|
||||
pipelineMaster = pipelineMainBus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
||||
import spinal.lib._
|
||||
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus}
|
||||
|
||||
case class SimpleBusConfig(addressWidth : Int, dataWidth : Int)
|
||||
|
||||
case class SimpleBusCmd(config : SimpleBusConfig) extends Bundle{
|
||||
val wr = Bool
|
||||
val address = UInt(config.addressWidth bits)
|
||||
val data = Bits(config.dataWidth bits)
|
||||
val mask = Bits(4 bit)
|
||||
}
|
||||
|
||||
case class SimpleBusRsp(config : SimpleBusConfig) extends Bundle{
|
||||
val data = Bits(config.dataWidth bits)
|
||||
}
|
||||
|
||||
|
||||
case class SimpleBus(config : SimpleBusConfig) extends Bundle with IMasterSlave {
|
||||
val cmd = Stream(SimpleBusCmd(config))
|
||||
val rsp = Flow(SimpleBusRsp(config))
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
master(cmd)
|
||||
slave(rsp)
|
||||
}
|
||||
}
|
||||
|
||||
class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
|
||||
val io = new Bundle{
|
||||
val iBus = slave(IBusSimpleBus(false))
|
||||
val dBus = slave(DBusSimpleBus())
|
||||
val masterBus = master(SimpleBus(simpleBusConfig))
|
||||
}
|
||||
|
||||
io.masterBus.cmd.valid := io.iBus.cmd.valid || io.dBus.cmd.valid
|
||||
io.masterBus.cmd.wr := io.dBus.cmd.valid && io.dBus.cmd.wr
|
||||
io.masterBus.cmd.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc
|
||||
io.masterBus.cmd.data := io.dBus.cmd.data
|
||||
io.masterBus.cmd.mask := io.dBus.cmd.size.mux(
|
||||
0 -> B"0001",
|
||||
1 -> B"0011",
|
||||
default -> B"1111"
|
||||
) |<< io.dBus.cmd.address(1 downto 0)
|
||||
io.iBus.cmd.ready := io.masterBus.cmd.ready && !io.dBus.cmd.valid
|
||||
io.dBus.cmd.ready := io.masterBus.cmd.ready
|
||||
|
||||
|
||||
val rspPending = RegInit(False) clearWhen(io.masterBus.rsp.valid)
|
||||
val rspTarget = RegInit(False)
|
||||
when(io.masterBus.cmd.fire && !io.masterBus.cmd.wr){
|
||||
rspTarget := io.dBus.cmd.valid
|
||||
rspPending := True
|
||||
}
|
||||
|
||||
when(rspPending && !io.masterBus.rsp.valid){
|
||||
io.iBus.cmd.ready := False
|
||||
io.dBus.cmd.ready := False
|
||||
io.masterBus.cmd.valid := False
|
||||
}
|
||||
|
||||
io.iBus.rsp.ready := io.masterBus.rsp.valid && !rspTarget
|
||||
io.iBus.rsp.inst := io.masterBus.rsp.data
|
||||
io.iBus.rsp.error := False
|
||||
|
||||
io.dBus.rsp.ready := io.masterBus.rsp.valid && rspTarget
|
||||
io.dBus.rsp.data := io.masterBus.rsp.data
|
||||
io.dBus.rsp.error := False
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpleBusConfig : SimpleBusConfig) extends Component{
|
||||
val io = new Bundle{
|
||||
val bus = slave(SimpleBus(simpleBusConfig))
|
||||
}
|
||||
|
||||
val ram = Mem(Bits(32 bits), onChipRamSize / 4)
|
||||
io.bus.rsp.valid := RegNext(io.bus.cmd.fire && !io.bus.cmd.wr) init(False)
|
||||
io.bus.rsp.data := ram.readWriteSync(
|
||||
address = (io.bus.cmd.address >> 2).resized,
|
||||
data = io.bus.cmd.data,
|
||||
enable = io.bus.cmd.valid,
|
||||
write = io.bus.cmd.wr,
|
||||
mask = io.bus.cmd.mask
|
||||
)
|
||||
io.bus.cmd.ready := True
|
||||
|
||||
if(onChipRamHexFile != null){
|
||||
def readHexFile(path : String, callback : (Int, Int) => Unit): Unit ={
|
||||
import scala.io.Source
|
||||
def hToI(that : String, start : Int, size : Int) = Integer.parseInt(that.substring(start,start + size), 16)
|
||||
|
||||
var offset = 0
|
||||
for (line <- Source.fromFile(path).getLines) {
|
||||
if (line.charAt(0) == ':'){
|
||||
val byteCount = hToI(line, 1, 2)
|
||||
val nextAddr = hToI(line, 3, 4) + offset
|
||||
val key = hToI(line, 7, 2)
|
||||
key match {
|
||||
case 0 =>
|
||||
for(i <- 0 until byteCount){
|
||||
callback(nextAddr + i, hToI(line, 9 + i * 2, 2))
|
||||
}
|
||||
case 2 =>
|
||||
offset = hToI(line, 9, 4) << 4
|
||||
case 4 =>
|
||||
offset = hToI(line, 9, 4) << 16
|
||||
case 3 =>
|
||||
case 1 =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val initContent = Array.fill[BigInt](ram.wordCount)(0)
|
||||
readHexFile(onChipRamHexFile,(address,data) => {
|
||||
initContent(address >> 2) |= BigInt(data) << ((address & 3)*8)
|
||||
})
|
||||
ram.initBigInt(initContent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MuraxSimpleBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean, simpleBusConfig : SimpleBusConfig) extends Component{
|
||||
assert(apb3Config.dataWidth == simpleBusConfig.dataWidth)
|
||||
|
||||
val io = new Bundle {
|
||||
val simpleBus = slave(SimpleBus(simpleBusConfig))
|
||||
val apb = master(Apb3(apb3Config))
|
||||
}
|
||||
|
||||
val simpleBusStage = SimpleBus(simpleBusConfig)
|
||||
simpleBusStage.cmd << (if(pipelineBridge) io.simpleBus.cmd.halfPipe() else io.simpleBus.cmd)
|
||||
simpleBusStage.rsp >-> io.simpleBus.rsp
|
||||
|
||||
val state = RegInit(False)
|
||||
simpleBusStage.cmd.ready := False
|
||||
|
||||
io.apb.PSEL(0) := simpleBusStage.cmd.valid
|
||||
io.apb.PENABLE := state
|
||||
io.apb.PWRITE := simpleBusStage.cmd.wr
|
||||
io.apb.PADDR := simpleBusStage.cmd.address.resized
|
||||
io.apb.PWDATA := simpleBusStage.cmd.data
|
||||
|
||||
simpleBusStage.rsp.valid := False
|
||||
simpleBusStage.rsp.data := io.apb.PRDATA
|
||||
when(!state) {
|
||||
state := simpleBusStage.cmd.valid
|
||||
} otherwise {
|
||||
when(io.apb.PREADY){
|
||||
state := False
|
||||
simpleBusStage.rsp.valid := !simpleBusStage.cmd.wr
|
||||
simpleBusStage.cmd.ready := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MuraxSimpleBusDecoder(master : SimpleBus, specification : List[(SimpleBus,SizeMapping)], pipelineMaster : Boolean) extends Area{
|
||||
val masterPipelined = SimpleBus(master.config)
|
||||
if(!pipelineMaster) {
|
||||
masterPipelined.cmd << master.cmd
|
||||
masterPipelined.rsp >> master.rsp
|
||||
} else {
|
||||
masterPipelined.cmd <-< master.cmd
|
||||
masterPipelined.rsp >> master.rsp
|
||||
}
|
||||
|
||||
val slaveBuses = specification.map(_._1)
|
||||
val memorySpaces = specification.map(_._2)
|
||||
|
||||
val hits = for((slaveBus, memorySpace) <- specification) yield {
|
||||
val hit = memorySpace.hit(masterPipelined.cmd.address)
|
||||
slaveBus.cmd.valid := masterPipelined.cmd.valid && hit
|
||||
slaveBus.cmd.payload := masterPipelined.cmd.payload
|
||||
hit
|
||||
}
|
||||
val noHit = !hits.orR
|
||||
masterPipelined.cmd.ready := (hits,slaveBuses).zipped.map(_ && _.cmd.ready).orR || noHit
|
||||
|
||||
val rspPending = RegInit(False) clearWhen(masterPipelined.rsp.valid) setWhen(masterPipelined.cmd.fire && !masterPipelined.cmd.wr)
|
||||
val rspNoHit = RegNext(False) init(False) setWhen(noHit)
|
||||
val rspSourceId = RegNextWhen(OHToUInt(hits), masterPipelined.cmd.fire)
|
||||
masterPipelined.rsp.valid := slaveBuses.map(_.rsp.valid).orR || (rspPending && rspNoHit)
|
||||
masterPipelined.rsp.payload := slaveBuses.map(_.rsp.payload).read(rspSourceId)
|
||||
|
||||
when(rspPending && !masterPipelined.rsp.valid) { //Only one pending read request is allowed
|
||||
masterPipelined.cmd.ready := False
|
||||
slaveBuses.foreach(_.cmd.valid := False)
|
||||
}
|
||||
}
|
||||
|
||||
class MuraxApb3Timer extends Component{
|
||||
val io = new Bundle {
|
||||
val apb = slave(Apb3(
|
||||
addressWidth = 8,
|
||||
dataWidth = 32
|
||||
))
|
||||
val interrupt = out Bool
|
||||
}
|
||||
|
||||
val prescaler = Prescaler(16)
|
||||
val timerA,timerB = Timer(16)
|
||||
|
||||
val busCtrl = Apb3SlaveFactory(io.apb)
|
||||
val prescalerBridge = prescaler.driveFrom(busCtrl,0x00)
|
||||
|
||||
val timerABridge = timerA.driveFrom(busCtrl,0x40)(
|
||||
ticks = List(True, prescaler.io.overflow),
|
||||
clears = List(timerA.io.full)
|
||||
)
|
||||
|
||||
val timerBBridge = timerB.driveFrom(busCtrl,0x50)(
|
||||
ticks = List(True, prescaler.io.overflow),
|
||||
clears = List(timerB.io.full)
|
||||
)
|
||||
|
||||
val interruptCtrl = InterruptCtrl(2)
|
||||
val interruptCtrlBridge = interruptCtrl.driveFrom(busCtrl,0x10)
|
||||
interruptCtrl.io.inputs(0) := timerA.io.full
|
||||
interruptCtrl.io.inputs(1) := timerB.io.full
|
||||
io.interrupt := interruptCtrl.io.pendings.orR
|
||||
}
|
Loading…
Reference in New Issue