Skip to content

Instantly share code, notes, and snippets.

@lapnd
Forked from jevinskie/jtag.py
Created December 13, 2021 16:12
Show Gist options
  • Save lapnd/60883ef11733e46d12b369802db3fb1d to your computer and use it in GitHub Desktop.
Save lapnd/60883ef11733e46d12b369802db3fb1d to your computer and use it in GitHub Desktop.
migen Altera JTAG
# JTAG TAP FSM -------------------------------------------------------------------------------------
class JTAGTAPFSM(Module):
def __init__(self, tms: Signal, tck: Signal, use_ieee_encoding=False, expose_signals=True):
self.submodules.fsm = fsm = ClockDomainsRenamer("jtag")(FSM())
# Debug counter
# self.tck_cnt = tck_cnt = Signal(16)
# self.sync.jtag += tck_cnt.eq(tck_cnt + 1)
fsm.act('test_logic_reset',
If(~tms, NextState('run_test_idle'))
)
fsm.act('run_test_idle',
If( tms, NextState('select_dr_scan'))
)
# DR
fsm.act('select_dr_scan',
If(~tms, NextState('capture_dr') ).Else(NextState('select_ir_scan'))
)
fsm.act('capture_dr',
If(~tms, NextState('shift_dr') ).Else(NextState('exit1_dr'))
)
fsm.act('shift_dr',
If( tms, NextState('exit1_dr'))
)
fsm.act('exit1_dr',
If(~tms, NextState('pause_dr') ).Else(NextState('update_dr'))
)
fsm.act('pause_dr',
If( tms, NextState('exit2_dr'))
)
fsm.act('exit2_dr',
If( tms, NextState('update_dr') ).Else(NextState('shift_dr'))
)
fsm.act('update_dr',
If( tms, NextState('select_dr_scan')).Else(NextState('run_test_idle'))
)
# IR
fsm.act('select_ir_scan',
If(~tms, NextState('capture_ir') ).Else(NextState('test_logic_reset'))
)
fsm.act('capture_ir',
If(~tms, NextState('shift_ir') ).Else(NextState('exit1_ir'))
)
fsm.act('shift_ir',
If( tms, NextState('exit1_ir'))
)
fsm.act('exit1_ir',
If(~tms, NextState('pause_ir') ).Else(NextState('update_ir'))
)
fsm.act('pause_ir',
If( tms, NextState('exit2_ir'))
)
fsm.act('exit2_ir',
If( tms, NextState('update_ir') ).Else(NextState('shift_ir'))
)
fsm.act('update_ir',
If( tms, NextState('select_dr_scan')).Else(NextState('run_test_idle'))
)
if use_ieee_encoding:
# 11491.1-2013 Table 6-3 "State assignments for example TAP controller" page 36 pdf page 58
self.fsm.encoding = {
'exit2_dr': 0,
'exit1_dr': 1,
'shift_dr': 2,
'pause_dr': 3,
'select_ir_scan': 4,
'update_dr': 5,
'capture_dr': 6,
'select_dr_scan': 7,
'exit2_ir': 8,
'exit1_ir': 9,
'shift_ir': 0xA,
'pause_ir': 0xB,
'run_test_idle': 0xC,
'update_ir': 0xD,
'capture_ir': 0xE,
'test_logic_reset': 0xF,
}
if expose_signals:
for state_name in fsm.actions:
reset_val = 0
if state_name == 'test_logic_reset':
reset_val = 1
sig = fsm.ongoing(state_name, reset=reset_val)
SHOUTING_NAME = state_name.upper()
hcs_name = SHOUTING_NAME
hcs = Signal(name=hcs_name)
setattr(self, hcs_name, hcs)
self.comb += hcs.eq(sig)
class AlteraJTAG(Module):
def __init__(self, primitive: str, reserved_pads: Record, chain=1):
self.reset = reset = Signal()
self.capture = capture = Signal()
self.shift = shift = Signal()
self.update = update = Signal()
#
self.runtest = runtest = Signal()
self.drck = drck = Signal()
self.sel = sel = Signal()
self.tck = tck = Signal()
self.tms = tms = Signal()
self.tdi = tdi = Signal()
self.tdo = tdo = Signal()
self.altera_reserved_tck = rtck = Signal()
self.altera_reserved_tms = rtms = Signal()
self.altera_reserved_tdi = rtdi = Signal()
self.altera_reserved_tdo = rtdo = Signal()
# inputs
# self.tdoutap = tdoutap = Signal() # fails synth on max10
self.tdouser = tdouser = Signal()
# self.tmscore = tmscore = Signal()
# self.tckcore = tckcore = Signal()
# self.tdicore = tdicore = Signal()
# self.corectl = corectl = Signal()
# self.ntdopinena = ntdopinena = Signal()
# outputs
self.tmsutap = tmsutap = Signal()
self.tckutap = tckutap = Signal()
self.tdiutap = tdiutap = Signal()
# self.tdocore = tdocore = Signal()
assert chain == 1
# # #
self.clock_domains.cd_jtag_inv = cd_jtag_inv = ClockDomain("jtag_inv")
self.comb += ClockSignal("jtag_inv").eq(~ClockSignal("jtag"))
self.comb += ResetSignal('jtag_inv').eq(ResetSignal("jtag"))
self.submodules.tap_fsm = JTAGTAPFSM(tms, tck)
self.sync.jtag_inv += reset.eq(self.tap_fsm.TEST_LOGIC_RESET)
self.sync.jtag_inv += capture.eq(self.tap_fsm.CAPTURE_DR)
self.specials += Instance(primitive,
o_shiftuser = shift,
o_updateuser = update,
#
o_runidleuser = runtest,
o_clkdruser = drck,
o_usr1user = sel,
# etc?
# i_tdoutap = tdoutap, # fails synth on max10
i_tdouser = tdouser,
# i_tmscore = tmscore, # nope on cyclone 10 lp
# i_tckcore = tckcore, # nope on cyclone 10 lp
# i_tdicore = tdicore, # nope on cyclone 10 lp
# i_corectl = corectl,
# i_ntdopinena = ntdopinena,
o_tmsutap = tmsutap,
o_tckutap = tckutap,
o_tdiutap = tdiutap,
# o_tdocore = tdocore, # nope on cyclone 10 lp
# reserved pins
i_tms = rtms,
i_tck = rtck,
i_tdi = rtdi,
o_tdo = rtdo,
)
self.comb += [
rtms.eq(reserved_pads.altera_reserved_tms),
rtck.eq(reserved_pads.altera_reserved_tck),
rtdi.eq(reserved_pads.altera_reserved_tdi),
reserved_pads.altera_reserved_tdo.eq(rtdo),
]
self.comb += [
tck.eq(tckutap),
tms.eq(tmsutap),
tdi.eq(tdiutap),
]
self.sync.jtag_inv += tdouser.eq(tdo)
class MAX10JTAG(AlteraJTAG):
def __init__(self, reserved_pads: Record, *args, **kwargs):
AlteraJTAG.__init__(self, "fiftyfivenm_jtag", reserved_pads, *args, **kwargs)
class Cyclone10LPJTAG(AlteraJTAG):
def __init__(self, reserved_pads: Record, *args, **kwargs):
AlteraJTAG.__init__(self, "cyclone10lp_jtag", reserved_pads, *args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment