0% found this document useful (0 votes)
56 views74 pages

Ss7.Verilog For Fsms

Uploaded by

ryujindance
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views74 pages

Ss7.Verilog For Fsms

Uploaded by

ryujindance
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 74

CPEN 211: Introduction to Microcomputers

Slide Set 7:
Verilog for Finite State Machines
Non-blocking assignments
More Synthesis Rules

Prof. Tor Aamodt

[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):

always @(<sensitivity_list>) begin


<sequence of statements in which order matters>
end
“posedge <expr>” is true only at times when
there is a change from 0 to 1 on <expr>

always @(posedge clk)


out = in ;

In class we will complete the waveform for “out” below:

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

always_ff @(posedge clk)


out = in ;

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]

reg [1:0] present_state;

always_ff @(posedge clk) begin


if (reset) S3 S1
present_state = 2'b00; [11] [01]
else begin
case (present_state)
2'b00: present_state = 2'b01;
2'b01: present_state = 2'b10; S2
[10]
2'b10: present_state = 2'b11;
2'b11: present_state = 2'b00;
default: present_state = 2'bxx;
endcase Always include a
end default statement in
out = present_state; your case statements.
end Use “don’t care” to
endmodule
Slide Set #7 make it easier to find bugs.
7
Let’s walk through this code in more detail:

always_ff @(posedge clk) begin

• 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

• If reset is not true we will do the else part

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

• We use a case statement to update the state to the next state.

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

always_ff @(posedge clk) begin


if (reset)
present_state = 2'b00;
else begin
case (present_state)
2'b00: present_state = 2'b01;
11
Reset Notes
• When power turns on (at time 0), flip-flops end up
with either a 0 or a 1 but we cannot reliably predict
which one for any given flip-flop.
• Any given flip-flop may tend to power on to 0 or 1.
Value may depend upon many factors (e.g., process
variation, temperature, wear out, EMI, etc…)
• ModelSim represents the uncertainty with
“Unknown” value “x” (i.e., a red line).

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

Flip-flop to represent state “S0”

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

NOTE: Replace “FSM_tb” with the module name of your testbench. 17


Can we use present_state = 2’b00
to represent both S0 and S1?

Different States with Same Output A: Yes


Yes
B: No ✔
C: Not sure
• In general, multiple states may have the SAME
Output value
• What if S1 outputs “00” (instead of “01”)?
S0
reset
[00]

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]

always_ff @(posedge clk) begin


if (reset)
present_state = 2'b00; S3 S1
else begin [11] [00]
[01]
case (present_state)
2'b00: present_state = 2'b10;
2'b10: present_state = 2'b11;
2'b11: present_state = 2'b00; S2
default: present_state = 2'bxx; [10]
endcase
end
out = present_state; This Verilog is WRONG. It does not implement
end the state machine with four states in the figure.
endmodule It implements a state machine with three states.
The two state machines are NOT the same. 19
S0
[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

module FSM2(clk, reset, in, out);


input clk, reset, in;
output out;
reg out;

reg [`SW-1:0] present_state;


0 0

always_ff @(posedge clk) begin Sa Sb


[0] 1 [1]
if (reset) begin
present_state = `Sa; reset 1

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;

… continued on next slide...


Slide Set #7 23
0 0

`Sb: if (in == 1'b0) Sa Sb


[0] 1 [1]
present_state = `Sb; 1

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

… check for reset …

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]

`Sb: begin reset 1


if (in == 1’b0) begin
present_state = `Sb;
end else begin
Sc 0 Sd
present_state = `Sc;
[1] [0]
0
end
1
out = 1'b1; 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

Two case statements:

Sa Sb Sc Sd

One case statement:

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:

The first to select the new state.

The second to select the output in that state.

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.

Using a single always block to design an FSM requires you to think


carefully about when things happen.

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

0 0 • Goal: Inputs should test every transition,


Sa Sb
including self loops, in the state machine.
[0] 1 [1]
• If number of edges is too many given your
reset 1 time constraints (e.g., during LPT-1) then
test as many as you can.
• IMPORTANT: Inputs (including reset)
should not change when there is a rising
Sc
[1]
0 Sd
[0]
edge on clk. (Besides being very confusing
0 to interpret, you may get mismatches
1 1 between RTL and gate level simulations if
you do not ensure this.)
Slide Set #7 33
Example Testbench for FSM
module FSM2_tb;
reg clk, reset, in, err;
wire out; These signals need to be declared as “reg” because
they will be assigned inside one of the initial blocks.
FSM2 dut(clk,reset,in,out);

initial begin We use “err” to record if an error occurred. Will initial


clk = 0; #5; be zero, then set to one when an error occurs. Note
forever begin that “err’ is not an input or output of dut. You can
clk = 1; #5; add “err” to waveform viewer to make it easy to find
clk = 0; #5;
end
when an error occurs. Can then focus on values of
end signals at that 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

reset = 1'b0; // remember to de-assert reset (otherwise get stuck in Sa)

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

reset = 0'b0; // remember to de-assert reset (otherwise get stuck in Sa)

$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

reset = 0'b0; // remember to de-assert reset (otherwise get stuck in Sa)

$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

// other inputs + state and output checks ...


Print a message at end so you
if( ~err ) $display("PASSED"); know all the tests completed.
$stop;
end
Slide Set #7 42
endmodule
Using “task” (testbench only)
Verilog has syntax construct called a “task”. Similar to a
function but can include time delay. Can be helpful for
repetitive checking code. Declared inside module where
used. Use ONLY in your testbench code.

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);

// declare a task for checking state and outputs


task my_checker;
input [`SW-1:0] expected_state;
input [`SW-1:0] expected_output;
begin
if( FSM2_tb2.dut.present_state !== expected_state ) begin
$display("ERROR ** state is %b, expected %b",
FSM2_tb2.dut.present_state, expected_state );
err = 1'b1;
end
if( out !== expected_output ) begin
$display("ERROR ** output is %b, expected %b", out, expected_output );
err = 1'b1;
end
end
endtask

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

Use the following style for your state


machines in Lab 6 and 7.

Slide Set #7 46
Finite State Machine: Implementation

state

next_state
D Q

CL s s

in out
n m
clk

Question: How do we get “state” to the reset state?

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

Question: How do we describe n-bit D-flip-flop in Verilog?

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

vDFF #(`SW) STATE(clk,next_state_reset,present_state);

assign next_state_reset = reset ? `Sa : next_state;

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

wire [`SW-1:0] present_state, next_state_reset;


0 0
reg [`SW-1:0] next_state;
Sa Sb
[0] 1 [1]
vDFF #(`SW) STATE(clk,next_state_reset,present_state);
reset 1

// 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

Two case statements in one always block:

FSM code using style guidelines:

Slide Set #7 52
Two case statements in one always block:

FSM code using style guidelines:

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”.

The “=” assignment is also called a blocking assignment.

Verilog also has a non-blocking assignment: “<=”.

The difference? Non-blocking assignments do not take effect


until the end of an always block.

Slide Set #7 56
Verilog’s Non-Blocking Assignment “<=”

always @(x or y) begin


z <= x & y;
w <= x | y;
end

Signals z and w get updated at the same


time, at the end of the always block. This is
because they were assigned using “<=”.

Slide Set #7 57
Non-blocking assignment (<=)

always @(x or y) begin


z <= x & y;
w <= z | y;
end This is strange: The assignment to w uses the old
value of z, not the new value! That is because z is
not updated until the end of the always block.

Slide Set #7 58
If z was a blocking-assignment…

always @(x or y) begin


z = x & y;
w <= z | y;
end
In this case, w would use the “new” value of z.
This is because the assignment to z used a blocking
assignment “=”. The next statement is “blocked” until the
update to z takes effect.

Slide Set #7 59
“Blocking” assignment “Non-Blocking” assignment

always_ff @(posedge clk) begin always_ff @(posedge clk) begin


b = a; b <= a;
c = b; c <= b;
end end

Synthesizes to: Synthesizes to:

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:

More on this: http://www.informit.com/articles/article.aspx?p=392278&seqNum=6


Slide Set #7 62
NOTE: Strictly speaking, we should probably use <= inside vDFF but ModelSim does “right thing” with ”=”.
Moral?

If you follow style guidelines and use vDFF for registers


you can use normal assignments “everywhere”.

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):

Rule 1: Every input (that can affect the output(s)) must be


in the sensitivity list or use the wildcard @(*)

Rule 2: Every output must be assigned a value for every


possible combination of the inputs

always @(sel or A or B) begin always @(*) begin


if (sel == 1'b0) if (sel == 1'b0)
Y = A; Y = A;
else else
Y = B; Y = B;
end end
Slide Set #7 64
Type 2: Purely Synchronous: Each output
changes only on the rising or falling edge of a
single clock

always_ff @(posedge CLK)


Z <= A & B;

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 3: Clock should not be not read/written inside of the always


block

Rule 4: The always block can only describe what happens in one clock cycle.

Rule 5: Only one purely synchronous always block per module


or you must use non-blocking assignment “<=” for always block outputs.

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;

NOTE: You will see the


inferred latch warning
Warning (10240): Verilog HDL
for this code, but that is Always Construct warning at
OK because here we ss6.v(295): inferring latch(es) for
*wanted* a latch. variable "Z", which holds its previous
value in one or more paths through
the always construct
Slide Set #7 67
For a purely level sensitive always block (Type 3):

Rule 1: Use always_latch (can also use “always @(*)”)

Rule 2: Clock should be in only one “if condition”.

Rule 3: Only signals that change on the same level of the same
clock should be assigned to in the same always block

Rule 4: Clock should not be not read/written inside of the 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).

always_ff @(posedge clk)


if (reset)
Z = 1'b0;
else
Z = A & B;

In Lab 2, the reset behaved differently: The Q outputs of the


DFFs were reset to zero immediately when MR was set to 1.
How do we specify such behavior in Verilog in a way that CAD
tools can recognize it and synthesize it?
Slide Set #7 69
Type 4: Synchronous with asynchronous reset.

always_ff @(posedge clk, posedge reset)


if (reset)
Z = 1'b0;
else
Z = A & B;

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.

Rule 6: Only one purely synchronous always block per module


or you must use non-blocking assignment “<=” for always block outputs.

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.

If one of your always blocks doesn’t, you need to


break it up into blocks, where each block does fit
into one of these categories.

NOTE: I am being a little bit conservative here…


some synthesizers may handle a few patterns not
described here. But don’t count on it.

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

wire [1:0] present_state, next_state_reset;


reg [1:0] next_state;

vDFF #(`SW) STATE(clk,next_state_reset,present_state);

// reset logic
assign next_state_reset = reset ? 2'b00 : next_state;

// next state and output logic


always_comb begin
case (present_state)
`Sa: {next_state,out} = { (in ? `Sb : `Sa), 1'b0 };
`Sb: {next_state,out} = { (in ? `Sc : `Sb), 1'b1 };
Type 1: Purely
`Sc: {next_state,out} = { (in ? `Sc : `Sd), 1'b1 }; Combinational logic
`Sd: {next_state,out} = { (in ? `Sd : `Sc), 1'b0 };
default: {next_state,out} = 3'b000;
endcase
end Slide Set #7 73
endmodule
Summary
• Two ways to code up a finite state machine in
Verilog.
• Second (following style guideline) is
preferable as it avoids a very common pitfall
causing output to be delayed by one cycle.
• “Self checking” testbenches for FSMs.
• Two new rules that are important to know
whenever writing synthesizable Verilog with
always blocks.
Slide Set #7 74

You might also like