Skip to content

Finite State Machines (FSM)

Mealy vs Moore Machines

  • Mealy Machine: output depends on both the current state and the current inputs
  • reacts faster to input changes (output can change immediately when input changes)
  • Moore Machine: output depends only on the current state
  • more stable outputs (output changes only on state transitions)

Align output behavior of Mealy and Moore FSMs

normally, the Mealy FSM reacts faster to input changes compared to Moore FSM.

we can register the output of Mealy FSM to align its output behavior with Moore FSM, making the output change only on state transitions.

1765245618379

the 2/3 always block implementations for Mealy FSM are similar, just the output logic differs. - the out = 1 takes additional one cycle in casae of 1 always block implementation, because the output logic is evaluated after the state transition. - in 2 always block implementation, the output logic is evaluated combinationally based on the current state and input, so the output can change immediately when the input changes. - mealy FSM cannot take 1 always block implementation, because the output depends on both the current state and the current inputs, which cannot be captured in a single always_ff block.

example FS: sequence detector "1010"

fsm_sequence_detector_2_always_blocks.sv
    module fsm_sequence_detector_2_always_blocks (
        input logic clk,
        input logic rst_n,
        input logic in,
        output logic out
    );
        // state encoding
        typedef enum logic [2:0] {
            S0, // initial state
            S1, // detected '1'
            S2, // detected '10'
            S3, // detected '101'
            S4  // detected '1010'
        } state_t;
        state_t current_state, next_state;

        // state transition
        always_ff @(posedge clk or negedge rst_n) begin
            if (!rst_n)
                current_state <= S0;
            else
                current_state <= next_state;
        end

        // next state logic
        always_comb begin
            case (current_state)
                S0: next_state = in ? S1 : S0;
                S1: next_state = in ? S1 : S2;
                S2: next_state = in ? S3 : S0;
                S3: next_state = in ? S1 : S4;
                S4: next_state = in ? S1 : S2;
                default: next_state = S0;
            endcase
        end

        // output logic (Moore machine)
        always_comb begin
            out = (current_state == S4) ? 1'b1 : 1'b0;
        end

Binary vs One-Hot Encoding

  • Binary Encoding: uses the minimum number of bits to represent states (log2(N) bits for N states)
  • Pros: fewer flip-flops, less area
  • Cons: more complex combinational logic for state transitions
  • example: do case(current_state) for state transition logic

  • One-Hot Encoding: uses one flip-flop per state (N bits for N states)

  • Pros: simpler combinational logic, faster state transitions
  • Cons: more flip-flops, more area, quartus will NOT generate state machine diagram
  • example: do if (current_state[S0]) for state transition logic

example FS: level to pulse converter mealy FSM

fsm_level_to_pulse_mealy.sv
    module fsm_level_to_pulse_mealy (
        input logic clk,
        input logic rst_n,
        input logic in,
        output logic out
    );
        // state encoding (one-hot)
        typedef enum logic [2:0] {
            S0 = 3'b001, // initial state
            S1 = 3'b010, // detected '1'
            S2 = 3'b100  // output pulse
        } state_t;
        state_t current_state, next_state;

        // state transition
        always_ff @(posedge clk or negedge rst_n) begin
            if (!rst_n)
                current_state <= S0;
            else
                current_state <= next_state;
        end

        // next state logic
        always_comb begin
            case (current_state)
                S0: next_state = in ? S1 : S0;
                S1: next_state = in ? S1 : S2;
                S2: next_state = in ? S1 : S0;
                default: next_state = S0;
            endcase
        end

        // output logic (Mealy machine)
        always_comb begin
            out = (current_state == S1 && !in) ? 1'b1 : 1'b0;
        end
    endmodule