FiniteStateMachine<StateIdentifier>.multi constructor
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,
]);
}