From e0f4bacaf4e88883ad8452f7fa7cb884a6061a22 Mon Sep 17 00:00:00 2001 From: goekce <18174744+goekce@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:31:17 +0100 Subject: [PATCH 1/4] add Murax config with native jtag --- doc/nativeJtag/README.md | 46 ++++-------------------- src/main/scala/vexriscv/demo/Murax.scala | 24 ++++++++++--- 2 files changed, 26 insertions(+), 44 deletions(-) diff --git a/doc/nativeJtag/README.md b/doc/nativeJtag/README.md index 10c5b7e..16f23ed 100644 --- a/doc/nativeJtag/README.md +++ b/doc/nativeJtag/README.md @@ -24,47 +24,15 @@ reader is capable of generating the Murax SoC as it is described there. The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary Scan logic controller. This allows for communication between the internally running design and the dedicated JTAG pins of the FPGA. -### Steps to enable Bscane2 +Run the following command at the top level of the repository. -After cloning all files from https://github.com/SpinalHDL/VexRiscv, go to the path: `src/main/scala/vexriscv/demo` -and find the `Murax.scala` file. -* Comment out the following lines to remove the toplevel jtag I/O pins in `Murax.scala`. Be aware that line numbers -as given could move with future changes to the file: +```sh +sbt "runMain vexriscv.demo.MuraxWithRamInitWithNativeJtag" ``` -[164] val jtag = slave(Jtag()) -… -[392] val jtagClkBuffer = SB_GB() -[393] jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck -[394] jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck -… -[398] murax.io.jtag.tdi <> io.jtag_tdi -[399] murax.io.jtag.tdo <> io.jtag_tdo -[400] murax.io.jtag.tms <> io.jtag_tms -``` -* In the `Murax.scala` file, delete the line: -``` -[253] io.jtag <> plugin.io.bus.fromJtag() -``` -* And add the lines: -``` -[254] val jtagCtrl = JtagTapInstructionCtrl() -[255] val tap = jtagCtrl.fromXilinxBscane2(userId = 2) -[256] jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK),0) -``` -Changing the above lines, removes the Murax SoC’s JTAG ports as pins of the FPGA and inserts the BSCANE2 Xilinx -Debug IP to which the JTAG signals are now connected. -* Add the following import statement at the beginning of `Murax.scala`: -``` -import spinal.lib.com.jtag.JtagTapInstructionCtrl -``` -With these changes in place, you generate the SoC with a demo program already in ram by use of: -``` -sbt "runMain vexriscv.demo.MuraxWithRamInit" -``` -A Verilog file is generated with the name `Murax.v` next to four `.bin` files inside the `VexRiscv` folder. These -files are the input to the Xilinx FPGA synthesis. Inside the `Murax.v` file, we can see that the BSCANE2 ports are -instantiated, confirming that the BSCANE2 has successfully been instantiated within the Murax SoC as a debug brige -to JTAG. + +The Murax configuration `MuraxWithRamInitWithNativeJtag` activates `WithNativeJtag` flag, which removes toplevel Jtag signals from the default Murax configuration and integrates `BSCANE2` plugin. + +After code generation you will see the Verilog file `Murax.v` next to four `.bin` files at the top level of the repository. These files are the input to the Xilinx FPGA synthesis. Inside the `Murax.v` file, we can see that the BSCANE2 ports are instantiated, confirming that the BSCANE2 has successfully been instantiated within the Murax SoC as a debug bridge to JTAG. ## 3. Xilinx Vivado - Programming Arty A7 FPGA There are many applications to program a FPGA. In our work we referred to the freely available Xilinx Vivado 2020 diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index d7022f5..b7145eb 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -17,6 +17,7 @@ import spinal.lib.com.spi.ddr._ import spinal.lib.bus.simple._ import scala.collection.mutable.ArrayBuffer import scala.collection.Seq +import spinal.lib.com.jtag.JtagTapInstructionCtrl /** * Created by PIC32F_USER on 28/07/2017. @@ -44,7 +45,9 @@ case class MuraxConfig(coreFrequency : HertzNumber, uartCtrlConfig : UartCtrlMemoryMappedConfig, xipConfig : SpiXdrMasterCtrl.MemoryMappingParameters, hardwareBreakpointCount : Int, - cpuPlugins : ArrayBuffer[Plugin[VexRiscv]]){ + withNativeJtag : Boolean, + cpuPlugins : ArrayBuffer[Plugin[VexRiscv]] + ){ require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions") val genXip = xipConfig != null @@ -69,6 +72,7 @@ object MuraxConfig{ xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, lengthWidth = 2) )), hardwareBreakpointCount = if(withXip) 3 else 0, + withNativeJtag = false, cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel new IBusSimplePlugin( resetVector = if(withXip) 0xF001E000l else 0x80000000l, @@ -162,7 +166,7 @@ case class Murax(config : MuraxConfig) extends Component{ val mainClk = in Bool() //Main components IO - val jtag = slave(Jtag()) + val jtag = ifGen(!config.withNativeJtag) (slave(Jtag())) //Peripherals IO val gpioA = master(TriStateArray(gpioWidth bits)) @@ -251,7 +255,13 @@ case class Murax(config : MuraxConfig) extends Component{ } case plugin : DebugPlugin => plugin.debugClockDomain{ resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut)) - io.jtag <> plugin.io.bus.fromJtag() + if (withNativeJtag) { + val jtagCtrl = JtagTapInstructionCtrl() + val tap = jtagCtrl.fromXilinxBscane2(userId = 2) + jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK),0) + } else { + io.jtag <> plugin.io.bus.fromJtag() + } } case _ => } @@ -526,6 +536,12 @@ object MuraxWithRamInit{ } } +object MuraxWithRamInitWithNativeJtag{ + def main(args: Array[String]) { + SpinalVerilog(Murax(MuraxConfig.default.copy(withNativeJtag = true, onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex"))) + } +} + object Murax_arty{ def main(args: Array[String]) { val hex = "src/main/c/murax/hello_world/build/hello_world.hex" @@ -533,11 +549,9 @@ object Murax_arty{ } } - object MuraxAsicBlackBox extends App{ println("Warning this soc do not has any rom to boot on.") val config = SpinalConfig() config.addStandardMemBlackboxing(blackboxAll) config.generateVerilog(Murax(MuraxConfig.default())) } - From 110b2a1e00c9da537e5d551d733eb21d4b440844 Mon Sep 17 00:00:00 2001 From: goekce <18174744+goekce@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:22:22 +0100 Subject: [PATCH 2/4] make JtagNative signal visible in generated code --- src/main/scala/vexriscv/demo/Murax.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index b7145eb..df64400 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -175,6 +175,10 @@ case class Murax(config : MuraxConfig) extends Component{ val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi))) } + val jtagNative = withNativeJtag generate new ClockingArea(debugClockDomain){ + val jtagCtrl = JtagTapInstructionCtrl() + val tap = jtagCtrl.fromXilinxBscane2(userId = 2) + } val resetCtrlClockDomain = ClockDomain( clock = io.mainClk, @@ -256,9 +260,7 @@ case class Murax(config : MuraxConfig) extends Component{ case plugin : DebugPlugin => plugin.debugClockDomain{ resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut)) if (withNativeJtag) { - val jtagCtrl = JtagTapInstructionCtrl() - val tap = jtagCtrl.fromXilinxBscane2(userId = 2) - jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK),0) + jtagNative.jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(jtagNative.tap.TCK),0) } else { io.jtag <> plugin.io.bus.fromJtag() } From bd3942166493496751b6c2ee727fcd76fca6afea Mon Sep 17 00:00:00 2001 From: goekce <18174744+goekce@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:25:54 +0100 Subject: [PATCH 3/4] fix indent --- src/main/scala/vexriscv/demo/Murax.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index df64400..43e05e4 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -175,10 +175,10 @@ case class Murax(config : MuraxConfig) extends Component{ val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi))) } - val jtagNative = withNativeJtag generate new ClockingArea(debugClockDomain){ - val jtagCtrl = JtagTapInstructionCtrl() - val tap = jtagCtrl.fromXilinxBscane2(userId = 2) - } + val jtagNative = withNativeJtag generate new ClockingArea(debugClockDomain){ + val jtagCtrl = JtagTapInstructionCtrl() + val tap = jtagCtrl.fromXilinxBscane2(userId = 2) + } val resetCtrlClockDomain = ClockDomain( clock = io.mainClk, From 41ea95f805f2213e14415a6b9642ea1c6ec78076 Mon Sep 17 00:00:00 2001 From: goekce <18174744+goekce@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:12:11 +0100 Subject: [PATCH 4/4] add argument for simulation frequency --- src/main/scala/vexriscv/demo/Murax.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index 43e05e4..d7432b5 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -540,7 +540,10 @@ object MuraxWithRamInit{ object MuraxWithRamInitWithNativeJtag{ def main(args: Array[String]) { - SpinalVerilog(Murax(MuraxConfig.default.copy(withNativeJtag = true, onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex"))) + val coreFrequency = if (args.nonEmpty) HertzNumber(BigDecimal(args(0))) else MuraxConfig.default.coreFrequency + val (scaledValue, unit) = coreFrequency.decompose + println(s"coreFrequency = $scaledValue $unit") + SpinalVerilog(Murax(MuraxConfig.default.copy(coreFrequency=coreFrequency, withNativeJtag = true, onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex"))) } }