from collections import namedtuple, OrderedDict
from migen.fhdl.std import *
from migen.fhdl.visit import NodeTransformer
class AnonymousState:
pass
NextState = namedtuple("NextState", "state")
class _LowerNextState(NodeTransformer):
def __init__(self, state_signal, next_state_signal, encoding, aliases):
self.state_signal = state_signal
self.next_state_signal = next_state_signal
self.encoding = encoding
self.aliases = aliases
def visit_unknown(self, node):
if isinstance(node, NextState):
index = _index_is(self.states, node.target_state)
estate = getattr(self.fsm, self.stnames[index])
return self.fsm.next_state(estate)
else:
return node
class FSM(Module):
def __init__(self):
self._actions = OrderedDict()
self._state_aliases = dict()
self.reset_state = None
def act(self, state, *statements):
if state not in self._actions:
self._actions[state] = []
self._actions[state] += statements
def delayed_enter(self, name, target, delay):
if delay:
state = name
for i in range(delay):
if i == delay - 1:
next_state = target
else:
next_state = AnonymousState()
self.act(state, NextState(next_state))
state = next_state
else:
self._state_aliases[name] = target
def finalize(self):
nstates = len(self._actions)
encoding = dict((s, n) for n, s in enumerate(self._actions.keys()))
state = Signal(max=nstates)
next_state = Signal(max=nstates)
lns = _LowerNextState(state, next_state, encoding, self._state_aliases)
cases = dict((encoding[k], lns.visit(v)) for k, v in self._actions.items() if v)
self.comb += [
next_state.eq(state),
Case(state, cases)
]
self.sync += state.eq(next_state)