Lec6 Verilog-HDL #2

advertisement
COMP211 Computer Logic Design
Lecture 6. Verilog HDL – Sequential Logic
Prof. Taeweon Suh
Computer Science Education
Korea University
Sequential Logic
• Verilog provides certain syntax, which turns into
sequential circuits
 In always statements, signals keep their old value until
an event in the sensitivity list takes place
 Statement inside always is executed only when the event
specified in the sensitivity list occurs
 Note that always statement could generate combinational
logic, depending on your description
always @ (sensitivity list)
begin
statement;
statement;
…
end
2
Korea Univ
D Flip-Flop
•
As studied, flip-flop samples input at the edge of the clock


•
always @(posedge clk) samples the input at the rising edge of the clock (clk)
always @(negedge clk) samples the input at the falling edge of the clock (clk)
Any output assigned in an always statement must be declared reg
•
Note that a variable declared reg is not necessarily to be a registered output
• We’ll see it later…
• <= or = can be used inside the always statement
• <= is called nonblocking assignment
• = is called blocking assignment
• We are going to discuss about this later
module flipflop(input
clk,
input
[3:0] d,
output reg [3:0] q);
always @ (posedge clk)
begin
q <= d;
// pronounced “q gets d”
end
endmodule
3
Korea Univ
D Flip-Flop Simulation
testbench
module Dflipflop(input
clk,
input
[3:0] d,
output reg [3:0] q);
`timescale 1ns / 1ns
module Dflipflop_tb();
reg
clock;
reg [3:0] data;
wire [3:0] q;
always @(posedge clk)
begin
q <= d;
end
parameter clk_period = 10;
Dflipflop dut(.clk(clock), .d(data), .q (q) );
endmodule
always
begin
clock = 1;
forever #(clk_period/2) clock = ~clock;
end
initial
begin
end
data
data
data
data
data
=
=
=
=
=
4'h0; #3;
4'h3; #(clk_period*2);
4'h5; #(clk_period*3);
4'hA; #(clk_period*3);
4'hC; #(clk_period*2);
endmodule
4
Korea Univ
D Flip-Flop with Sync and Async Reset
DFF with Synchronous Reset
DFF with Asynchronous Reset
module ff_syncR(input
clk,
input
reset,
input
[3:0] d,
output reg [3:0] q);
module ff_asyncR(input
clk,
input
reset,
input
[3:0] d,
output reg [3:0] q);
// synchronous reset
// sensitively list has only clk
// asynchronous reset
// sensitivity list has both clk and reset
always @(posedge clk)
begin
if (reset) q <= 4'b0;
else
q <= d;
end
endmodule
always @ (posedge clk, posedge reset)
begin
if (reset) q <= 4'b0;
else
q <= d;
end
endmodule
5
Korea Univ
D Flip-Flop with Sync Reset
module ff_syncR(input
clk,
input
reset,
input
[3:0] d,
output reg [3:0] q);
`timescale 1ns / 1ns
module ff_syncR_tb( );
reg
clk;
reg
reset;
reg [3:0] d;
wire [3:0] q;
// synchronous reset
always @(posedge clk)
begin
if (reset) q <= 4'b0;
else
q <= d;
end
parameter clk_period = 10;
ff_syncR
always
begin
end
initial
begin
endmodule
end
initial
begin
endmodule
6
end
dut(clk, reset, d, q);
clk = 1;
forever #(clk_period/2) clk = ~clk;
reset
reset
reset
reset
reset
d
d
d
d
d
=
=
=
=
=
=
=
=
=
=
1; #3;
1; #(clk_period*2);
0; #(clk_period*3);
1; #(clk_period*2);
0; #(clk_period*3);
4'h0; #3;
4'h3; #(clk_period*2);
4'h5; #(clk_period*3);
4'hA; #(clk_period*3);
4'hC; #(clk_period*2);
Korea Univ
D Flip-Flop with Enable
`timescale 1ns / 1ns
module ff_en(input
clk,
input
reset,
input
en,
input
[3:0] d,
output reg [3:0] q);
module ff_en_tb();
reg
clk;
reg
reg
reg [3:0] d;
wire [3:0] q;
reset;
en;
parameter clk_period = 10;
ff_en dut(clk, reset, en, d, q);
// asynchronous reset and enable
always @(posedge clk, posedge reset)
begin
if (reset) q <= 4'b0;
else if (en) q <= d;
end
always
begin
clk = 1;
forever #(clk_period/2) clk = ~clk;
end
initial
begin
end
endmodule
initial
begin
end
initial
begin
end
reset = 1; #3;
reset = 1; #(clk_period*2);
reset = 0;
en
en
en
en
d
d
d
d
d
=
=
=
=
=
=
=
=
=
1; #3;
1; #(clk_period*5);
0; #(clk_period);
1;
4'h0; #3;
4'h3; #(clk_period*2);
4'h5; #(clk_period*3);
4'hA; #(clk_period*3);
4'hC; #(clk_period*2);
endmodule
7
Korea Univ
D Latch
• As studied, a D-latch is
• transparent when the clock is high
• opaque when the clock is low (retaining its old value)
• Try to avoid using latches unless you have a good reason to
use them because latches may transfer unwanted input to
output like glitches
• Instead, use flip-flops
module latch(input
clk,
input
[3:0] d,
output reg [3:0] q);
always @ (clk, d)
begin
if (clk) q <= d;
end
endmodule
8
Korea Univ
D Latch Simulation
`timescale 1ns / 1ns
module latch(input
clk,
input
[3:0] d,
output reg [3:0] q);
module latch_tb( );
reg
clk;
reg [3:0] d;
wire [3:0] q;
always @(clk, d)
begin
if (clk) q <= d;
end
parameter clk_period = 10;
latch latch_dut(clk, d, q);
always
begin
clk = 1;
forever #(clk_period/2) clk = ~clk;
end
endmodule
initial
begin
end
d
d
d
d
d
d
d
d
d
d
=
=
=
=
=
=
=
=
=
=
4'h0; #3;
4'h3; #(clk_period*2);
4'h4; #(clk_period/5);
4'h5; #(clk_period/5);
4'h6; #(clk_period/5);
4'h7; #(clk_period/5);
4'h8; #(clk_period/5);
4'h9; #(clk_period*3);
4'hA; #(clk_period*3);
4'hC; #(clk_period*2);
endmodule
9
Korea Univ
Useful Behavioral Statements
• Keywords that must be inside always statements
 if / else
 case, casez
• Again, variables assigned in an always statement
must be declared as reg even if they’re not actually
intended to be registers
 In other words, all signals on the left side of <= and =
inside always should be declared as reg
10
Korea Univ
Combinational Logic using always
• The always statement can also describe
combinational logic (not generating flip-flops)
// combinational logic using an always statement
module gates(input
[3:0] a, b,
output reg [3:0] y1, y2, y3, y4, y5);
always @
begin
y1 =
y2 =
y3 =
y4 =
y5 =
end
(*)
a &
a |
a ^
~(a
~(a
//
//
b;
//
b;
//
b;
//
& b); //
| b); //
need begin/end because there is
more than one statement in always
AND
OR
XOR
NAND
NOR
endmodule
This hardware could be described with assign statements using fewer
lines of code, so it’s better to use assign statements in this case.
11
Korea Univ
Combinational Logic using case
module sevenseg(input [3:0] data, output reg [6:0] segments);
always @(*)
begin
case (data)
//
abc_defg
0: segments = 7'b111_1110;
1: segments = 7'b011_0000;
2: segments = 7'b110_1101;
3: segments = 7'b111_1001;
4: segments = 7'b011_0011;
5: segments = 7'b101_1011;
6: segments = 7'b101_1111;
7: segments = 7'b111_0000;
8: segments = 7'b111_1111;
9: segments = 7'b111_1011;
default: segments <= 7'b000_0000; // required
endcase
end
endmodule
What kind of circuit would it generate?
12
Korea Univ
Combinational Logic using case
• In order for a case statement to imply combinational
logic, all possible input combinations must be
described by the HDL
 Remember to use a default statement when necessary,
that is, when all the possible combinations are not listed in
the body of the case statement
 Otherwise, what kind of circuit do you think the statement
would generate?
13
Korea Univ
Combinational Logic using casez
• The casez statement is used to describe truth
tables with don’t cares
 ‘don’t cares’ are indicated with ? in the casez statement
module priority_casez(input
[3:0] a,
output reg [3:0] y);
always @(*)
begin
casez(a)
4'b1???:
4'b01??:
4'b001?:
4'b0001:
default:
endcase
end
y
y
y
y
y
=
=
=
=
=
4'b1000;
4'b0100;
4'b0010;
4'b0001;
4'b0000;
// ? = don’t care
endmodule
14
Korea Univ
Priority Circuit Simulation
module priority_casez(input
[3:0] a,
output reg [3:0] y);
always @(*)
begin
casez(a)
4'b1???:
4'b01??:
4'b001?:
4'b0001:
default:
endcase
end
y
y
y
y
y
=
=
=
=
=
4'b1000;
4'b0100;
4'b0010;
4'b0001;
4'b0000;
`timescale 1ns / 1ns
module priority_casez_tb();
reg [3:0] a;
wire [3:0] y;
parameter clk_period = 10;
priority_casez
initial
begin
a =
a =
a =
a =
a =
a =
end
endmodule
4'b0110;
4'b1110;
4'b0101;
4'b0011;
4'b0001;
4'b0000;
dut(a, y);
#(clk_period*2);
#(clk_period*2);
#(clk_period*2);
#(clk_period*2);
#(clk_period*2);
#(clk_period*2);
endmodule
15
Korea Univ
Parameterized Modules
• HDLs permit variable bit widths using parameterized
modules
 So far, all of our modules have had fixed-width inputs and outputs
 Verilog allows a #(parameter …)statement to define parameters
before the inputs and outputs
module mux2
#(parameter width = 8) // name and default value
(input [width-1:0] d0, d1,
input
s,
output [width-1:0] y);
assign y = s ? d1 : d0;
endmodule
Instance with 8-bit bus width (uses default):
mux2 mux1(d0, d1, s, out);
Instance with 12-bit bus width:
mux2 #(12) lowmux(d0, d1, s, out);
16
Korea Univ
Blocking and Nonblocking Statements
• In the always statement,
 = indicates blocking statement
 <= indicates nonblocking statement
• Blocking statements are evaluated in the order in which
they appear in the code
 Like one would expect in a standard programming language
such as C language
• Nonblocking statements are evaluated concurrently
 All of the statements are evaluated concurrently before any of
the signals on the left hand sides are updated
17
Korea Univ
Blocking vs Nonblocking Example
• What kinds of circuit would be generated?
module sync_nonblocking
(input
clk,
input
d,
output reg q);
module sync_blocking
(input
clk,
input
d,
output reg q);
reg n1;
reg n1;
always @(posedge clk)
begin
n1 <= d; // nonblocking
q <= n1; // nonblocking
end
always @(posedge clk)
begin
n1 = d; // blocking
q = n1; // blocking
end
endmodule
endmodule
18
Korea Univ
Blocking vs Nonblocking Example
1-bit full adder
S = A + B + Cin
Cout = AB + ACin + BCin
Let P = A + B
Let G = AB
S = P + Cin
Cout = AB + (A + B)Cin = G + PCin
19
Korea Univ
Full Adder with Blocking Statements
module fulladder(input
a, b, cin,
output reg s, cout);
reg p, g;
always @(*)
begin
p = a ^ b;
g = a & b;
// blocking
// blocking
s = p ^ cin; // blocking
cout = g | (p & cin); // blocking
end
endmodule
• Like a high-level language, the blocking statements are evaluated
in the order they appear in the body of the module
 Suppose that all the inputs and internal nodes are initially 0
 At some time later, a changes to 1
1.
2.
3.
4.
p ← 1^0 =1
g ← 1•0 =0
s ← 1^0 =1
cout ← 0 + 1 • 0 = 0
20
Korea Univ
Full Adder with Nonblocking Statements
module fulladder(input
a, b, cin,
output reg s, cout);
reg p, g;
always @(*)
begin
p <= a ^ b;
g <= a & b;
// nonblocking
// nonblocking
s <= p ^ cin;
// nonblocking
cout <= g | (p & cin); // nonblocking
end
endmodule
• Nonblocking statements are evaluated concurrently
 Suppose that all the inputs and internal nodes are initially 0
 At some time later, a changes to 1
1.
2.
•
•
p ← 1 ^ 0 = 1, g ← 1 • 0 = 0,
p ← 1 ^ 0 = 1, g ← 1 • 0 = 0,
s ← 0 ^ 0 = 0, cout ← 0 + 0 • 0 = 0
s ← 1 ^ 0 = 1, cout ← 0 + 1 • 0 = 0
It makes simulation slow though it synthesizes to the same hardware
Also kind of hard to figure out what the circuit is doing… This kinds of coding should be
avoided
21
Korea Univ
Blocking and Nonblocking Recap
• Some statements implies (generates) completely
different logic as shown in the flip-flop case
• Some statements implies (generates) the same logic
no matter which statement you use as we have
seen in the full-adder case
 But, it affects the simulation time
• So, choose wisely which statement you have to use
22
Korea Univ
Rules for Signal Assignment
• Use always @(posedge clk) and nonblocking assignments to
model synchronous sequential logic
always @(posedge clk)
q <= d; // nonblocking statement
• Use continuous assignment statements to model simple
combinational logic
assign y = a & b;
• Use always @(*) and blocking assignments to model more
complicated combinational logic where the always statement is
helpful
• Do not make assignments to the same signal in more than one
always statement or continuous assignment statement
23
Korea Univ
FSM Revisit
• Synchronous sequential circuit can be drawn like below
 These are called FSMs
 Super-important in digital circuit design and very straightforward to
understand
• FSM is composed of
 State register
 Combinational logic that
• Computes the next state based on current state and input
• Computes the outputs based on current state (and input)
Moore FSM
inputs
M
next
state
logic
k
next
state
CLK
k
state
output
logic
N
outputs
Mealy FSM
inputs
M
next
state
logic
k
CLK
k state
next
state
24
output
logic
N
outputs
Korea Univ
Traffic Light Revisit
• A simplified traffic light controller
 Traffic sensors: TA, TB
• Each sensor becomes TRUE if students are present
• Each sensor becomes FALSE if the street is empty
 Lights: LA, LB
• Each light receives digital inputs specifying whether it should be green,
yellow, or red
TA
Reset
Bravado
LA
Academic
Labs
TB
TA
Dining
Hall
LB
TA
S1
LA: yellow
LB: red
LA
TA
TB
S0
LA: green
LB: red
LB
Ave.
Dorms
Blvd.
S3
LA: red
LB: yellow
Fields
S2
LA: red
LB: green
TB
TB
25
Korea Univ
Moore FSM in Verilog
TA
Reset
TA
S0
LA: green
LB: red
S3
LA: red
LB: yellow
// next state logic
always @ (*)
case (state)
S0: if (~TA) nextstate
else
nextstate
S1: nextstate <= S2;
S2: if (~TB) nextstate
else
nextstate
S3:
nextstate
default:
nextstate
endcase
S1
LA: yellow
LB: red
S2
LA: red
LB: green
TB
module moore_traffic_light
(input
clk, reset, TA, TB,
output reg [1:0] LA, LB);
[1:0] state, nextstate;
parameter
parameter
parameter
parameter
S0
S1
S2
S3
=
=
=
=
<=
<=
<=
<=
S3;
S2;
S0;
S0;
// output logic
always @ (*)
if (state == S0) begin
LA = green;
LB = red;
end
else if (state == S1) begin
LA = yellow;
LB = red;
end
else if (state == S2) begin
LA = red;
LB = green;
end
else begin
LA = red;
LB = yellow;
end
TB
reg
<= S1;
<= S0;
2’b00;
2’b01;
2’b10;
2’b11;
parameter green = 2’b00;
parameter yellow = 2’b01;
parameter red
= 2’b10;
// state register
always @ (posedge clk, posedge reset)
if (reset) state <= S0;
else
state <= nextstate;
endmodule
26
Korea Univ
Testbench for Traffic Light FSM
`timescale
1ns/1ps
always
begin
clk = 1;
forever #(clk_period/2) clk = ~clk;
end
module moore_traffic_light_tb();
reg clk, reset;
reg TA, TB;
wire [1:0] LA, LB;
initial
begin
TA =
TA =
TA =
TA =
TA =
TA =
end
parameter clk_period = 10;
moore_traffic_light dut(.clk
(clk),
.reset (reset),
.TA
(TA),
.TB
(TB),
.LA
(LA),
.LB
(LB) );
0;
0;
1;
0;
0;
1;
TB
TB
TB
TB
TB
TB
=
=
=
=
=
=
0;
0;
1;
1;
0;
0;
#3
#(clk_period)
#(clk_period*5)
#(clk_period*4)
#(clk_period*4)
endmodule
initial
begin
reset = 1;
#13
reset = 0;
end
27
Korea Univ
Simulation with ModelSim
• Useful tips in using ModelSim
 To display state information as described in Verilog code
• Format: radix define name { …. }
• Example: radix define mystate {2’b00 “S0” , 2’b01 “S1” , 2’b10 “S2” , 2’b11 “S3”}
•
radix define mylight {2'b00 "green“ , 2'b01 "yellow“ , 2'b10 "red"}
 Save the display information for the use in the future
• File->Save Format, Then click on “OK”
• By default, it will save the waveform format to “wave.do”
28
Korea Univ
Snail FSM Revisit
• There is a snail
 The snail crawls down a paper tape with 1’s and 0’s on it
 The snail smiles whenever the last four digits it has crawled over
are 1101
Moore FSM: arcs indicate input
reset
0
1
S0
0
1
1
S1
0
0
0
S2
0
1
1
S3
0
S4
1
0
0
Mealy FSM: arcs indicate input/output
reset
1/0
1/0
S1
S0
0/0
0/0
1/1
0/0
S2
1/0
29
S3
0/0
Korea Univ
Moore FSM in Verilog
Moore FSM: arcs indicate input
1
reset
1
0
S0
0
0
1
S1
0
1
0
S2
0
1
S3
0
S4
1
// Next State Logic
always @(*)
begin
case (state)
S0: if (bnum) #delay nextstate <= S1;
else
#delay nextstate <= S0;
S1: if (bnum) #delay nextstate <= S2;
else
#delay nextstate <= S0;
0
0
S2: if (bnum) #delay nextstate <= S2;
else
#delay nextstate <= S3;
module moore_snail(input clk, reset, bnum,
output reg smile);
S3: if (bnum) #delay nextstate <= S4;
else
#delay nextstate <= S0;
reg [2:0] state, nextstate;
parameter
parameter
parameter
parameter
parameter
S0
S1
S2
S3
S4
=
=
=
=
=
S4: if (bnum) #delay nextstate <= S2;
else
#delay nextstate <= S0;
3'b000;
3'b001;
3'b010;
3'b011;
3'b100;
parameter delay = 1;
// state register
always @(posedge reset, posedge clk)
begin
if (reset) #delay state <= S0;
else
#delay state <= nextstate;
end
default:
endcase
#delay nextstate <= S0;
end
// Output Logic
always @(*)
begin
if (state == S4) smile <= 1'b1 ;
else
smile <= 1'b0 ;
end
endmodule
30
Korea Univ
Mealy FSM in Verilog
// Next State and Output Logic
always @(*)
begin
case (state)
S0: begin
#delay smile <= 1'b0;
if (bnum) #delay nextstate <= S1;
else
#delay nextstate <= S0;
end
Mealy FSM: arcs indicate input/output
1/1
reset
1/0
1/0
S0
0/0
S1
0/0
0/0
S2
1/0
module mealy_snail(input
output reg
S3
S1: begin
#delay smile <= 1'b0;
if (bnum) #delay nextstate <= S2;
else
#delay nextstate <= S0;
end
0/0
S2: begin
#delay smile <= 1'b0;
if (bnum) #delay nextstate <= S2;
else
#delay nextstate <= S3;
end
clk, reset, bnum,
smile);
reg [1:0] state, nextstate;
parameter
parameter
parameter
parameter
S0
S1
S2
S3
=
=
=
=
2'b00;
2'b01;
2'b10;
2'b11;
S3: begin
if (bnum)
else
if (bnum)
else
end
parameter delay = 1;
// state register
always @(posedge reset, posedge clk)
begin
if (reset) #delay state <= S0;
else
#delay state <= nextstate;
#delay
#delay
#delay
#delay
smile <= 1'b1;
smile <= 1'b0;
nextstate <= S1;
nextstate <= S0;
default: begin
#delay smile <= 1'b0;
#delay nextstate <= S0;
end
endcase
end
end
endmodule
31
Korea Univ
Testbench for Snail FSM
initial
begin
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
bnum
end
`timescale 1ns/1ps
module fsm_snail_tb( );
reg clk, reset, bnum;
wire smile_moore;
wire smile_mealy;
parameter clk_period = 10;
moore_snail
moore_snail_uut
(clk, reset, bnum, smile_moore);
mealy_snail
mealy_snail_uut
(clk, reset, bnum, smile_mealy);
initial
begin
reset = 1;
#13
reset = 0;
end
=
=
=
=
=
=
=
=
=
=
=
=
=
=
0;
0;
1;
0;
0;
0;
1;
1;
0;
1;
1;
0;
1;
0;
#3;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
#clk_period;
// Smile
// Smile
endmodule
always
begin
clk = 1;
forever #(clk_period/2) clk = ~clk;
end
32
Korea Univ
Simulation with ModelSim
•
Use radices below for display purpose


radix define moore_state {3'b000 "S0” , 3'b001 "S1” , 3'b010 "S2” , 3'b011 "S3” ,
3'b100 "S4"}
radix define mealy_state {2'b00 "S0” , 2'b01 "S1” , 2'b10 "S2” , 2'b11 "S3"}
33
Korea Univ
Testbench and TestVector
• Testbench
 HDL code written to test another HDL module, the device
under test (dut) (also called the unit under test (uut))
 Testbench contains statements to apply input to the DUT
and ideally to check the correct outputs are produced
• Testvectors
 Inputs to DUT and desired output patterns from DUT
• Types of testbenches
 Simple testbench
 Self-checking testbench
 Self-checking testbench with testvectors
34
Korea Univ
Simple Testbench Revisit
testbench
module sillyfunction
(input a, b, c,
output y);
assign y = ~a & ~b & ~c |
a & ~b & ~c |
a & ~b & c;
endmodule
testvectors
`timescale
1ns/1ps
module testbench1();
reg a, b, c;
wire y;
// instantiate device under test
sillyfunction dut(a, b, c, y);
// apply inputs
initial begin
a = 0; b = 0;
c = 1; #10;
b = 1; c = 0;
c = 1; #10;
a = 1; b = 0;
c = 1; #10;
b = 1; c = 0;
c = 1; #10;
end
one at a time
c = 0; #10;
#10;
c = 0; #10;
#10;
endmodule
35
Korea Univ
Self-checking Testbench Revisit
module testbench2();
reg a, b, c;
wire y;
a = 1; b = 0; c = 0; #10;
if (y !== 1) $display("100
c = 1; #10;
if (y !== 1) $display("101
b = 1; c = 0; #10;
if (y !== 0) $display("110
c = 1; #10;
if (y !== 0) $display("111
end
// instantiate device under test
sillyfunction dut(a, b, c, y);
// apply inputs one at a time
// checking results
initial begin
a = 0; b = 0; c = 0; #10;
if (y !== 1) $display("000 failed.");
c = 1; #10;
if (y !== 0) $display("001 failed.");
b = 1; c = 0; #10;
if (y !== 0) $display("010 failed.");
c = 1; #10;
if (y !== 0) $display("011 failed.");
failed.");
failed.");
failed.");
failed.");
endmodule
testvectors
36
Korea Univ
Self-Checking Testbench with
Testvectors
•
Writing code for each test vector is tedious, especially
for modules that require a large number of vectors
•
A better approach is to place the test vectors in a
separate file
•
Then, testbench reads the file, applies input to DUT
and compares the DUT’s outputs with expected outputs
1.
2.
3.
4.
Generate clock for assigning inputs, reading outputs
Read testvectors file into array
Assign inputs and expected outputs to signals
Compare outputs to expected outputs and report errors if there
is discrepancy
37
Korea Univ
Testbench with Testvectors
•
Testbench clock is used to assign inputs (on the rising
edge) and compare outputs with expected outputs (on
the falling edge)
CLK
Assign
Inputs
•
Compare
Outputs to
Expected
The testbench clock may also be used as the clock
source for synchronous sequential circuits
38
Korea Univ
Testvector File Example
example.tv contains vectors of abc_yexpected
000_1
001_0
010_0
011_0
100_1
101_1
110_0
111_0
module sillyfunction(input a, b, c,
output y);
assign y =
~a & ~b & ~c |
a & ~b & ~c |
a & ~b & c;
endmodule
39
Korea Univ
Self-Checking Testbench with
Testvectors
1. Generate clock for assigning inputs, reading outputs
2. Read testvectors file into array
3. Assign inputs and expected outputs to signals
module testbench3();
reg
clk, reset;
reg
a, b, c, yexpected;
wire
y;
reg [31:0] vectornum, errors;
reg [3:0] testvectors[10000:0];
// array of testvectors
// instantiate device under test
sillyfunction dut(a, b, c, y);
// generate clock
always
begin
clk = 1; #5; clk = 0; #5;
end
// at start of test, load vectors
// and pulse reset
initial
begin
$readmemb("example.tv", testvectors);
vectornum = 0; errors = 0;
reset = 1;
#27;
reset = 0;
end
// Note: $readmemh reads testvector files written in
// hexadecimal
// apply test vectors on rising edge of clk
always @(posedge clk)
begin
#1; {a, b, c, yexpected} = testvectors[vectornum];
end
40
Korea Univ
Self-Checking Testbench with
Testvectors
4. Compare outputs to expected outputs and report errors
if there is discrepancy
// check results on falling edge of clk
always @(negedge clk)
begin
if (~reset)
begin // skip during reset
if (y !== yexpected) begin
$display("Error: inputs = %b“, {a, b, c});
$display(" outputs = %b (%b expected)“, y, yexpected);
errors = errors + 1;
end
// increment array index and read next testvector
vectornum = vectornum + 1;
if (testvectors[vectornum] === 4'bx) begin
$display("%d tests completed with %d errors“, vectornum, errors);
$finish;
end
end
endmodule
// Note: “===“ and “!==“ can compare values that are x or z.
41
Korea Univ
HDL Summary
• HDLs are extremely important tools for modern
digital designers
 Once you have learned Verilog-HDL or VHDL, you will
be able to design digital systems much faster than
drawing schematics
 Debug cycle is also often much faster because
modifications require code changes instead of tedious
schematic rewriting
 However, the debug cycle can be much longer with
HDLs if you don’t have a good idea of the hardware
your code implies
42
Korea Univ
HDL Summary
• The most important thing to remember when you are
writing HDL code is that you are describing real
hardware! (not writing a software program)
• The most common beginner’s mistake is to write HDL
code without thinking about the hardware you intend to
produce
 If you don’t know what hardware your code is implying, you are
almost certain not to get what you want
 So, probably sketch a block diagram of your system
• Identify which portions are combinational logic, sequential logic, FSMs
and so on, so forth
• Write HDL code for each portion and then merge together
43
Korea Univ
Backup Slides
44
Korea Univ
N: 2N Decoder Example
module decoder
#(parameter
(input
output reg
N = 3)
[N-1:0]
a,
[2**N-1:0] y);
always @(*)
begin
y = 0;
y[a] = 1;
end
endmodule
45
Korea Univ
Download