COMP541 State Machines – II: Verilog Descriptions Montek Singh Sep 24, 2014 1 Today’s Topics Lab preview: “Debouncing” a switch Verilog styles for FSM Don’t forget to check synthesis output and console msgs. State machine styles Moore vs. Mealy 2 The eight individual high-efficiency LEDs are an they will turn on when a logic high voltage is ap are not user-accessible indicate power-on, FPG status. Lab Preview: Buttons and Debouncing Mechanical switches “bounce” vibrations cause them to go to 1 and 0 a number of times called “chatter” hundreds of times! 3.3V C4 BTNL Buttons D9 BTNR A8 BTNU We want to do 2 things: “Debounce”: Any ideas? Synchronize with clock B8 BTNS 3.3V i.e., only need to look at it at the next +ve edge of clock Think about (for Wed class): What does it mean to “press the button”? Think carefully!! What if button is held down for a long time? C9 BTND Slide Switches SW0 T10 SW1 T9 SW2 V9 SW3 M8 SW4 N8 SW5 U8 3 Verilog coding styles for FSMs 4 Verilog coding styles First: More on Verilog procedural/behavioral statements if-then-else case statement Then: How to specify an FSM Using two always blocks Using a single always block?? Using three always blocks 5 Verilog procedural statements All variables/signals assigned in an always statement must be declared as reg Unfortunately, the language designers made things unnecessarily complicated not every signal declared as reg is actually registered it is possible to declare reg X, even when X is the output of a combinational function, and does not need a register! whattt???!! They thought it would be awesome to let the Verilog compiler figure out if a function is combinational or sequential! a real pain sometimes you will suffer through it later in the semester if not careful! Verilog procedural statements These statements are often convenient: if / else case, casez more convenient than “? : ” conditional expressions especially when deeply nested But: these must be used only inside always blocks again, some genius decided that Result: designers often do this: declare a combinational output as reg X so they can use if/else/case statements to assign to X HOPE the Verilog compiler will optimize away the unintended latch/reg Example: Comb. Logic using case module decto7seg(input [3:0] data, output reg [7:0] segments); // reg is optimized away always @(*) Note the *: case (data) it means that when any inputs // abcdefgp used in the body of the always 0: segments <= 8'b11111100; block change. 1: segments <= 8'b01100000; 2: segments <= 8'b11011010; This include “data” 3: segments <= 8'b11110010; 4: segments <= 8'b01100110; 5: segments <= 8'b10110110; 6: segments <= 8'b10111110; 7: segments <= 8'b11100000; 8: segments <= 8'b11111110; 9: segments <= 8'b11110110; default: segments <= 8'b0000001; // required endcase endmodule Beware the unintended latch! Very easy to unintentionally specify a latch/register in Verilog! how does it arise? you forgot to define output for some input combination in order for a case statement to imply combinational logic, all possible input combinations must be described one of the most common mistakes! one of the biggest sources of headache! you will do it a gazillion times this is yet another result of the the hangover of software programming forgetting everything in hardware runs in parallel, and time is continuous Solution good programming practice remember to use a default statement with cases every if must have a matching else check synthesizer output / console messages 9 Beware the unintended latch! Example: multiplexer out is output of combinational block select no latch/register is intended in this circuit A recommended Verilog: B out assign out = select? A : B; But, an if statement (inside an always block) will incorrectly introduce a reg: if (select) out <= A; if (!select) out <= B; reg added to save old value if condition is false to avoid extra reg, cover all cases within one statement: if (select) out <= A; else out <= B; 10 Combinational Logic using casez casez allows case patterns to use don’t cares module priority_casez(input [3:0] a, output reg [3:0] y); // reg will be optimized away always @(*) casez(a) 4'b1???: 4'b01??: 4'b001?: 4'b0001: default: endcase endmodule y y y y y <= <= <= <= <= 4'b1000; 4'b0100; 4'b0010; 4'b0001; 4'b0000; // ? = don’t care Blocking vs. Nonblocking Assignments (review) <= is a “nonblocking assignment” Occurs simultaneously with others = is a “blocking assignment” Occurs in the order it appears in the file // nonblocking assignments module syncgood(input clk, input d, output reg q); reg n1; always @(posedge clk) begin n1 <= d; // nonblocking q <= n1; // nonblocking end endmodule // blocking assignments module syncbad(input clk, input d, output reg q); reg n1; always @(posedge clk) begin n1 = d; // blocking q = n1; // blocking end endmodule Cheat Sheet for comb. vs seq. logic Sequential logic: Use always @(posedge clk) Use nonblocking assignments (<=) Do not make assignments to the same signal in more than one always block! e.g.: always @ (posedge clk) q <= d; // nonblocking Cheat Sheet for comb. vs seq. logic Combinational logic: Use continuous assignments (assign …) whenever readable assign y = a & b; OR Use always @ (*) All variables must be assigned in every situation! must have a default case in case statement must have a closing else in an if statement do not make assignments to the same signal in more than one always or assign statement Revisit the sequence recognizer (from last lecture) 15 Let’s encode states using localparam module seq_rec (input CLK, input RESET, input X, output reg Z); reg [1:0] state; localparam A = 2'b00, B = 2'b01, C = 2'b10, D = 2'b11; Notice that we have assigned codes to the states. localparam is more appropriate here than parameter because these constants should be invisible/inaccessible to parent module. 16 Next State logic reg [1:0] next_state; // optimized away always @(*) begin case (state) A: if (X == 1) next_state <= B; else next_state <= A; B: if(X) next_state <= C; else next_state <= A; C: if(X) next_state <= C; else next_state <= D; D: if(X) next_state <= B; else next_state <= A; default: next_state <= A; endcase The last 3 cases do same thing. end Just sparse syntax. 17 Register for storing state Register with reset synchronous reset (Lab 5) Notice that state only gets updated on posedge of clock (or on reset) reset occurs only at clock transition always @(posedge CLK) if (RESET == 1) state <= A; else state <= next_state; prefer synchronous reset asynchronous reset reset occurs whenever RESET goes high always @(posedge CLK or posedge RESET) if (RESET == 1) state <= A; else state <= next_state; use asynchronous reset only if you really need it! 18 Output // Z declared as: output reg Z // reg is optimized away always @(*) case(state) A: Z <= 0; B: Z <= 0; C: Z <= 0; D: Z <= X ? 1 : 0; default: Z <= 0; endcase 19 Comment on Code Could shorten it somewhat Don’t need three always clauses Although it’s clearer to have combinational code be separate Don’t need next_state, for example Can just set state on clock Template helps synthesizer Check to see whether your state machines were recognized 2 Verilog: specifying FSM using 2 blocks Let us divide FSM into two modules one stores and update state another produces outputs 21 Verilog: specifying FSM using 2 blocks reg [1:0] state; reg outp; … always @(posedge clk) case (state) s1: if (x1 == 1'b1) state <= s2; else state <= s3; s2: state <= s4; s3: state <= s4; s4: state <= s1; endcase //default not required for always @(*) case (state) s1: outp s2: outp s3: outp s4: outp default: outp endcase <= <= <= <= <= 1'b1; 1'b1; 1'b0; 1'b0; 1'b0; seq logic! //default required for comb logic! 22 Synthesis (see console output) Synthesizing Unit <v_fsm_2>. Related source file is "v_fsm_2.v". Found finite state machine <FSM_0> for signal <state>. ----------------------------------------------------------------------| States | 4 | | Transitions | 5 | | Inputs | 1 | | Outputs | 1 | | Clock | clk (rising_edge) | | Reset | reset (positive) | | Reset type | asynchronous | | Reset State | 00 | | Power Up State | 00 | | Encoding | automatic | | Implementation | LUT | ----------------------------------------------------------------------Summary: inferred 1 Finite State Machine(s). Unit <v_fsm_2> synthesized. 23 Incorrect: Putting all in one always Using one always block generally incorrect! (But may work for Moore FSMs) ends up with unintended registers for outputs! always@(posedge clk) case (state) s1: if (x1 == 1'b1) else s2: begin state <= s4; end s3: begin state <= s4; end s4: begin state <= s1; end endcase begin state <= s2; outp <= 1'b1; end begin state <= s3; outp <= 1'b0; end outp <= 1'b1; outp <= 1'b0; outp <= 1'b0; 24 Synthesis Output Synthesizing Unit <v_fsm_1>. Related source file is "v_fsm_1.v". Found finite state machine <FSM_0> for signal <state>. ----------------------------------------------------------------------| States | 4 | | Transitions | 5 | | Inputs | 1 | | Outputs | 4 | | Clock | clk (rising_edge) | | Reset | reset (positive) | | Reset type | asynchronous | | Reset State | 00 | | Power Up State | 00 | | Encoding | automatic | | Implementation | LUT | ----------------------------------------------------------------------Found 1-bit register for signal <outp>. Summary: inferred 1 Finite State Machine(s). inferred 1 D-type flip-flop(s). 25 Textbook Uses 3 always Blocks 26 Three always Blocks reg [1:0] state; reg [1:0] next_state; … … … always @(*) // Process 1 case (state) s1: if (x1==1'b1) next_state <= s2; else next_state <= s3; s2: next_state <= s4; s3: next_state <= s4; s4: next_state <= s1; default: next_state <= s1; endcase reg outp; … … … always @(*) // Process case (state) s1: outp <= s2: outp <= s3: outp <= s4: outp <= default: outp <= endcase 3 1'b1; 1'b1; 1'b0; 1'b0; 1'b0; always @(posedge clk) // Process 2 if (RESET == 1) state <= s1; else state <= next_state; 27 Synthesis (again, no unintended latch) Synthesizing Unit <v_fsm_3>. Related source file is "v_fsm_3.v". Found finite state machine <FSM_0> for signal <state>. ----------------------------------------------------------------------| States | 4 | | Transitions | 5 | | Inputs | 1 | | Outputs | 1 | | Clock | clk (rising_edge) | | Reset | reset (positive) | | Reset type | asynchronous | | Reset State | 00 | | Power Up State | 00 | | Encoding | automatic | | Implementation | LUT | ----------------------------------------------------------------------Summary: inferred 1 Finite State Machine(s). Unit <v_fsm_3> synthesized. 28 My Preference The one with 3 always blocks Easy to visualize the state transitions For really simple state machines: 2 always blocks is okay too Never put everything into 1 always block! Follow my template fsm_3blocktemplate.v (posted on the website) 29 Moore vs. Mealy FSMs? So, is there a practical difference? Moore FSM inputs M next state logic k next state CLK k state output logic N outputs Mealy FSM inputs M next state logic CLK next k state k state output logic N outputs 30 Moore vs. Mealy Recognizer Mealy FSM reset 1/1 1/0 S0 1/0 S1 0/0 S2 0/0 S3 1/0 0/0 0/0 Mealy FSM: arcs indicate input/output Moore FSM reset 1 S0 0 0 S1 0 0 0 1 1 1 S2 0 1 S3 0 0 S4 1 0 Moore and Mealy Timing Diagram Cycle 1 Cycle 2 Cycle 3 Cycle 4 Cycle 5 Cycle 6 Cycle 7 Cycle 8 1 1 1 0 1 1 0 Cycle 9 Cycle 10 CLK Reset A 1 0 Moore Machine S ?? S0 S1 S2 S2 S3 S4 S2 S3 S4 S0 S1 S2 S3 S1 S0 Y Mealy Machine S Y ?? S0 S1 S2 S2 S3 Moore vs. Mealy FSM Schematic Moore Mealy A CLK S'2 S'1 S'0 A S2 Y CLK S2 S1 S1 S'0 S0 S1 Reset S0 Reset S0 S'1 S1 S0 Y Next VGA Displays timing generation uses 2D xy-counter 34