Merge pull request #434 from goekce/master

add Murax config with native jtag based on the docs
This commit is contained in:
Dolu1990 2024-11-15 11:47:51 +01:00 committed by GitHub
commit 7f2bccbef2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 44 deletions

View File

@ -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 SoCs 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

View File

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