Add Murax SoC (wip)
This commit is contained in:
parent
493f7721cb
commit
1450077b70
|
@ -0,0 +1,241 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.com.jtag.Jtag
|
||||
import spinal.lib.com.uart.Uart
|
||||
import spinal.lib.io.TriStateArray
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{plugin, VexRiscvConfig, VexRiscv}
|
||||
|
||||
/**
|
||||
* Created by PIC32F_USER on 28/07/2017.
|
||||
*
|
||||
* Murax is a very light SoC which could work without any external component.
|
||||
* Should fit in ICE40 devices
|
||||
*/
|
||||
|
||||
|
||||
case class MuraxConfig(coreFrequency : HertzNumber,
|
||||
onChipRamSize : BigInt)
|
||||
|
||||
object MuraxConfig{
|
||||
def default = MuraxConfig(
|
||||
coreFrequency = 12 MHz,
|
||||
onChipRamSize = 4 kB
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
val mainClk = in Bool
|
||||
|
||||
//Main components IO
|
||||
val jtag = slave(Jtag())
|
||||
|
||||
//Peripherals IO
|
||||
// val gpioA = master(TriStateArray(32 bits))
|
||||
// val uart = master(Uart())
|
||||
}
|
||||
|
||||
|
||||
val resetCtrlClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
config = ClockDomainConfig(
|
||||
resetKind = BOOT
|
||||
)
|
||||
)
|
||||
|
||||
val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
|
||||
val mainClkResetUnbuffered = False
|
||||
|
||||
//Implement an counter to keep the reset axiResetOrder high 64 cycles
|
||||
// Also this counter will automaticly do a reset when the system boot.
|
||||
val systemClkResetCounter = Reg(UInt(6 bits)) init(0)
|
||||
when(systemClkResetCounter =/= U(systemClkResetCounter.range -> true)){
|
||||
systemClkResetCounter := systemClkResetCounter + 1
|
||||
mainClkResetUnbuffered := True
|
||||
}
|
||||
when(BufferCC(io.asyncReset)){
|
||||
systemClkResetCounter := 0
|
||||
}
|
||||
|
||||
//Create all reset used later in the design
|
||||
val mainClkReset = RegNext(mainClkResetUnbuffered)
|
||||
val systemReset = RegNext(mainClkResetUnbuffered)
|
||||
}
|
||||
|
||||
|
||||
val systemClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.systemReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val debugClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.mainClkReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val system = new ClockingArea(systemClockDomain) {
|
||||
val cpu = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
new PcManagerSimplePlugin(
|
||||
resetVector = 0x00000000l,
|
||||
fastPcCalculation = true
|
||||
),
|
||||
new IBusSimplePlugin(
|
||||
interfaceKeepData = false,
|
||||
catchAccessFault = false
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false
|
||||
),
|
||||
// new CsrPlugin(CsrPluginConfig.smallest),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = false
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = true
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false,
|
||||
executeInsertion = true
|
||||
),
|
||||
new LightShifterPlugin,
|
||||
new DebugPlugin(debugClockDomain),
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = false,
|
||||
bypassMemory = false,
|
||||
bypassWriteBack = false,
|
||||
bypassWriteBackBuffer = false,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = false,
|
||||
prediction = NONE
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
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 : DBusSimplePlugin => dBus = plugin.dBus
|
||||
/* case plugin : CsrPlugin => {
|
||||
plugin.externalInterrupt := BufferCC(io.coreInterrupt)
|
||||
plugin.timerInterrupt := timerCtrl.io.interrupt
|
||||
}*/
|
||||
case plugin : DebugPlugin => {
|
||||
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
||||
io.jtag <> plugin.io.bus.fromJtag()
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
|
||||
|
||||
val mainBus = SimpleBus()
|
||||
|
||||
//Priority to dBus, cmd transactions can change on the fly !
|
||||
val cpuToMainBusBridge = 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 rspTarget = RegInit(False)
|
||||
when(mainBus.cmd.fire){
|
||||
rspTarget := dBus.cmd.valid
|
||||
}
|
||||
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
|
||||
|
||||
//Default states
|
||||
/* mainBus.cmd.ready := False
|
||||
mainBus.rsp.valid := False
|
||||
mainBus.rsp.payload.assignDontCare()*/
|
||||
}
|
||||
|
||||
val ram = new Area{
|
||||
def bus = mainBus//SimpleBus()
|
||||
val ram = Mem(Bits(32 bits), (onChipRamSize / 4).toInt)
|
||||
bus.rsp.valid := RegNext(bus.cmd.fire && !bus.cmd.wr) init(False)
|
||||
bus.rsp.data := ram.readWriteSync(
|
||||
address = bus.cmd.address.resized,
|
||||
data = bus.cmd.data,
|
||||
enable = bus.cmd.valid,
|
||||
write = bus.cmd.wr,
|
||||
mask = bus.cmd.mask
|
||||
)
|
||||
bus.cmd.ready := True
|
||||
}
|
||||
|
||||
|
||||
/* val interconnect = new Area {
|
||||
ramPort.enable := iBus.cmd.valid || dBus.cmd.valid
|
||||
ramPort.
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
object Murax{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.default))
|
||||
}
|
||||
}
|
|
@ -46,6 +46,7 @@ object DBusSimpleBus{
|
|||
maximumPendingReadTransactions = 1
|
||||
)
|
||||
}
|
||||
|
||||
case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||
val cmd = Stream(DBusSimpleCmd())
|
||||
val rsp = DBusSimpleRsp()
|
||||
|
|
Loading…
Reference in New Issue