diff --git a/examples/fsm.py b/examples/fsm.py new file mode 100644 index 000000000..2ee86e546 --- /dev/null +++ b/examples/fsm.py @@ -0,0 +1,9 @@ +from migen.fhdl.structure import * +from migen.fhdl import verilog +from migen.corelogic.fsm import FSM + +s = Signal() +myfsm = FSM('FOO', 'BAR') +myfsm.act(myfsm.FOO, s.eq(1), myfsm.next_state(myfsm.BAR)) +myfsm.act(myfsm.BAR, s.eq(0), myfsm.next_state(myfsm.FOO)) +print(verilog.convert(myfsm.get_fragment(), {s})) diff --git a/migen/corelogic/fsm.py b/migen/corelogic/fsm.py new file mode 100644 index 000000000..a3d3ccb67 --- /dev/null +++ b/migen/corelogic/fsm.py @@ -0,0 +1,29 @@ +from migen.fhdl.structure import * + +class FSM: + def __init__(self, *states): + self._state_bv = BV(bits_for(len(states)-1)) + self._state = Signal(self._state_bv) + self._next_state = Signal(self._state_bv) + for state, n in zip(states, range(len(states))): + setattr(self, state, Constant(n, self._state_bv)) + self.actions = [[] for i in range(len(states))] + + def reset_state(self, state): + self._state.reset = state + + def next_state(self, state): + return self._next_state.eq(state) + + def act(self, state, *statements): + self.actions[state.n] += statements + + def get_fragment(self): + cases = [[Constant(s, self._state_bv)] + a + for s, a in zip(range(len(self.actions)), self.actions) if a] + comb = [ + self._next_state.eq(self._state), + Case(self._state, *cases) + ] + sync = [self._state.eq(self._next_state)] + return Fragment(comb, sync) diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py index 90b6e416e..354406c89 100644 --- a/migen/fhdl/structure.py +++ b/migen/fhdl/structure.py @@ -131,12 +131,14 @@ def _cst(x): else: return x +_forbidden_prefixes = {'inst', 'source', 'sink', 'fsm'} + def _try_class_name(frame): while frame is not None: try: cl = frame.f_locals['self'] prefix = cl.__class__.__name__.lower() - if prefix != 'inst' and prefix != 'source' and prefix != 'sink': + if prefix not in _forbidden_prefixes: return prefix except KeyError: pass