Introduction Basically a FSM consists of combinational, sequential and output logic. Combinational logic is used to decide the next state of the FSM, sequential logic is used to store the current state of the FSM. The output logic is a mixture of both combo and seq logic as shown in the figure below. Types of State Machines There are many ways to code these state machines, but before we get into the coding styles, let's first understand the basics a bit. There are two types of state machines: Mealy State Machine : Its output depends on current state and current inputs. In the above picture, the blue dotted line makes the circuit a mealy state machine. Moore State Machine : Its output depends on current state only. In the above picture, when blue dotted line is removed the circuit becomes a Moore state machine. Depending on the need, we can choose the type of state machine. In general, or you can say most of the time, we end up using Mealy FSM. Encoding Style Since we need to represent the state machine in a digital circuit, we need to represent each state in one of the following ways: Binary encoding : each state is represented in binary code (i.e. 000, 001, 010....) Gray encoding : each state is represented in gray code (i.e. 000, 001, 011,...) One Hot : only one bit is high and the rest are low (i.e. 0001, 0010, 0100, 1000) One Cold : only one bit is low, the rest are high (i.e. 1110,1101,1011,0111) Most of the time we use one hot encoding. Example To help you follow the tutorial, I have taken a simple arbiter as the example; this has got two request inputs and two grant outputs, as shown in the signal diagram below. When req_0 is asserted, gnt_0 is asserted When req_1 is asserted, gnt_1 is asserted When both req_0 and req_1 are asserted then gnt_0 is asserted i.e. higher priority is given to req_0 over req_1. We can symbolically translate into a FSM diagram as shown in figure below, here FSM has got following states. IDLE : In this state FSM waits for the assertion of req_0 or req_1 and drives both gnt_0 and gnt_1 to inactive state (low). This is the default state of the FSM, it is entered after the reset and also during fault recovery condition. GNT0 : FSM enters this state when req_0 is asserted, and remains here as long as req_0 is asserted. When req_0 is de-asserted, FSM returns to the IDLE state. GNT1 : FSM enters this state when req_1 is asserted, and remains there as long as req_1 is asserted. When req_1 is de-asserted, FSM returns to the IDLE state. Coding Methods Now that we have described our state machine clearly, let's look at various methods of coding a FSM. We use one-hot encoding, and all the FSMs will have the following code in common, so it will not be repeated again and again. Using A Function For Combo Logic ``` 1 //----------------------------------------------------- 2 // This is FSM demo program using function 3 // Design Name : fsm_using_function 4 // File Name : fsm_using_function.v 5 //----------------------------------------------------- 6 module fsm_using_function ( 7 clock , // clock 8 reset , // Active high, syn reset 9 req_0 , // Request 0 10 req_1 , // Request 1 11 gnt_0 , // Grant 0 12 gnt_1 13 ); 14 //-------------Input Ports----------------------------- 15 input clock,reset,req_0,req_1; 16 //-------------Output Ports---------------------------- 17 output gnt_0,gnt_1; 18 //-------------Input ports Data Type------------------- 19 wire clock,reset,req_0,req_1; 20 //-------------Output Ports Data Type------------------ 21 reg gnt_0,gnt_1; 22 //-------------Internal Constants-------------------------- 23 parameter SIZE = 3 ; 24 parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; 25 //-------------Internal Variables--------------------------- 26 reg [SIZE-1:0] state ;// Seq part of the FSM 27 wire [SIZE-1:0] next_state ;// combo part of FSM 28 //----------Code startes Here------------------------ 29 assign next_state = fsm_function(state, req_0, req_1); 30 //----------Function for Combo Logic----------------- 31 function [SIZE-1:0] fsm_function; 32 input [SIZE-1:0] state ; 33 input req_0 ; 34 input req_1 ; 35 case(state) 36 IDLE : if (req_0 == 1'b1) begin 37 fsm_function = GNT0; 38 end else if (req_1 == 1'b1) begin 39 fsm_function= GNT1; 40 end else begin 41 fsm_function = IDLE; 42 end 43 GNT0 : if (req_0 == 1'b1) begin 44 fsm_function = GNT0; 45 end else begin 46 fsm_function = IDLE; 47 end 48 GNT1 : if (req_1 == 1'b1) begin 49 fsm_function = GNT1; 50 end else begin 51 fsm_function = IDLE; 52 end 53 default : fsm_function = IDLE; 54 endcase 55 endfunction 56 //----------Seq Logic----------------------------- 57 always @ (posedge clock) 58 begin : FSM_SEQ 59 if (reset == 1'b1) begin 60 state <= #1 IDLE; 61 end else begin 62 state <= #1 next_state; 63 end 64 end 65 //----------Output Logic----------------------------- 66 always @ (posedge clock) 67 begin : OUTPUT_LOGIC 68 if (reset == 1'b1) begin 69 gnt_0 <= #1 1'b0; 70 gnt_1 <= #1 1'b0; 71 end 72 else begin 73 case(state) 74 IDLE : begin 75 gnt_0 <= #1 1'b0; 76 gnt_1 <= #1 1'b0; 77 end 78 GNT0 : begin 79 gnt_0 <= #1 1'b1; 80 gnt_1 <= #1 1'b0; 81 end 82 GNT1 : begin 83 gnt_0 <= #1 1'b0; 84 gnt_1 <= #1 1'b1; 85 end 86 default : begin 87 gnt_0 <= #1 1'b0; 88 gnt_1 <= #1 1'b0; 89 end 90 endcase 91 end 92 end // End Of Block OUTPUT_LOGIC 93 94 endmodule // End of Module arbiter ``` You could download file fsm_using_function.v here Using Two Always Blocks ``` 1 //----------------------------------------------------- 2 // This is FSM demo program using always block 3 // Design Name : fsm_using_always 4 // File Name : fsm_using_always.v 5 //----------------------------------------------------- 6 module fsm_using_always ( 7 clock , // clock 8 reset , // Active high, syn reset 9 req_0 , // Request 0 10 req_1 , // Request 1 11 gnt_0 , // Grant 0 12 gnt_1 13 ); 14 //-------------Input Ports----------------------------- 15 input clock,reset,req_0,req_1; 16 //-------------Output Ports---------------------------- 17 output gnt_0,gnt_1; 18 //-------------Input ports Data Type------------------- 19 wire clock,reset,req_0,req_1; 20 //-------------Output Ports Data Type------------------ 21 reg gnt_0,gnt_1; 22 //-------------Internal Constants-------------------------- 23 parameter SIZE = 3 ; 24 parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; 25 //-------------Internal Variables--------------------------- 26 reg [SIZE-1:0] state ;// Seq part of the FSM 27 reg [SIZE-1:0] next_state ;// combo part of FSM 28 //----------Code startes Here------------------------ 29 always @ (state or req_0 or req_1) 30 begin : FSM_COMBO 31 next_state = 3'b000; 32 case(state) 33 IDLE : if (req_0 == 1'b1) begin 34 next_state = GNT0; 35 end else if (req_1 == 1'b1) begin 36 next_state= GNT1; 37 end else begin 38 next_state = IDLE; 39 end 40 GNT0 : if (req_0 == 1'b1) begin 41 next_state = GNT0; 42 end else begin 43 next_state = IDLE; 44 end 45 GNT1 : if (req_1 == 1'b1) begin 46 next_state = GNT1; 47 end else begin 48 next_state = IDLE; 49 end 50 default : next_state = IDLE; 51 endcase 52 end 53 //----------Seq Logic----------------------------- 54 always @ (posedge clock) 55 begin : FSM_SEQ 56 if (reset == 1'b1) begin 57 state <= #1 IDLE; 58 end else begin 59 state <= #1 next_state; 60 end 61 end 62 //----------Output Logic----------------------------- 63 always @ (posedge clock) 64 begin : OUTPUT_LOGIC 65 if (reset == 1'b1) begin 66 gnt_0 <= #1 1'b0; 67 gnt_1 <= #1 1'b0; 68 end 69 else begin 70 case(state) 71 IDLE : begin 72 gnt_0 <= #1 1'b0; 73 gnt_1 <= #1 1'b0; 74 end 75 GNT0 : begin 76 gnt_0 <= #1 1'b1; 77 gnt_1 <= #1 1'b0; 78 end 79 GNT1 : begin 80 gnt_0 <= #1 1'b0; 81 gnt_1 <= #1 1'b1; 82 end 83 default : begin 84 gnt_0 <= #1 1'b0; 85 gnt_1 <= #1 1'b0; 86 end 87 endcase 88 end 89 end // End Of Block OUTPUT_LOGIC 90 91 endmodule // End of Module arbiter ``` You could download file fsm_using_always.v here Using Single Always For Sequential, Combo And Output Logic ``` 1 //==================================================== 2 // This is FSM demo program using single always 3 // for both seq and combo logic 4 // Design Name : fsm_using_single_always 5 // File Name : fsm_using_single_always.v 6 //===================================================== 7 module fsm_using_single_always ( 8 clock , // clock 9 reset , // Active high, syn reset 10 req_0 , // Request 0 11 req_1 , // Request 1 12 gnt_0 , // Grant 0 13 gnt_1 14 ); 15 //=============Input Ports============================= 16 input clock,reset,req_0,req_1; 17 //=============Output Ports=========================== 18 output gnt_0,gnt_1; 19 //=============Input ports Data Type=================== 20 wire clock,reset,req_0,req_1; 21 //=============Output Ports Data Type================== 22 reg gnt_0,gnt_1; 23 //=============Internal Constants====================== 24 parameter SIZE = 3 ; 25 parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100 ; 26 //=============Internal Variables====================== 27 reg [SIZE-1:0] state ;// Seq part of the FSM 28 reg [SIZE-1:0] next_state ;// combo part of FSM 29 //==========Code startes Here========================== 30 always @ (posedge clock) 31 begin : FSM 32 if (reset == 1'b1) begin 33 state <= #1 IDLE; 34 gnt_0 <= 0; 35 gnt_1 <= 0; 36 end else 37 case(state) 38 IDLE : if (req_0 == 1'b1) begin 39 state <= #1 GNT0; 40 gnt_0 <= 1; 41 end else if (req_1 == 1'b1) begin 42 gnt_1 <= 1; 43 state <= #1 GNT1; 44 end else begin 45 state <= #1 IDLE; 46 end 47 GNT0 : if (req_0 == 1'b1) begin 48 state <= #1 GNT0; 49 end else begin 50 gnt_0 <= 0; 51 state <= #1 IDLE; 52 end 53 GNT1 : if (req_1 == 1'b1) begin 54 state <= #1 GNT1; 55 end else begin 56 gnt_1 <= 0; 57 state <= #1 IDLE; 58 end 59 default : state <= #1 IDLE; 60 endcase 61 end 62 63 endmodule // End of Module arbiter ``` You could download file fsm_using_single_always.v here