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
|
||||
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
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue