-
-
Save lapnd/60883ef11733e46d12b369802db3fb1d to your computer and use it in GitHub Desktop.
migen Altera JTAG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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