jtag: make it easier to assign MFR ID externally
This commit is contained in:
parent
34d45b4fb0
commit
fd7f4a4c0f
@ -32,17 +32,19 @@ class JtagControl extends Bundle {
|
||||
|
||||
/** Aggregate JTAG block IO.
|
||||
*/
|
||||
class JtagBlockIO(irLength: Int) extends Bundle {
|
||||
class JtagBlockIO(irLength: Int, hasIdcode:Boolean = true) extends Bundle {
|
||||
|
||||
val jtag = Flipped(new JTAGIO())
|
||||
val control = new JtagControl
|
||||
val output = new JtagOutput(irLength)
|
||||
val idcode = if (hasIdcode) Some(Input(new JTAGIdcodeBundle())) else None
|
||||
|
||||
override def cloneType = new JtagBlockIO(irLength).asInstanceOf[this.type]
|
||||
override def cloneType = new JtagBlockIO(irLength, hasIdcode).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
/** Internal controller block IO with data shift outputs.
|
||||
*/
|
||||
class JtagControllerIO(irLength: Int) extends JtagBlockIO(irLength) {
|
||||
class JtagControllerIO(irLength: Int) extends JtagBlockIO(irLength, false) {
|
||||
val dataChainOut = Output(new ShifterIO)
|
||||
val dataChainIn = Input(new ShifterIO)
|
||||
|
||||
@ -140,7 +142,7 @@ object JtagTapGenerator {
|
||||
* @param irLength length, in bits, of instruction register, must be at least 2
|
||||
* @param instructions map of instruction codes to data register chains that select that data
|
||||
* register; multiple instructions may map to the same data chain
|
||||
* @param idcode optional idcode, tuple of (instruction code, idcode)
|
||||
* @param idcode optional idcode instruction. idcode UInt will come from outside this core.
|
||||
*
|
||||
* @note all other instruction codes (not part of instructions or idcode) map to BYPASS
|
||||
* @note initial instruction is idcode (if supported), otherwise all ones BYPASS
|
||||
@ -158,25 +160,30 @@ object JtagTapGenerator {
|
||||
* TODO:
|
||||
* - support concatenated scan chains
|
||||
*/
|
||||
def apply(irLength: Int, instructions: Map[BigInt, Chain], idcode:Option[(BigInt, BigInt)]=None): JtagBlockIO = {
|
||||
def apply(irLength: Int, instructions: Map[BigInt, Chain], icode: Option[BigInt] = None): JtagBlockIO = {
|
||||
|
||||
val internalIo = Wire(new JtagBlockIO(irLength, icode.isDefined))
|
||||
|
||||
|
||||
// Create IDCODE chain if needed
|
||||
val allInstructions = idcode match {
|
||||
case Some((icode, idcode)) => {
|
||||
val idcodeChain = Module(CaptureChain(UInt(32.W)))
|
||||
idcodeChain.suggestName("idcodeChain")
|
||||
require(idcode % 2 == 1, "LSB must be set in IDCODE, see 12.1.1d")
|
||||
require(((idcode >> 1) & ((1 << 11) - 1)) != JtagIdcode.dummyMfrId, "IDCODE must not have 0b00001111111 as manufacturer identity, see 12.2.1b")
|
||||
val allInstructions = icode match {
|
||||
case (Some(icode)) => {
|
||||
require(!(instructions contains icode), "instructions may not contain IDCODE")
|
||||
idcodeChain.io.capture.bits := idcode.U(32.W)
|
||||
val idcodeChain = Module(CaptureChain(new JTAGIdcodeBundle()))
|
||||
idcodeChain.suggestName("idcodeChain")
|
||||
val i = internalIo.idcode.get.asUInt()
|
||||
assert(i % 2.U === 1.U, "LSB must be set in IDCODE, see 12.1.1d")
|
||||
assert(((i >> 1) & ((1.U << 11) - 1.U)) =/= JtagIdcode.dummyMfrId.U,
|
||||
"IDCODE must not have 0b00001111111 as manufacturer identity, see 12.2.1b")
|
||||
idcodeChain.io.capture.bits := internalIo.idcode.get
|
||||
instructions + (icode -> idcodeChain)
|
||||
} case None => instructions
|
||||
|
||||
}
|
||||
case None => instructions
|
||||
}
|
||||
|
||||
val bypassIcode = (BigInt(1) << irLength) - 1 // required BYPASS instruction
|
||||
val initialInstruction = idcode match { // 7.2.1e load IDCODE or BYPASS instruction after entry into TestLogicReset
|
||||
case Some((icode, _)) => icode
|
||||
case None => bypassIcode
|
||||
}
|
||||
val initialInstruction = icode.getOrElse(bypassIcode) // 7.2.1e load IDCODE or BYPASS instruction after entry into TestLogicReset
|
||||
|
||||
require(!(allInstructions contains bypassIcode), "instructions may not contain BYPASS code")
|
||||
|
||||
@ -230,12 +237,11 @@ object JtagTapGenerator {
|
||||
|
||||
chainToSelect.map(mapInSelect)
|
||||
|
||||
val internalIo = Wire(new JtagBlockIO(irLength))
|
||||
|
||||
controllerInternal.io.jtag <> internalIo.jtag
|
||||
controllerInternal.io.control <> internalIo.control
|
||||
controllerInternal.io.output <> internalIo.output
|
||||
|
||||
internalIo
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,13 @@ package jtag
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class JTAGIdcodeBundle extends Bundle {
|
||||
val version = UInt(4.W)
|
||||
val partNumber = UInt(16.W)
|
||||
val mfrId = UInt(11.W)
|
||||
val always1 = UInt(1.W)
|
||||
}
|
||||
|
||||
object JtagIdcode {
|
||||
/** Generates a JTAG IDCODE as a 32-bit integer, using the format in 12.1.1d.
|
||||
*/
|
||||
|
@ -64,6 +64,7 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
||||
val dmi = new DMIIO()(p)
|
||||
val jtag = Flipped(new JTAGIO(hasTRSTn = false))
|
||||
val jtag_reset = Bool(INPUT)
|
||||
val jtag_mfr_id = UInt(INPUT, 11)
|
||||
val fsmReset = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
@ -210,12 +211,19 @@ class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Actual JTAG TAP
|
||||
val idcode = Wire(init = new JTAGIdcodeBundle().fromBits(0.U))
|
||||
idcode.always1 := 1.U
|
||||
idcode.version := c.idcodeVersion.U
|
||||
idcode.partNumber := c.idcodePartNum.U
|
||||
idcode.mfrId := io.jtag_mfr_id
|
||||
|
||||
val tapIO = JtagTapGenerator(irLength = 5,
|
||||
instructions = Map(dtmJTAGAddrs.DMI_ACCESS -> dmiAccessChain,
|
||||
dtmJTAGAddrs.DTM_INFO -> dtmInfoChain),
|
||||
idcode = Some((dtmJTAGAddrs.IDCODE, JtagIdcode(c.idcodeVersion, c.idcodePartNum, c.idcodeManufId))))
|
||||
icode = Some(dtmJTAGAddrs.IDCODE)
|
||||
)
|
||||
|
||||
tapIO.idcode.get := idcode
|
||||
tapIO.jtag <> io.jtag
|
||||
|
||||
tapIO.control.jtag_reset := io.jtag_reset
|
||||
|
@ -24,6 +24,7 @@ trait PeripheryJTAGDTMBundle extends HasTopLevelNetworksBundle {
|
||||
|
||||
val jtag = new JTAGIO(hasTRSTn = false).flip
|
||||
val jtag_reset = Bool(INPUT)
|
||||
val jtag_mfr_id = UInt(INPUT, 11)
|
||||
|
||||
}
|
||||
|
||||
@ -36,6 +37,7 @@ trait PeripheryJTAGDTMModule extends HasTopLevelNetworksModule {
|
||||
|
||||
dtm.clock := io.jtag.TCK
|
||||
dtm.io.jtag_reset := io.jtag_reset
|
||||
dtm.io.jtag_mfr_id := io.jtag_mfr_id
|
||||
dtm.reset := dtm.io.fsmReset
|
||||
|
||||
outer.coreplex.module.io.debug.dmi <> dtm.io.dmi
|
||||
@ -79,6 +81,7 @@ trait PeripheryDebugBundle extends HasTopLevelNetworksBundle {
|
||||
|
||||
val jtag = (p(IncludeJtagDTM)).option(new JTAGIO(hasTRSTn = false).flip)
|
||||
val jtag_reset = (p(IncludeJtagDTM)).option(Bool(INPUT))
|
||||
val jtag_mfr_id = (p(IncludeJtagDTM)).option(UInt(INPUT, 11))
|
||||
|
||||
val ndreset = Bool(OUTPUT)
|
||||
val dmactive = Bool(OUTPUT)
|
||||
@ -96,6 +99,7 @@ trait PeripheryDebugModule extends HasTopLevelNetworksModule {
|
||||
|
||||
dtm.clock := io.jtag.get.TCK
|
||||
dtm.io.jtag_reset := io.jtag_reset.get
|
||||
dtm.io.jtag_mfr_id := io.jtag_mfr_id.get
|
||||
dtm.reset := dtm.io.fsmReset
|
||||
|
||||
outer.coreplex.module.io.debug.dmi <> dtm.io.dmi
|
||||
|
@ -28,6 +28,7 @@ class TestHarness()(implicit p: Parameters) extends Module {
|
||||
val dtm = Module(new SimDTM).connect(clock, reset, dut.io.debug.get, io.success)
|
||||
} else {
|
||||
val jtag = Module(new JTAGVPI).connect(dut.io.jtag.get, dut.io.jtag_reset.get, reset, io.success)
|
||||
dut.io.jtag_mfr_id.get := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||
}
|
||||
|
||||
val mmio_sim = Module(LazyModule(new SimAXIMem(1, 4096)).module)
|
||||
|
Loading…
Reference in New Issue
Block a user