soc/cores/jtag: Review/Cleanup JTAGTAPFSM and avoid specific CorrectedOngoingResetFSM.
This commit is contained in:
parent
40799332a0
commit
b2448ba50e
|
@ -1,37 +0,0 @@
|
||||||
#
|
|
||||||
# This file is part of LiteX.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2021 Jevin Sweval <jevinsweval@gmail.com>
|
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
from migen.genlib.fsm import FSM
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CorrectedOngoingResetFSM(FSM):
|
|
||||||
"""
|
|
||||||
This wrapper is needed for FSMs where an ongoing signal from the FSM's reset state is used.
|
|
||||||
|
|
||||||
With the existing FSM, on SoC reset the FSM will be in the reset state
|
|
||||||
but its ongoing signal will not be asserted because the existing FSM
|
|
||||||
does not set the reset values of the ongoing signals.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.ongoing_signals = OrderedDict()
|
|
||||||
|
|
||||||
def ongoing(self, state, *args, **kwargs):
|
|
||||||
is_ongoing = super().ongoing(state, *args, **kwargs)
|
|
||||||
self.ongoing_signals[state] = is_ongoing
|
|
||||||
return is_ongoing
|
|
||||||
|
|
||||||
def do_finalize(self, *args, **kwargs):
|
|
||||||
for state, is_ongoing in self.ongoing_signals.items():
|
|
||||||
is_ongoing.reset = 1 if state == self.reset_state else 0
|
|
||||||
if is_ongoing.reset.value:
|
|
||||||
# since the default is high, must explicitly deassert in all other states
|
|
||||||
for other_state in set(self.actions) - set([state]):
|
|
||||||
self.actions[other_state].append(is_ongoing.eq(0))
|
|
||||||
super().do_finalize(*args, **kwargs)
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# This file is part of LiteX.
|
# This file is part of LiteX.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
# Copyright (c) 2019-2022 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>
|
# Copyright (c) 2019 Antti Lukats <antti.lukats@gmail.com>
|
||||||
# Copyright (c) 2017 Robert Jordens <jordens@gmail.com>
|
# Copyright (c) 2017 Robert Jordens <jordens@gmail.com>
|
||||||
# Copyright (c) 2021 Gregory Davill <greg.davill@gmail.com>
|
# Copyright (c) 2021 Gregory Davill <greg.davill@gmail.com>
|
||||||
|
@ -18,70 +18,143 @@ from litex.soc.interconnect import stream
|
||||||
# JTAG TAP FSM -------------------------------------------------------------------------------------
|
# JTAG TAP FSM -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class JTAGTAPFSM(Module):
|
class JTAGTAPFSM(Module):
|
||||||
def __init__(self, tms: Signal, tck: Signal, expose_signals=True):
|
def __init__(self, tms):
|
||||||
self.submodules.fsm = fsm = ClockDomainsRenamer("jtag")(CorrectedOngoingResetFSM())
|
self.submodules.fsm = fsm = FSM(reset_state="TEST_LOGIC_RESET")
|
||||||
|
|
||||||
fsm.act("test_logic_reset",
|
def JTAGTAPFSMState(name, transitions={}):
|
||||||
If(~tms, NextState("run_test_idle"))
|
logic = []
|
||||||
)
|
|
||||||
fsm.act("run_test_idle",
|
# Transitions logic.
|
||||||
If( tms, NextState("select_dr_scan"))
|
nextstates = {}
|
||||||
|
nextstates[0] = NextState(transitions.get(0, name))
|
||||||
|
nextstates[1] = NextState(transitions.get(1, name))
|
||||||
|
logic.append(Case(tms, nextstates))
|
||||||
|
|
||||||
|
# Ongoing logic.
|
||||||
|
ongoing = Signal()
|
||||||
|
setattr(self, name, ongoing)
|
||||||
|
logic.append(ongoing.eq(1))
|
||||||
|
|
||||||
|
# Add logic to state.
|
||||||
|
fsm.act(name, *logic)
|
||||||
|
|
||||||
|
# Test-Logic-Reset.
|
||||||
|
# -----------------
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "TEST_LOGIC_RESET",
|
||||||
|
transitions = {
|
||||||
|
0 : "RUN_TEST_IDLE",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# DR
|
# Run-Test/Idle.
|
||||||
fsm.act("select_dr_scan",
|
# --------------
|
||||||
If(~tms, NextState("capture_dr") ).Else(NextState("select_ir_scan"))
|
JTAGTAPFSMState(
|
||||||
)
|
name = "RUN_TEST_IDLE",
|
||||||
fsm.act("capture_dr",
|
transitions = {
|
||||||
If(~tms, NextState("shift_dr") ).Else(NextState("exit1_dr"))
|
1 : "SELECT_DR_SCAN",
|
||||||
)
|
}
|
||||||
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
|
# DR-Scan.
|
||||||
fsm.act("select_ir_scan",
|
# --------
|
||||||
If(~tms, NextState("capture_ir") ).Else(NextState("test_logic_reset"))
|
JTAGTAPFSMState(
|
||||||
|
name = "SELECT_DR_SCAN",
|
||||||
|
transitions = {
|
||||||
|
0 : "CAPTURE_DR",
|
||||||
|
1 : "SELECT_IR_SCAN",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("capture_ir",
|
JTAGTAPFSMState(
|
||||||
If(~tms, NextState("shift_ir") ).Else(NextState("exit1_ir"))
|
name = "CAPTURE_DR",
|
||||||
|
transitions = {
|
||||||
|
0 : "SHIFT_DR",
|
||||||
|
1 : "EXIT1_DR",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("shift_ir",
|
JTAGTAPFSMState(
|
||||||
If( tms, NextState("exit1_ir"))
|
name = "SHIFT_DR",
|
||||||
|
transitions = {
|
||||||
|
1 : "EXIT1_DR",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("exit1_ir",
|
JTAGTAPFSMState(
|
||||||
If(~tms, NextState("pause_ir") ).Else(NextState("update_ir"))
|
name = "EXIT1_DR",
|
||||||
|
transitions = {
|
||||||
|
0 : "PAUSE_DR",
|
||||||
|
1 : "UPDATE_DR",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("pause_ir",
|
JTAGTAPFSMState(
|
||||||
If( tms, NextState("exit2_ir"))
|
name = "PAUSE_DR",
|
||||||
|
transitions = {
|
||||||
|
1 : "EXIT2_DR",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("exit2_ir",
|
JTAGTAPFSMState(
|
||||||
If( tms, NextState("update_ir") ).Else(NextState("shift_ir"))
|
name = "EXIT2_DR",
|
||||||
|
transitions = {
|
||||||
|
0 : "SHIFT_DR",
|
||||||
|
1 : "UPDATE_DR",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
fsm.act("update_ir",
|
JTAGTAPFSMState(
|
||||||
If( tms, NextState("select_dr_scan")).Else(NextState("run_test_idle"))
|
name = "UPDATE_DR",
|
||||||
|
transitions = {
|
||||||
|
0 : "RUN_TEST_IDLE",
|
||||||
|
1 : "SELECT_DR_SCAN",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if expose_signals:
|
# IR-Scan.
|
||||||
for state_name in fsm.actions:
|
# --------
|
||||||
state_sig = fsm.ongoing(state_name)
|
JTAGTAPFSMState(
|
||||||
SHOUTING_NAME = state_name.upper()
|
name = "SELECT_IR_SCAN",
|
||||||
shouting_sig = Signal(name=SHOUTING_NAME)
|
transitions = {
|
||||||
setattr(self, SHOUTING_NAME, shouting_sig)
|
0 : "CAPTURE_IR",
|
||||||
self.comb += shouting_sig.eq(state_sig)
|
1 : "TEST_LOGIC_RESET",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "CAPTURE_IR",
|
||||||
|
transitions = {
|
||||||
|
0 : "SHIFT_IR",
|
||||||
|
1 : "EXIT1_IR",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "SHIFT_IR",
|
||||||
|
transitions = {
|
||||||
|
1 : "EXIT1_IR",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "EXIT1_IR",
|
||||||
|
transitions = {
|
||||||
|
0 : "PAUSE_IR",
|
||||||
|
1 : "UPDATE_IR",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "PAUSE_IR",
|
||||||
|
transitions = {
|
||||||
|
1 : "EXIT2_IR",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "EXIT2_IR",
|
||||||
|
transitions = {
|
||||||
|
0 : "SHIFT_IR",
|
||||||
|
1 : "UPDATE_IR",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
JTAGTAPFSMState(
|
||||||
|
name = "UPDATE_IR",
|
||||||
|
transitions = {
|
||||||
|
0 : "RUN_TEST_IDLE",
|
||||||
|
1 : "SELECT_DR_SCAN",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Altera JTAG --------------------------------------------------------------------------------------
|
# Altera JTAG --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -124,7 +197,7 @@ class AlteraJTAG(Module):
|
||||||
self.comb += ResetSignal("jtag_inv").eq(ResetSignal("jtag"))
|
self.comb += ResetSignal("jtag_inv").eq(ResetSignal("jtag"))
|
||||||
|
|
||||||
# connect the TAP state signals that LiteX expects but the HW IP doesn't provide
|
# connect the TAP state signals that LiteX expects but the HW IP doesn't provide
|
||||||
self.submodules.tap_fsm = JTAGTAPFSM(tms, tck)
|
self.submodules.tap_fsm = ClockDomainsRenamer("jtag")(JTAGTAPFSM(tms))
|
||||||
self.sync.jtag_inv += reset.eq(self.tap_fsm.TEST_LOGIC_RESET)
|
self.sync.jtag_inv += reset.eq(self.tap_fsm.TEST_LOGIC_RESET)
|
||||||
self.sync.jtag_inv += capture.eq(self.tap_fsm.CAPTURE_DR)
|
self.sync.jtag_inv += capture.eq(self.tap_fsm.CAPTURE_DR)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue