Lecture 3: Continuation of
SystemVerilog
Last Lecture
• Talked about combinational logic always
statements. e.g.,
module ex2(input logic a, b, c,
output logic f);
logic t; // internal signal
always_comb
should use “=“ (called “blocking”
begin
assignment) in comb. logic always
t = a & b; statements. RHS just takes output
f = t | c; from the previous equation.
end
The order of statements matters!
endmodule
2
This Lecture
• Talk about “clocked always statements”, which
generate combinational logic gates and flip-flops
• Unfortunately, SystemVerilog does not have well-
defined semantics for describing flip-flops and finite
state machines (FSMs)
• Instead, SystemVerilog relies on idioms to describe
flip-flops and FSMs (i.e., the use of coding templates
that synthesis tools will interpret to mean flip-flops
and FSMs)
• If you do not follow these “templates”, your code
may still simulate correctly, but may produce
incorrect hardware
3
D Flip-Flop
module flop(input logic clk,
input logic [3:0] d,
output logic [3:0] q);
always_ff @(posedge clk)
q <= d; // pronounced “q gets d”
• Verilog calls “<=“ a “non-blocking” assignment.
endmodule • It means “wait until next clk tick” before updating “q”
• This is why synthesis will produce a positive edge-trigged D-FF
• “always_ff” indicates that this is a “clocked always statement
Slide derived from slides by Harris & Harris from their book 4
Resettable D Flip-Flop
module flopr(input logic clk,
input logic reset,
input logic [3:0] d,
output logic [3:0] q);
// synchronous reset
always_ff @(posedge clk)
if (reset) q <= 4'b0; • Using this “template”, the “if” part
else q <= d; specifies the “reset” condition, and
the “else” part specifies what gets
endmodule stored “q” after next clk tick
• Synthesis tools will recognize this
“template”
clk
[3:0] [3:0] [3:0] [3:0]
d[3:0] D[3:0] Q[3:0] q[3:0]
reset R
q[3:0]
Slide derived from slides by Harris & Harris from their book 5
Resettable D Flip-Flop
module flopr(input logic clk,
input logic reset,
input logic [3:0] d,
output logic [3:0] q);
// asynchronous reset
always_ff @(posedge clk, posedge reset)
if (reset) q <= 4'b0; • By specifying the “reset”
else q <= d; signal here, synthesis tools
will understand the if-then-
endmodule
else template matches to
an asynchronously
resettable D-FF
clk
[3:0] [3:0] [3:0] [3:0]
d[3:0] D[3:0] Q[3:0] q[3:0] • Again this works because
R synthesis tools recognize
reset this template.
q[3:0]
Slide derived from slides by Harris & Harris from their book 6
Resettable D Flip-Flop
module flopr_n(input logic clk,
input logic reset_n,
input logic [3:0] d,
output logic [3:0] q);
// asynchronous reset
always_ff @(posedge clk, negedge reset_n)
if (!reset_n) q <= 4'b0; • By specifying the “negedge
else q <= d; reset_n” signal here,
synthesis tools will
endmodule
asynchronously resettable
D-FFs that are reset on the
“falling” edge of reset_n
clk
[3:0] [3:0] [3:0] [3:0]
d[3:0] D[3:0] Q[3:0] q[3:0] • The template requires the if-
R then-else to use
reset _n
q[3:0] if (!reset_n) … else ….
Slide derived from slides by Harris & Harris from their book 7
Creating logic gates + FFs
module ex4(input logic clk,
input logic t, c,
output logic f);
always_ff @(posedge clk)
begin
f <= t & c; • Positive edge triggered register (D-FF) produced for “f”.
end • “<=“ means LHS stores“new” value after next clk tick.
endmodule
8
Clocked always statements
module ex5(input logic clk,
input logic a, b, c,
output logic f);
logic t;
always_ff @(posedge clk)
begin
D-FF t <= a & b; LHS stores output of AND-gate to “t” register
produced for f <= t & c;
“t” and “f” end RHS reads from “t” register
endmodule
LHS goes into FF RHS taken
from FF
output
9
Clocked always statements
module ex6(input logic clk, reset_n, a, b, c,
output logic f);
logic t;
always_ff @ (posedge clk, negedge reset_n)
begin
if (!reset_n) begin Template specifies async
this if part specifies
t <= 0; how registers should reset edge-triggered D-FFs
f <= 0; be initialized
end else begin Positive edge-triggered on
t <= a & b; “clk”
f <= t & c;
Async reset negative edge
end on “reset_n”
end
endmodule RHS taken from FF output
LHS goes into FF
resets on neg edge of reset_n
10
Clocked always statements
module ex7 (input logic clk, reset_n, op,
input logic [3:0] x,
output logic [3:0] dataout);
always_ff @ (posedge clk, negedge reset_n)
begin
if (!reset_n) this if part specifies how registers should be initialized
dataout <= 4'b0000;
else • this else part specifies how registers should be updated at
if (op) each cycle.
dataout <= dataout + x; • all “outputs” (LHS) are stored in a register in a clocked
else always stmt. LHS specifies “new” value that will be stored
dataout <= dataout - x; after next clk tick.
end • should use “<=“ instead of “=“, which means on the RHS,
endmodule the value is the “current” value of the register.
If-then-else & case stmts
translated as MUXes
Arithmetic operators (e.g. “+”) are
replaced with library logic
all “outputs” (LHS) are
implementations.
stored in a register in a
clocked always stmt. 11
Clocked always statements
module ex8 (input logic clk, reset_n, op,
input logic [3:0] x,
output logic [3:0] dataout);
logic [3:0] y, z;
always_ff@(posedge clk,negedge reset_n) always_ff@(posedge clk,negedge reset_n)
begin if (!reset_n) begin
if (!reset_n) dataout <= 4'b0000;
y <= 4'b0000; z <= 4'b0000;
else end else begin
if (op) z <= y + 1; writes to “z” reg
y <= y + x; dataout <= dataout + z; reads from “z” reg
else end
y <= y - x; endmodule
end 1st always stmt 2nd always stmt
writes to “z” reg
output from clocked
always stmt is reads from “z” reg
output of reg.
12
Mixing statements
module ex9 (input logic clk, reset_n, op,
input logic [3:0] x,
output logic [3:0] dataout);
logic [3:0] y, z;
assign z = y + 1;
assign dataout = z + 1;
always_ff@(posedge clk, negedge reset_n)
begin
if (!reset_n)
y <= 4'b0000;
else
if (op) always_ff statement the 2 assign statements
y <= y + x;
else takes most recent
y <= y - x; value of “z”
end
endmodule
13
Mixing statements
module ex10 (input logic clk, reset_n, op,
input logic [3:0] x, same behavior as ex9, but using always_comb
output logic [3:0] dataout); instead of 2 assign statements
logic [3:0] y, z;
always_comb
begin
should use “=“ in comb. logic
z = y + 1;
always stmts. no reg. RHS just
dataout = z + 1;
takes output from the previous eqn.
end
always_ff@(posedge clk, negedge reset_n)
begin
if (!reset_n) The 2nd always_ff statement The 1st always_comb statement
y <= 4'b0000;
else takes =st recent
if (op) value of “z”
y <= y + x;
else
y <= y - x;
end
endmodule
14
Last Lecture: Divide by 3 FSM
• Output should be “1” every 3 clock cycles
S2
S0
S1
The double circle indicates the reset state
Slide derived from slides by Harris & Harris from their book 15
Finite State Machines (FSMs)
• A simple Moore machine looks like the
following
CLK
M next
next k state k output N
inputs state
state
outputs
logic
logic
Slide derived from slides by Harris & Harris from their book 16
FSM Example in SystemVerilog
module divideby3FSM (input logic clk, reset_n,
output logic q);
enum logic [1:0] {S0=2’b00, S1=2’b01, S2=2’b10} state; // declare states as
enum
// next state logic and state register
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
state <= S0;
else begin
case (state)
state transition graph is the same
S0: state <= S1;
thing as a state transition table, which
S1: state <= S2;
S2: state <= S0;
can be specify as a case statement
endcase
end
end
// output logic
assign q = (state == S0); output is “1” every clock cycles when we are in state S0
endmodule
17