From 59b197479e8b45d791900a8d7da50fe01fdb469b Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Sat, 20 Feb 2021 22:44:01 +0100 Subject: [PATCH] Source code formatting --- .scalafmt.conf | 9 +- project/plugins.sbt | 1 + src/main/scala/mupq/IceBlackbox.scala | 181 ++++++++--------- src/main/scala/mupq/PQVexRiscv.scala | 181 ++++++++--------- src/main/scala/mupq/PQVexRiscvArty.scala | 69 ++++--- src/main/scala/mupq/PQVexRiscvIcoboard.scala | 74 ++++--- src/main/scala/mupq/PQVexRiscvSim.scala | 77 ++++---- src/main/scala/mupq/PQVexRiscvUP5K.scala | 49 +++-- src/main/scala/mupq/XilinxBlackbox.scala | 193 ++++++++++--------- 9 files changed, 446 insertions(+), 388 deletions(-) create mode 100644 project/plugins.sbt diff --git a/.scalafmt.conf b/.scalafmt.conf index ac8fcc6..da58bfa 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,8 +1,11 @@ -version = "2.3.2" -align = more +version = 2.7.5 maxColumn = 100 +align.preset = more +align.multiline = false +newlines.source = keep +danglingParentheses.callSite = false continuationIndent.callSite = 2 continuationIndent.defnSite = 2 +continuationIndent.extendSite = 0 verticalMultiline.arityThreshold = 4 verticalMultiline.newlineAfterOpenParen = true - diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..bcda4ae --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") diff --git a/src/main/scala/mupq/IceBlackbox.scala b/src/main/scala/mupq/IceBlackbox.scala index d700a4c..39343f3 100644 --- a/src/main/scala/mupq/IceBlackbox.scala +++ b/src/main/scala/mupq/IceBlackbox.scala @@ -2,66 +2,69 @@ package mupq import spinal.core._ -/** - * BlackBox model for the PLL present in Ice40 FPGAs. +/** BlackBox model for the PLL present in Ice40 FPGAs. */ class Ice40PLLPad(divF: Int, divR: Int, divQ: Int) extends BlackBox { val generic = new Generic { - val FEEDBACK_PATH = "SIMPLE" + val FEEDBACK_PATH = "SIMPLE" val DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED" val DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED" - val PLLOUT_SELECT = "GENCLK" - val FDA_FEEDBACK = B(0xF, 4 bits) - val FDA_RELATIVE = B(0xF, 4 bits) - val DIVF = B(divF, 7 bits) - val DIVR = B(divR, 4 bits) - val DIVQ = B(divQ, 3 bits) - val FILTER_RANGE = B(0x2, 3 bits) + val PLLOUT_SELECT = "GENCLK" + val FDA_FEEDBACK = B(0xf, 4 bits) + val FDA_RELATIVE = B(0xf, 4 bits) + val DIVF = B(divF, 7 bits) + val DIVR = B(divR, 4 bits) + val DIVQ = B(divQ, 3 bits) + val FILTER_RANGE = B(0x2, 3 bits) } val io = new Bundle { - val RESETB = in Bool - val BYPASS = in Bool - val PACKAGEPIN = in Bool + val RESETB = in Bool + val BYPASS = in Bool + val PACKAGEPIN = in Bool val PLLOUTGLOBAL = out Bool - val LOCK = out Bool + val LOCK = out Bool } noIoPrefix() setBlackBoxName("SB_PLL40_PAD") } class Ice40PLL2FCore( - divF: Int, divR: Int, divQ: Int -) extends BlackBox { + divF: Int, + divR: Int, + divQ: Int +) +extends BlackBox { val generic = new Generic { - val FEEDBACK_PATH = "PHASE_AND_DELAY" + val FEEDBACK_PATH = "PHASE_AND_DELAY" val DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED" val DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED" - val PLLOUT_SELECT_PORTA = "SHIFTREG_0deg" - val PLLOUT_SELECT_PORTB = "SHIFTREG_90deg" - val SHIFTREG_DIV_MODE = False - val FDA_FEEDBACK = B(0xF, 4 bits) - val FDA_RELATIVE = B(0xF, 4 bits) - val DIVF = B(divF, 7 bits) - val DIVR = B(divR, 4 bits) - val DIVQ = B(divQ, 3 bits) - val FILTER_RANGE = B(0x7, 3 bits) + val PLLOUT_SELECT_PORTA = "SHIFTREG_0deg" + val PLLOUT_SELECT_PORTB = "SHIFTREG_90deg" + val SHIFTREG_DIV_MODE = False + val FDA_FEEDBACK = B(0xf, 4 bits) + val FDA_RELATIVE = B(0xf, 4 bits) + val DIVF = B(divF, 7 bits) + val DIVR = B(divR, 4 bits) + val DIVQ = B(divQ, 3 bits) + val FILTER_RANGE = B(0x7, 3 bits) } val io = new Bundle { - val RESETB = in Bool - val BYPASS = in Bool - val REFERENCECLK = in Bool + val RESETB = in Bool + val BYPASS = in Bool + val REFERENCECLK = in Bool val PLLOUTGLOBALA = out Bool val PLLOUTGLOBALB = out Bool - val LOCK = out Bool + val LOCK = out Bool } noIoPrefix() setBlackBoxName("SB_PLL40_2F_CORE") } -class Ice40IO(pinType: Int = 0, pullup: Boolean = false, negTrigger: Boolean = false) extends BlackBox { +class Ice40IO(pinType: Int = 0, pullup: Boolean = false, negTrigger: Boolean = false) +extends BlackBox { val generic = new Generic { val PIN_TYPE = B(pinType, 6 bits) - val PULLUP = if (pullup) True else False + val PULLUP = if (pullup) True else False // val NEG_TRIGGER = if (negTrigger) True else False // val IO_STANDARD = "SB_LVCMOS" } @@ -72,7 +75,7 @@ class Ice40IO(pinType: Int = 0, pullup: Boolean = false, negTrigger: Boolean = f // val INPUT_CLK = in Bool // val OUTPUT_CLK = in Bool val OUTPUT_ENABLE = in Bool - val D_OUT_0 = in Bool + val D_OUT_0 = in Bool // val D_OUT_1 = in Bool val D_IN_0 = out Bool // val D_IN_1 = out Bool @@ -81,80 +84,78 @@ class Ice40IO(pinType: Int = 0, pullup: Boolean = false, negTrigger: Boolean = f setBlackBoxName("SB_IO") } -/** - * BlackBox model for the large SPRAM blocks of Ice40 UltraPlus FPGAs. +/** BlackBox model for the large SPRAM blocks of Ice40 UltraPlus FPGAs. */ class Ice40SPRAM extends BlackBox { val io = new Bundle { - val ADDRESS = in Bits (14 bits) - val DATAIN = in Bits (16 bits) - val DATAOUT = out Bits (16 bits) - val MASKWREN = in Bits (4 bits) - val WREN = in Bool + val ADDRESS = in Bits (14 bits) + val DATAIN = in Bits (16 bits) + val DATAOUT = out Bits (16 bits) + val MASKWREN = in Bits (4 bits) + val WREN = in Bool val CHIPSELECT = in Bool - val CLOCK = in Bool - val STANDBY = in Bool - val SLEEP = in Bool - val POWEROFF = in Bool + val CLOCK = in Bool + val STANDBY = in Bool + val SLEEP = in Bool + val POWEROFF = in Bool } noIoPrefix() mapClockDomain(clock = io.CLOCK) setBlackBoxName("SB_SPRAM256KA") } -/** - * BlackBox Model for DSA +/** BlackBox Model for DSA */ -class Ice40Multiplier(registerOutput : Boolean = false) extends BlackBox { +class Ice40Multiplier(registerOutput: Boolean = false) extends BlackBox { val generics = new Generic { - val A_REG = B"0" - val B_REG = B"0" - val C_REG = B"0" - val D_REG = B"0" - val TOP_8X8_MULT_REG = B"0" - val BOT_8X8_MULT_REG = B"0" + val A_REG = B"0" + val B_REG = B"0" + val C_REG = B"0" + val D_REG = B"0" + val TOP_8X8_MULT_REG = B"0" + val BOT_8X8_MULT_REG = B"0" val PIPELINE_16X16_MULT_REG1 = B"0" val PIPELINE_16X16_MULT_REG2 = if (registerOutput) B"1" else B"0" - val TOPOUTPUT_SELECT = B"11" - val TOPADDSUB_LOWERINPUT = B"00" - val TOPADDSUB_UPPERINPUT = B"0" - val TOPADDSUB_CARRYSELECT = B"00" - val BOTOUTPUT_SELECT = B"11" - val BOTADDSUB_LOWERINPUT = B"00" - val BOTADDSUB_UPPERINPUT = B"0" - val BOTADDSUB_CARRYSELECT = B"00" - val MODE_8X8 = B"0" - val A_SIGNED = B"0" - val B_SIGNED = B"0" + val TOPOUTPUT_SELECT = B"11" + val TOPADDSUB_LOWERINPUT = B"00" + val TOPADDSUB_UPPERINPUT = B"0" + val TOPADDSUB_CARRYSELECT = B"00" + val BOTOUTPUT_SELECT = B"11" + val BOTADDSUB_LOWERINPUT = B"00" + val BOTADDSUB_UPPERINPUT = B"0" + val BOTADDSUB_CARRYSELECT = B"00" + val MODE_8X8 = B"0" + val A_SIGNED = B"0" + val B_SIGNED = B"0" } val io = new Bundle { - val CLK = in Bool - val CE = in Bool - val A = in Bits(16 bits) - val AHOLD = in Bool - val B = in Bits(16 bits) - val BHOLD = in Bool - val C = in Bits(16 bits) - val CHOLD = in Bool - val D = in Bits(16 bits) - val DHOLD = in Bool - val IRSTTOP = in Bool - val ORSTTOP = in Bool - val OLOADTOP = in Bool - val ADDSUBTOP = in Bool - val OHOLDTOP = in Bool - val O = out Bits(32 bits) - val IRSTBOT = in Bool - val ORSTBOT = in Bool - val OLOADBOT = in Bool - val ADDSUBBOT = in Bool - val OHOLDBOT = in Bool - val CI = in Bool - val CO = out Bool - val ACCUMCI = in Bool - val ACCUMCO = out Bool - val SIGNEXTIN = in Bool + val CLK = in Bool + val CE = in Bool + val A = in Bits (16 bits) + val AHOLD = in Bool + val B = in Bits (16 bits) + val BHOLD = in Bool + val C = in Bits (16 bits) + val CHOLD = in Bool + val D = in Bits (16 bits) + val DHOLD = in Bool + val IRSTTOP = in Bool + val ORSTTOP = in Bool + val OLOADTOP = in Bool + val ADDSUBTOP = in Bool + val OHOLDTOP = in Bool + val O = out Bits (32 bits) + val IRSTBOT = in Bool + val ORSTBOT = in Bool + val OLOADBOT = in Bool + val ADDSUBBOT = in Bool + val OHOLDBOT = in Bool + val CI = in Bool + val CO = out Bool + val ACCUMCI = in Bool + val ACCUMCO = out Bool + val SIGNEXTIN = in Bool val SIGNEXTOUT = out Bool } noIoPrefix() diff --git a/src/main/scala/mupq/PQVexRiscv.scala b/src/main/scala/mupq/PQVexRiscv.scala index 7a4ec32..5e6536f 100644 --- a/src/main/scala/mupq/PQVexRiscv.scala +++ b/src/main/scala/mupq/PQVexRiscv.scala @@ -16,13 +16,14 @@ import vexriscv.demo.MuraxApb3Timer import vexriscv.plugin._ abstract class PQVexRiscv( - cpuPlugins : () => Seq[Plugin[VexRiscv]], - ibusRange : SizeMapping, - genUART : Boolean = true, - gpioWidth : Int = 0, - genTimer : Boolean = false -) extends Component { - val coreFrequency : HertzNumber + cpuPlugins: () => Seq[Plugin[VexRiscv]], + ibusRange: SizeMapping, + genUART: Boolean = true, + gpioWidth: Int = 0, + genTimer: Boolean = false +) +extends Component { + val coreFrequency: HertzNumber /* Clock and resets */ @@ -30,26 +31,27 @@ abstract class PQVexRiscv( val mainClock: Bool = Bool - val resetCtrlClockDomain: ClockDomain = ClockDomain( - clock = mainClock, - config = ClockDomainConfig(resetKind = BOOT)) + val resetCtrlClockDomain: ClockDomain = + ClockDomain(clock = mainClock, config = ClockDomainConfig(resetKind = BOOT)) val resetCtrl = new ClockingArea(resetCtrlClockDomain) { val bufferedReset = BufferCC(asyncReset) - val mainClockReset = RegNext(bufferedReset) + val mainClockReset = RegNext(bufferedReset) val systemClockReset = RegNext(bufferedReset) } val systemClockDomain: ClockDomain = ClockDomain( clock = mainClock, reset = resetCtrl.systemClockReset, - frequency = FixedFrequency(coreFrequency)) + frequency = FixedFrequency(coreFrequency) + ) val debugClockDomain: ClockDomain = ClockDomain( clock = mainClock, reset = resetCtrl.mainClockReset, - frequency = FixedFrequency(coreFrequency)) + frequency = FixedFrequency(coreFrequency) + ) /* Bus interconnect */ val busConfig = PipelinedMemoryBusConfig( @@ -57,23 +59,22 @@ abstract class PQVexRiscv( dataWidth = 32 ) - val busSlaves = ArrayBuffer[(PipelinedMemoryBus, SizeMapping)]() + val busSlaves = ArrayBuffer[(PipelinedMemoryBus, SizeMapping)]() val busMasters = ArrayBuffer[(PipelinedMemoryBus, SizeMapping)]() /* VexRiscv Core */ - var jtag : Jtag = null + var jtag: Jtag = null val core = new ClockingArea(systemClockDomain) { - val timerInterrupt = False + val timerInterrupt = False val externalInterrupt = False - val config = VexRiscvConfig( - plugins = cpuPlugins() ++ Seq(new DebugPlugin(debugClockDomain, 3))) + val config = VexRiscvConfig(plugins = cpuPlugins() ++ Seq(new DebugPlugin(debugClockDomain, 3))) val cpu = new VexRiscv(config) /* Wire the Busses / Lines to the plugins */ - var ibus : PipelinedMemoryBus = PipelinedMemoryBus(busConfig) - var dbus : PipelinedMemoryBus = PipelinedMemoryBus(busConfig) + var ibus: PipelinedMemoryBus = PipelinedMemoryBus(busConfig) + var dbus: PipelinedMemoryBus = PipelinedMemoryBus(busConfig) for (plugin <- cpu.plugins) plugin match { case plugin: IBusSimplePlugin => val cpuibus = plugin.iBus.toPipelinedMemoryBus() @@ -95,15 +96,15 @@ abstract class PQVexRiscv( case _ => } - busMasters += dbus -> SizeMapping(0l, (1l << 32l)) + busMasters += dbus -> SizeMapping(0L, (1L << 32L)) busMasters += ibus -> ibusRange } /* Peripherals */ - var gpio : TriStateArray = null + var gpio: TriStateArray = null - var uart : Uart = null + var uart: Uart = null val peripherals = new ClockingArea(systemClockDomain) { if (gpioWidth > 0) { @@ -114,7 +115,7 @@ abstract class PQVexRiscv( uart = Uart() } - if(genUART || gpioWidth > 0 || genTimer) { + if (genUART || gpioWidth > 0 || genTimer) { val apbBridge = new PipelinedMemoryBusToApbBridge( apb3Config = Apb3Config( addressWidth = 20, @@ -124,7 +125,7 @@ abstract class PQVexRiscv( pipelinedMemoryBusConfig = busConfig ) - busSlaves += apbBridge.io.pipelinedMemoryBus -> SizeMapping(0xF0000000l, 1 MiB) + busSlaves += apbBridge.io.pipelinedMemoryBus -> SizeMapping(0xf0000000L, 1 MiB) val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]() @@ -137,15 +138,15 @@ abstract class PQVexRiscv( if (genUART) { val uartCtrlConfig = UartCtrlMemoryMappedConfig( uartCtrlConfig = UartCtrlGenerics( - dataWidthMax = 8, + dataWidthMax = 8, clockDividerWidth = 20, - preSamplingSize = 1, - samplingSize = 3, - postSamplingSize = 1 + preSamplingSize = 1, + samplingSize = 3, + postSamplingSize = 1 ), initConfig = UartCtrlInitConfig( baudrate = 115200, - dataLength = 7, //7 => 8 bits + dataLength = 7, //7 => 8 bits parity = UartParityType.NONE, stop = UartStopType.ONE ), @@ -157,13 +158,13 @@ abstract class PQVexRiscv( val uartCtrl = Apb3UartCtrl(uartCtrlConfig) uart <> uartCtrl.io.uart - core.externalInterrupt setWhen(uartCtrl.io.interrupt) - apbMapping += uartCtrl.io.apb -> (0x10000, 4 KiB) + core.externalInterrupt setWhen (uartCtrl.io.interrupt) + apbMapping += uartCtrl.io.apb -> (0x10000, 4 KiB) } if (genTimer) { val timer = new MuraxApb3Timer() - core.timerInterrupt setWhen(timer.io.interrupt) + core.timerInterrupt setWhen (timer.io.interrupt) apbMapping += timer.io.apb -> (0x20000, 4 KiB) } @@ -174,7 +175,7 @@ abstract class PQVexRiscv( } } - def buildInterconnect() : Unit = { + def buildInterconnect(): Unit = { assert(!SizeMapping.verifyOverlapping(busSlaves.map(_._2))) val crossbar = new ClockingArea(systemClockDomain) { val interconnect = new PipelinedMemoryBusInterconnect() @@ -182,69 +183,75 @@ abstract class PQVexRiscv( /* Setup the interconnect */ interconnect.addSlaves(busSlaves: _*) /* Check which masters overlap with which slaves */ - def overlaps(a : SizeMapping, b : SizeMapping) : Boolean = if (a.base < b.base) a.end >= b.base else b.end >= a.base - interconnect.addMasters(busMasters.map(m => m._1 -> busSlaves.filter(s => overlaps(m._2, s._2)).map(s => s._1).toSeq): _*) + def overlaps(a: SizeMapping, b: SizeMapping): Boolean = + if (a.base < b.base) a.end >= b.base else b.end >= a.base + interconnect.addMasters( + busMasters.map(m => + m._1 -> busSlaves.filter(s => overlaps(m._2, s._2)).map(s => s._1).toSeq): _* + ) } } Component.current.addPrePopTask(() => buildInterconnect()) } -object PQVexRiscv -{ +object PQVexRiscv { type PluginSeq = Seq[Plugin[VexRiscv]] type PluginGen = () => PluginSeq /** Basic set of Plugins (conforms mostly to rv32i) */ - def baseConfig(base: PluginGen = () => Seq()) = () => base() ++ Seq( - new IBusSimplePlugin( - resetVector = 0x80000000l, - cmdForkOnSecondStage = true, - cmdForkPersistence = false, - prediction = NONE, - catchAccessFault = false, - compressedGen = false - ), - new DBusSimplePlugin( - catchAddressMisaligned = false, - catchAccessFault = false, - earlyInjection = false - ), - new CsrPlugin( - CsrPluginConfig.smallest(0x80000000l).copy( - mtvecAccess = CsrAccess.READ_WRITE, - mcycleAccess = CsrAccess.READ_ONLY, - minstretAccess = CsrAccess.READ_ONLY - ) - ), - new DecoderSimplePlugin( - catchIllegalInstruction = false - ), - new RegFilePlugin( - regFileReadyKind = plugin.SYNC, - zeroBoot = false - ), - new IntAluPlugin, - new SrcPlugin( - separatedAddSub = false, - executeInsertion = false - ), - new FullBarrelShifterPlugin, - new HazardSimplePlugin( - bypassExecute = true, - bypassMemory = true, - bypassWriteBack = true, - bypassWriteBackBuffer = true, - pessimisticUseSrc = false, - pessimisticWriteRegFile = false, - pessimisticAddressMatch = false - ), - new BranchPlugin( - earlyBranch = false, - catchAddressMisaligned = false - ), - new YamlPlugin("cpu0.yaml") - ) + def baseConfig(base: PluginGen = () => Seq()) = () => + base() ++ Seq( + new IBusSimplePlugin( + resetVector = 0x80000000L, + cmdForkOnSecondStage = true, + cmdForkPersistence = false, + prediction = NONE, + catchAccessFault = false, + compressedGen = false + ), + new DBusSimplePlugin( + catchAddressMisaligned = false, + catchAccessFault = false, + earlyInjection = false + ), + new CsrPlugin( + CsrPluginConfig + .smallest(0x80000000L) + .copy( + mtvecAccess = CsrAccess.READ_WRITE, + mcycleAccess = CsrAccess.READ_ONLY, + minstretAccess = CsrAccess.READ_ONLY + ) + ), + new DecoderSimplePlugin( + catchIllegalInstruction = false + ), + new RegFilePlugin( + regFileReadyKind = plugin.SYNC, + zeroBoot = false + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false, + executeInsertion = false + ), + new FullBarrelShifterPlugin, + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), + new BranchPlugin( + earlyBranch = false, + catchAddressMisaligned = false + ), + new YamlPlugin("cpu0.yaml") + ) /** Plugins for a small multiplier */ def smallMultiplier = Seq( diff --git a/src/main/scala/mupq/PQVexRiscvArty.scala b/src/main/scala/mupq/PQVexRiscvArty.scala index 695639c..f4d6c7c 100644 --- a/src/main/scala/mupq/PQVexRiscvArty.scala +++ b/src/main/scala/mupq/PQVexRiscvArty.scala @@ -19,11 +19,11 @@ import spinal.lib.com.jtag.sim.JtagTcp import vexriscv.VexRiscv import vexriscv.plugin.Plugin -case class PipelinedMemoryBusXilinxRam(size : BigInt, latency : Int = 1) extends Component{ +case class PipelinedMemoryBusXilinxRam(size: BigInt, latency: Int = 1) extends Component { require(size % 4 == 0, "Size must be multiple of 4 bytes") require(size > 0, "Size must be greater than zero") val busConfig = PipelinedMemoryBusConfig(log2Up(size), 32) - val io = new Bundle{ + val io = new Bundle { val bus = slave(PipelinedMemoryBus(busConfig)) } @@ -31,7 +31,8 @@ case class PipelinedMemoryBusXilinxRam(size : BigInt, latency : Int = 1) extends dataWidth = 32, numWords = size / 4, readLatency = latency, - byteWrite = true) + byteWrite = true + ) ram.io.dina := io.bus.cmd.data ram.io.addra := io.bus.cmd.address.asBits >> 2 @@ -47,27 +48,27 @@ case class PipelinedMemoryBusXilinxRam(size : BigInt, latency : Int = 1) extends io.bus.rsp.data := ram.io.douta } - class PQVexRiscvArty( - val ramBlockSizes : Seq[BigInt] = Seq[BigInt](64 KiB, 64 KiB), - val clkFrequency : HertzNumber = 100 MHz, - val coreFrequency : HertzNumber = 50 MHz, - cpuPlugins : () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() -) extends PQVexRiscv ( + val ramBlockSizes: Seq[BigInt] = Seq[BigInt](64 KiB, 64 KiB), + val clkFrequency: HertzNumber = 100 MHz, + val coreFrequency: HertzNumber = 200 MHz, + cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() +) +extends PQVexRiscv( cpuPlugins = cpuPlugins, - ibusRange = SizeMapping(0x80000000l, ramBlockSizes.reduce(_ + _)) + ibusRange = SizeMapping(0x80000000L, ramBlockSizes.reduce(_ + _)) ) { val io = new Bundle { val RST = in Bool val CLK = in Bool /* UART */ val TXD = out Bool // TXD - val RXD = in Bool // RXD + val RXD = in Bool // RXD /* JTAG */ val TDO = out Bool // TDO - val TCK = in Bool // TCK - val TDI = in Bool // TDI - val TMS = in Bool // TMS + val TCK = in Bool // TCK + val TDI = in Bool // TDI + val TMS = in Bool // TMS } noIoPrefix() @@ -97,8 +98,8 @@ class PQVexRiscvArty( io.TXD := uart.txd val memory = new ClockingArea(systemClockDomain) { - val ramBlocks = ramBlockSizes.zipWithIndex.map(t => PipelinedMemoryBusXilinxRam(t._1, 2)) - var curAddr : BigInt = 0x80000000l + val ramBlocks = ramBlockSizes.zipWithIndex.map(t => PipelinedMemoryBusXilinxRam(t._1, 2)) + var curAddr: BigInt = 0x80000000L for (block <- ramBlocks) { busSlaves += block.io.bus -> SizeMapping(curAddr, block.size) curAddr += block.size @@ -107,28 +108,42 @@ class PQVexRiscvArty( } object PQVexRiscvArty { - def main(args: Array[String]) : Unit = { + def main(args: Array[String]): Unit = { case class PQVexRiscvArtyConfig( ramBlocks: Seq[BigInt] = Seq(64 KiB, 64 KiB), clkFrequency: HertzNumber = 100 MHz, - coreFrequency: HertzNumber = 50 MHz, + coreFrequency: HertzNumber = 300 MHz, cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.baseConfig() ) val optParser = new OptionParser[PQVexRiscvArtyConfig]("PQVexRiscvArty") { head("PQVexRiscvArty board") - help("help") text("print usage text") - opt[Seq[Int]]("ram") action((r, c) => c.copy(ramBlocks = r.map(_ KiB))) text("SRAM Blocks in KiB") valueName(",") - opt[Int]("clk") action((r, c) => c.copy(clkFrequency = (r MHz))) text("Input clock freqency in MHz") valueName("") - opt[Int]("core") action((r, c) => c.copy(coreFrequency = (r MHz))) text("Target core freqency in MHz") valueName("") - opt[Unit]("mul") action((_, c) => c.copy(cpuPlugins = PQVexRiscv.withDSPMultiplier(c.cpuPlugins))) + help("help") text ("print usage text") + opt[Seq[Int]]("ram") action ((r, c) => + c.copy(ramBlocks = + r.map(_ KiB))) text ("SRAM Blocks in KiB") valueName (",") + opt[Int]("clk") action ((r, c) => + c.copy(clkFrequency = (r MHz))) text ("Input clock freqency in MHz") valueName ("") + opt[Int]("core") action ((r, c) => + c.copy(coreFrequency = (r MHz))) text ("Target core freqency in MHz") valueName ("") + opt[Unit]("mul") action ((_, c) => + c.copy(cpuPlugins = PQVexRiscv.withDSPMultiplier(c.cpuPlugins))) } val config = optParser.parse(args, PQVexRiscvArtyConfig()) match { case Some(config) => config - case None => ??? + case None => ??? } - SpinalConfig( + val report = SpinalConfig( mode = Verilog, - targetDirectory = "rtl" - ).generate(new PQVexRiscvArty(ramBlockSizes = config.ramBlocks, clkFrequency = config.clkFrequency, coreFrequency = config.coreFrequency, cpuPlugins = config.cpuPlugins)) + targetDirectory = "rtl/gen" + ).generate( + new PQVexRiscvArty( + ramBlockSizes = config.ramBlocks, + clkFrequency = config.clkFrequency, + coreFrequency = config.coreFrequency, + cpuPlugins = config.cpuPlugins + ) + ) + println(s"Core freqency is set to ${config.coreFrequency.toDouble / 1e6} MHz") + report.mergeRTLSource(s"rtl/gen/${report.toplevelName}.aux") } } diff --git a/src/main/scala/mupq/PQVexRiscvIcoboard.scala b/src/main/scala/mupq/PQVexRiscvIcoboard.scala index cfd72d9..4284869 100644 --- a/src/main/scala/mupq/PQVexRiscvIcoboard.scala +++ b/src/main/scala/mupq/PQVexRiscvIcoboard.scala @@ -10,18 +10,18 @@ import spinal.lib.bus.simple._ import vexriscv._ import vexriscv.plugin._ -case class GenericSRAM(addrWidth : Int = 16, dataWidth : Int = 16) extends Bundle with IMasterSlave { +case class GenericSRAM(addrWidth: Int = 16, dataWidth: Int = 16) extends Bundle with IMasterSlave { val selWidth: Int = (dataWidth / 8) - val addr = Bits(addrWidth bits) - val dataOut = Bits(dataWidth bits) - val dataIn = Bits(dataWidth bits) - val ce_n = Bool /* ~ChipEnable */ - val oe_n = Bool /* ~OutputEnable */ - val we_n = Bool /* ~WriteEnable */ - val sel_n = Bits(selWidth bits) /* ~Byte Control */ - - override def asMaster() : Unit = { - out(addr,dataOut, ce_n, oe_n, we_n, sel_n) + val addr = Bits(addrWidth bits) + val dataOut = Bits(dataWidth bits) + val dataIn = Bits(dataWidth bits) + val ce_n = Bool /* ~ChipEnable */ + val oe_n = Bool /* ~OutputEnable */ + val we_n = Bool /* ~WriteEnable */ + val sel_n = Bits(selWidth bits) /* ~Byte Control */ + + override def asMaster(): Unit = { + out(addr, dataOut, ce_n, oe_n, we_n, sel_n) in(dataIn) } } @@ -29,22 +29,22 @@ case class GenericSRAM(addrWidth : Int = 16, dataWidth : Int = 16) extends Bundl class PipelinedMemoryBusSRAM(busConfig: PipelinedMemoryBusConfig) extends Component { require(busConfig.dataWidth == 32, "Only 32 bit busses supported") val io = new Bundle { - val bus = slave(PipelinedMemoryBus(busConfig)) + val bus = slave(PipelinedMemoryBus(busConfig)) val clk90deg = in Bool - val sram = master(GenericSRAM(19, 16)) + val sram = master(GenericSRAM(19, 16)) } - val addr = Reg(Bits(io.sram.addrWidth bit)) - val dataOut = Reg(Bits(16 bit)) - val dataIn = Bits(16 bit) - val we_n = RegNext(True) init(true) + val addr = Reg(Bits(io.sram.addrWidth bit)) + val dataOut = Reg(Bits(16 bit)) + val dataIn = Bits(16 bit) + val we_n = RegNext(True) init (true) val selAllSet = B(2 bits, default -> true) - val sel_n = Reg(selAllSet) init(selAllSet) + val sel_n = Reg(selAllSet) init (selAllSet) io.sram.addr := addr dataIn := io.sram.dataIn io.sram.dataOut := dataOut - io.sram.ce_n := RegNext(False) init(true) + io.sram.ce_n := RegNext(False) init (true) io.sram.we_n := we_n || !io.clk90deg io.sram.oe_n := !we_n io.sram.sel_n := sel_n @@ -53,15 +53,15 @@ class PipelinedMemoryBusSRAM(busConfig: PipelinedMemoryBusConfig) extends Compon val cmd = RegNextWhen(io.bus.cmd.payload, io.bus.cmd.fire) io.bus.cmd.ready := False - val data = Reg(Bits(32 bit)) - val valid = RegNext(False) init(false) + val data = Reg(Bits(32 bit)) + val valid = RegNext(False) init (false) io.bus.rsp.data := data io.bus.rsp.valid := valid addr.assignDontCare() dataOut.assignDontCare() - val IDLE : State = new State with EntryPoint + val IDLE: State = new State with EntryPoint IDLE.whenIsActive { io.bus.cmd.ready := True when(io.bus.cmd.valid) { @@ -94,11 +94,12 @@ class PipelinedMemoryBusSRAM(busConfig: PipelinedMemoryBusConfig) extends Compon } class PQVexRiscvIcoboard( - val coreFrequency : HertzNumber = 20 MHz, - cpuPlugins : () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withSmallMultiplier() -) extends PQVexRiscv( + val coreFrequency: HertzNumber = 20 MHz, + cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withSmallMultiplier() +) +extends PQVexRiscv( cpuPlugins = cpuPlugins, - ibusRange = SizeMapping(0x80000000l, 1 MiB), + ibusRange = SizeMapping(0x80000000L, 1 MiB), gpioWidth = 3, genTimer = true ) { @@ -111,14 +112,14 @@ class PQVexRiscvIcoboard( val led3 = out Bool /* UART */ val pmod3_8 = out Bool // TXD - val pmod3_9 = in Bool // RXD + val pmod3_9 = in Bool // RXD /* JTAG */ val pmod4_1 = out Bool // TDO - val pmod4_3 = in Bool // TCK - val pmod4_7 = in Bool // TDI - val pmod4_8 = in Bool // TMS + val pmod4_3 = in Bool // TCK + val pmod4_7 = in Bool // TDI + val pmod4_8 = in Bool // TMS /* SRAM */ - val sram_addr = out Bits(19 bits) + val sram_addr = out Bits (19 bits) // val sram_data = inout(Analog(Vec(Bool, 16))) val sram_data = master(TriStateArray(16 bits)) val sram_ce_n = out Bool @@ -130,16 +131,13 @@ class PQVexRiscvIcoboard( /* Remove io_ prefix from generated Verilog */ noIoPrefix() /* PLL config 100mhz -> 20mhz (using icepll tool of icestorm) */ - val pll = new Ice40PLL2FCore( - divR = 4, - divF = 0, - divQ = 5) + val pll = new Ice40PLL2FCore(divR = 4, divF = 0, divQ = 5) pll.io.REFERENCECLK := io.clk_100mhz pll.io.BYPASS := False pll.io.RESETB := True - val clk_20mhz = Bool + val clk_20mhz = Bool val clk_20mhz_90deg = Bool clk_20mhz := pll.io.PLLOUTGLOBALA clk_20mhz_90deg := pll.io.PLLOUTGLOBALB @@ -157,7 +155,7 @@ class PQVexRiscvIcoboard( val memory = new ClockingArea(systemClockDomain) { val ram = new PipelinedMemoryBusSRAM(busConfig) - busSlaves += ram.io.bus -> SizeMapping(0x80000000l, 1 MiB) + busSlaves += ram.io.bus -> SizeMapping(0x80000000L, 1 MiB) // val ice40io : Seq[Ice40IO] = (0 to 15).map(_ => new Ice40IO(0x29)) // ice40io.zipWithIndex.foreach { case (tio, i) => // tio.io.D_OUT_0 := ram.io.sram.dataOut(i) @@ -187,7 +185,7 @@ class PQVexRiscvIcoboard( } object PQVexRiscvIcoboard { - def main(args: Array[String]) : Unit = { + def main(args: Array[String]): Unit = { SpinalConfig( mode = Verilog, targetDirectory = "rtl" diff --git a/src/main/scala/mupq/PQVexRiscvSim.scala b/src/main/scala/mupq/PQVexRiscvSim.scala index 7a0e5c0..6014529 100644 --- a/src/main/scala/mupq/PQVexRiscvSim.scala +++ b/src/main/scala/mupq/PQVexRiscvSim.scala @@ -19,28 +19,28 @@ import spinal.lib.com.jtag.sim.JtagTcp import vexriscv.VexRiscv import vexriscv.plugin.Plugin -case class PipelinedMemoryBusRam(size : BigInt, initialContent : File = null) extends Component{ +case class PipelinedMemoryBusRam(size: BigInt, initialContent: File = null) extends Component { require(size % 4 == 0, "Size must be multiple of 4 bytes") require(size > 0, "Size must be greater than zero") val busConfig = PipelinedMemoryBusConfig(log2Up(size), 32) - val io = new Bundle{ + val io = new Bundle { val bus = slave(PipelinedMemoryBus(busConfig)) } val ram = Mem(Bits(32 bits), size / 4) - io.bus.rsp.valid := Delay(io.bus.cmd.fire && !io.bus.cmd.write, 2, init=False) + io.bus.rsp.valid := Delay(io.bus.cmd.fire && !io.bus.cmd.write, 2, init = False) val rdata = ram.readWriteSync( address = io.bus.cmd.address >> 2, - data = io.bus.cmd.data, - enable = io.bus.cmd.valid, - write = io.bus.cmd.write, - mask = io.bus.cmd.mask + data = io.bus.cmd.data, + enable = io.bus.cmd.valid, + write = io.bus.cmd.write, + mask = io.bus.cmd.mask ) - io.bus.rsp.data := RegNext(rdata) init(0) + io.bus.rsp.data := RegNext(rdata) init (0) io.bus.cmd.ready := True if (initialContent != null) { - val input = new FileInputStream(initialContent) + val input = new FileInputStream(initialContent) val initContent = Array.fill[BigInt](ram.wordCount)(0) val fileContent = Array.ofDim[Byte](Seq(input.available, initContent.length * 4).min) input.read(fileContent) @@ -52,23 +52,21 @@ case class PipelinedMemoryBusRam(size : BigInt, initialContent : File = null) ex } } - - - class PQVexRiscvSim( - val ramBlockSizes : Seq[BigInt] = Seq[BigInt](256 KiB, 128 KiB), - val initialContent : File = null, - val coreFrequency : HertzNumber = 12 MHz, - cpuPlugins : () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() -) extends PQVexRiscv( + val ramBlockSizes: Seq[BigInt] = Seq[BigInt](256 KiB, 128 KiB), + val initialContent: File = null, + val coreFrequency: HertzNumber = 12 MHz, + cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() +) +extends PQVexRiscv( cpuPlugins = cpuPlugins, - ibusRange = SizeMapping(0x80000000l, ramBlockSizes.reduce(_ + _)) + ibusRange = SizeMapping(0x80000000L, ramBlockSizes.reduce(_ + _)) ) { val io = new Bundle { val asyncReset = in Bool - val mainClock = in Bool - val uart = master(Uart()) - val jtag = slave(Jtag()) + val mainClock = in Bool + val uart = master(Uart()) + val jtag = slave(Jtag()) } asyncReset := io.asyncReset @@ -78,8 +76,10 @@ class PQVexRiscvSim( jtag <> io.jtag val memory = new ClockingArea(systemClockDomain) { - val ramBlocks = ramBlockSizes.zipWithIndex.map(t => PipelinedMemoryBusRam(t._1, if (t._2 == 0) initialContent else null)) - var curAddr : BigInt = 0x80000000l + val ramBlocks = + ramBlockSizes.zipWithIndex.map(t => + PipelinedMemoryBusRam(t._1, if (t._2 == 0) initialContent else null)) + var curAddr: BigInt = 0x80000000L for (block <- ramBlocks) { busSlaves += block.io.bus -> SizeMapping(curAddr, block.size) curAddr += block.size @@ -98,25 +98,36 @@ object PQVexRiscvSim { ) val optParser = new OptionParser[PQVexRiscvSimConfig]("PQVexRiscvSim") { head("PQVexRiscvSim simulator") - help("help") text("print usage text") - opt[File]("uart") action((f, c) => c.copy(uartOutFile = new FileOutputStream(f, true))) text("File for UART output (will be appended)") valueName("") - opt[File]("init") action((f, c) => c.copy(initFile = f)) text("Initialization file for first RAM block") valueName("") - opt[Seq[Int]]("ram") action((r, c) => c.copy(ramBlocks = r.map(_ KiB))) text("SRAM Blocks in KiB") valueName(",") + help("help") text ("print usage text") + opt[File]("uart") action ((f, c) => + c.copy(uartOutFile = + new FileOutputStream( + f, + true))) text ("File for UART output (will be appended)") valueName ("") + opt[File]("init") action ((f, c) => + c.copy(initFile = f)) text ("Initialization file for first RAM block") valueName ("") + opt[Seq[Int]]("ram") action ((r, c) => + c.copy(ramBlocks = + r.map(_ KiB))) text ("SRAM Blocks in KiB") valueName (",") } val config = optParser.parse(args, PQVexRiscvSimConfig()) match { case Some(config) => config - case None => ??? + case None => ??? } val compiled = SimConfig.allOptimisation.compile { - new PQVexRiscvSim(config.ramBlocks, config.initFile, cpuPlugins=config.cpuPlugins) + new PQVexRiscvSim( + config.ramBlocks, + config.initFile, + cpuPlugins = config.cpuPlugins + ) } compiled.doSim("PqVexRiscvSim", 42) { dut => - val mainClkPeriod = (1e12 / dut.coreFrequency.toDouble).toLong - val jtagClkPeriod = mainClkPeriod * 4 - val uartBaudRate = 115200 + val mainClkPeriod = (1e12 / dut.coreFrequency.toDouble).toLong + val jtagClkPeriod = mainClkPeriod * 4 + val uartBaudRate = 115200 val uartBaudPeriod = (1e12 / uartBaudRate.toDouble).toLong val clockDomain = ClockDomain(dut.io.mainClock, dut.io.asyncReset) @@ -143,7 +154,7 @@ object PQVexRiscvSim { } else { sleep(uartBaudPeriod) var byte = 0 - var i = 0 + var i = 0 while (i < 8) { if (uartPin.toBoolean) { byte |= 1 << i diff --git a/src/main/scala/mupq/PQVexRiscvUP5K.scala b/src/main/scala/mupq/PQVexRiscvUP5K.scala index a381242..1c1706a 100644 --- a/src/main/scala/mupq/PQVexRiscvUP5K.scala +++ b/src/main/scala/mupq/PQVexRiscvUP5K.scala @@ -18,10 +18,10 @@ class PipelinedMemoryBusSPRAM(busConfig: PipelinedMemoryBusConfig) extends Compo /* Tie together two RAMS to get 32-bit width */ val rams: Array[Ice40SPRAM] = (0 to 1).map(_ => new Ice40SPRAM).toArray - val enable = io.bus.cmd.valid - val mask = io.bus.cmd.mask + val enable = io.bus.cmd.valid + val mask = io.bus.cmd.mask /* Fan out the simple byte mask of the bus to bit masks */ - val maskLow = mask(1) ## mask(1) ## mask(0) ## mask(0) + val maskLow = mask(1) ## mask(1) ## mask(0) ## mask(0) val maskHigh = mask(3) ## mask(3) ## mask(2) ## mask(2) for ((ram, i) <- rams.zipWithIndex) { /* Don't ever sleep */ @@ -49,22 +49,23 @@ class PipelinedMemoryBusSPRAM(busConfig: PipelinedMemoryBusConfig) extends Compo } class PQVexRiscvUP5K( - val coreFrequency : HertzNumber = 12 MHz, - cpuPlugins : () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() -) extends PQVexRiscv( + val coreFrequency: HertzNumber = 12 MHz, + cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.withDSPMultiplier() +) +extends PQVexRiscv( cpuPlugins = cpuPlugins, - ibusRange = SizeMapping(0x80000000l, 128 KiB) + ibusRange = SizeMapping(0x80000000L, 128 KiB) ) { val io = new Bundle { val ice_clk = in Bool /* UART */ val iob_8a = out Bool // TXD - val iob_9b = in Bool // RXD + val iob_9b = in Bool // RXD /* JTAG */ - val iob_23b = out Bool // TDO - val iob_25b_g3 = in Bool // TCK - val iob_24a = in Bool // TDI - val iob_29b = in Bool // TMS + val iob_23b = out Bool // TDO + val iob_25b_g3 = in Bool // TCK + val iob_24a = in Bool // TDI + val iob_29b = in Bool // TMS } asyncReset := False mainClock := io.ice_clk @@ -90,29 +91,35 @@ class PQVexRiscvUP5K( val memory = new ClockingArea(systemClockDomain) { val ram1 = new PipelinedMemoryBusSPRAM(busConfig) - busSlaves += ram1.io.bus -> SizeMapping(0x80000000l, 64 KiB) + busSlaves += ram1.io.bus -> SizeMapping(0x80000000L, 64 KiB) val ram2 = new PipelinedMemoryBusSPRAM(busConfig) - busSlaves += ram2.io.bus -> SizeMapping(0x80000000l + (64 KiB).toLong, 64 KiB) + busSlaves += ram2.io.bus -> SizeMapping(0x80000000L + (64 KiB).toLong, 64 KiB) } } object PQVexRiscvUP5K { - def main(args: Array[String]) : Unit = { + def main(args: Array[String]): Unit = { case class PQVexRiscvUP5KConfig( cpuPlugins: () => Seq[Plugin[VexRiscv]] = PQVexRiscv.baseConfig() ) val optParser = new OptionParser[PQVexRiscvUP5KConfig]("PQVexRiscvUP5K") { head("PQVexRiscvUP5K board") - help("help") text("print usage text") - opt[Unit]("mul") action((_, c) => c.copy(cpuPlugins = PQVexRiscv.withDSPMultiplier(c.cpuPlugins))) + help("help") text ("print usage text") + opt[Unit]("mul") action ((_, c) => + c.copy(cpuPlugins = PQVexRiscv.withDSPMultiplier(c.cpuPlugins))) } val config = optParser.parse(args, PQVexRiscvUP5KConfig()) match { case Some(config) => config - case None => ??? + case None => ??? } - SpinalConfig( + val report = SpinalConfig( mode = Verilog, - targetDirectory = "rtl" - ).generate(new PQVexRiscvUP5K(cpuPlugins = config.cpuPlugins)) + targetDirectory = "rtl/gen" + ).generate( + new PQVexRiscvUP5K( + cpuPlugins = config.cpuPlugins + ) + ) + report.mergeRTLSource(s"rtl/gen/${report.toplevelName}.aux") } } diff --git a/src/main/scala/mupq/XilinxBlackbox.scala b/src/main/scala/mupq/XilinxBlackbox.scala index ed326fb..f03522b 100644 --- a/src/main/scala/mupq/XilinxBlackbox.scala +++ b/src/main/scala/mupq/XilinxBlackbox.scala @@ -3,44 +3,44 @@ package mupq import spinal.core._ case class XilinxPLLSpec( - pfdMin : HertzNumber = 19 MHz, - pfdMax : HertzNumber = 450 MHz, - vcoMin : HertzNumber = 800 MHz, - vcoMax : HertzNumber = 1600 MHz + pfdMin: HertzNumber = 19 MHz, + pfdMax: HertzNumber = 450 MHz, + vcoMin: HertzNumber = 800 MHz, + vcoMax: HertzNumber = 1600 MHz ) { - /** - * Calculates the parameters for a PLL/MMCM + /** Calculates the parameters for a PLL/MMCM * * @param clkIn Input frequency of the PLL * @param clkOut Output ferquencies (up to 6) of the PLL * @ - * */ - def calcPLLParameters(clkIn : HertzNumber, clkOut : Seq[HertzNumber]) : Tuple3[Int, Int, Array[Int]] = { + def calcPLLParameters( + clkIn: HertzNumber, + clkOut: Seq[HertzNumber] + ): Tuple3[Int, Int, Array[Int]] = { require(clkOut.length > 0 && clkOut.length <= 6, "Number of output clocks must be 1-6") // def gcd(a : Long, b : Long) : Long = if(b == 0) a else gcd(b, a % b) // def lcm(a : Long, b : Long) : Long = (a * b).abs / gcd(a, b) // val commonFreq = clkOut.map(_.toLong).reduceLeft((a, b) => lcm(a, b)) // println(f"Finding D/M for common frequency ${commonFreq}") - val d_min : Int = (clkIn.toDouble / pfdMax.toDouble).ceil.toInt - val d_max : Int = (clkIn.toDouble / pfdMin.toDouble).floor.toInt - val m_min : Int = ((vcoMin.toDouble / clkIn.toDouble) * d_min).ceil.toInt - val m_max : Int = ((vcoMax.toDouble / clkIn.toDouble) * d_max).floor.toInt + val d_min: Int = (clkIn.toDouble / pfdMax.toDouble).ceil.toInt + val d_max: Int = (clkIn.toDouble / pfdMin.toDouble).floor.toInt + val m_min: Int = ((vcoMin.toDouble / clkIn.toDouble) * d_min).ceil.toInt + val m_max: Int = ((vcoMax.toDouble / clkIn.toDouble) * d_max).floor.toInt // println(f"d_min: $d_min d_max: $d_max m_min: $m_min m_max: $m_max m_ideal: ${d_min * vcoMax.toLong / clkIn.toLong}") val cand = (for { - d <- d_min to d_max; m <- m_min to m_max - val vco = clkIn.toLong * m / d - if (vco >= vcoMin.toLong && // Don't exeed VCOMIN - vco <= vcoMax.toLong && // Don't exeed VCOMAX - clkOut.forall( // VCO should be a multiple of all output frequencies (but at most 128) - f => vco % f.toLong == 0 && vco / f.toLong < 128 - )) - } yield (d, m, vco) - ).sortBy((x) => (-x._3, x._2, x._1)) // Priority sort: highest VCO with lowest m and d + d <- d_min to d_max; m <- m_min to m_max + val vco = clkIn.toLong * m / d + if (vco >= vcoMin.toLong && // Don't exeed VCOMIN + vco <= vcoMax.toLong && // Don't exeed VCOMAX + clkOut.forall( // VCO should be a multiple of all output frequencies (but at most 128) + f => vco % f.toLong == 0 && vco / f.toLong < 128)) + } yield (d, m, vco)).sortBy((x) => + (-x._3, x._2, x._1)) // Priority sort: highest VCO with lowest m and d assert(cand.length != 0, "Unable to find valid configuration!") @@ -57,58 +57,64 @@ case class XilinxPLLSpec( } object XilinxPLLCalc { - def main(args: Array[String]) : Unit = { + def main(args: Array[String]): Unit = { val spec = XilinxPLLSpec() - println(spec.calcPLLParameters(33 MHz, Array(528 MHz, 264 MHz, 176 MHz, 132 MHz, 66 MHz, 33 MHz))) + println( + spec.calcPLLParameters(33 MHz, Array(528 MHz, 264 MHz, 176 MHz, 132 MHz, 66 MHz, 33 MHz)) + ) println(spec.calcPLLParameters(100 MHz, Array(50 MHz))) } } -class XilinxPLLBase(clkIn : HertzNumber, clkOut : Seq[HertzNumber], - specs : XilinxPLLSpec = XilinxPLLSpec()) extends BlackBox { +class XilinxPLLBase( + clkIn: HertzNumber, + clkOut: Seq[HertzNumber], + specs: XilinxPLLSpec = XilinxPLLSpec() +) +extends BlackBox { val (d, m, o) = specs.calcPLLParameters(clkIn, clkOut) - val outdiv = o ++ Array.fill(6 - o.length) {1} + val outdiv = o ++ Array.fill(6 - o.length) { 1 } val generic = new Generic { - val BANDWIDTH = "OPTIMIZED" - val CLKFBOUT_MULT = m - val CLKFBOUT_PHASE = 0.0 - val CLKIN1_PERIOD = 1e9 / clkIn.toDouble - val CLKOUT0_DIVIDE = outdiv(0) - val CLKOUT1_DIVIDE = outdiv(1) - val CLKOUT2_DIVIDE = outdiv(2) - val CLKOUT3_DIVIDE = outdiv(3) - val CLKOUT4_DIVIDE = outdiv(4) - val CLKOUT5_DIVIDE = outdiv(5) + val BANDWIDTH = "OPTIMIZED" + val CLKFBOUT_MULT = m + val CLKFBOUT_PHASE = 0.0 + val CLKIN1_PERIOD = 1e9 / clkIn.toDouble + val CLKOUT0_DIVIDE = outdiv(0) + val CLKOUT1_DIVIDE = outdiv(1) + val CLKOUT2_DIVIDE = outdiv(2) + val CLKOUT3_DIVIDE = outdiv(3) + val CLKOUT4_DIVIDE = outdiv(4) + val CLKOUT5_DIVIDE = outdiv(5) val CLKOUT0_DUTY_CYCLE = 0.5 val CLKOUT1_DUTY_CYCLE = 0.5 val CLKOUT2_DUTY_CYCLE = 0.5 val CLKOUT3_DUTY_CYCLE = 0.5 val CLKOUT4_DUTY_CYCLE = 0.5 val CLKOUT5_DUTY_CYCLE = 0.5 - val CLKOUT0_PHASE = 0.0 - val CLKOUT1_PHASE = 0.0 - val CLKOUT2_PHASE = 0.0 - val CLKOUT3_PHASE = 0.0 - val CLKOUT4_PHASE = 0.0 - val CLKOUT5_PHASE = 0.0 - val DIVCLK_DIVIDE = d - val REF_JITTER1 = 0.01 - val STARTUP_WAIT = "TRUE" + val CLKOUT0_PHASE = 0.0 + val CLKOUT1_PHASE = 0.0 + val CLKOUT2_PHASE = 0.0 + val CLKOUT3_PHASE = 0.0 + val CLKOUT4_PHASE = 0.0 + val CLKOUT5_PHASE = 0.0 + val DIVCLK_DIVIDE = d + val REF_JITTER1 = 0.01 + val STARTUP_WAIT = "TRUE" } val io = new Bundle { - val CLKFBIN = in Bool + val CLKFBIN = in Bool val CLKFBOUT = out Bool - val CLKIN1 = in Bool - val CLKOUT0 = out Bool - val CLKOUT1 = out Bool - val CLKOUT2 = out Bool - val CLKOUT3 = out Bool - val CLKOUT4 = out Bool - val CLKOUT5 = out Bool - val LOCKED = out Bool - val PWRDWN = in Bool - val RST = in Bool + val CLKIN1 = in Bool + val CLKOUT0 = out Bool + val CLKOUT1 = out Bool + val CLKOUT2 = out Bool + val CLKOUT3 = out Bool + val CLKOUT4 = out Bool + val CLKOUT5 = out Bool + val LOCKED = out Bool + val PWRDWN = in Bool + val RST = in Bool } noIoPrefix() setBlackBoxName("PLLE2_BASE") @@ -123,45 +129,54 @@ class XilinxGlobalBuffer extends BlackBox { setBlackBoxName("BUFG") } -class XilinxSinglePortRAM(val dataWidth : Int, val numWords : BigInt, val readLatency : Int = 1, val byteWrite : Boolean = true) extends BlackBox { - require(!byteWrite || dataWidth % 8 == 0, "dataWidth must be multiple of 8 if byteWrite is enabled") +class XilinxSinglePortRAM( + val dataWidth: Int, + val numWords: BigInt, + val readLatency: Int = 1, + val byteWrite: Boolean = true +) +extends BlackBox { + require( + !byteWrite || dataWidth % 8 == 0, + "dataWidth must be multiple of 8 if byteWrite is enabled" + ) val addrWidth = log2Up(numWords) val generic = new Generic { - val ADDR_WIDTH_A : Int = addrWidth - val AUTO_SLEEP_TIME : Int = 0 - val BYTE_WRITE_WIDTH_A : Int = if (byteWrite) 8 else dataWidth - val CASCADE_HEIGHT : Int = 0 - val ECC_MODE : String = "no_ecc" - val MEMORY_INIT_FILE : String = "none" - val MEMORY_INIT_PARAM : String = "0" - val MEMORY_OPTIMIZATION : String = "true" - val MEMORY_PRIMITIVE : String = "block" - val MEMORY_SIZE : Int = dataWidth * numWords.toInt - val MESSAGE_CONTROL : Int = 0 - val READ_DATA_WIDTH_A : Int = dataWidth - val READ_LATENCY_A : Int = readLatency - val READ_RESET_VALUE_A : String = "0" - val RST_MODE_A : String = if (ClockDomain.current.config.resetKind == ASYNC) "ASYNC" else "SYNC" - val SIM_ASSERT_CHK : Int = 0 - val USE_MEM_INIT : Int = 0 - val WAKEUP_TIME : String = "disable_sleep" - val WRITE_DATA_WIDTH_A : Int = dataWidth - val WRITE_MODE_A : String = "read_first" + val ADDR_WIDTH_A: Int = addrWidth + val AUTO_SLEEP_TIME: Int = 0 + val BYTE_WRITE_WIDTH_A: Int = if (byteWrite) 8 else dataWidth + val CASCADE_HEIGHT: Int = 0 + val ECC_MODE: String = "no_ecc" + val MEMORY_INIT_FILE: String = "none" + val MEMORY_INIT_PARAM: String = "0" + val MEMORY_OPTIMIZATION: String = "true" + val MEMORY_PRIMITIVE: String = "block" + val MEMORY_SIZE: Int = dataWidth * numWords.toInt + val MESSAGE_CONTROL: Int = 0 + val READ_DATA_WIDTH_A: Int = dataWidth + val READ_LATENCY_A: Int = readLatency + val READ_RESET_VALUE_A: String = "0" + val RST_MODE_A: String = if (ClockDomain.current.config.resetKind == ASYNC) "ASYNC" else "SYNC" + val SIM_ASSERT_CHK: Int = 0 + val USE_MEM_INIT: Int = 0 + val WAKEUP_TIME: String = "disable_sleep" + val WRITE_DATA_WIDTH_A: Int = dataWidth + val WRITE_MODE_A: String = "read_first" } val io = new Bundle() { - val dina = in Bits(dataWidth bits) - val addra = in Bits(addrWidth bits) - val wea = in Bits((if (byteWrite) dataWidth / 8 else dataWidth) bits) - val douta = out Bits(dataWidth bits) - val clka = in Bool - val rsta = in Bool - val ena = in Bool - val regcea = in Bool + val dina = in Bits (dataWidth bits) + val addra = in Bits (addrWidth bits) + val wea = in Bits ((if (byteWrite) dataWidth / 8 else dataWidth) bits) + val douta = out Bits (dataWidth bits) + val clka = in Bool + val rsta = in Bool + val ena = in Bool + val regcea = in Bool val injectsbiterra = in Bool - val sbiterra = out Bool + val sbiterra = out Bool val injectdbiterra = in Bool - val dbiterra = out Bool - val sleep = in Bool + val dbiterra = out Bool + val sleep = in Bool } noIoPrefix() setBlackBoxName("xpm_memory_spram")