Lecture 12 – FSM I
Ryan Robucci
1. State Machines Basics
Mealy Machine
Moore Machine
2. References
- \(\dagger\) A Practical Introduction to Hardware Software Codesign Patrick Shaumont
- \(\dagger\)\(\dagger\) The Verilog® Hardware Description Language,
Donald E. Thomas (Author), Philip R. Moorby (Author)
ISBN:9781402070891
Amazon Link
- Examples for rescheduling
3. Implementation of Mealy and Moore Machines
4. State-Machine Implementation
- All Finite State Machines can be partitioned into a combinatorial and sequential parts
- Often these two pieces are coded in separate code blocks, but they may also be combined sometimes
- Note: some simple register-specific operations such a synchronous reset are coded in either the combination or the sequential blocks, but are often coded in the sequential block to indicate selection of register configuration. An asynchronous clear should be part of the sequential block.
5. State-Machine Verilog Implementation
module FSM (clk, clear, x,y); input logic clk, clear; input logic [2:0] x; output logic [1:0] y; // Declare the symbolic names for states //Verilog: localparam [6:0] S1 = 7'b0000001,S2 = 7'b0000010, S7 = 7'b1000000; typedef enum int {S0,S1,S2} state_t; // Declare current state and next state variables //Verilog: reg [2:0] CS,NS; state_t CS,NS; always_ff @ (posedge clk or posedge clear) begin if (clear == 1'b1) CS <= S0; else CS <= NS; end always_comb begin //always @ (CS, x) case (CS) S0 : begin y = 2'b00; if (x[2] && ~x[1] && x[0]) NS = S1; else if (x[2] && x[1] && ~x[0]) NS = S2; else NS = S0; end S1 : begin y = 2'b10; ... end
6. Mealy Implementation
module FSM (clk, clear, x,y); input logic clk, clear; input logic [2:0] x; output logic [1:0] y; // States typedef enum int {S0,S1,S2} state_t; // Declare current state and next state variables state_t CS,NS; always_ff @ (posedge CLOCK or posedge clear) begin if (clear == 1'b1) CS <= S1; else CS <= NS; end always_comb begin //always @ (CS, x) case (CS) S1 : begin y = {x[2] , ~x[1] && x[0]}; if (x[2] && ~x[1] && x[0]) NS = S2; else if (x[2] && x[1] && ~x[0]) NS = S4; else NS = S1; end S2 : begin y = 2'b10; ...
- every output bit must be well-defined for every case and input to avoid latches
- for NS, every output bit is set in every case to avoid latches
7. SystemVerilog FSM State Register
Verilog
reg [7:0] CS,NS; //reg!=register localparam S_init = 8'b00000000; localparam S_start0 = 8'b00000001; localparam S_start1 = 8'b00000010;
SystemVerilog
enum int {S_init, S_start0,S_start1} state_t; state_t CS,NS;
SystemVerilog enum:
- meaningful enum symbols displayed in waveform viewers and loggers
Symbol accessed as string through member function
name()
:$strobe("State %s %0d",CS.name(),CS);
- When automatic FSM state reencoding is used, shouldn't put much human effort into providing encodings
- using localparam to provide state encodings requires significant effort and careful use
- later: discuss that with default settings, many synthesizers replace user-provided encodings for FSM states
- therefore use of
enum int
seems appropriate when finally using synthesizer-generated encodings
8. Single Always Block Style for Registered Output Logic (Registered-Output Mealy)
always_ff @ (posedge CLOCK or posedge CLEAR) begin: FSM logic _temp; if (CLEAR == 1'b1) begin CS <= S1; end else begin case (CS) S1 : begin _temp = ~x[1]; //intermediate logic (blocking assignment) y <= {x[2] , _temp & x[0]}; //register intent (non-blocking assignment) if (x[2] && _temp && x[0]) CS <= S2; //register intent (non-blocking assignment) else if (x[2] && x[1] && ~x[0]) CS <= S4; else CS <= S1; end S2 : begin y <= {x[1] && ~x[1] , x[0]}; . . .
- Embedded combination circuit signal assignments ended with blocking assignment and thus encode "immediate" effect. All consumers of blocking assignment results should be within this code block. Even within the block, no consumer should rely on a value assigned from a blocking statement in a previous trigger event.
- Remember, any variable written to inside an edge-triggered block can become a register regardless of the use of blocking or non-blocking…consider every output variable, combinational and sequential, in every case and branch of decision tree and make sure assignments are always made to avoid latches
9. Coding Style for State Machines
🛰️ Registered Output with Three-Always Block Style
- Registered output can cause “cycle delays” so some output transitions need to be coded along with the state transition into a state rather than with the state they are supposed to coincide with (discuss output on prev. slide)
- Sometimes this feels like you’re coding outputs in the “previous state” or coding output ahead of time to account for register delay. I refer to it as coding the output along with the state transition it coincides with. This leads to additional lines of code as you need to code each output logic possibly for every transition to a state rather than once per state
- To avoid this “code bloat”, yet another approach is to code the registered outputs in a separate block. This leads to three blocks:
- Combinatorial Next State Logic along with any combinatorial outputs
- Sequential State Register
- Sequential Registered Outputs according to the destination (next) state from the combinatorial Block.
- Good contrasting examples can be found here: http://www.sunburst-design.com/papers/CummingsSNUG2003SJ_SystemVerilogFSM.pdf
10. Example State-Machine: An Arbitrator
Block Diagram
Example Operation Timing Diagram
- Assume peripherals need a start signal for two-clock cycles
- in the next cycle they present busy as low
- then in the following cycle after they present busy as high and hold it until it coincides with a new result
Statemachine
- Using more states simplifies output logic
- Using fewer states requires more output logic and, in the code shown effectively embeds extended state information in additional registers
Code (In-Class)
Code (using registered Outputs With Single Always Block)
module control_with_state_machine2( input logic clk, input logic rst, output logic startA, // start signal to peripheral A output logic startB, // start signal to peripheral B input logic busyA, // busy signal from peripheral A input logic busyB, // busy signal from peripheral B output logic ready, // ready signal to primary input logic sel0A1B, // peripheral select input logic start // go signal from primary ); enum int {S_init, S_start0,S_start1} state_t state_t CS,NS; always_ff @ (posedge clk) begin if (rst == 1) CS<=S_init; else case (CS) S_init: begin if (start == 1) begin startA <= ~sel_0A1B; startB <= sel_0A1B; sel_0A1B_saved<= sel_0A1B; CS<=S_start0; end else begin startA <= 0; startB <= 0; CS<=S_init; end end S_start0: begin //startA <= startA; //startB <= startB; CS<=S_start1; end S_start1: begin startA <= 0; startB <= 0; CS<=S_wait_for_result; end S_wait_for_result: begin automatic bit [15:0] _result16; startA <= 0; startB <= 0; if (~sel_0A1B_saved && ~busyA || ~sel_0A1B_saved && ~busyB) begin startCS<=S_result_H; if (~sel_0A1B_saved) begin _result16 = resultA; end else begin _result16 = resultB; end result <= {result[31:16],_result16} end end S_result_H: begin automatic bit [15:0] _result16; if (~sel_0A1B_saved) begin _result16 = resultA; end else begin _result16 = resultB; end result <= {_result16,result[15:0]} ready <= 1; end endcase end endmodule
NOTE FSM to tackle Design Complexity
- this is a good point to consider why we build state machines and coding hardware HDL vs software
- a key advantage of a state machine for a logic designer is that the complexity of a large task can be broken down into smaller problems represented by the work done in each state
- unfortunately the hardware designer must be critical of the synthesizer, because the value of hardware itself is in optimization more often than in software which is more often focused on function
- this splits the mind of the designer and makes the overall design task more challenging and time-consuming
- software optimization tools are mature and displace the need for humans to spend time on optimizations, while hardware design tools are maturing
Internal Timing Diagram for FSM
Place holder for in-class timing diagram. Key concepts:
- Identification of implied combinatorial signals including register inputs (outputs and state (NS))
- Arrival of input changes versus response timing
- Coincidence of Code and Output Timing
11. Registered Outputs 3-Always-Block Style
module control_with_state_machine2( input logic clk, input logic rst, output logic startA, //start signal to peripheral A output logic startB, //start signal to peripheral B input logic busyA, //busy signal from peripheral A input logic busyB, //busy signal from peripheral B output logic ready, //ready signal to primary input logic sel_0A1B, //go signal from primary input logic start //go signal from primary ); enum int {S_init, S_start0,S_start1} state_t state_t CS,NS; assign ready = ~(sel_0A1B?busyB_n:busyA_n); // extra combinational logic outside state machine always_ff @ (posedge clk) begin if (rst == 1) CS<=S_init; else CS<=NS; end always_comb begin NS = CS; case (CS) S_init: begin if (go) begin NS = S_start0; end end S_start0: NS = S_start1; S_start1: NS = S_init; endcase end always_ff @ (posedge clk) begin case (NS) S_init: startA <= 0; startB <= 0; S_start0: startA <= ~selAnB; startB <= selAnB; S_start1: startA <= startA; startB <= startB; endcase end endmodule
- also need to consider appropriate resets and defaults logic
12. When is registered-output not appropriate?
Note that the specification from the following timing diagram could not be satisfied by registered logic, since values are passed through the interface intra-cycle, (within the same cycle, rather than only from one cycle to the next)
13. Finite State Machine (FSM)
- Characterized by
- A set of states
- A set of inputs and outputs
- A state transition function
- An output function
- Hardware Implementation
- Current State held in a register
- Any additional status information held in status register
- Next-State and State Control Logic Determines next state and control signals based on registers
- Datapath implements operations on data under control of sate control logic