How to Code a State Machine in Verilog

Not to long ago, I wrote a post about what a state machine is. That post covered the state machine as a concept and way to organize your thoughts. Well, if you are looking to use state machines in FPGA design, the idea isn’t much help without knowing how to code it.

As you know from the last post, a state machine is made up of three components. The next state logic, state register and output logic.

The first component I’ll go through is the next state logic. This is coded directly from the state diagram.

I’m going to put the state diagram here for reference.

Stepper motor controller state diagram.
Stepper motor controller state diagram.
This block of code creates the state variables. This way each state can be referenced by name.
This block of code creates the state variables. This way each state can be referenced by name.
This block of code creates the state registers that hold the next_state and present_state variables. This is which circle you are on, on the state diagram.
This block of code creates the state registers that hold the next_state and present_state variables. This is which circle you are on on the state diagram.
This is the first chunk of the state logic. It shows, if you are in state sig4, based on the input what the next state is. This encapsulates the arrows on the state diagram.
This is the first chunk of the state logic. It shows, if you are in state sig4, based on the input what the next state is. This encapsulates the arrows on the state diagram.
This is the second chunk of the next state logic. It defines where you go next if you are in sig3 or sig2.
This is the second chunk of the next state logic. It defines where you go next if you are in sig3 or sig2.
This is the third chunk of next state logic. It defines what to do if you are in state sig1 or sig0.
This is the third chunk of next state logic. It defines what to do if you are in state sig1 or sig0.
This is the output logic. This is represented on the state diagram as the purple text.
This is the output logic. This is represented on the state diagram as the purple text.
This is the state register. It moves the next_state to the present_state on the positive clock edge. This is what makes movement between the states in the state diagram happen.
This is the state register. It moves the next_state to the present_state on the positive clock edge. This is what makes movement between the states in the state diagram happen.

For more information on this state diagram and full code. You can view the instructable on driving a stepper motor with FPGA. This works with the Basys 3,  Nexys A7, Cmod A7, and Cmod S7.

Author

11 Comments on “How to Code a State Machine in Verilog”

    1. I’ve translated Kaitlyn’s example into VHDL:

      library IEEE;
      use IEEE.STD_LOGIC_1164.ALL;

      entity state_machine is
      Port (
      CLK : in STD_LOGIC;
      RST : in STD_LOGIC;
      dir : in STD_LOGIC;
      en : in STD_LOGIC;
      sigout : out STD_LOGIC_VECTOR(3 downto 0)
      );
      end state_machine;

      architecture Behavioral of state_machine is

      –define a new type to hold state values
      type state_type is (STATE_0, STATE_1, STATE_2, STATE_3, STATE_4);

      –present state will turn into the state register
      –present state is driven by next state at the clock edge
      signal present_state, next_state : state_type;

      begin

      –controls transitions to next state
      state_register_logic:
      process(CLK, RST) begin
      if (RST = ‘1’) then –reset logic
      present_state <= STATE_0;
      elsif (CLK'event and CLK = '1') then –if rising edge of clock
      present_state
      if (dir = ‘0’ and en = ‘1’) then
      next_state <= STATE_3;
      elsif (dir = '1' and en = '1') then
      next_state <= STATE_1;
      else
      next_state
      if (dir = ‘0’ and en = ‘1’) then
      next_state <= STATE_2;
      elsif (dir = '1' and en = '1') then
      next_state <= STATE_4;
      else
      next_state
      if (dir = ‘0’ and en = ‘1’) then
      next_state <= STATE_1;
      elsif (dir = '1' and en = '1') then
      next_state <= STATE_3;
      else
      next_state
      if (dir = ‘0’ and en = ‘1’) then
      next_state <= STATE_4;
      elsif (dir = '1' and en = '1') then
      next_state <= STATE_2;
      else
      next_state
      if ( en = ‘1’) then
      next_state <= STATE_1;
      else
      next_state
      sigout
      sigout
      sigout
      sigout
      sigout <= "0000";
      end case;
      end process;

      end Behavioral;

  1. Hey,

    Great article, thanks.

    I was wondering if you can provide a blog post about designing a simple digital phase modulator, I’m interested in building my own Software Defined Radio, applying my FPGA knowledge in designing most of the digital components of the radio would be amazing.

    Much Regards
    Abdullah

  2. Hi Fredrik,

    Unfortunately I don’t know VHDL well enough to confidently write up a similar post, I’m in the process of learning. However, I found this blog post that has a VHDL example.
    http://vhdlguru.blogspot.com/2010/04/how-to-implement-state-machines-in-vhdl.html

    If you get stuck at any point in writing your state machine please feel free to post on forum.blog.digilentinc.com. There’s a whole community of people like me willing to help you out!

    Kaitlyn

  3. Hi Abdullah,
    I haven’t done any Digital Phase Modulation myself but it looks like from my brief internet search that it’s similar to PWM. If this is the case I’m working on a instructable and blog post on using servos with FPGA which uses PWM. That should be posted relatively soon.

    If not, and in the mean time I would post on forum.blog.digilentinc.com. One of the members of the Digilent Forum may have already done this and likely would be better help than me.

    Kaitlyn

  4. Hi Kaitlyn,
    I am in process of learning Verilog and SysVerilog these days, and i used your blog as a test by just referencing the state diagram. Please checkout my code, i am currently in process of writing a test bench for it as well.

    //***************************************************************************************
    module FSM(input i_enable, input i_dir, input i_clk, input i_rst_n, output reg [`WIDTH-1:0] o_output);
    //***************************************************************************************
    parameter Sig0 = 3’b000;
    parameter Sig1 = 3’b001;
    parameter Sig2 = 3’b010;
    parameter Sig3 = 3’b011;
    parameter Sig4 = 3’b100;
    parameter Sig5 = 3’b101; // NOTUSED
    parameter Sig6 = 3’b110; // NOTUSED
    parameter Sig7 = 3’b111; // NOTUSED

    reg [`WIDTH-2:0] curr_state;
    reg [`WIDTH-2:0] next_state;

    //Sequential logic for storing current state
    always @ (posedge i_clk or negedge i_rst_n) begin
    if (~i_rst_n)
    curr_state <= Sig0;
    else
    curr_state <= next_state;
    end

    //Combintational logic for next state logic
    always @ (curr_state, i_enable, i_dir) begin // Input and Current State for Mealy Machine
    case(curr_state)
    Sig0: begin
    if (i_enable)
    next_state <= Sig1;
    else
    next_state <= Sig0 // Default
    end
    Sig1: begin
    if (i_enable && i_dir)
    next_state <= Sig2;
    else if (i_enable && !i_dir)
    next_state <= Sig4;
    else if (!i_enable)
    next_state <= Sig0;
    end
    Sig2: begin
    if (i_enable && i_dir)
    next_state <= Sig3;
    else if (i_enable && !i_dir)
    next_state <= Sig1;
    else if (!i_enable)
    next_state <= Sig0;
    end
    Sig3: begin
    if (i_enable && i_dir)
    next_state <= Sig4;
    else if (i_enable && !i_dir)
    next_state <= Sig2;
    else if (!i_enable)
    next_state <= Sig0;
    end
    Sig4: begin
    if (i_enable && i_dir)
    next_state <= Sig1;
    else if (i_enable && !i_dir)
    next_state <= Sig3;
    else if (!enable)
    next_sate <= Sig0;
    end
    endcase // curr_state
    end

    always @ (i_clk) begin
    if (~i_rst_n)
    o_output <= {4{1'b0}};
    else begin
    case(curr_state)
    Sig0: o_output <= {4{1'b0}};
    Sig1: o_output <= 4'b1000;
    Sig2: o_output <= 4'b0100;
    Sig3: o_output <= 4'b0010;
    Sig4: o_output <= 4'b0001;
    default: o_output <= 4'b1000;
    endcase // curr_state
    end
    end

    endmodule //FSM

    1. Hey Yasir,
      I’d recommend posting on Forum.blog.digilentinc.com. There is a whole community of excited FPGA enthusiasts that could help you out with your code.

Leave a Reply

Your email address will not be published. Required fields are marked *