Skip to content

Instantly share code, notes, and snippets.

@allexoll
Created October 7, 2021 13:04
Show Gist options
  • Save allexoll/e921ed46e42ab56c29b6f0b25015902e to your computer and use it in GitHub Desktop.
Save allexoll/e921ed46e42ab56c29b6f0b25015902e to your computer and use it in GitHub Desktop.
// from a jtag main standpoint. the jtag debugger either updates(write to) the DR, or captures it (read from)
def readAndWrite[T<: Data](captureData: T, updateData: T, captureReady: Bool, updateValid:Bool)(instructionId: Int) = {
val area = new JtagTapInstructionReadWrite(captureData, updateData, captureReady)
map(area.ctrl, instructionId)
updateValid := RegNext(area.ctrl.enable && area.ctrl.update)
area
}
/**
* Usefull to create a jtag tap instruction that has a different data input/output, with a captureReady
*/
class JtagTapInstructionReadWrite[T <: Data](captureData: T, updateData: T, captureReady: Bool) extends Area {
val ctrl = JtagTapInstructionCtrl()
assert(widthOf(captureData) == widthOf(updateData)) // tdo is also clocked by tck
val shifter = Reg(Bits(widthOf(captureData) bits))
val store = Reg(Bits(widthOf(updateData) bit)) // for clean update
captureReady := False
when(ctrl.enable) {
when(ctrl.capture) { // when the jtag is capturing the TAP
shifter := B(captureData)
}
when(ctrl.shift) { // tdi DR shifting
shifter := (ctrl.tdi ## shifter) >> 1
}
when(ctrl.update) {
store := shifter
captureReady := True // ready for new data
}
}
ctrl.tdo := shifter.lsb // tdo DR shifting
updateData.assignFromBits(store)
}
/*
Example with riscv DTM register mapping and access.
*/
/*
ID code should be [version(4bits):partNumber(16):maufID(11):0b1]
*/
class JtagDTM(c: SystemDebuggerConfig, idcode: Bits = B"x10001FFF") extends Component{
val io = new Bundle {
val jtag = slave(Jtag())
val remote = master(DMI(c.memAddressWidth))
}
val system = new Area {
val dtmcs = new Area {
val dmihardreset = Bool()
val dmireset = Bool()
val idle = UInt(3 bits)
val dmistat = Reg(UInt(2 bits)) init 0
val abits = UInt(6 bits)
val version = UInt(4 bits)
dmihardreset := False
dmireset := False
idle := 1
abits := c.memAddressWidth
version := 1 // version 0.13 and 1.0
}
// Aggregate dtmcs
val dtmcs_agr = Bits(32 bits)
dtmcs_agr(31 downto 18) := 0
dtmcs_agr(17) := dtmcs.dmihardreset
dtmcs_agr(16) := dtmcs.dmireset
dtmcs_agr(15) := False
dtmcs_agr(14 downto 12) := dtmcs.idle.asBits
dtmcs_agr(11 downto 10) := dtmcs.dmistat.asBits
dtmcs_agr(9 downto 4) := dtmcs.abits.asBits
dtmcs_agr(3 downto 0) := dtmcs.version.asBits
}
val dmi_capture = Bits(c.memAddressWidth+32+2 bits)
val dmi_update = Bits(c.memAddressWidth+32+2 bits)
dmi_capture := B"x0".resize(66)
val capture_ready = Bool()
val update_valid = Bool()
val jtag = ClockDomain(io.jtag.tck)(new Area{
val tap = new JtagTap(io.jtag, 5)
val idcodeArea = tap.idcode(B"x10001FFF")(1) // to identify a specific silicon version
// the lsb of idcode should be 1 because the tap will be bypassed if it is not
val dtmcs = tap.read(system.dtmcs_agr)(0x10) // For debugging
val dmi = tap.readAndWrite(dmi_capture.addTag(crossClockDomain), dmi_update.addTag(crossClockDomain),capture_ready.addTag(crossClockDomain),update_valid.addTag(crossClockDomain))(0x11)
})
io.remote.req.payload.address := dmi_update(c.memAddressWidth + 33 downto 34)
io.remote.req.payload.data := dmi_update(33 downto 2)
io.remote.req.payload.op := dmi_update(1 downto 0)
io.remote.req.valid := update_valid.rise()
val rsp = io.remote.rsp
rsp.ready := capture_ready.rise()
when(rsp.valid){
dmi_capture := dmi_update(c.memAddressWidth + 33 downto 34) ## rsp.payload.data ## rsp.payload.op
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment