Verilog HDL Module3
Verilog HDL Module3
MODULE – 3
Gate-Level Modeling: Modeling using basic Verilog gate primitives, description of and/or and
buf/not type gates, rise, fall and turn-off delays, min, max, and typical delays.
Dataflow Modeling: Continuous assignments, delay specification, expressions, operators,
operands, operator types.
3.1 Gate Types
A logic circuit can be designed by use of logic gates. Verilog supports basic logic gates as
predefined primitives. These primitives are instantiated like modules except that they are
predefined in Verilog and do not need a module definition. All logic circuits can be designed
by using basic gates. There are two classes of basic gates: and/or gates and buf/not gates.
3.1.1 And /Or Gates
And/or gates have one scalar output and multiple scalar inputs. The first terminal in the list
of gate terminals is an output and the other terminals are inputs. The output of a gate is
evaluated as soon as one of the inputs changes. The and/or gates available in Verilog are:
and, or, xor, nand, nor, xnor.
The corresponding logic symbols for these gates are shown in Figure 3.1. Consider the
gates with two inputs. The output terminal is denoted by out. Input terminals are denoted
by i1 and i2.
instantiate hundreds of gates without giving them a name. More than two inputs can be
specified in a gate instantiation. Gates with more than two inputs are instantiated by
simply adding more input ports in the gate instantiation. Verilog automatically
instantiates the appropriate gate.
Example 3.1: Gate Instantiation of And/Or Gates
wire OUT, IN1, IN2;
// basic gate instantiations.
and a1(OUT, IN1, IN2);
nand na1(OUT, IN1, IN2);
or or1(OUT, IN1, IN2);
nor nor1(OUT, IN1, IN2);
xor x1(OUT, IN1, IN2);
xnor nx1(OUT, IN1, IN2);
// More than two inputs;
nand na1_3inp(OUT, IN1, IN2, IN3);
// gate instantiation without instance name
and (OUT, IN1, IN2); // legal gate instantiation
Table 3.1: Truth tables for And/0r gates.
The truth tables for these gates define how outputs for the gates are computed from
the inputs. Truth tables are defined assuming two inputs. The truth tables for these gates
are shown in Table 3.1. Outputs of gates with more than two inputs are computed by
applying the truth table iteratively.
3.1.2 Buf/Not Gates
Buf/not gates have one scalar input and one or more scalar outputs. The last terminal in
the port list is connected to the input. Other terminals are connected to the outputs. We will
discuss gates that have one input and one output. Two basic buf/not gate primitives are
provided in Verilog: buf not
The symbols for these logic gates are shown in Figure 3.2.
Bufif/notif
Gates with an additional control signal on buf and not gates are also available.
bufif1 notif1 bufif0 notif0
These gates propagate only if their control signal is asserted. They propagate z if their control
signal is deasserted. Symbols for bufif/notif are shown in Figure 3.3.
These gates are used when a signal is to be driven only when the control signal is asserted.
Such a situation is applicable when multiple drivers drive the signal. These drivers are
designed to drive the signal on mutually exclusive control signals. Example 3-3 shows
examples of instantiation of bufif and notif gates.
Example 3.3: Gate instantiation of bufif / notif gates
//Instantiation of bufif gates.
bufif1 b1 (out, in, ctrl);
bufif0 b0 (out, in, ctrl);
//Instantiation of notif gates
notif1 n1 (out, in, ctrl);
notif0 n0 (out, in, ctrl);
3.1.3 Array of Instances
There are many situations when repetitive instances are required. These instances differ
from each other only by the index of the vector to which they are connected. To simplify
specification of such instances, Verilog HDL allows an array of primitive instances to be
defined. Example3.4 shows an example of an array of instances.
Example 3.4: Simple Array of Primitive Instances
wire [7:0] OUT, IN1, IN2;
// basic gate instantiations. nand n_gate[7:0](OUT, IN1, IN2);
// This is equivalent to the following 8 instantiations
nand n_gate0(OUT[0], IN1[0], IN2[0]);
nand n_gate1(OUT[1], IN1[1], IN2[1]);
nand n_gate2(OUT[2], IN1[2], IN2[2]);
nand n_gate3(OUT[3], IN1[3], IN2[3]);
nand n_gate4(OUT[4], IN1[4], IN2[4]);
nand n_gate4(OUT[4], IN1[4], IN2[4]);
nand n_gate4(OUT[5], IN1[5], IN2[5]);
nand n_gate4(OUT[6], IN1[6], IN2[6]);
nand n_gate4(OUT[7], IN1[7], IN2[7]);
3.1.4 Examples
Gate-level multiplexer: Design of 4-to-1 multiplexer with 2 select signals. The I/O diagram
and the truth table for the multiplexer are shown in Figure 3.4.
S1 = 0; S0 = 1;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
// choose IN2
S1 = 1; S0 = 0;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
// choose IN3 S1 = 1; S0 = 1;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
end
endmodule
4-bit Ripple Carry Full Adder
Design of a 4-bit full adder: The basic building block is a 1-bit full adder. The logic diagram
for a 1-bit full adder is shown in Figure 3.6.
Fall delay
The fall delay is associated with a gate output transition to a 0 from another value.
Turn-off delay
The turn-off delay is associated with a gate output transition to the high impedance value
(z) from another value. If the value changes to x, the minimum of the three delays is
considered.
Three types of delay specifications are allowed. If only one delay is specified, this value
is used for all transitions. If two delays are specified, they refer to the rise and fall delay
values. The turn-off delay is the minimum of the two delays. If all three delays are specified,
they refer to rise, fall, and turn-off delay values. If no delays are specified, the default value
is zero. Examples of delay specification are shown in Example 3.10.
Example 3.10: Types of Delay Specification:
// Delay of delay_time for all transitions
and #(delay_time) a1(out, i1, i2);
// Rise and Fall Delay Specification.
and #(rise_val, fall_val) a2(out, i1, i2);
// Rise, Fall, and Turn-off Delay Specification
bufif0 #(rise_val, fall_val, turnoff_val) b1 (out, in, control);
Examples of delay specification:
and #(5) a1(out, i1, i2); //Delay of 5 for all transitions
and #(4,6) a2(out, i1, i2); // Rise = 4, Fall = 6
bufif0 #(3,4,5) b1 (out, in, control); // Rise = 3, Fall = 4, Turn-off= 5
Min/Typ/Max Values
Verilog provides an additional level of control for each type of delay mentioned above. For
each type of delay-rise, fall, and turn-off-three values, min, typ, and max, can be specified.
Any one value can be chosen at the start of the simulation. Min/typ/max values are used to
model devices whose delays vary within a minimum and maximum range because of the IC
fabrication process variations.
Min value
The min value is the minimum delay value that the designer expects the gate to have.
Typ val
The typ value is the typical delay value that the designer expects the gate to have.
Max value
The max value is the maximum delay value that the designer expects the gate to have.
Min, typ, or max values can be chosen at Verilog run time. Method of choosing a
min/typ/max value may vary for different simulators or operating systems. (For Verilog- XL,
the values are chosen by specifying options +maxdelays, +typdelays, and +mindelays at run
time. If no option is specified, the typical delay value is the default). This allows the designers
the flexibility of building three delay values for each transition into their design. The designer
can experiment with delay values without modifying the design.
Examples of min, typ, and max value specification for Verilog-XL are shown in Example3-11.
wire out;
assign out = in1 & in2;
//Same effect is achieved by an implicit continuous assignment
wire out = in1 & in2;
3.14.3 Implicit Net Declaration
If a signal name is used to the left of the continuous assignment, an implicit net declaration
will be inferred for that signal name. If the net is connected to a module port, the width of
the inferred net is equal to the width of the module port.
// Continuous assign. out is a net.
wire i1, i2;
assign out = i1 & i2; //Note that out was not declared as a wire but an implicit wire
// declaration for out is done by the simulator
3.5 Delays
Delay values control the time between the change in a right-hand-side operand and when the
new value is assigned to the left-hand side. Three ways of specifying delays in continuous
assignment statements are regular assignment delay, implicit continuous assignment delay,
and net declaration delay.
3.5.1 Regular Assignment Delay
The first method is to assign a delay value in a continuous assignment statement. The delay
value is specified after the keyword assign. Any change in values of in1 or in2 will result in a
delay of 10 time units before re-computation of the expression in1 & in2, and the result will
be assigned to out. If in1 or in2 changes value again before 10 time units when the result
propagates to out, the values of in1 and in2 at the time of re-computation are considered.
This property is called inertial delay. An input pulse that is shorter than the delay of the
assignment statement does not propagate to the output.
assign #10 out = in1 & in2; // Delay in a continuous assign
3.5.2 Implicit Continuous Assignment Delay
An equivalent method is to use an implicit continuous assignment to specify both a delay
and an assignment on the net.
//implicit continuous assignment delay
wire #10 out = in1 & in2; //
same as
wire out;
assign #10 out = in1 & in2;
The declaration above has the same effect as defining a wire out and declaring a continuous
assignment on out.
3.5.3 Net Declaration Delay
A delay can be specified on a net when it is declared without putting a continuous
assignment on the net. If a delay is specified on a net out, then any value change applied to
the net out is delayed accordingly. Net declaration delays can also be used in gate-level
modeling.
//Net Delays
wire # 10 out;
assign out = in1 & in2;
//The above statement has the same effect as the following:
wire out;
assign #10 out = in1 & in2;
3.6 Expressions, Operators, and Operands
Dataflow modeling describes the design in terms of expressions instead of primitive gates.
Expressions, operators, and operands form the basis of dataflow modeling.
3.6.1 Expressions
Expressions are constructs that combine operators and operands to produce a result.
// Examples of expressions. Combines operands and operators
a^b
addr1[20:17] + addr2[20:17]
in1 | in2
3.6.2 Operands
Operands can be any one of the data types defined, Data Types. Some constructs will take only
certain types of operands. Operands can be constants, integers, real numbers, nets, registers,
times, bit-select (one bit of vector net or a vector register), part-select (selected bits of the vector
net or register vector), and memories or function calls.
integer count, final_count;
final_count = count + 1;//count is an integer operand
real a, b, c;
+5 // Positive 5
Negative numbers are represented as 2's complement internally in Verilog. It is
advisable to use negative numbers only of the type integer or real in expressions. Designers
should avoid negative numbers of the type <sss>'<base> <nnn> in expressions because they
are converted to unsigned 2's complement numbers and hence yield unexpected results.
Examples:
//Advisable to use integer or real numbers
-10 / 5// Evaluates to 2
//Do not use numbers of type <sss> '<base> <nnn>
-'d10 / 5 // Is equivalent (2's complement of 10)/5 - (232 - 10)/5 // where 32 is the default
//machine word width. This evaluates to an incorrect and unexpected result.
3.7.2 Logical Operators
Logical operators are logical and (&&), logical-or (||) and logical-not (!). Operators && and ||
are binary operators. Operator ! is a unary operator. Logical operators follow these conditions:
1. Logical operators always evaluate to 1-bit value, 0 (false), 1 (true), or x(ambiguous).
2. If an operand is not equal to zero, it is equivalent to a logical 1 (true condition). If it is equal
to zero, it is equivalent to a logical 0 (false condition).If any operand bit is x or z, it is
equivalent to x (ambiguous condition) and as is normally treated by simulators as a false
condition.
3. Logical operators take variables or expressions as operands.
Use of parentheses to group logical operation is highly recommended to improve
readability. Also, the user does not have to remember the precedence of operators.
Examples:
1) A = 3, B=0;
A && B / Evaluates to 0. Equivalent to (logical -1 && logical-0)
A || B // Evaluates to 1. Equivalent to (logical -1 || logical-0)
!A // Evaluates to 0. Equivalent to not (logical -1)
!B // Evaluates to 1. Equivalent to not (logical -0)
2) A = 2’b0x, B = 2'b10;
A && B / Evaluates to x. Equivalent to (x && logical-1)
3) (a==2) && (b==3) // Evaluates to 1 if both a==2 and b==3 are true.
// Evaluates to 0 if either is false.
3.7.3 Relational Operators
22 Mohammed Saleem| Asst. Prof., Dept. of E & C, PACE
[email protected] [VERILOG HDL [18EC56]]
Relational operators are greater than (>), less than (<), greater than or equal (>=), and less
than or equal to (<=). If relational operators are used in an expression, the expression returns
a logical value of 1 if the expression is true and 0 if the expression is false. If there are any
unknown or z bits in the operands, the espresso takes a value x. These operators function
exactly as the corresponding operators in the C programming language.
Examples:
//A=4, B=3
// X = 4’b1010, Y = 4’b1101, Z = 4’b1xxx;
A <= B // Evaluates to a logical 0
A > B // Evaluate to a logical 1
Y >= X // Evaluates to a logical 1
Y < Z // Evaluates to an x
3.7.4 Equality Operators
Equality operators are logical equality (==), logical inequality (!=), case equality (===) and raw
inequality (!== ). When used in an expression, equality operators return logical value 1 if true,
0 if false. These operators compare the two operands bit by bit, with zero filling if the operands
are of unequal length. Table 3.5 lists the operators.
Table 3.5
Expression Description Possible logical value
a == b a equal to b, result unknown if x or z in a or b 0, 1, x
a != b a not equal to b, result unknown if x or z in a or b 0, 1, x
a === b a equal to b, including x and z 0, 1
a !== b a not equal to b, including x and z 0, 1
It is important to note the difference between the logical equality operators (==, !=) and case
equality operators (===, !==). The logical equality operators (==, !=) will yield an x if either
operand has x or z in its bits. However, the case equality operators (===, !==) compare both
operands bit by bit and compare all bits, including x and z. The result is 1 if the operands
match exactly, including x and z bits. The result is 0 if the operands do not match exactly.
Case equality operators never result in an x.
Examples:
// A = 4, B = 3
// X=4'b1010, Y = 4'bl101
23 Mohammed Saleem| Asst. Prof., Dept. of E & C, PACE
[email protected] [VERILOG HDL [18EC56]]
Examples:
// X = 4’b1010, Y = 4’b1101
// Z= 4’b10x1
~X // Negation. Result is 4’b0101
X&Y // Bitwise and. Result is 4'b1000
X | Y // Bitwise or Result is 4'b1111
X ^ Y // Bitwise xor. Result is 4'b0111
X ^~ Y // Bitwise xnor. Result is 4'b1000
X & Z // Result is 4’b10x0
It is important to distinguish bitwise operators ~, &, and | from logical operators !, &&,
||. Logical operators always yield s logical value 0, 1, x, whereas bitwise operators yield a
bit-by-bit value. Logical operators perform a logical operation, not a bit by bit operation.
// X = 4b1010, Y = 4’b0000;
X | Y / bitwise operation. Result is 4’b1010
X || Y / logical operation. Equivalent to 1 ||0. Result is 1.
3.7.6 Reduction Operators
Reduction operators are and (&), nand (~&), or (|), nor(~|), xor(^), and xnor(~^, ^~). Reduction
operators take only one operand. Reduction operators perform a bitwise operation on a single
vector operand and yield a 1-bit result. The difference is that bitwise operations are on bits
from two different operands, whereas reduction operations are on the bits of the same
operand. Reduction Operators work bit by bit from right to left. Reduction nand, reduction
nor, and reduction xnor are computed by inverting the result of the reduction and, reduction
or, and reduction xor, respectively.
Example:
// x = 4'b1010
&X //Equivalent to 1& 0 & 1 & 0. Results in 1’b0
|X//Equivalent to 1| 0 | 1 | 0. Results in 1'b1
^X //Equivalent to 1 ^ 0 ^ 1 ^0. Result in 1’b0
//A reduction xor or xnor can be used for even or odd parity generation of a vector.
The use of a similar set of symbols for logical (!, &&, ||), bitwise (~, &, |, ^ ), and
reduction operators (&, |, ^) is somewhat confusing initially. The difference lies in the number
of operands each operator takes and also the value of results computed.
3.7.7 Shift Operators
Shift operators are right shift (>>), left shift (<<), arithmetic right shift (>>>) and arithmetic
left shift (<<<). Regular shift operators shift a vector operand to the right or the left by a
specified number of bits. The operands are the vector and the number of bits to shift.
When the bits are shifted, the vacant bit positions are filled with zeros. Shift operations
does not wrap around. Arithmetic shift operators use the context of the expression to
determine the value with which to fill the vacated bits.
Example:
// x = 4’b1100
Y = X >> 1: Y is 4'b0110. Shift right 1 bit. 0 filled in MSB position
Y = X << 1; //Y is 4 b1000. Shift left 1 bit. 0 filled in LSB position
Y = X << 2; //Y is 4 b0000. Shift Left 2 bits.
integer a, b, c//Signed data types
a = 0;
b = -10; // 00111...10110 binary
c = a+ (b>>> 3): //Results in -2 decimal, due to arithmetic shift.
Shift operators are useful because they allow the designer to model shift operations, shift-
and-add algorithms for multiplication, and other useful operations.
3.7.8 Concatenation Operator
The concatenation operator ( { , } ) provides a mechanism to append multiple operands. The
operands must be sized. Unsized operands are not allowed because the size of each operand
must be known for computation of the size of the result.
Concatenations are expressed as operands within braces, with commas separating the
operands. Operands can be scalar nets or registers, vector nets or registers, bit-select, part-
select, or sized constants.
Example:
// A = 1'b1, B = 2'b00, C = 2'b10, D = 3'bl10;
Y = {B, C} // Result Y is 4'b0010
Y = {A, B, C, D, 3'b001} // Result Y is 11’b10010110001
Y = {A, B[0], C[1]) // Result Y is 3’b101
3.7.9 Replication Operator
Repetitive concatenation of the same number can be expressed by using a replication
constant. A replication constant specifies how many times to replicate the number inside the
brackets ( { } )
Example:
reg A;
reg [1:0] B, C;
reg [2:0] D;
A= 1’b1, B = 2’b00, C= 2’b10, D = 3'b110;
Y= {4 {A} } // Result Y is 4’b1111
Y = {4{A}, 2(B} } Result is 8’b11110000
Y = {4{A}, 2{B}, C} // Result Y is 10’b1111000010
3.7.10 Conditional Operator:
The conditional operator (?:) takes three operands.
Usage: condition_expression ? true_expression : false_expression
The condition expression (condition_expression) is first evaluated. If the result is true (logical
1), then the true_expression is evaluated. If the result is false (logical 0), then the
false_expression is evaluated. If the result is x (ambiguous), then both true_expression and
false_expression are evaluated and their results are compared, bit by bit, to return for each
bit position an x if the bits are different and the value of the bits if they are the same.
The action of a conditional operator is similar to a multiplexer. Alternately, it can be
compared to the if-else expression.
Conditional operators are frequently used in dataflow modeling to model conditional
assignments. The conditional expression acts as a switching control.
// model functionality of a tristate buffer
assign addr_bus = drive_enable ? addr_out : 36'bz;
//model functionality of a 2-to-1 mux
assign out = control ? in1 : in0;
Conditional operations can be nested. Each true_expression or false_expression can
itself be a conditional operation. In the example that follows, convince yourself that (A==3)
and control are the two select signals of 4-to-1 multiplexer with n, m, y, x as the inputs and
out as the output signal.
assign out = (A == 3) ? (control ? x : y) : ( control ? m : n);
We can use assignment statements instead of gates to model the logic equations of the
multiplexer. Notice that everything is same as the gate-level Verilog description except that
computation of out is done by specifying one logic equation by using operators instead of
individual gate instantiations. I/O ports remain the same. This important so that the
interface with the environment does not change. Only the internals of the module change.
Example 3.15: 4-to-1 Multiplexer, Using Logic Equations
// Module 4-to-1 multiplexer using data flow. logic equation
// Compare to gate-level model
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram output out;
input i0, i1, i2, i3; input s1, s0;
//Logic equation for out
assign out = (~s1 & ~s0 & i0)| (~s1 & s0 & i1) | (s1 & ~s0 & i2) | (s1 & s0 & i3) ;
endmodule
Method 2: conditional operator
There is a more concise way to specify the 4-to-1 multiplexers. Conditional operators can be
used to implement 4-to-1 multiplexers.
Example3.16: 4-to-1 Multiplexer, Using Conditional Operators
// Module 4-to-1 multiplexer using data flow. Conditional operator.
// Compare to gate-level model
module multiplexer4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram output out;
input i0, i1, i2, i3;
input s1, s0;
// Use nested conditional operator
assign out = s1 ? ( s0 ? i3 : i2) : (s0 ? i1 : i0) ;
endmodule
In the simulation of the multiplexer, the gate-level module can be substituted with the
dataflow multiplexer modules described above. The stimulus module will not change. The
simulation results will be identical. By encapsulating functionality inside a module, we can
replace the gate-level module with a dataflow module without affecting the other modules in
the simulation. This is a very powerful feature of Verilog.
Figure 3.11: T- flip flop Figure 3.12: Negative edge triggered D flip flop
Given the above diagrams, we write the corresponding Verilog, using dataflow statements in
a top-down fashion. First we design the module counter. The code is shown in. The code
contains instantiation of four T_FF modules.
Example 3.18: Verilog code for ripple counter
module counter(Q , clock, clear);
// I/O ports
output [3:0] Q;
input clock, clear;
// Instantiate the T flipflops
T_FF tff0(Q[0], clock, clear);
T_FF tff1(Q[1], Q[0], clear);
T_FF tff2(Q[2], Q[1], clear);
T_FF tff3(Q[3], Q[2], clear);
endmodule
32 Mohammed Saleem| Asst. Prof., Dept. of E & C, PACE
[email protected] [VERILOG HDL [18EC56]]