Skip to content

Commit

Permalink
Merge pull request #434 from goekce/master
Browse files Browse the repository at this point in the history
add Murax config with native jtag based on the docs
  • Loading branch information
Dolu1990 authored Nov 15, 2024
2 parents 4cf81af + 41ea95f commit 7f2bccb
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 44 deletions.
46 changes: 7 additions & 39 deletions doc/nativeJtag/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 24 additions & 5 deletions src/main/scala/vexriscv/demo/Murax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand All @@ -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,
Expand Down Expand Up @@ -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))
Expand All @@ -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,
Expand Down Expand Up @@ -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 _ =>
}
Expand Down Expand Up @@ -526,18 +538,25 @@ 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"
SpinalVerilog(Murax(MuraxConfig.default(false).copy(coreFrequency = 100 MHz,onChipRamSize = 32 kB, onChipRamHexFile = hex)))
}
}


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()))
}

0 comments on commit 7f2bccb

Please sign in to comment.