Modeling Styles and Testbenching in Verilog HDL: Dr. Belgacem Ben Youssef

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 46

Modeling Styles and TestBenching in Verilog HDL

Dr. Belgacem Ben Youssef

1
Learning Objectives

1. Review modeling styles and design techniques used with


Verilog HDL: Behavioral, Structural, and Data Flow.

2. Introduce test-benching for simulation.

3. Present how to employ User-Defined Primitives (UDP) and


forever loops.

2
Modeling Styles in Verilog

 A module can be described in any one (or a


combination) of the following modeling techniques:

 Structural (or Gate-level) modeling using


instantiation of primitive gates and user defined
modules.
 This describes the circuit by specifying the gates and how they
are connected with each other.
 Dataflow modeling using continuous assignment
statements with the keyword assign
 This is mostly used for describing combinational circuits.
 Behavioral modeling using procedural assignment
statements with keyword always
 This is used to describe digital systems at a higher level of
abstraction (algorithmically).
In terms of Descriptions of Circuits

 Structural Description – This is directly equivalent to


the schematic of a circuit and is specifically oriented to
describing hardware structures using the components of
a circuit.
  Describes the module’s functionality from a
combination of simpler modules

 Dataflow Description – This describes a circuit in terms


of function rather than structure and is made up of
concurrent assignment statements or their equivalent.
Concurrent assignment statements are executed
concurrently, that is in parallel whenever one of the
values on the right hand side of the statement changes.
In terms of Descriptions of Circuits (2)

 Behavioral Description – This refers to a


description of a circuit at a level higher than the
logic level. This type of description is also referred
to as the register transfer(s) level (RTL).
  Expresses the module’s functionality descriptively and
algorithmically.

 Hierarchical Description – Descriptions, that


represent circuits using a hierarchy, have multiple
entities, one for each element of the hierarchy.
Module Instantiation (Call) Syntax
In structural modeling, we may use module instantiation
(module calls). Its syntax is as follows:

module_name instance_name(.port_name([expression])
{, .port_name([expression])});

 instance_name: Can be any legal Verilog identifier and the port


connections specify how the module is connected to the rest of
the circuit.
 The name of the module’s instance is different from the
module name.
  Can instantiate many times, but must use a different name
each time.
 port_name: specifies name of a port in the sub-circuit.
 expression: specifies a connection to that port.
 The .port_name is provided so that the order of signals can
be different from the one in the module statement.
Example of Structural Modeling
// Data Flow model for circuit given by:
// Y = A’B’C’ + A B’C’+ A B’C
module example(input a, b, c,
output y);
assign y = !a && !b && !c || a && !b && !c || a && !b && c;
endmodule

We can obtain a structural model


of Y by employing a number of module example_structure(input a, b, c, output y);

user defined modules: wire inv_a, inv_b, inv_c;


module myinv(input a, output y); wire and3_0, and3_1, and3_2;
assign y = !a ;
myinv inva (.a (a), .y (inv_a));
endmodule
myinv invb (.a (b), .y (inv_b));
myinv invc (.a (c), .y (inv_c));
module myand3(input a, b, c, output y);
assign y = a && b && c;
myand3 and3_y0 (.a (inv_a), .b (inv_b), .c (inv_c), .y (and3_0));
endmodule myand3 and3_y1 (.a (a), .b (inv_b), .c (inv_c), .y (and3_1));
myand3 and3_y2 (.a (a), .b (inv_b), .c (c), .y (and3_2));
module myor3(input a, b, c, output y);
assign y = a || b || c; myor3 or3_y (.a (and3_0), .b (and3_1), .c (and3_2), .y (y));
endmodule
endmodule
More on Previous Example
 The equivalent code for previous example using behavioral
modeling:
// Behavioral model
module example(input a, b, c,
output reg y);
always @(a, b, c) begin
y = !a && !b && !c || a && !b && !c || a && !b && c;
end
endmodule
 In module instantiation statements, we can either use:
1. Ordered port connections, as in:
myand3 and3_y0 (inv_a, inv_b, inv_c, and3_0);
2. Named port connections, as in:
myand3 and3_y0 (.a (inv_a), .b (inv_b), .c (inv_c), .y (and3_0));
OR
myand3 and3_y0 (.b (inv_b), .c (inv_c), .y (and3_0), . a(inv_a));
 changing the order of port names is only permitted in named
port connections.
Structural Modeling – cont.
 Another Example: Given the full adder module (fulladd()) on
the bottom left, we can use it to structurally model a 4-bit
ripple-carry adder by using 4 instances of the fulladd() module
(or sub-circuit).
 The adder4 module instantiates 4 copies of the full adder. In
the first 3 instantiation statements, we used ordered port
connections because the signals are listed in the same order
as given in the declaration of the fulladd() module.
 The last instantiation statement gives an example of named
port connections module adder4 (carryin, X, Y, S, carryout);
(using the .port_name). input carryin;
input [3:0] X, Y;
output [3:0] S;
module fulladd (Cin, x, y, s, Cout); output carryout;
input Cin, x, y; wire [3:1] C;
output s, Cout;  
  fulladd stage0 (carryin, X[0], Y[0], S[0], C[1]);
assign s = x ^ y ^ Cin; fulladd stage1 (C[1], X[1], Y[1], S[1], C[2]);
assign Cout = (x && y) || fulladd stage2 (C[2], X[2], Y[2], S[2], C[3]);
(Cin && x) || (Cin && y); fulladd stage3 (.Cout(carryout), .s(S[3]), .y(Y[3]), .x(X[3]), .Cin(C[3]));
endmodule  
endmodule
Design Methodologies in Modeling

 As we’ve seen, two or more modules can be combined to build a


hierarchical description of a design.

 There are two basic types of design methodologies:

 Top down: In top-down design, the top level block is defined and then sub-blocks
necessary to build the top level block are identified.
 Bottom up: Here the building blocks are first identified and then combined to build the
top level block.

 In a top-down design example, a 4-bit binary adder is defined as


top-level block with 4 full adder blocks. Then, we describe two half-adders
that are required to create the full adder.

 In a bottom-up design example, the half-adder is defined, then the


full adder is constructed and the 4-bit adder is built from the full adders.
Design Methodologies - Example

 A bottom-up hierarchical description of a 4-


bit adder is described in Verilog as follows:
 Half Adder: defined by instantiating primitive
gates.
 Then, define the Full Adder by instantiating two
half-adders.
 Finally, the third module describes the 4-Bit
Adder by instantiating 4 full adders.
 ie, using 4 instances of the full adder.
 Note: In Verilog, one module definition
cannot be placed within another module
description.
4-Bit Adder – The Half Adder
4-Bit Adder – cont.
4-Bit Adder – cont.
//Gate-level hierarchical description of 4-bit adder
module halfadder (S,C,x,y);
input x,y;
output S,C;
//Instantiate primitive gates
xor g1(S,x,y);
and g2(C,x,y);
endmodule

module fulladder (S,C,x,y,z);


input x,y,z;
output S,C;
wire S1,D1,D2; //Outputs of first XOR and two AND gates
//Instantiate the half adders
halfadder HA1(S1,D1,x,y), HA2(S,D2,S1,z);
or g1(C,D2,D1);
endmodule
4-Bit Adder – cont.

module _4bit_adder (S,C4,A,B,C0);


input [3:0] A,B;
input C0;
output [3:0] S;
output C4;
wire C1,C2,C3; //Intermediate carries

//Instantiate the full adder


fulladder FA0 (S[0],C1,A[0],B[0],C0),
FA1 (S[1],C2,A[1],B[1],C1),
FA2 (S[2],C3,A[2],B[2],C2),
FA3 (S[3],C4,A[3],B[3],C3);
endmodule
Tri-State Buffers

 Tri-state buffers, also known as three-state gates have a


control input that can place the gate into a high-impedance
state. (symbolized by z in Verilog HDL).
 The bufif1 gate behaves like a normal buffer if control=1.
The output goes to a high-impedance state z when control=0.
 bufif0 gate behaves in a similar way except that the high-
impedance state occurs when control=1
 Two not gates operate in a similar manner except that the
output is the complement of the input, when the gate is not in
a high impedance state (notif1 and notif0).
 The gates are instantiated with the statement:

gate_type name (output, input, control);


Tri-State Buffers (Three-State Gates) in
Verilog
Tri-State Buffers (Three-State Gates) in
Verilog

bufif1 notif1 bufif0 notif0


Verilog Example

NOTE:
1. The output of 3-state
gates can be connected
together to form a
common output line. To
identify such connections,
module muxtri(A,B,select,out);
Verilog HDL uses the
input A,B,select;
keyword tri (for tri-state)
output OUT;
to indicate that the output
tri OUT;
has multiple drivers.
bufif1 g1(OUT,A,select);
2. The above circuit bufif0 g2(OUT,B,select);
represents a 2-to-1 endmodule
multiplexer (see the code
on the right).
Logic Simulation

 A simulator interprets the HDL description and produces a


readable output, such as a timing diagram, that predicts how
the hardware will behave before its is actually fabricated.
 Simulation allows the detection of functional errors in a
design without having to physically create the circuit.
 The stimulus that tests the functionality of the design is
called a testbench.

 To simulate a digital system:


 Design is first described/modeled in Verilog HDL.
 Then, verified by simulating the design and checking it with
a testbench, which is also written in Verilog HDL.
Logic Simulation

 Logic simulation is a
fast, accurate
method of analyzing
a circuit to see and
evaluate its
waveforms.
Gate Delays in Verilog

 Sometimes it is necessary to specify the amount of delay


from the input to the output of gates.

 In Verilog, the delay is specified in terms of time units and


the symbol #.

 The association of a time unit with physical time is made


using timescale compiler directive.
 Compiler directive starts with the backquote (`) symbol.
`timescale 1ns/100ps

 The first number specifies the unit of measurement for


time delays (here 1 unit of time = 1 ns).
 The second number specifies the precision for which the
delays are rounded off, in this case to 0.1ns.
Example of Module with Gate Delays
//Description of circuit with delay
module circuit_with_delay
(A,B,C,x,y);
input A,B,C;
output x,y;
wire e;
and #(30) g1(e,A,B);
not #(10) g2(y,C);
or #(20) g3(x,e,y);
endmodule
More on Gate Delays
 In Verilog, a designer can specify the gate delays in a gate
primitive instance.
 This helps the designer to get a real-time behavior of the
logic circuit.

 Rise delay: It is equal to the time taken by a gate output


transition to 1, from another value 0, x, or z.

 Fall delay: It is equal to the time taken by a gate output


transition to 0, from another value 1, x, or z.

 Turn-off delay: It is equal to the time taken by a gate output


transition to high impedance state, from another value 1, x,
or z.
More on Gate Delays - Rules
 If only one delay value is specified, it is used for all delays.
 If two values are specified, they are considered as rise, and
fall delays. The turn-off delay is equal to the minimum of these
two values.
 If three values are specified, they are considered as rise, fall,
and turn-off delays, respectively.
 The default value of all delays is zero.

and #(5) and_1 (out, in0, in1);
// All delay values are 5 time units.

nand #(3,4,5) nand_1 (out, in0, in1);


// rise delay = 3, fall delay = 4, and turn-off delay = 5.

or #(3,4) or_1 (out, in0, in1);


// rise delay = 3, fall delay = 4, and turn-off delay = min(3,4) = 3.
TestBenching in Verilog
 In order to simulate a circuit modeled in Verilog HDL, it is
necessary to apply inputs to the circuit in order for the
simulator to generate an output response.

 A Verilog HDL description (code) that provides the stimulus


to a design is called a testbench.
 An initial statement that specifies inputs between the
keywords begin and end is part of this code.
 In next example, initially ABC = 000 (A,B and C are each set to
1’b0 (ie, one binary digit with a value 0).
 $finish is a system task call used to end the simulation.
 In your testbench, declare reg variable for each input port, and
wire for each output port.
 Notice the presence of the delay symbol # in the testbench  this is
used as Delay control ≡ number of time units to delay a
statement‘s execution relative to the previous statement.
Example Model with its Testbench
// Testbench for a simple circuit
module circuit_with_delay module stimcrct;
(A,B,C,x,y);
reg A,B,C;
input A,B,C; wire x,y;
output x,y;
wire e; circuit_with_delay cwd(A,B,C,x,y);

and #(30) g1(e,A,B); initial


not #(10) g2(y,C); begin
or #(20) g3(x,e,y); A = 1'b0; B = 1'b0; C = 1'b0;
#100
A = 1'b1; B = 1'b1; C = 1'b1;
endmodule #100 $finish;
end
endmodule
Another Example of a Testbench

 Code to model AND gate: These inputs are desired:

`timescale 1 ns/1 ns 1
X
0
module And2(X, Y, F);
1
Y
input X, Y; 0
output F; time
reg F;
10 20 30 (ns)

always @(X, Y) begin


F = X && Y; 1
end F
Expected output 
0
endmodule
Testbench

 Idea: Create a new "Testbench" module that provides test


vectors to the component's inputs.

Testbench
X_s
procedure

X CompToTest
Y_s F_s
Y (And2) F

Steps and Characteristics of a testbench module include:

 Module with no ports.


 Declare reg variable for each input port, wire for each output
port.
 Instantiate (by calling) module, map variables to ports.
 Set variable values at desired times, using initial statement.
Testbench - 2

 `timescale – compiler directive telling compiler that from this point


forward, 1 time unit means 1 ns
 # – Delay control: `timescale 1 ns/1 ns
number of time units
module Testbench();
to delay this statement's
execution relative to reg X_s, Y_s;
previous statement. wire F_s;

And2 CompToTest(X_s, Y_s, F_s);


 Valid time units in Verilog:
s (seconds), initial begin
ms (milliseconds), // Test all possible input combinations
us (microseconds),
ns (nanoseconds), ps (picoseconds), Y_s = 0; X_s = 0;
and fs (femtoseconds) #10 Y_s = 0; X_s = 1;
#10 Y_s = 1; X_s = 0;
#10 Y_s = 1; X_s = 1;
#10 $finish;
end

endmodule
Testbench - 3

 After providing the testbench code to the simulator:


 Simulator generates waveforms
  We can then check to see if behavior of the model is correct.
 Output of simulator:

1
X_s
0
1
Y_s
0
1
F_s
0
time
10 20 30 (ns)
Component Instantiations – Combinational
Circuits
X
F X F
 Circuit – A connection of modules Y
 Also known as structure.
 A circuit is a second way to describe a Modules to be used
module.
Module instances
 Instance – An occurrence of a module
in a circuit:
K
 May be multiple instances of a P And2_1 N1
W
module. N2 And2_2
S
 e.g., A Car's modules: tires, Inv_1
engine, windows, etc., with 4 tire BeltWarn
instances, 1 engine instance, 6
window instances, etc.

32
Module Instantiations – Combinational Circuits
 Creating a circuit:
1. Start definition of a new module `timescale 1 ns/1 ns

2. Declare nets for connecting module module BeltWarn(K, P, S, W);


instances:
input K, P, S;
 N1, N2 output W;
 Note: W is also declared as a
net. By defaults outputs are wire N1, N2;

considered wire nets unless And2 And2_1(K, P, N1);


explicitly declared as a reg Inv Inv_1(S, N2);
variable. And2 And2_2(N1, N2, W);

3. Create module instances, create endmodule


connections.
x F
X
F X F
Y K
P And2_1 N1
W module Inv(X, F);
N2 And2_2
“BeltWarn” example: Turn input X;
S
on warning light (w=1) if car Inv_1
output F;
reg F;
key is in ignition (k=1), BeltWarn
person is seated (p=1), and always @(X) begin
F = !X;
seatbelt is not fastened (s=0) end
33
endmodule
Module Instantiations

`timescale 1 ns/1 ns
 Module instantiation module BeltWarn(K, P, S, W);
Statement: input K, P, S;
And2 And2_1(K, P, N1); output W;

Note: Ports ordered wire N1, N2;


as in original And2
module definition And2 And2_1(K, P, N1);
Inv Inv_1(S, N2);
Connects instantiated module's And2 And2_2(N1, N2, W);

ports to nets and variables endmodule

Name of new module instance And2_1


K And2_2
Must be distinct; hence And2_1 and And2_2 N1
P W
Name of module to instantiate N2
S

Inv_1 BeltWarn

34
Module Instantiations
 Example: How to complete
a 2x1 mux circuit's module `timescale 1 ns/1 ns
instantiations: Mux2 module Mux2(I1, I0, S0, D);
I0
D input I1, I0;
1. Start definition of a new I1 input S0;
S0 output D;
module (done)
wire N1, N2, N3;
(Draw desired circuit,
And2_1
if not already done) N2 Or2_1 Inv Inv_1 (S0, N1);
I0
And2 And2_1 (I0, N1, N2);
2. Declare nets N1 D And2 And2_2 (I1, S0, N3);
N3
for internal wires I1 Or2 Or2_1 (N2, N3, D);

And2_2 endmodule
3. Create module
Inv_1
instances and connect S0
ports

35
Simulating the Circuit

 Same testbench format for BeltWarn


module as for earlier And2 module
`timescale 1 ns/1 ns
Testbench
module Testbench();
X_s
procedure

XCompToTest reg K_s, P_s, S_s;


Y_s F_s wire W_s;
Y(And2) F
BeltWarn CompToTest(K_s, P_s, S_s, W_s);

initial begin
K_s = 0; P_s = 0; S_s = 0;
Testbench #10 K_s = 0; P_s = 1; S_s = 0;
#10 K_s = 1; P_s = 1; S_s = 0;
K_s #10 K_s = 1; P_s = 1; S_s = 1;
K
procedure

P_s CompToTest W_s


#10 $finish;
P (BeltWarn) W end
S_s S endmodule

“BeltWarn” example: Turn on


K BeltWarn warning light (w=1) if car key
P W is in ignition (k=1), person is
S seated (p=1), and seatbelt is
36
not fastened (s=0)
Simulating the Circuit

`timescale 1 ns/1 ns
 Simulate testbench file to
obtain waveforms module Testbench();

reg K_s, P_s, S_s;


wire W_s;

1 BeltWarn CompToTest(K_s, P_s, S_s, W_s);


K_s
0
initial begin
1 K_s = 0; P_s = 0; S_s = 0;
P_s
0 #10 K_s = 0; P_s = 1; S_s = 0;
#10 K_s = 1; P_s = 1; S_s = 0;
1 nTB
.v
S_s #10 K_s = 1; P_s = 1; S_s = 1;
0 #10 finish;
War

end
1
Belt

W_s
0 endmodule

10 20 30time (ns)
Simulator

37
User Defined Primitives (UDP)

User Defined Primitives (UDP):


 The logic gates (ie, the built-in gate primitives) used in
Verilog HDL descriptions with keywords and, or, xor, etc., are
defined by the system and are referred to as system
primitives.
 That’s why we call them built-in primitives.

 In addition to those built-in gate primitives:

 The user can create additional primitives by defining


them in tabular form.

 These type of circuits are referred to as user-defined


primitives.
User Defined Primitives - 2

Features of User Defined Primitives (UDPs):


 UDPs do not use the keyword module. Instead they are
declared with the keyword primitive.
 There can be only one output and it must be listed first in the
port list and declared with an output keyword.
 There can be any number of inputs. The order in which they are
listed in the input declaration must conform to the order in
which they are given values in the truth table that follows.
 The truth table is enclosed within the keywords table and
endtable.
 The values of the inputs are listed in order with a colon at end
of list (:).
 The output is always the last entry in a row followed by a
semicolon (;).
 The UDP ends with the keyword endprimitive.
Example of a User Defined Primitive
// Verilog HDL Code to define a User Defined Primitive (UDP)
primitive crctp (x,A,B,C);
output x;
input A,B,C;
// Truth table for x(A,B,C) = sum of minterms (0,2,4,6,7)

table
/* A B C : x (Note that this is only a
comment) */
0 0 0 : 1;
0 0 1 : 0;
0 1 0 : 1;
0 1 1 : 0;
1 0 0 : 1;
1 0 1 : 0;
1 1 0 : 1;
1 1 1 : 1;
endtable
endprimitive
Calling a User Defined Primitive

 How to call and use a UDP: // Instantiate primitive


module declare_crctp;
reg x,y,z;
wire w;
crctp inst1(w,x,y,z);
endmodule

 Disadvantages of UDPs:
 Only 1 output is allowed.
 Difficult to write correctly when the number of inputs
becomes large (in case of large truth table).
Data Formats - User Defined
Primitives
 One way to help with large truth tables.
 Shorthand symbols for signal values/levels are available so that
UDP tables can be written in a concise manner.

Symbols Meaning Explanation


? 0, 1, x Cannot be specified in an
output field
b 0, 1 Cannot be specified in an
output field
- No change in state value Can be specified only in
output field of a sequential
UDP
* (??) Any value change in the
signal
Example

 The following example defines the logical OR operation using


a UDP.
primitive udp_or(out, a, b);
output out;
input a, b;
table
// a b : out
0 0 : 0;
1 ? : 1; //? Expanded to 0, 1, x
? 1 : 1; //? Expanded to 0, 1, x
0 x : x;
x 0 : x;
endtable
endprimitive
Forever Loop in Verilog
 The keyword forever in Verilog creates a block of code that will
run continuously. This is similar to a while loop with an
expression that evaluates to true; e,g., while (1).
 forever loops should not be used in synthesizable code.
 They are intended for use in simulation testbenches only.
 The forever statement is used in initial blocks.

module forever_example ();


   reg r_Clock;
   initial
     begin
r_Clock = 1'b0;
       forever
         #10 r_Clock = !r_Clock;
      end
   endmodule
 Example can be used for clock generation.
Another Example of Forever Loop

 Example 2: Create a clk_gen Verilog HDL module, which


generates a clock signal that initially goes to zero for 15 ns,
afterwards goes to one for 5 ns, and then repeats this pattern
indefinitely.

module clk_gen ();


   reg clock;
   initial
     begin
clock = 1'b0;
       forever begin
         #15 clock = 1’b1;
#5 clock = 1’b0;
     end
end
   endmodule
Summary

 In this unit, we covered the following topics:

 Modeling styles in Verilog and their relationship to different


design approaches of digital circuits.

 Testbenching to produce simulation of modeled circuits.

 User defined primitives and forever loops in Verilog.

You might also like