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..d7432b5 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)) @@ -171,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, @@ -251,7 +259,11 @@ 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) { + jtagNative.jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(jtagNative.tap.TCK),0) + } else { + io.jtag <> plugin.io.bus.fromJtag() + } } case _ => } @@ -526,6 +538,15 @@ object MuraxWithRamInit{ } } +object MuraxWithRamInitWithNativeJtag{ + def main(args: Array[String]) { + 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"))) + } +} + object Murax_arty{ def main(args: Array[String]) { val hex = "src/main/c/murax/hello_world/build/hello_world.hex" @@ -533,11 +554,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())) } -