FiniteStateMachine<StateIdentifier>.multi constructor

FiniteStateMachine<StateIdentifier>.multi(
  1. List<Logic> _clks,
  2. Logic reset,
  3. StateIdentifier resetState,
  4. List<State<StateIdentifier>> _states
)

Creates an finite state machine for the specified list of _states, with an initial state of resetState (when synchronous reset is high) and transitions on positive edges of any of _clks.

Implementation

FiniteStateMachine.multi(
    this._clks, this.reset, this.resetState, this._states)
    : _stateWidth = _logBase(_states.length, 2),
      currentState =
          Logic(name: 'currentState', width: _logBase(_states.length, 2)),
      nextState =
          Logic(name: 'nextState', width: _logBase(_states.length, 2)) {
  _validate();

  var stateCounter = 0;
  for (final state in _states) {
    _stateLookup[state.identifier] = state;
    _stateValueLookup[state] = stateCounter++;
  }

  Combinational([
    Case(
        currentState,
        _states
            .map((state) => CaseItem(
                    Const(_stateValueLookup[state], width: _stateWidth), [
                  ...state.actions,
                  Case(
                      Const(1),
                      state.events.entries
                          .map((entry) => CaseItem(entry.key, [
                                nextState <
                                    _stateValueLookup[
                                        _stateLookup[entry.value]]
                              ]))
                          .toList(growable: false),
                      conditionalType: state.conditionalType,
                      defaultItem: [
                        nextState < getStateIndex(state.defaultNextState),
                      ])
                ]))
            .toList(growable: false),
        conditionalType: ConditionalType.unique,
        defaultItem: [
          nextState < currentState,

          // zero out all other receivers from state actions...
          // even though out-of-state is unreachable,
          // we don't want any inferred latches
          ..._states
              .map((state) => state.actions)
              .flattened
              .map((conditional) => conditional.receivers)
              .flattened
              .toSet()
              .map((receiver) => receiver < 0)
        ])
  ]);

  Sequential.multi(_clks, reset: reset, resetValues: {
    currentState: _stateValueLookup[_stateLookup[resetState]]
  }, [
    currentState < nextState,
  ]);
}