0
0
VerilogHow-ToBeginner · 3 min read

How to Encode States in FSM Verilog: Syntax and Examples

In Verilog, states in an FSM are encoded using parameter or localparam constants with binary, one-hot, or gray code values. You define each state as a unique bit pattern and use a reg variable to hold the current state, updating it in a case statement inside an always block.
📐

Syntax

To encode states in Verilog FSM, you declare each state as a named constant using parameter or localparam. Then, use a reg variable to store the current state. The state transitions happen inside an always block with a case statement.

  • parameter/localparam: Define state names and their binary codes.
  • reg [width-1:0] state: Holds the current state value.
  • always @(posedge clk or posedge reset): Updates state on clock or reset.
  • case(state): Controls transitions based on current state.
verilog
localparam IDLE = 2'b00, STATE1 = 2'b01, STATE2 = 2'b10;
reg [1:0] state, next_state;

always @(posedge clk or posedge reset) begin
  if (reset)
    state <= IDLE;
  else
    state <= next_state;
end

always @(*) begin
  case(state)
    IDLE: next_state = STATE1;
    STATE1: next_state = STATE2;
    STATE2: next_state = IDLE;
    default: next_state = IDLE;
  endcase
end
💻

Example

This example shows a simple FSM with three states encoded in binary. The FSM cycles through states IDLE, STATE1, and STATE2 on each clock cycle, resetting to IDLE when reset is high.

verilog
module fsm_example(
  input wire clk,
  input wire reset,
  output reg [1:0] state
);

  localparam IDLE = 2'b00;
  localparam STATE1 = 2'b01;
  localparam STATE2 = 2'b10;

  reg [1:0] next_state;

  always @(posedge clk or posedge reset) begin
    if (reset)
      state <= IDLE;
    else
      state <= next_state;
  end

  always @(*) begin
    case(state)
      IDLE: next_state = STATE1;
      STATE1: next_state = STATE2;
      STATE2: next_state = IDLE;
      default: next_state = IDLE;
    endcase
  end

endmodule
⚠️

Common Pitfalls

Common mistakes when encoding FSM states include:

  • Using overlapping or non-unique codes for states, causing unpredictable behavior.
  • Not resetting the state register properly, leading to unknown start states.
  • Using too few bits for state encoding, which can cause truncation or incorrect state representation.
  • Mixing encoding styles without consistency (e.g., some states binary, others one-hot).

Always ensure each state has a unique code and the state register is reset.

verilog
/* Wrong: overlapping states */
localparam IDLE = 2'b00;
localparam STATE1 = 2'b00; // Error: same as IDLE

/* Right: unique states */
localparam IDLE = 2'b00;
localparam STATE1 = 2'b01;
📊

Quick Reference

Encoding StyleDescriptionBit WidthUse Case
BinaryStates encoded as binary numbersMinimum bits to cover statesMost common, compact
One-hotEach state has one bit set highNumber of statesSimpler logic, faster but uses more bits
Gray codeOnly one bit changes between statesMinimum bitsReduces glitches in some hardware

Key Takeaways

Define each FSM state as a unique constant using parameter or localparam.
Use a reg variable to hold the current state and update it in an always block.
Choose an encoding style (binary, one-hot, gray) based on design needs.
Always reset the state register to a known state to avoid undefined behavior.
Avoid overlapping or non-unique state codes to prevent logic errors.