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)