350 likes | 592 Views
COMP541 State Machines – II: Verilog Descriptions. Montek Singh Sep 24, 2014. 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.
E N D
COMP541State Machines – II: Verilog Descriptions Montek Singh Sep 24, 2014
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
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! • We want to do 2 things: • “Debounce”: Any ideas? • Synchronize with clock • 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?
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
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 alwaysblocks • 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 @(*) case (data) // abcdefgp 0: segments <= 8'b11111100; 1: segments <= 8'b01100000; 2: segments <= 8'b11011010; 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 Note the *: it means that when any inputs used in the body of the always block change. This include “data”
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
Beware the unintended latch! • Example: multiplexer • out is output of combinational block • no latch/register is intended in this circuit • recommended Verilog: 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; select A out B
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???: y <= 4'b1000; // ? = don’t care 4'b01??: y <= 4'b0100; 4'b001?: y <= 4'b0010; 4'b0001: y <= 4'b0001; default: y <= 4'b0000; endcase endmodule
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 @(posedgeclk) • Use nonblockingassignments (<=) • Do not make assignments to the same signal in more than one always block! • e.g.: always @ (posedgeclk) 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)
Let’s encode states using localparam module seq_rec(input CLK, input RESET, input X, output reg Z); reg [1:0] state; localparamA = 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.
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 end The last 3 cases do same thing. Just sparse syntax.
Register for storing state • Register with reset • synchronous reset (Lab 5) • 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! Notice that state only gets updated on posedge of clock (or on reset)
Output // Z declared as: output regZ // 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
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
Verilog: specifying FSM using 2 blocks • Let us divide FSM into two modules • one stores and update state • another produces outputs
Verilog: specifying FSM using 2 blocks reg [1:0] state; regoutp; … always @(posedgeclk) 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 seq logic! always @(*) case (state) s1: outp <= 1'b1; s2: outp <= 1'b1; s3: outp <= 1'b0; s4: outp <= 1'b0; default: outp <= 1'b0; //default required for comb logic! endcase
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.
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@(posedgeclk) case (state) s1: if (x1 == 1'b1) begin state <= s2; outp <= 1'b1; end else begin state <= s3; outp <= 1'b0; end s2: begin state <= s4; outp <= 1'b1; end s3: begin state <= s4; outp <= 1'b0; end s4: begin state <= s1; outp <= 1'b0; end endcase
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).
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 always @(posedgeclk) // Process 2 if (RESET == 1) state <= s1; else state <= next_state; regoutp; … … … always @(*) // Process 3 case (state) s1: outp <= 1'b1; s2: outp <= 1'b1; s3: outp <= 1'b0; s4: outp <= 1'b0; default: outp <= 1'b0; endcase
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.
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)
Moore vs. Mealy FSMs? • So, is there a practical difference?
Moore vs. Mealy Recognizer Mealy FSM: arcs indicate input/output
Moore vs. Mealy FSM Schematic • Moore • Mealy
Next • VGA Displays • timing generation • uses 2D xy-counter