Ss7.Verilog For Fsms
Ss7.Verilog For Fsms
Slide Set 7:
Verilog for Finite State Machines
Non-blocking assignments
More Synthesis Rules
[background: Facebook social network visualization; software finite state machines are extensively in networking protocols]
Learning Objectives
After completing this slide set you should be able to:
• Write finite state machine descriptions in Verilog
using edge sensitive always blocks.
• Avoid common mistakes in the timing of updates to
signals.
• Write finite state machine descriptions using a less
error prone style (following the style guidelines)
Slide Set #7 2
Recall (from Slide Set 6):
Slide Set #7 3
Warning: When you are writing Verilog you are describing hardware
behavior. The “description” in an always block will have little resemblance to
the actual hardware implementation. However, provided you follow the
synthesis rules your hardware will implement the same behavior.
In Slide Set #6 we learned the synthesis rule for combinational logic; in this
slide set we add a rule for describing synchronous sequential logic.
Slide Set #7 4
D Flip-flop
in out
D Q
clk
^
Slide Set #7 5
Finite State Machines
Next, let’s write a Verilog module describing the
following FSM’s behavior:
reset S0
[00]
S3 S1
[11] [01]
S2
[10]
IMPORTANT: This example is much simpler than most real FSMs because the
output is different in each state. Do NOT use this example for your labs.
Slide Set #7 6
WARNINGS: 1. Since the output in
each state is different we can write
simplified code. 2. This code does not
follow the style guidelines (we will see
a “better” way to code a finite state
module FSM(clk,reset,out); machine later in the slide set).
input clk, reset;
output [1:0] out;
S0
reg [1:0] out; reset [00]
• This defines the start of an always block that contains a sequence of code
where order matters.
• Statements that are evaluated whenever clk changes from 0 to 1 (the
“positive” edge).
• There is no “delay” between statements!
• Once end of always block is reached, wait until clk goes from 0 to 1 again.
if (reset)
present_state = 2'b00;
• We reset present state if reset is true. Note this reset occurs at a rising edge
of clock “clk”. This is called a “synchronous reset”. The MR input to the DFF in
Lab #2 is an “asynchronous reset” as it does not wait for a clock edge.
Slide Set #7 8
else begin
case (present_state)
2'b00: present_state = 2'b01;
2'b01: present_state = 2'b10;
2'b10: present_state = 2'b11;
2'b11: present_state = 2'b00;
default: present_state = 2'bxx;
endcase
out = present_state;
• In this very simple example, we assign out to be equal to the updated value of
present_state WARNING! Using output for state encoding (as in this example)
only works if every state has a different output.
9
always_ff @(posedge clk) begin
When is next time always
if (reset)
block code is “evaluated”?
S0
present_state = 2'b00; reset [00]
else begin A: 5
case (present_state) B: 10
2'b00: present_state = 2'b01; C: 15
2'b01: present_state = 2'b10; S3 D: 20 S1
2'b10: present_state = 2'b11; [11] E: Not sure [01]
2'b11: present_state = 2'b00;
default: present_state = 2'bxx;
endcase S2
end [10]
out = present_state;
end
clk
reset
present_state
out
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80
Slide Set #7 10
time
Do the red lines at time 0
ModelSim Simulation mean there is a problem?
A: Yes
B: No ✔
C: Not sure
Master Slave
M
D
Q
B B
CLK
A A
Slide Set #7 12
Reset Notes
• Circuit with a synchronous reset will have unknown
state and outputs before the first rising edge when
reset is asserted.
• Recall Rule 1 of debugging is “Understand the
system”. This red line is expected and not a “bug”!
• In your electronic gadgets there is a power on reset
circuit that applies a reset (so you don’t have to).
Slide Set #7 13
S0
reset [00]
S3 S1
[11] [01]
S2
Slide Set #7 14
[10]
Technology Map Viewer
Tools > Netlist Viewers > Technology Map Viewer
Quartus used 6-flip-flops in the implementation of our FSM. One flip-flop per state
(Quartus used a one-hot coded representation)
Slide Setand
#7 one for each output bit. 15
Gate-Level Simulation in ModelSim
Quartus inverted reset state encoding. E.g., “0” for present_state.00 means we are in
state 00 but other states follow usual one hot encoding we saw in flipped lecture.
Slide Set #7 16
Gate-Level Simulation: How?
Adjust settings in Quartus. Do this before compiling.
Assignments > Settings > EDA Tools Settings > Simulation
Set “Tool name” to “Model-Sim Altera” and “Format for output netlist” to Verilog.
In ModelSim use transcript window to start simulation specifying libraries that model
FPGA internal blocks:
vsim -t 1ps -L cyclonev_ver -L altera_ver -L altera_mf_ver \
-L 220model_ver -L sgate_ver -L altera_lnsim_ver FSM_tb
S3 S1
[11] [00]
[01]
S2
[10]
Slide Set #7 18
Does this Verilog code correctly
implement the desired state
machine?
A: Yes
module FSM(clk,reset,out);
B:
B: No
No
input clk, reset; C: Not sure
output [1:0] out;
reg [1:0] out;
S0
reset
reg [1:0] present_state; [00]
S3 S1
[11] [00]
[01]
S2
[10] Slide Set #7 20
A more realistic example:
0 0
Sa Sb
[0] 1 [1]
1
reset
Sc 0 Sd
[1] [0]
0
1 1
NOTE: output for State “Sa” is same as output for State “Sd”.
Slide Set #7 21
Let’s Complete the waveform for this state machine
0 0
Sa Sb
[0] 1 [1]
present_state
1
reset CL
CL next_state out
in
Sc 0 Sd
[1] [0]
clk
0
1 1
1
clk
0
1
in
0
present_state
state Sa
next_state Sa
1
out
0
Slide Set #7
22
`define SW 2
`define Sa 2'b00 WARNING: You may encounter
`define Sb 2'b01 syntax errors if you cut & paste
`define Sc 2'b10 this code for Lab 3.
`define Sd 2'b11
out = 1'b0;
end else begin
case (present_state) 0
Sc Sd
`Sa: if (in == 1'b0) [1] [0]
0
present_state = `Sa;
1 1
else
present_state = `Sb;
else reset
present_state = `Sc;
0
`Sc: if (in == 1'b1) Sc
[1]
Sd
[0]
0
present_state = `Sc; 1 1
else
present_state = `Sd;
`Sd: if (in == 1'b1) present_state
present_state = `Sd;
else CL
CL next_state out
present_state = `Sc;
in
default: present_state = 2'bxx; clk
endcase
case (present_state)
`Sa: out = 1'b0; This case statement replaces:
`Sb: out = 1'b1;
`Sc: out = 1'b1; out = present_state;
`Sd: out = 1’b0;
default: out = 1'bx; from prior example. This extra case is
endcase required because we need to know
end the new “present_state” we will be in
end after the rising edge of clk. 24
endmodule
Can we combine case statements?
always_ff @(posedge clk) begin
case (present_state)
`Sa: begin
if (in == 1’b0) begin
present_state = `Sa;
end else begin
present_state = `Sb;
end 0 0
out = 1'b0; Sa Sb
end [0] 1 [1]
end
… cases for `Sc and `Sd …
default: begin present_state = 2'bxx; out = 1'bx; end
endcase Slide Set #7 25
0 0
Sa Sb
[0] 1 [1]
1
reset
Sc 0 Sd
[1] [0]
`define Sa 2'b00
0 `define Sb 2'b01
1 1 `define Sc 2'b10
`define Sd 2'b11
Sa Sb Sc Sd
Sa Sb Sc Sd
Slide Set #7 26
Moral?
Use two separate case statements when coding
an FSM using the style in the above example:
Slide Set #7 27
Does one cycle delay really matter? Yes!
Complex designs (e.g., Lab 6 and 7) have many state
machines that interact together.
Example (each rectangle is a separate state machine):
car_ew
Intersection lights
car_lt FSM 9
4
Each block is
light
done
done
load
on
time
an FSM that 3
operates in
Light
parallel (at FSM
Timer
same time).
3
Signals go in both direction.
tdone
tload
time
Timer
28
Summary: FSM Using 1 Always Block
with 2 Case Statements
Need to use two case statements because output should correspond
to the state after clock edge: first case changes the state, second case
updates output to match that state.
Later in this slide we we will see how to code the same state machine
following the style guidelines in the textbook Appendix.
Which should you use? You need to be able to read code in either
style as you may see either in industry. If you have a choice, I
recommend writing your own code using the style later in this slide
set.
Slide Set #7 29
Testbenches for State Machines (1)
• Testing is VERY important for state machines!
• You will save lots of time in Lab 6 and 7 if you
learn how to write really good test benches for
state machines.
• Testing is very important for lab proficiency test.
• Even a single error (one character) is enough to
fail proficiency test…. BUT you can find most
errors with a good testbench and avoid all others
by following style guidelines (next FSM example).
Slide Set #7 30
Testbenches for State Machines (2)
• Use two initial blocks: one for clock and another for
other DUT inputs.
• Use a “self checking” test bench, which tests for
expected present state (not in gate level simulation)
and output after each input (and a rising edge of clk).
• Test each transition between states that should be in
state machine. Test for transitions that should NOT be
in the state machine. Test outputs.
• Print out messages using $display and use “task”
to avoid repetitive code in you testbench.
• Record presence of errors using signal (“err”) so can
report whether all checks pass at end.
• Look at results in waveform.
Slide Set #7 31
Hierarchical Signal Names
• Verilog allows “hierarchical names”
• Helps you easily check internal signals of DUT.
• NOT synthesizable. Use only in testbenches.
Does NOT work with gate level simulation.
• Syntax (full path):
<top_level_module> { . <indentifier> } +
Example: tb.DUT.present_state
• Syntax (relative path):
<instance label> { . <indentifier> } +
Example: DUT.present_state
Slide Set #7 32
Testbench: Input waveform
clk
reset
in
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
time
Slide Set #7 34
Example Testbench for FSM
module FSM2_tb;
reg clk, reset, in, err;
wire out;
Recall we use a wire for outputs of module
FSM2 dut(clk,reset,in,out);
instantiations.
initial begin
clk = 0; #5; This initial block generates the clock
forever begin input (clk) to the FSM. NOTE: The
clk = 1; #5; first rising edge of clk is at time=5,
clk = 0; #5; the second rising edge is at
end
end
time=15.
clk
reset
in
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
time
Slide Set #7 35
Example Testbench for FSM
module FSM2_tb;
reg clk, reset, in, err;
wire out;
FSM2 dut(clk,reset,in,out);
initial begin
clk = 0; #5;
forever begin
clk = 1; #5;
clk = 0; #5;
end
end
Initialize “err” to zero.
initial begin
reset = 1'b1;
in = 1’b0;
err = 1'b0;
#10; // wait until after rising edge of clock at time 5, before rising edge at time 15
clk
reset
in
5 10 15 20 25 30 35 40
Slide Set45#7 50 55 60 65 70 75 80 85 90 36
time
Example Testbench for FSM
module FSM2_tb; 0 0
reg clk, reset, in, err; Sa Sb
[0] [1]
wire out; 1
reset 1
FSM2 dut(clk,reset,in,out);
Sc 0 Sd
initial begin [1] [0]
0
clk = 0; #5; 1 1
forever begin
clk = 1; #5;
clk = 0; #5;
clk
end
end reset
in
initial begin
reset = 1'b1; 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
in = 1'b0; time
err = 1'b0;
#10; // wait until after rising edge of clock at time 5, before rising edge at time 15
// check whether in expected state (you should also look at waveforms)
if( FSM2_tb.dut.present_state !== `Sa ) begin
$display("ERROR ** state is %b, expected %b",
FSM2_tb.dut.present_state, `Sa );
err = 1'b1;
end
Slide Set #7 37
Example Testbench for FSM
module FSM2_tb;
reg clk, reset, in, err;
wire out;
FSM2 dut(clk,reset,in,out);
a !== b treats a and b as
initial begin
having four possible values:
clk = 0; #5;
0, 1, x and z.
forever begin
clk = 1; #5; What’s wrong with “a != b”?
clk = 0; #5; If a or b is x (unknown) or z (high
end impedance) then result of “a
end != b” is x (unknown). Unknown
x is treated as false by “if” (so
initial begin we don’t catch the error).
reset = 1'b1;
in = 1’b0;
err = 1'b0;
#10; // wait until after rising edge of clock at time 5, before rising edge at time 15
// check whether in expected state (you should also look at waveforms)
if( FSM2_tb.dut.present_state !== `Sa ) begin
$display("ERROR ** state is %b, expected %b",
FSM2_tb.dut.present_state, `Sa );
err = 1'b1;
end Set “err” to one to record that error occurred. 38
Slide Set #7
… continued on next slide...
// also check whether output is correct
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
err = 1'b1;
end
0 0
Sa Sb
[0] 1 [1]
reset 1
Sc 0 Sd
[1] [0]
0
1 1
clk
reset
in
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
timeSlide Set #7 39
// also check whether output is correct
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
err = 1'b1;
end
clk
reset
in
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
time
Slide Set #7 40
// also check whether output is correct
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
err = 1'b1;
end
$display("checking Sa->Sa");
in = 1'b0; // when in Sa should stay in state Sa if input is 0
#10; // wait for rising edge of clock before checking states and output
if( FSM2_tb.dut.present_state !== `Sa ) begin
0 0
$display("ERROR ** state is %b, expected %b",
FSM2_tb.dut.present_state, `Sa ); Sa Sb
[0] 1 [1]
err = 1'b1;
1
end
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
0
err = 1'b1; Sc Sd
[1] [0]
0
end
1 1
clk
reset
in
Slide Set #7 41
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
// also check whether output is correct
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
err = 1'b1;
end
$display("checking Sa->Sa");
in = 1'b0; // when in Sa should stay in state Sa if input is 0
#10; // wait for rising edge of clock before checking states and output
if( FSM2_tb.dut.present_state !== `Sa ) begin
$display("ERROR ** state is %b, expected %b",
FSM2_tb.dut.present_state, `Sa );
err = 1'b1;
end
if( out !== 1'b0 ) begin
$display("ERROR ** output is %b, expected %b", out, 1'b0 );
err = 1'b1;
end
task <identifer> ;
{ <input or output declaration> }
begin
{ <Verilog statement> }+
end
endtask
Slide Set #7 43
Self-checking Testbench using task
module FSM2_tb2;
reg clk, reset, in, err;
wire out;
FSM2 dut(clk,reset,in,out);
Slide Set #7 44
… continued on next slide...
initial begin
clk = 0; #5;
forever begin 0 0
clk = 1; #5; Sa Sb
clk = 0; #5; [0] 1 [1]
end
reset 1
end
initial begin
reset = 1'b1; in = 1'b0; err = 1'b0; #10;
Sc 0 Sd
my_checker(`Sa, 1'b0); [1] [0]
0
reset = 1'b0; // remember to de-assert reset
1 1
$display("checking Sa->Sa");
in = 1'b0; #10;
my_checker(`Sa, 1'b0);
$display("checking Sa->Sb");
in = 1'b1; #10;
my_checker(`Sb, 1'b1); # checking Sa->Sa
# checking Sa->Sb
$display("checking Sb->Sb");
in = 1'b0; #10; # checking Sb->Sb
my_checker(`Sb, 1'b1); # PASSED
# ** Note: $stop
//… checks for other state transitions ...
if( ~err ) $display("PASSED");
else $display("FAILED");
$stop; Slide Set #7 45
end
Less Error Prone Coding Style for FSMs
Slide Set #7 46
Finite State Machine: Implementation
state
next_state
D Q
CL s s
in out
n m
clk
Slide Set #7 47
Text: Dally §14.4
Finite State Machine with
“Synchronous” Reset: Implementation
`Sa
2'b00 1
next_state_reset state
D Q
2
next_state
0
CL 2
reset
in out
1 1
clk
Slide Set #7 48
Verilog for n-bit D Flip Flop
(“Register”)
//---------------------------------------------
// define flip-flop
//---------------------------------------------
module vDFF(clk, in, out) ;
parameter n = 1; // width
input clk ;
input [n-1:0] in ;
output [n-1:0] out ;
reg [n-1:0] out ; in n n out
D Q
always_ff @(posedge clk)
out = in ;
endmodule clk
^
Slide Set #7 49
Verilog for Mux and DFF:
`Sa
2'b00 1
2 next_state_reset present_state
state
D Q
2 2
next_state 0
2
reset clk
Slide Set #7 50
module FSM2Good(clk, reset, in, out);
input clk, reset, in; present_state
output out; `Sa
2'b00 1
next_state_reset state
reg out; D Q
2
next_state
0
`define SW 2 CL 2
reset
in out
`define Sa 2'b00
1 1
`define Sb 2'b01
`define Sc 2'b10 clk
`define Sd 2'b11
// reset logic
assign next_state_reset = reset ? `Sa : next_state;
Sc 0 Sd
[1] [0]
0
// next state and output logic 1 1
always @(*) begin
case (present_state)
`Sa: {next_state,out} = { (in ? `Sb : `Sa), 1'b0 };
`Sb: {next_state,out} = { (in ? `Sc : `Sb), 1'b1 };
`Sc: {next_state,out} = { (in ? `Sc : `Sd), 1'b1 };
`Sd: {next_state,out} = { (in ? `Sd : `Sc), 1'b0 };
default: {next_state,out} = { {`SW{1’bx}}, 1'bx };
endcase
end Slide Set #7 51
endmodule
0 0
Sa Sb
[0] 1 [1]
Sc 0 Sd
`define Sa 2'b00
[1] [0]
0 `define Sb 2'b01
1 1 `define Sc 2'b10
`define Sd 2'b11
Slide Set #7 52
Two case statements in one always block:
Slide Set #7 53
Displaying States in ModelSim
• By default states show up in ModelSim waveform in their
binary encoding.
• You can define a custom ‘radix’ to plot states helps with
debugging using the “radix define” command in the
ModelSim Transcript window:
VSIM 7> radix define States { 2'b00 "Sa", 2'b01 "Sb", 2'b10 "Sc", 2'b11 "Sd", -default hex }
Slide Set #7 54
Non-Blocking Assignments
Slide Set #7 55
A normal assignment “=” takes effect “immediately”.
Slide Set #7 56
Verilog’s Non-Blocking Assignment “<=”
Slide Set #7 57
Non-blocking assignment (<=)
Slide Set #7 58
If z was a blocking-assignment…
Slide Set #7 59
“Blocking” assignment “Non-Blocking” assignment
Slide Set #7 60
Which circuit does the following Verilog describe?
always_ff @(posedge clk)
q1 = d1;
always_ff @(posedge clk)
q2 = q1;
A:
B:
Slide Set #7 61
Simulation errors w/ blocking assignments and “@(posedge clk)”:
// following style guidelines – OK
vDFF #(1) dff1(clk, d1, q1);
vDFF #(1) dff2(clk, q1, q2);
// non-blocking - OK
always_ff @(posedge clk)
q1 <= d1;
always_ff @(posedge clk)
q2 <= q1;
// blocking – BAD: simulation differs from synthesis! Quartus synthesizes:
always_ff @(posedge clk)
q1 = d1;
always_ff @(posedge clk)
q2 = q1;
ModelSim simulates:
If you do not use vDFF for all your state then make sure
to use non-blocking assignment “<=” for the outputs of
your “always_ff @(posedge clk)” blocks!
Slide Set #7 63
We saw this rule in Slide Set 6….
For purely combinational processes (Type 1):
Slide Set #7 65
For a purely synchronous always block (Type 2):
Rule 1: Only the clock should be in the sensitivity list and should
be put after one of the keywords “posedge” or “negedge”
Rule 2: Only signals that change on the same edge of the same
clock should be assigned to in the same always block
Rule 4: The always block can only describe what happens in one clock cycle.
Slide Set #7 66
Type 3: Purely level sensitive. Output changes
only when clock is high.
always_latch
if (CLK == 1'b1)
Z = A & B;
Rule 3: Only signals that change on the same level of the same
clock should be assigned to in the same always block
Slide Set #7 68
Reset, revisited
Recall a synchronous reset can be specified using an if inside a
synchronous (Type 2) always block (this is what we did for our
FSM example in the first style).
Slide Set #7 70
For a synchronous with asynchronous reset always block (Type 4):
Rule 1: Only the clock and reset should be in the sensitivity list and both should
be put after one of the keywords “posedge” or “negedge”
Rule 2: All code must be “nested” within a single if statement that first checks if reset is asserted;
if reset is asserted, must set outputs to a constant value.
Rule 3: Only signals that change on the same edge of the same
clock should be assigned to in the same always block
Rule 4: Clock and reset should not be not read/written inside of the always
block
Rule 5: The always block can only describe what happens in one clock cycle.
Slide Set #7 71
Final Rule (the most important rule of all):
If you want to synthesize your circuit, every always
block must fall exactly into one of these categories.
Every always block. Every single one. No
exceptions.
Slide Set #7 72
module FSM2Good(clk, reset, in, out);
input clk, reset, in; present_state
output out; `Sa
2'b00 1
next_state_reset state
reg out; D Q
2
next_state
0
`define SW 2 CL 2
reset
in out
`define Sa 2'b00
1 1
`define Sb 2'b01
`define Sc 2'b10 clk
`define Sd 2'b11
// reset logic
assign next_state_reset = reset ? 2'b00 : next_state;