Merge pull request #434 from goekce/master
add Murax config with native jtag based on the docs
This commit is contained in:
commit
7f2bccbef2
|
@ -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
|
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.
|
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`
|
```sh
|
||||||
and find the `Murax.scala` file.
|
sbt "runMain vexriscv.demo.MuraxWithRamInitWithNativeJtag"
|
||||||
* 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:
|
|
||||||
```
|
```
|
||||||
[164] val jtag = slave(Jtag())
|
|
||||||
…
|
The Murax configuration `MuraxWithRamInitWithNativeJtag` activates `WithNativeJtag` flag, which removes toplevel Jtag signals from the default Murax configuration and integrates `BSCANE2` plugin.
|
||||||
[392] val jtagClkBuffer = SB_GB()
|
|
||||||
[393] jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck
|
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.
|
||||||
[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.
|
|
||||||
|
|
||||||
## 3. Xilinx Vivado - Programming Arty A7 FPGA
|
## 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
|
There are many applications to program a FPGA. In our work we referred to the freely available Xilinx Vivado 2020
|
||||||
|
|
|
@ -17,6 +17,7 @@ import spinal.lib.com.spi.ddr._
|
||||||
import spinal.lib.bus.simple._
|
import spinal.lib.bus.simple._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
import scala.collection.Seq
|
import scala.collection.Seq
|
||||||
|
import spinal.lib.com.jtag.JtagTapInstructionCtrl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by PIC32F_USER on 28/07/2017.
|
* Created by PIC32F_USER on 28/07/2017.
|
||||||
|
@ -44,7 +45,9 @@ case class MuraxConfig(coreFrequency : HertzNumber,
|
||||||
uartCtrlConfig : UartCtrlMemoryMappedConfig,
|
uartCtrlConfig : UartCtrlMemoryMappedConfig,
|
||||||
xipConfig : SpiXdrMasterCtrl.MemoryMappingParameters,
|
xipConfig : SpiXdrMasterCtrl.MemoryMappingParameters,
|
||||||
hardwareBreakpointCount : Int,
|
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")
|
require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions")
|
||||||
val genXip = xipConfig != null
|
val genXip = xipConfig != null
|
||||||
|
|
||||||
|
@ -69,6 +72,7 @@ object MuraxConfig{
|
||||||
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, lengthWidth = 2)
|
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, lengthWidth = 2)
|
||||||
)),
|
)),
|
||||||
hardwareBreakpointCount = if(withXip) 3 else 0,
|
hardwareBreakpointCount = if(withXip) 3 else 0,
|
||||||
|
withNativeJtag = false,
|
||||||
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
resetVector = if(withXip) 0xF001E000l else 0x80000000l,
|
resetVector = if(withXip) 0xF001E000l else 0x80000000l,
|
||||||
|
@ -162,7 +166,7 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
val mainClk = in Bool()
|
val mainClk = in Bool()
|
||||||
|
|
||||||
//Main components IO
|
//Main components IO
|
||||||
val jtag = slave(Jtag())
|
val jtag = ifGen(!config.withNativeJtag) (slave(Jtag()))
|
||||||
|
|
||||||
//Peripherals IO
|
//Peripherals IO
|
||||||
val gpioA = master(TriStateArray(gpioWidth bits))
|
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 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(
|
val resetCtrlClockDomain = ClockDomain(
|
||||||
clock = io.mainClk,
|
clock = io.mainClk,
|
||||||
|
@ -251,8 +259,12 @@ case class Murax(config : MuraxConfig) extends Component{
|
||||||
}
|
}
|
||||||
case plugin : DebugPlugin => plugin.debugClockDomain{
|
case plugin : DebugPlugin => plugin.debugClockDomain{
|
||||||
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
||||||
|
if (withNativeJtag) {
|
||||||
|
jtagNative.jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(jtagNative.tap.TCK),0)
|
||||||
|
} else {
|
||||||
io.jtag <> plugin.io.bus.fromJtag()
|
io.jtag <> plugin.io.bus.fromJtag()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case _ =>
|
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{
|
object Murax_arty{
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]) {
|
||||||
val hex = "src/main/c/murax/hello_world/build/hello_world.hex"
|
val hex = "src/main/c/murax/hello_world/build/hello_world.hex"
|
||||||
|
@ -533,11 +554,9 @@ object Murax_arty{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
object MuraxAsicBlackBox extends App{
|
object MuraxAsicBlackBox extends App{
|
||||||
println("Warning this soc do not has any rom to boot on.")
|
println("Warning this soc do not has any rom to boot on.")
|
||||||
val config = SpinalConfig()
|
val config = SpinalConfig()
|
||||||
config.addStandardMemBlackboxing(blackboxAll)
|
config.addStandardMemBlackboxing(blackboxAll)
|
||||||
config.generateVerilog(Murax(MuraxConfig.default()))
|
config.generateVerilog(Murax(MuraxConfig.default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue