diff options
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/demo/Briey.scala')
-rw-r--r-- | VexRiscv/src/main/scala/vexriscv/demo/Briey.scala | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/demo/Briey.scala b/VexRiscv/src/main/scala/vexriscv/demo/Briey.scala new file mode 100644 index 0000000..32e6d62 --- /dev/null +++ b/VexRiscv/src/main/scala/vexriscv/demo/Briey.scala @@ -0,0 +1,490 @@ +package vexriscv.demo + + +import vexriscv.plugin._ +import vexriscv._ +import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig} +import spinal.core._ +import spinal.lib._ +import spinal.lib.bus.amba3.apb._ +import spinal.lib.bus.amba4.axi._ +import spinal.lib.com.jtag.Jtag +import spinal.lib.com.jtag.sim.JtagTcp +import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder} +import spinal.lib.com.uart.{Apb3UartCtrl, Uart, UartCtrlGenerics, UartCtrlMemoryMappedConfig} +import spinal.lib.graphic.RgbConfig +import spinal.lib.graphic.vga.{Axi4VgaCtrl, Axi4VgaCtrlGenerics, Vga} +import spinal.lib.io.TriStateArray +import spinal.lib.memory.sdram.SdramGeneration.SDR +import spinal.lib.memory.sdram._ +import spinal.lib.memory.sdram.sdr.sim.SdramModel +import spinal.lib.memory.sdram.sdr.{Axi4SharedSdramCtrl, IS42x320D, SdramInterface, SdramTimings} +import spinal.lib.misc.HexTools +import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal} +import spinal.lib.system.debugger.{JtagAxi4SharedDebugger, JtagBridge, SystemDebugger, SystemDebuggerConfig} + +import scala.collection.mutable.ArrayBuffer +import scala.collection.Seq + +case class BrieyConfig(axiFrequency : HertzNumber, + onChipRamSize : BigInt, + sdramLayout: SdramLayout, + sdramTimings: SdramTimings, + cpuPlugins : ArrayBuffer[Plugin[VexRiscv]], + uartCtrlConfig : UartCtrlMemoryMappedConfig) + +object BrieyConfig{ + + def default = { + val config = BrieyConfig( + axiFrequency = 50 MHz, + onChipRamSize = 4 kB, + sdramLayout = IS42x320D.layout, + sdramTimings = IS42x320D.timingGrade7, + uartCtrlConfig = UartCtrlMemoryMappedConfig( + uartCtrlConfig = UartCtrlGenerics( + dataWidthMax = 8, + clockDividerWidth = 20, + preSamplingSize = 1, + samplingSize = 5, + postSamplingSize = 2 + ), + txFifoDepth = 16, + rxFifoDepth = 16 + ), + cpuPlugins = ArrayBuffer( + new PcManagerSimplePlugin(0x80000000l, false), + // new IBusSimplePlugin( + // interfaceKeepData = false, + // catchAccessFault = true + // ), + new IBusCachedPlugin( + resetVector = 0x80000000l, + prediction = STATIC, + config = InstructionCacheConfig( + cacheSize = 4096, + bytePerLine =32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchIllegalAccess = true, + catchAccessFault = true, + asyncTagMemory = false, + twoCycleRam = true, + twoCycleCache = true + ) + // askMemoryTranslation = true, + // memoryTranslatorPortConfig = MemoryTranslatorPortConfig( + // portTlbSize = 4 + // ) + ), + // new DBusSimplePlugin( + // catchAddressMisaligned = true, + // catchAccessFault = true + // ), + new DBusCachedPlugin( + config = new DataCacheConfig( + cacheSize = 4096, + bytePerLine = 32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchAccessError = true, + catchIllegal = true, + catchUnaligned = true + ), + memoryTranslatorPortConfig = null + // memoryTranslatorPortConfig = MemoryTranslatorPortConfig( + // portTlbSize = 6 + // ) + ), + new StaticMemoryTranslatorPlugin( + ioRange = _(31 downto 28) === 0xF + ), + new DecoderSimplePlugin( + catchIllegalInstruction = true + ), + new RegFilePlugin( + regFileReadyKind = plugin.SYNC, + zeroBoot = false + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false, + executeInsertion = true + ), + new FullBarrelShifterPlugin, + new MulPlugin, + new DivPlugin, + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), + new BranchPlugin( + earlyBranch = false, + catchAddressMisaligned = true + ), + new CsrPlugin( + config = CsrPluginConfig( + catchIllegalAccess = false, + mvendorid = null, + marchid = null, + mimpid = null, + mhartid = null, + misaExtensionsInit = 66, + misaAccess = CsrAccess.NONE, + mtvecAccess = CsrAccess.NONE, + mtvecInit = 0x80000020l, + mepcAccess = CsrAccess.READ_WRITE, + mscratchGen = false, + mcauseAccess = CsrAccess.READ_ONLY, + mbadaddrAccess = CsrAccess.READ_ONLY, + mcycleAccess = CsrAccess.NONE, + minstretAccess = CsrAccess.NONE, + ecallGen = false, + wfiGenAsWait = false, + ucycleAccess = CsrAccess.NONE, + uinstretAccess = CsrAccess.NONE + ) + ), + new YamlPlugin("cpu0.yaml") + ) + ) + config + } +} + + + +class Briey(val config: BrieyConfig) extends Component{ + + //Legacy constructor + def this(axiFrequency: HertzNumber) { + this(BrieyConfig.default.copy(axiFrequency = axiFrequency)) + } + + import config._ + val debug = true + val interruptCount = 4 + def vgaRgbConfig = RgbConfig(5,6,5) + + val io = new Bundle{ + //Clocks / reset + val asyncReset = in Bool() + val axiClk = in Bool() + val vgaClk = in Bool() + + //Main components IO + val jtag = slave(Jtag()) + val sdram = master(SdramInterface(sdramLayout)) + + //Peripherals IO + val gpioA = master(TriStateArray(32 bits)) + val gpioB = master(TriStateArray(32 bits)) + val uart = master(Uart()) + val vga = master(Vga(vgaRgbConfig)) + val timerExternal = in(PinsecTimerCtrlExternal()) + val coreInterrupt = in Bool() + } + + val resetCtrlClockDomain = ClockDomain( + clock = io.axiClk, + config = ClockDomainConfig( + resetKind = BOOT + ) + ) + + val resetCtrl = new ClockingArea(resetCtrlClockDomain) { + val systemResetUnbuffered = False + // val coreResetUnbuffered = 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 systemResetCounter = Reg(UInt(6 bits)) init(0) + when(systemResetCounter =/= U(systemResetCounter.range -> true)){ + systemResetCounter := systemResetCounter + 1 + systemResetUnbuffered := True + } + when(BufferCC(io.asyncReset)){ + systemResetCounter := 0 + } + + //Create all reset used later in the design + val systemReset = RegNext(systemResetUnbuffered) + val axiReset = RegNext(systemResetUnbuffered) + val vgaReset = BufferCC(axiReset) + } + + val axiClockDomain = ClockDomain( + clock = io.axiClk, + reset = resetCtrl.axiReset, + frequency = FixedFrequency(axiFrequency) //The frequency information is used by the SDRAM controller + ) + + val debugClockDomain = ClockDomain( + clock = io.axiClk, + reset = resetCtrl.systemReset, + frequency = FixedFrequency(axiFrequency) + ) + + val vgaClockDomain = ClockDomain( + clock = io.vgaClk, + reset = resetCtrl.vgaReset + ) + + val axi = new ClockingArea(axiClockDomain) { + val ram = Axi4SharedOnChipRam( + dataWidth = 32, + byteCount = onChipRamSize, + idWidth = 4 + ) + + val sdramCtrl = Axi4SharedSdramCtrl( + axiDataWidth = 32, + axiIdWidth = 4, + layout = sdramLayout, + timing = sdramTimings, + CAS = 3 + ) + + + val apbBridge = Axi4SharedToApb3Bridge( + addressWidth = 20, + dataWidth = 32, + idWidth = 4 + ) + + val gpioACtrl = Apb3Gpio( + gpioWidth = 32, + withReadSync = true + ) + val gpioBCtrl = Apb3Gpio( + gpioWidth = 32, + withReadSync = true + ) + val timerCtrl = PinsecTimerCtrl() + + + val uartCtrl = Apb3UartCtrl(uartCtrlConfig) + uartCtrl.io.apb.addAttribute(Verilator.public) + + + val vgaCtrlConfig = Axi4VgaCtrlGenerics( + axiAddressWidth = 32, + axiDataWidth = 32, + burstLength = 8, + frameSizeMax = 2048*1512*2, + fifoSize = 512, + rgbConfig = vgaRgbConfig, + vgaClock = vgaClockDomain + ) + val vgaCtrl = Axi4VgaCtrl(vgaCtrlConfig) + + + + val core = new Area{ + val config = VexRiscvConfig( + plugins = cpuPlugins += new DebugPlugin(debugClockDomain) + ) + + val cpu = new VexRiscv(config) + var iBus : Axi4ReadOnly = null + var dBus : Axi4Shared = null + for(plugin <- config.plugins) plugin match{ + case plugin : IBusSimplePlugin => iBus = plugin.iBus.toAxi4ReadOnly() + case plugin : IBusCachedPlugin => iBus = plugin.iBus.toAxi4ReadOnly() + case plugin : DBusSimplePlugin => dBus = plugin.dBus.toAxi4Shared() + case plugin : DBusCachedPlugin => dBus = plugin.dBus.toAxi4Shared(true) + case plugin : CsrPlugin => { + plugin.externalInterrupt := BufferCC(io.coreInterrupt) + plugin.timerInterrupt := timerCtrl.io.interrupt + } + case plugin : DebugPlugin => debugClockDomain{ + resetCtrl.axiReset setWhen(RegNext(plugin.io.resetOut)) + io.jtag <> plugin.io.bus.fromJtag() + } + case _ => + } + } + + + val axiCrossbar = Axi4CrossbarFactory() + + axiCrossbar.addSlaves( + ram.io.axi -> (0x80000000L, onChipRamSize), + sdramCtrl.io.axi -> (0x40000000L, sdramLayout.capacity), + apbBridge.io.axi -> (0xF0000000L, 1 MB) + ) + + axiCrossbar.addConnections( + core.iBus -> List(ram.io.axi, sdramCtrl.io.axi), + core.dBus -> List(ram.io.axi, sdramCtrl.io.axi, apbBridge.io.axi), + vgaCtrl.io.axi -> List( sdramCtrl.io.axi) + ) + + + axiCrossbar.addPipelining(apbBridge.io.axi)((crossbar,bridge) => { + crossbar.sharedCmd.halfPipe() >> bridge.sharedCmd + crossbar.writeData.halfPipe() >> bridge.writeData + crossbar.writeRsp << bridge.writeRsp + crossbar.readRsp << bridge.readRsp + }) + + axiCrossbar.addPipelining(sdramCtrl.io.axi)((crossbar,ctrl) => { + crossbar.sharedCmd.halfPipe() >> ctrl.sharedCmd + crossbar.writeData >/-> ctrl.writeData + crossbar.writeRsp << ctrl.writeRsp + crossbar.readRsp << ctrl.readRsp + }) + + axiCrossbar.addPipelining(ram.io.axi)((crossbar,ctrl) => { + crossbar.sharedCmd.halfPipe() >> ctrl.sharedCmd + crossbar.writeData >/-> ctrl.writeData + crossbar.writeRsp << ctrl.writeRsp + crossbar.readRsp << ctrl.readRsp + }) + + axiCrossbar.addPipelining(vgaCtrl.io.axi)((ctrl,crossbar) => { + ctrl.readCmd.halfPipe() >> crossbar.readCmd + ctrl.readRsp << crossbar.readRsp + }) + + axiCrossbar.addPipelining(core.dBus)((cpu,crossbar) => { + cpu.sharedCmd >> crossbar.sharedCmd + cpu.writeData >> crossbar.writeData + cpu.writeRsp << crossbar.writeRsp + cpu.readRsp <-< crossbar.readRsp //Data cache directly use read responses without buffering, so pipeline it for FMax + }) + + axiCrossbar.build() + + + val apbDecoder = Apb3Decoder( + master = apbBridge.io.apb, + slaves = List( + gpioACtrl.io.apb -> (0x00000, 4 kB), + gpioBCtrl.io.apb -> (0x01000, 4 kB), + uartCtrl.io.apb -> (0x10000, 4 kB), + timerCtrl.io.apb -> (0x20000, 4 kB), + vgaCtrl.io.apb -> (0x30000, 4 kB) + ) + ) + } + + io.gpioA <> axi.gpioACtrl.io.gpio + io.gpioB <> axi.gpioBCtrl.io.gpio + io.timerExternal <> axi.timerCtrl.io.external + io.uart <> axi.uartCtrl.io.uart + io.sdram <> axi.sdramCtrl.io.sdram + io.vga <> axi.vgaCtrl.io.vga +} + +//DE1-SoC +object Briey{ + def main(args: Array[String]) { + val config = SpinalConfig() + config.generateVerilog({ + val toplevel = new Briey(BrieyConfig.default) + toplevel.axi.vgaCtrl.vga.ctrl.io.error.addAttribute(Verilator.public) + toplevel.axi.vgaCtrl.vga.ctrl.io.frameStart.addAttribute(Verilator.public) + toplevel + }) + } +} + +//DE1-SoC with memory init +object BrieyWithMemoryInit{ + def main(args: Array[String]) { + val config = SpinalConfig() + config.generateVerilog({ + val toplevel = new Briey(BrieyConfig.default) + toplevel.axi.vgaCtrl.vga.ctrl.io.error.addAttribute(Verilator.public) + toplevel.axi.vgaCtrl.vga.ctrl.io.frameStart.addAttribute(Verilator.public) + HexTools.initRam(toplevel.axi.ram.ram, "src/main/ressource/hex/muraxDemo.hex", 0x80000000l) + toplevel + }) + } +} + + +//DE0-Nano +object BrieyDe0Nano{ + def main(args: Array[String]) { + object IS42x160G { + def layout = SdramLayout( + generation = SDR, + bankWidth = 2, + columnWidth = 9, + rowWidth = 13, + dataWidth = 16 + ) + + def timingGrade7 = SdramTimings( + bootRefreshCount = 8, + tPOW = 100 us, + tREF = 64 ms, + tRC = 60 ns, + tRFC = 60 ns, + tRAS = 37 ns, + tRP = 15 ns, + tRCD = 15 ns, + cMRD = 2, + tWR = 10 ns, + cWR = 1 + ) + } + val config = SpinalConfig() + config.generateVerilog({ + val toplevel = new Briey(BrieyConfig.default.copy(sdramLayout = IS42x160G.layout)) + toplevel + }) + } +} + + + +import spinal.core.sim._ +object BrieySim { + def main(args: Array[String]): Unit = { + val simSlowDown = false + SimConfig.allOptimisation.compile(new Briey(BrieyConfig.default)).doSimUntilVoid{dut => + val mainClkPeriod = (1e12/dut.config.axiFrequency.toDouble).toLong + val jtagClkPeriod = mainClkPeriod*4 + val uartBaudRate = 115200 + val uartBaudPeriod = (1e12/uartBaudRate).toLong + + val clockDomain = ClockDomain(dut.io.axiClk, dut.io.asyncReset) + clockDomain.forkStimulus(mainClkPeriod) + + val tcpJtag = JtagTcp( + jtag = dut.io.jtag, + jtagClkPeriod = jtagClkPeriod + ) + + val uartTx = UartDecoder( + uartPin = dut.io.uart.txd, + baudPeriod = uartBaudPeriod + ) + + val uartRx = UartEncoder( + uartPin = dut.io.uart.rxd, + baudPeriod = uartBaudPeriod + ) + + val sdram = SdramModel( + dut.io.sdram, + dut.config.sdramLayout, + clockDomain + ) + + dut.io.coreInterrupt #= false + } + } +} |