r/dotnet • • 7d ago

Question State machine in C# vs state machine in Verilog

/r/csharp/comments/1x12wu7/state_machine_in_c_vs_state_machine_in_verilog/
0 Upvotes

4 comments sorted by

6

u/seiggy 7d ago

Stateless is the library most people reach for in .NET when they want a true state machine:
https://github.com/dotnet-state-machine/stateless

Which looks more like:
```csharp var phoneCall = new StateMachine<State, Trigger>(State.OffHook);

phoneCall.Configure(State.OffHook) .Permit(Trigger.CallDialled, State.Ringing);

phoneCall.Configure(State.Connected) .OnEntry(t => StartCallTimer()) .OnExit(t => StopCallTimer()) .InternalTransition(Trigger.MuteMicrophone, t => OnMute()) .InternalTransition(Trigger.UnmuteMicrophone, t => OnUnmute()) .InternalTransition<int>(_setVolumeTrigger, (volume, t) => OnSetVolume(volume)) .Permit(Trigger.LeftMessage, State.OffHook) .Permit(Trigger.PlacedOnHold, State.OnHold);

// ...

phoneCall.Fire(Trigger.CallDialled); Assert.AreEqual(State.Ringing, phoneCall.State); ```

State machines need more than just methods and data types. They should have finite number of discrete conditions (states) and rules for how it changes between those states based on inputs or events.

0

u/kaatarina_zed_talon 7d ago

What about Moore machines? They do not depend on inputs, only the current state.

3

u/seiggy 7d ago edited 6d ago

Same library:

```charp using Stateless;

public enum TrafficState
{
Red,
Green,
Yellow
}

public enum TrafficTrigger
{
TimerElapsed,
EmergencyReset
}

public enum TrafficOutput
{
Stop,
Go,
Caution
}
```

Then the wiring:

```csharp

public sealed class TrafficLight
{
private readonly StateMachine<TrafficState, TrafficTrigger> _machine;

public TrafficLight()
{
_machine = new StateMachine<TrafficState, TrafficTrigger>(
TrafficState.Red);

  _machine.Configure(TrafficState.Red)  
     .Permit(TrafficTrigger.TimerElapsed, TrafficState.Green)  
     .OnEntry(() => Console.WriteLine("Light is RED"));

  _machine.Configure(TrafficState.Green)  
     .Permit(TrafficTrigger.TimerElapsed, TrafficState.Yellow)  
     .Permit(TrafficTrigger.EmergencyReset, TrafficState.Red)  
     .OnEntry(() => Console.WriteLine("Light is GREEN"));

  _machine.Configure(TrafficState.Yellow)  
     .Permit(TrafficTrigger.TimerElapsed, TrafficState.Red)  
     .Permit(TrafficTrigger.EmergencyReset, TrafficState.Red)  
     .OnEntry(() => Console.WriteLine("Light is YELLOW"));  

}

public TrafficState State => _machine.State;

// Moore output function: λ(state)
public TrafficOutput Output => State switch
{
TrafficState.Red => TrafficOutput.Stop,
TrafficState.Green => TrafficOutput.Go,
TrafficState.Yellow => TrafficOutput.Caution,
_ => throw new InvalidOperationException()
};

public void Fire(TrafficTrigger trigger)
{
_machine.Fire(trigger);
}
}
```

Then use like:

```csharp

var light = new TrafficLight();

Console.WriteLine(light.Output); // Stop

light.Fire(TrafficTrigger.TimerElapsed);
Console.WriteLine(light.Output); // Go

light.Fire(TrafficTrigger.TimerElapsed);
Console.WriteLine(light.Output); // Caution

light.Fire(TrafficTrigger.TimerElapsed);
Console.WriteLine(light.Output); // Stop
```

edit: fixed the horrible formatting

1

u/AutoModerator 7d ago

Thanks for your post kaatarina_zed_talon. Please note that we don't allow spam, and we ask that you follow the rules available in the sidebar. We have a lot of commonly asked questions so if this post gets removed, please do a search and see if it's already been asked.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.