In today’s environment the MOS transistor is the basic element around which a VLSI
is built. Designers familiar with logic gates and their configurations at the circuit level may
choose to do their designs using MOS transistors. Verilog has the provision to do the design
description at the switch level using such MOS transistors. Switch level modeling forms the
basic level of modeling digital circuits. The switches are available as primitives in Verilog;
they are central to design description at this level. Basic gates can be defined in terms of such
switches. By repeated and successive instantiation of such switches, more involved circuits
can be modeled.
Designers familiar with logic gates, digital functional blocks, and their interplay can
successfully carry out a complete VLSI design without any involvement at the switch level.
BASIC TRANSISTOR SWITCHES
Consider an NMOS transistor of the depletion type. When used in a digital circuit, it
can be in one of three modes:
VG < VS where VG and VS are the gate and source voltages with respect to the drain:
The transistor is OFF and offers very high impedance across the source and the drain. It is
in the z state.
VG ≡ Vs: The transistor is in the active region. It presents a resistance between the source
and the drain. The value depends on the technology. Such a resistive state of the transistor
can be modeled in Verilog. A transistor in this mode can be represented as a resistance in
Verilog – as pull1 or pull0 depending on whether the drain is connected to supply1 or
source is connected to supply0.
VG> VS: The transistor is fully turned on. It presents very low resistance (~0 Ω) between
the source and drain.
An enhanced-mode NMOS transistor also has the above three modes of operation.
Similar modes are possible for the PMOS transistor also.
Basic Switch Primitives
Different switch primitives are available in Verilog. Consider an nmos switch. A
typical instantiation has the form
nmos (out, in, control);
nmos – a keyword – represents an NMOS transistor functioning as a switch. The
switch has three terminals – in, out and control. When the control input is at 1 (high) state, the
switch is on. It connects the input lead to the output side and offers zero impedance. When
the control input is low, the switch is OFF and output is left floating (z state). If the control is
in the z or the x state, output may take corresponding values.
Pending : Fig. 161 (a) nmos switch (b) pmos switch
The keyword pmos represents a PMOS transistor functioning as a switch. The PMOS
switch has three terminals. A typical instantiation of the switch has the form
pmos (out, in, control);
When the control is at 1 (high) state, the switch is off. Output is left floating. When
control is at 0 (low) state, the switch is on, input is connected to output, and output is at the
same state as input. For other input values, output is at other values.
When instantiating an nmos or a pmos switch, a name can be assigned to the switch.
But the name is not essential. The nmos and pmos switches function as unidirectional
switches.
Resistive Switches
nmos and pmos represent switches of low impedance in the on-state, rnmos and
rpmos represent the resistive counterparts of these respectively. Typical instantiations have
the form
rnmos (output, input, control);
rpmos (output, input, control);
With rnmos if the control 1 input is at 1 (high) state, the switch is ON and functions
as a definite resistance. It connects input to output through a resistance. When control 1 is at
the 0 (low) state, the switch is OFF and leaves output floating.
The rpmos switch is ON when control is at 0 (low) state. It inserts a definite resistance
between the input and the output signals but retains the signal value.
Because rpmos and rnmos are resistive switches, they reduce the signal strength when
in the on state. The reduced strength is mostly one level below the original strength. The only
exceptions are small and hi-z. For these the strength and the state remain unaltered. Therpmos and rnmos switches function as unidirectional switches; the signal flow is from the
input to the output side.
Pending : Table 25 Input and Output strengths for Resistive Switches
pullupand pulldown
A MOS transistor functions as a resistive element when in the active state. Realization
of resistance in this form takes less silicon area in the IC as compared to a resistance realized
directly, pullup and pulldown represent such resistive elements. A typical instantiation here
has the form
pullup (X);
Here the net X is pulled up to the supply1 through a resistance. Similarly, the instantiation
pulldown (y);
pulls y down to the supply0 level through a resistance. The pullup and pulldown primitives
can be used as loads for switches or to connect the unused input ports to VCC or GND,
respectively. They can also form loads of switches in logic circuits.
The default strengths for pullup and pulldown are pull1 and pull0 respectively. One
can also specify strength values for the respective nets. For example,
pullup (strong1) (X);
specifies a resistive pullup of net X to supply1. One can also assign names to the pullup and
pulldown primitives. Thus
pullup (strong1) rs (X)
represents an instantiation of pullup designated rs having strength strong1.
Difference between tri and pullup or pulldown is to be understood clearly, pullup is
a functional element; it represents a resistive connection to supply1. In contrast tri1 is a type
of net; in the absence of an assignment, it remains connected to supply1. A similar difference
exists between pulldown and tri0.
Example 28: CMOS Inverter
Pending : Fig.162 CMOS Inverter
A CMOS inverter is formed by connecting an nmos and a pmos switch in series
across the supply. The output terminals are joined together to form the common output.
Similarly, the input is used as the common control input to both the switches.
module cmosinv (out,in);
input in;
output out;
supply0 a;
supply1 b;
nmos(out,a,in);
pmos(out,b,in);
endmodule
Example 29: CMOS NOR gate
Pending : Fig.163 CMOS NOR Gate
module cmosnor (y,a,b);
input a,b;
output y;
wire c;
supply0 z;
supply1 x;
pmos(c,x,a);
pmos(y,c,b);
nmos(y,z,a);
nmos(y,z,b);
endmodule
Example 30: CMOS NAND Gate
Pending : Fig.164 CMOS NAND Gate
CMOS SWITCH
A CMOS switch is formed by connecting a PMOS and an NMOS switch in parallel –
the input leads are connected together on the one side and the output leads are connected
together on the other side. Fig.165 shows the switch so formed. It has two control inputs:
N_Control turns ON the NMOS transistor and keeps it ON when it is in the 1 state.
P_Control turns ON the PMOS transistor and keeps it ON when it is in the 0 state.
The CMOS switch is instantiated as shown below.
cmos csw (out, in, Ncontrol, P_control);
Significance of the different terms is as follows:
cmos : The keyword for the switch instantiation
CSW: Name assigned to the switch in the instantiation
out: Name assigned to the output variable in the instantiation
in: Name assigned to the input variable in the instantiation
N_Control: Name assigned to the control variable of the NMOS transistor in the instantiation
P_Control: Name assigned to the control variable of the PMOS transistor in the instantiation
Switch – 1:
Pending : Fig. 165 CMOS Switch
module cmos(out,in,nctr,pctr);
input in,nctr,pctr;
output out;
nmos gn(out,in,nctr);
pmos(out,in,pctr);
endmodule
Switch – 2:
Pending : Fig. 166 CMOS Switch
module cmos(out,in,con);
input in,con;
output out;
wire pctr;
not gn(pctr,con)
nmos gn(out,in,nctr);
cmos gc(out,in,con,pctr);
endmodule
Example 31: A RAM Cell
Fig.167 shows a basic ram cell with facilities for writing data, storing data, and
reading data. When switch sw2 is on, qb – the output of inverter g1 – forms the input to the
inverter g2 and vice versa. The g1-g2 combination functions as a latch and freezes the last
state entry before SW2 turns on.
The step-by-step function of the cell is as follows:
• When WSb (write/store) is high, switch SW1 is ON, and switch SW2 OFF. With Sw1 on,
input Din is connected to the input of gate g1 and remains so connected.
• When WSb goes low, din is isolated, since SW1 is OFF. But SW2 is ON and the data
remains latched in the latch formed by g1-g2. In other words the data Din is stored in
the RAM cell formed by g1-g2.
• When RD (Read) goes active (=1), the latched state is available as output Do. Reading is
normally done when the latch is in the stored state.
Pending : Fig. 167 A Dynamic RAM Cell
module ram1(do,din,wr,rd);
output do; input din,wr,rd;
wire qb,q;
tri do;
scw sww(q,din,wr), swr(do,q,rd);
not (pull1,pull0) n1(qb,q), n2(q,qb);
endmodule
module scw(out,in,n_ctr);
output out; input in,n_ctr;
wire p_ctr;
assign p_ctr = ~n_ctr;
cmos sw(out,in,n_ctr,p_ctr);
endmodule
BI-DIRECTIONAL GATES
The gates discussed so far (nmos, pmos, rnmos, rpmos, rcmos) are all unidirectional
gates. When turned ON, the gate establishes a connection and makes the signal at the input
side available at the output side. Verilog has a set of primitives for bi-directional switches as
well. They connect the nets on either side when ON and isolate them when OFF. The signal
flow can be in either direction. None of the continuous-type assignments at higher levels
dealt with so far has a functionality equivalent to the bi-directional gates. There are six types
of bidirectional gates.
tran and rtran
The tran gate is a bi-directional gate of two ports. When instantiated, it connects the
two ports directly. Thus the instantiation
tran (s1, s2);
connects the signal lines s1 and s2. Either line can be input, inout or output, rtran is the
resistive counterpart of tran.
3.2 tranif1 and rtranif1
tranif1 is a bi-directional switch turned ON/OFF through a control line. It is in the ONstate when the control signal is at 1 (high) state. When the control line is at state 0 (low), the
switch is in the OFF state. A typical instantiation has the form
tranif1 (s1, s2, c);
Here C is the control line. If c=l, s1 and s2 are connected and signal transmission can be in
either direction, rtranif1 is the resistive counterpart of tranif1. It is instantiated in an
identical manner.
3.3 tranif0 and rtranif0
tranif0 and rtranif0 are again bi-directional switches. The switch is OFF if the control line is
in the 1 (high) state, and it is ON when the control line is in the 0 (low) state. A typical
instantiation has the form
tranif0 (s1, s2, C);
With the above instantiation, if C = 0, Si and S2 are connected and signal transmission can be
in either direction. If C = 1, the switch is OFF and Si and S2 are isolated from each other.
rtranif0 is the resistive counterpart of tranif0.
Observations:
Any instantiation of a bi-directional switch of the above types can be given a name. But a
name is not essential. It is true of the other switches also.
With the bi-directional switches the signal on either side can be of input, output, or
inout type. They can be nets or appearing as ports in the module. But the type
declaration on the two sides has to be consistent.
The connections to the bi-directional terminals of each of the bi-directional switches have
to be scalars or individual bits of vectors and not vector themselves.
In the above instantiation s1 can be an input port in a module. In that case, s2 has to be a
net forming an input to another instantiated module or circuit block. s2 can be of output
or inout type also. But it cannot be another input port.
• s1 and s2 – both cannot be output ports.
• s1 and s2 – both can be inout ports.
With tran, tranif1, and tranif0 bi-directional switches if the input signal has strength
supply1 (supply0), the output side signal has strength strong1 (strong0). For all other
strength values of the input signal, the strength value of the output side signal retains the
strength of the input side signal.
With rtran, rtranif1 and rtranif switches the output side signal strength is less than that
of the input side signal. The strength reduction is on the lines shown in Table 26 for
rnmos, rpmos, and rcmos switches.
Pending : Table 26 Bidirectional Gates
Pending : Fig. 168 Bus switching using Bidirectional Gates
Example 32: RAM Cell
Fig.169 shows a single RAM cell. It can be instantiated in vector form to form a fullfledged ram. a_d is the decoded address line. When active, it turns on the bi-directional
switch g3 and establishes a two-way connection between net ddd and net q. g1 and g2
together form a latch in feedback fashion. When g3 is OFF, the latch stores the state it was
last in. It is connected to ddd through g3 by activating a_d for writing and reading. The
following are possible after such selection and connection:
When wr = 1, cmos gate g4 turns ON; the data at the input port di (with strength
strongO / strongl) are connected to q through ddd. It forces the latch to its state – since
q has strength pullO / pulll only – di prevails here. This constitutes the write operation.
When rd = 1, cmos gate g5 turns ON. The net ddd is connected to the output net do.
The data stored in the latch are made available at the output port do. This
constitutes the read operation.
Pending : Fig. 169 A RAM Cell using Bidirectional Gates
module ram_cell1(do,di,wr,rd,a_d);
output do; input di,wr,rd,a_d;
wire ddd,q,qb,wrb,rdb;
not (rdb,rd), (wrb,wr);
not(pull1,pull0) (q,qb), (qb,q);
tranif1 g3(ddd,q,a_d);
cmos g4(ddd,di,wr,wrb), g5(do,ddd,rd,rdb);
endmodule
TIME DELAYS WITH SWITCH PRIMITIVES
For example, an NMOS switch instantiated as
nmos g1 (out, in, Ctrl );
has no delay associated with it. The instantiation
nmos(delayl) g2 (out, in, Ctrl );
has delayl as the delay for the output to rise, fall, and turn OFF. The instantiation
nmos(delay_r, delay_f) g3 (out, in, ctrl);
has delay_r as the rise-time for the output. delay_f is the fall-time for the output. The turn-off
time is zero. The instantiation
nmos (delay_r, delay_f, delay_o) g4 (out, in, ctrl );
has delay_r as the rise-time for the output. delay_f is the fall-time for the output delay_0 is the
time to turn OFF when the control signal ctrl goes from 0 to 1. Delays can be assigned to the
other uni-directional gates (rcmos, pmos, rpmos, cmos, and rcmos) in a similar manner. Bidirectional switches do not delay transmission – their rise- and fall-times are zero. They can
have only turn-on and turn-off delays associated with them, tran has no delay associated with
it.
trainf1 (delay_r, delay_f) g5 (out, in, ctrl );
represents an instantiation of the controlled bi-directional switch. When control changes from
0 to 1, the switch turns on with a delay of delay_r. When control changes from 1 to 0, the
switch turns off with a delay of delay_f.
transif1 (delayO) g2 (out, in, ctrl );
represents an instantiation with delayO as the delay for the switch to turn on when control
changes from 0 to 1, with the same delay for it to turn off when control changes from 1 to 0.
When a delay value is not specified in an instantiation, the turn-on and turn-off are
considered to be ideal that is, instantaneous. Delay values similar to the above illustrations
can be associated with rtranif1, tranif0, and rtranif0 as well.
INSTANTIATIONS WITH STRENGTHS AND DELAYS
In the most general form of instantiation, strength values and delay values can be combined.
For example, the instantiation
nmos (strong1, strong0) (delay_r, delay_f, delay_o ) gg (s1, s2, ctrl) ;
means the following:
It has strength strong0 when in the low state and strength strong1 when in the high state.
When output changes state from low to high, it has a delay time of delay_r.
When the output changes state from high to low, it has a delay time of delay_f.
When output turns-off it has a turn-off delay time of delay _o.
rnmos, pmos, and rpmos switches too can be instantiated in the general form in the same
manner. The general instantiation for the bi-directional gates too can be done similarly.
STRENGTH CONTENTION WITH TRIREG NETS
Strength contention in transistor switches can be resolved by using trireg nets. Such
storage can be assigned one of three strengths – large, medium, or small. Driving such a net
from different sources can lead to contention; the relative strength levels of the sources also
have a say in the signal level taken by the net.
EXAMPLE 33:
Pending : Fig. 170 An Example circuit to illustrate strength contention in switch primitives
Pending : Fig. 171 Module for the fig. 170
Pending : Fig. 172 Changes in signal values at different times
Pending : Fig. 173 Simulation Results
SYSTEM TASKS, FUNCTIONS, AND COMPILER DIRECTIVES
PARAMETERS
The parameter constructs facilitate such flexibility. Constants signifying timing values,
ranges of variables, wires, etc., can be specified in terms of assigned names. Such assigned
names are called parameters. The parameter values can be specified and changed to suit the
design environment or test environment. Such changes are effected and frozen at
instantiation. The assigned values cannot change during testing or synthesis. In this respect a
parameter is different from a net or a variable.
Two types of parameters are of use in modules:
Parameters related to timings, time delays, rise and fall times, etc., are technologyspecific and used during simulation. Parameter values can be assigned or overridden with
the keyword “specparam” preceding the assignments.
Parameters related to design, bus width, and register size are of a different category.
They are related to the size or dimension of a specific design; they are technologyindependent. Assignment or overriding is with assignments following the keyword
“defparam”.
Timing-Related Parameter
Example 34: Half Adder Module
module ha_l(s,ca,a,b);
input a,b; output s,ca;
xor #(1,2) (s,a,b);
and #(3,4) (ca,a,b);
endmodule
//test-bench module tstha_l();
reg a,b; wire s,ca;
ha_l hh(s,ca,a,b);
initial begin a=0;b=0; end
always begin #5 a=l;b=0; #5 a=0;b=l; #5 a=l;b=l; #5 a=0;b=0; end
initial $monitor($time , ” a = %b , b = %b ,out carry = %b , outsum = %b “
,a,b,ca,s);
initial #30 Sstop;
endmodule
Parameter Declarations and Assignments
Declaration of parameters in a design as well as assignments to them can be effected
using the keyword “Parameter.” A declaration has the form
parameter alpha = a, beta = b
where
parameter is the keyword,
alpha and beta are the names assigned to two parameters and
a, b are values assigned to alpha and beta, respectively.
In general a and b can be constant expressions. The parameter values can be
overridden during instantiation but cannot be changed during the run-time. If a parameter
assignment is made through the keyword “localparam,” its value cannot be overridden.
Observations:
• As mentioned earlier, parameters are constants which can be altered during compilation
but not during runtime.
• A Parameter can be signed or unsigned in nature; it can be an integer or a real number.
• Its nature – signed or not, real or integral type as well as range – can be specified at the
time of declaration or decided by default based on assignment.
Examples
parameter a = 3; // a is a positive integer
parameter b = – 3; // b is a signed integer
parameter c = 3.0, d = 3.0e2; //c and d are unsigned real numbers.
In all the above cases the parameter type and range are decided by default.
parameter integer e = 3; /* e is declared to be an integer type of parameter and assigned
the value 3. */
parameter real f = 3.0; /* f is declared to be a real unsigned real number and assigned
the value 3. */
In the last two cases the parameter type is declared explicitly and remains so.
Whenever a parameter value is overridden during instantiation, type, signed/unsigned, etc.,
remain unchanged.
Example 35: Half Adder Module
module ha_2(s,ca,a,b);
input a,b; output s,ea;
parameter dllr=l,dl2f=2,dl3r=3,dl4f=4;
xor #(dllr,dl2f) (s,a,b);
and #(dl3r,dl4f) (ca,a,b);
endmodule
//test-bench module tstha_2();
reg a,b; wire s,ea;
ha_2 hh(s,ca,a,b);
initial begin a=0;b=0; end
always begin #5 a=l;b=0; #5 a=0;b=l; #5 a=l;b=l; #5 a=0;b=0; end
initial $monitor($time , ” a = %b , b = %b ,out carry = %b , outsum = %b “
,a,b,ca,s);
initial #30 Sstop;
endmodule
Type Declarations for Parameters
The above examples do not have any type declaration statements for the parameters
dllr, dl2f, dl3r, and dl4f. However, integer value assignments are made to each of them;
implicitly they are taken as integers by the simulator. But in general one can use constant
expressions on the right-hand side of the assignments. For example,
parameter dllr =1, dl2f=dllr+ 1, dl3r=3 , dl4f= dl2f*2;
As mentioned earlier, all four parameters are automatically taken as integers by the simulator.
If the above statement is modified as
parameter dllr =1, dl2f =dllr + 1.0, dl3r =3 , dl4f = dl2P2;
the parameter types will be radically different, dllr and dl3r will be treated as integers but dl2f
and hence dl4f will be treated as real. However, the numerical values assigned will remain
unaltered and hence the simulation results too will be the same.
PATH DELAYS
The time delays discussed so far are all delays associated with individual operations
or activities in a module. They refer to basic circuit elements in a design – at the microlevel
itself. These are called “distributed delays” in LRM. Verilog has the provision to specify and
check delays associated with total paths – from any input to any output of a module. Such
paths and delays are at the chip or system level. They are referred to as “module path delays.”
Constructs available make room for specifying their paths and assigning delay values to them separately or together.
Specify Blocks
Module paths are specified and values assigned to their delays through specify blocks.
They are used to specify rise time, fall time, path delays pulse widths, and the like.
specify
specparam rise_time = 5, fall_time = 6; (a =>b) = (rise_time, fall_time);
(c => d) = (6, 7);
endspecify
The block starts with the keyword “specify” and ends with the keyword
“endspecify”. Specify blocks can appear anywhere within a module. The block can have
two types of statements:
One type starts with the keyword specparam and assigns numerical values to timing
parameters declared elsewhere. The specparam statements can appear within a
module or within a specify block. The right sides of the assignments can be constants
or constant expressions involving such parameters already assigned.
The second type specifies paths and assigns values to time delays to them.
A specify block can have only the above types of assignments. Circuit function
assignments, assignments to module parameters, etc., are not permitted within it.
Module Paths
Module paths can be specified in different ways inside a specify block. The simplest
has the form
A*>B
Here “A” is the source and “B” the destination. The source can be an input or an inout
port. The destination can be output or an inout port. The symbol combination “*>” specifies
the path from the source to the destination. It encompasses all the possible paths from A to B.
If A and B are scalars, it signifies a single path.
If A is a vector and B is a scalar, it signifies all the paths from every bit of A to the scalar
B. Thus if A is a 4-bit-wide vector, 4 paths are specified.
If A is a scalar and B is a vector, it signifies all the paths from A to every bit of the vector
B. Thus if B is an 8-bit vector, it signifies all 8 possible paths.
If both A and B are vectors, it signifies all the possible paths from eveiy bit of the vector
A to every bit of the vector B; thus if A is a 4-bit vector and B is an 8-bit vector, it
signifies 4 * 8 = 32 possible paths; a total of 32 delay values (all being equal to each
other) are implied here.
Pending : Fig. 174 Illustration of the difference between the operations *> and =>
Fig.174 (a) illustrates a case of all possible paths from a 2-bit vector A to another 2-
bit vector B; the specification implies 4 paths. A statement of the type
C => D
signifies only all the parallel paths. Here C and D have to be vectors of the same size. The
path specified signifies transmission from every bit of vector C to the corresponding bit of
vector D. In this sense the path description is more restrictive than that of A*>B above.
Fig.174 (b) illustrates a case of all possible parallel paths from a 2-bit vector C to another 2-
bit vector D; the specification implies a total of 2 paths only.
The assignment
(a,b *> S) =1;
implies that
The propagation delay from input a to output S is 1 ns and
The propagation delay from input b to the output S is also 1 ns.
Further the delay value is 1 ns for the change in the state of s from 0 to 1 as well as
from 1 to 0.
Similarly the statement
(a,b *> ca) = 2;
implies that the delay from a to ca as well as that from b to ca is 2 ns; further, it holds for any
transition in ca.
Example 36: Half Adder Module with path delays
module ha_7(s,ca,a,b);
input a,b; output s,ca;
specify
(a,b*>s)=l;
(a,b*>ca)=2;
endspecify xor (s,a,b);
and (ca,a,b);
endmodule
//test-bench module tstha_7();
reg a,b; wire s,ca;
ha_7 hh(s,ca,a,b);
initial begin a=0;b=0; end
always begin #5 a=l;b=0; #5 a=0;b=l; #5 a=l;b=l; #5 a=0;b=0; end
initial $monitor($time , ” a = %b , b = %b ,out carry = %b , outsum = %b “
,a,b,ca,s);
initial #30 Sstop;
endmodule
Conditional Pin-to-Pin Delays
The pin to pin path of a signal may change depending on the value of another signal;
in turn the number of circuit elements in the alternate path may differ.
Edge-Sensitive Paths
Behavior level modules can have signal paths activated following an edge in a
different signal. Verilog has the provision to specify such delays during simulation. They can
be specified in a variety of ways. The path may get activated following a positive edge or a
negative edge in a signal. The path delay may be specified for rise or fall in the output or for
positive or negative polarity transitions separately. The delay assignment can be made
conditional on an expression; such a path specification is an “edge sensitive state dependent
path”.
Pulse Filtering and its Control
All transitions on an input pin with less than a specified module path delay are termed
“pulses.” Normally, when a module path delay is specified, all pulses are ignored; that is, the
simulator does not take cognizance of such narrow transitions. However, response to such
narrow pulses can be specified through specparam in a specify block. A statement
specparam PATHPULSE$ (X , y) = (a, b);
implies the following concerning the module pulse path from X to y:
• Ignore all pulses of width less than a ns. a is referred to as the “rejection limit” for the
pulse path.
• Take cognizance of all the pulses wider than b ns. Note that the specification has
relevance only if the delay value for the pulse path (specified in the specify block) is
larger than b.
• For all pulses of width value between a and b, the output is in error and in x state.
The PATHPULSE$ specification is governed by the following:
• It has to appear within a specify block as a specparam assignment as shown above.
• It specifies the limits for the path pulse-error limit as well as reject limit for the specified
path.
• A statement as
specparam PATHPULSE$ = (a, b);
implies that a and b are the error and reject limits for the pulse widths for all the paths
specified within the specify block; the simulator checks for the pulse width and if it is
between a and b values, the output goes to x state.
• A set of statements
specparam PATHPULSE$ (X, Y) = (a, b);
specparam PATHPULSE$ = (c, d);
implies that for the path from X to Y, a and b are the error and reject limits, respectively;
further, for all other pulse paths within the specify block, the limits for error and rejection
are c and d, respectively. If only one limit is specified as
specparam PATHPULSE$ =a;
a is taken as the error limit as well as reject limit for the concerned paths.
MODULE PARAMETERS
Module parameters are associated with size of bus, register, memory, ALU, and so on.
They can be specified within the concerned module but their value can be altered during
instantiation. The alterations can be brought about through assignments made with
defparam. Such defparam assignments can appear anywhere in a module.The rules of
assigning values for the module parameters, deciding their size, type, etc., are all similar to
those of specify parameters.
Pending : Fig.175 ALU Module
SYSTEM TASKS AND FUNCTIONS
Verilog has a number of System Tasks and Functions defined in the LRM. They are
for taking output from simulation, control simulation, debugging design modules, testing
modules for specifications, etc. A “$” sign preceding a word or a word group signifies a
system task or a system function. Some of the system tasks and functions have been
extensively used in the earlier chapters. Some others with the potential for common use are
described and illustrated here. The complete list is available in the LRM.
Output Tasks
A number of system tasks are available to output values of variables and selected
messages, etc., on the monitor. Out of these $monitor and $display tasks have been
extensively used in the preceding chapters. These and related tasks are discussed below.
$display Used to display the arguments in the desired format.
$displayb
$displayo
$displayh
$displayd
$write Used to display the argument with specified format but does not advance to
the new line
$writeb
$writeo
$writeh
$writed
%m Used to display instantiated modules in another module.
$strobe Used to display sampled version of a variable or a set of variables.
Display Tasks
The $display task, whenever encountered, displays the arguments in the desired
format; and the display advances to a new line. $ write task carries out the desired display but
does not advance to the new line. For both the format is identical to that of scanf and printf
in C language. The features are briefly outlined here:
• The arguments are displayed in the same order as they appear in the display statement.
• The arguments can be variables, an expression involving variables, or quoted strings.
• The strings are output as such except the escape sequences. An escape sequence starts
with the character \ or the character %.
• “\” signifies one of a set of special characters.
• “%m” signifies that the hierarchical name of the particular argument is to be displayed
“%” followed by a character specifies the format for display of the following argument
or an aspect of the following argument.
• If the format for the display of an argument is not specified, a default format is assumed.
It is binary for $displayb and $writeb, octal for $displayo and $writeo, decimal for
$displayd and $writed, hex for $displayh and $writeh.
• If any argument is in the form of an expression, it is evaluated and the result displayed
or written; it is sized automatically. With decimal numbers the leading zeros are
suppressed. Insertion of a “0” character (zero digit) between the “%” symbol and the
radix overrides the automatic sizing.
FILE-BASED TASKS AND FUNCTIONS
LRM has the provision to accommodate and integrate design and test modules kept in
different files. It makes room for structuring the design in an elegant manner and developing
it with a “cross-functional” approach. Different facilities are specified in the LRM. That to
output results to a file is discussed here as a specific case. To carry out any file-based task,
the file has to be opened, reading, writing, etc., completed and the file closed. The keywords
for all file-based tasks start with the letter f to distinguish them from the other tasks.
Writing out to a file
$fdisplay
$fwrite
$fstrobe
$fmonitor
$fflush
reading from a file
$readmemb
$readmemh
$fscanf
String formatting functions
$swrite
$sformat
$sscanf
Example 37: Half Adder Test Bench
module ha_test;
reg a,b; wire s,co; integer filen;
ha hh(s,co,a,b);
initial
begin
a=0;
b=0;
filen=$fopen(“ha_f.txt”);
end
always
begin
#5 a=0; b=1;
#5 a=1; b=0;
#5 a=1; b=1;
#5 a=0; b=0;
end
initial $fmonitor(filen, $time“a=%b, b=%b, s=%b, co=%b”, a,b,s,co);
initial
begin
$fdisplay (filen);
#30 $stop;
$fclose(filen);
end
endmodule
COMPILER DIRECTIVES
A number of compiler directives are available in Verilog. They allow for macros,
inclusion of files, and timescale-related parameters for simulation. All compiler directives are
preceded by the ‘ (accent grave) character. Representative compiler directives are discussed
here with illustrations.
‘define Directive
The “define directive is for macro substitution. It substitutes the macro by a defined
text. Hence a macro name can be used in place of such a group of characters in the listing
wherever the group is to appear. Subsequently, the macro name can be substituted during compilation by the actual text. The ‘define directive is used to define and associate the
desired text with the macro name.
The ‘define compiler directive can also be used to substitute a number by a macro
name. It allows for deciding bus-width, specific delay values, etc., at compilation time.
Pending : Fig.176 ALU Module
Time-Related Tasks
A set of compiler directives and system tasks relate to the running time of simulation
as well as the delays in the concerned modules. A wide range of timescales as well as
precision levels are available for selection during simulation.
‘timescale
The ‘ timescale compiler directive allows the time scale to be specified for the design. When
a ‘timescale directive is encountered in a file, the same is valid for all subsequent modules
within the file. The ‘ timescale directive has two components.
Pending : Fig.177 Timescale structure
A few examples are given below:
• ‘timescale 1 ms/100 ps
implies that in the following design all the time values specified are in ms and they have a
precision of 100 ps. Thus
3, 3.0, 3.022 are all inteipreted as 3 ms;
3.1, 3.12,3.199 are all inteipreted as 3.1 ms; and
0.1, 0.12 are interpreted as 100 ps .
‘timescale 1 ms/1 ms
implies that in the following design all the time values specified are in ms and they have a
precision of 1 ms. Thus
3, 3.0, 3.022, 3.1, 3.12, 3.199 are all interpreted as 3 ms and
0.1, 0.12 are interpreted as 0 ms .
$timeformat
The timescale and the format for display can be changed during simulation with the
help of $timef ormat task. The syntax for the task is explained in Figure 11.58. Whenever
“p,s” (microsecond) is to be specified for defining or changing time scale, it is specified as
“us.” Conventions for all other timescale values (s, ms, ns, ps, and fs) remain unaltered.
A negative number in the 0 to -15 range signifying time unit: 0 stands for s, -1 for 0.1s
and so on; -15 implies fem to second. any convenient s t r i n g t o b e displayed as such
$timeformat ( -aa)
An integer specifying precision: it represents the number of digits to the right of the
decimal point “cc”, dd
An integer specifying the field width for the display
Simulation Time
Simulation time value can be obtained, displayed or used in specific expressions; a
limited amount of flexibility is available here: –
• $time returns the value of simulation time as an integer.
• $realtime returns the value of simulation time as a real number.
Default Timescale
If the time scale values are not specified in the source file, simulation is carried out
with the default values specified in the tool used for simulation. The default value of time
unit is taken as nanosecond
HIERARCHICAL ACCESS
Pending : Fig. 178 Hierarchical Access
Pending : Fig.179 Hierarchical Access using functions
USER DEFINED PRIMITIVES (UDP)
The primitives available in Verilog are all of the gate or switch types. Verilog has the
provision for the user to define primitives – called “user defined primitive (UDP)” and use
them. A UDP can be defined anywhere in a source text and instantiated in any of the
modules. Their definition is in the form of a table in a specific format. It makes the UDP
types of functions simple, elegant, and attractive.
UDPs are basically of two types – combinational and sequential. A combinational
UDP is used to define a combinational scalar function and a sequential UDP for a sequential
function.
Combinational UDPs
A combinational UDP accepts a set of scalar inputs and gives a scalar output. An
inout declaration is not supported by a UDP. The UDP definition is on par with that of a
module; that is, it is defined independently like a module and can be used in any other
module. The definition cannot be within any other module.
Pending : Fig.180 and gate primitive
• The first statement starts with the keyword “primitive”, it is followed by the name
assigned to the primitive and the port declarations.
• A UDP can have only one output port. It has to be the first in the port list.
• All the ports following the first are input ports and are all scalars.
• inout ports are not permitted in a UDP definition.
• Output and input are declared in the body of the UDP.
• The behavior block of the primitive is given in the form of a table. It is specified between
keywords table and endtable.
• The combinational function is defined as a set of rows ( akin to the truth table).
• All the input values are specified first – each in a separate field in the same order as they
appear in the port declaration.
• A colon and then the output value follow the set of input values. The statement ends with
a semicolon – as with every statement in Verilog.
• A comment line is inserted in the example following the “table” entry. It facilitates
understanding the tabular entries.
• All the inputs are nets – wire-type. Hence there is no need for a separate type definition.
• Output can be of the net or reg type depending upon the type of primitive – explained
later.
• The last keyword statement – “endprimitive” — signifies the end of the definition.
Sequential UDPs
Any sequential circuit has a set of possible states. When it is in one of the specified
states, the next state to be taken is described as a function of the input logic variables and the
present state [Wakerly], A positive or a negative going edge or a simple change in a logic
variable can trigger the transition from the present state of the circuit to the next state. A
sequential UDP can accommodate all these. The definition still remains tabular as with the
combinational UDP. The next state can be specified in terms of the present state, the values
of input logic variables and their transitions. The definition differs from that of a
combinational UDP in two respects:
• The output has to be defined as a reg. If a change in any of the inputs so demands, the
output can change.
Values of all the input variables as well as the present state of the output can affect the
next state of the output. In each row the input values are entered in different fields in the
same sequence as they are specified in the input port list. It is followed by a colon (:).
The value of the present state is entered in the next field which is again followed by a
colon (:). The next state value of the output occupies the last field. A semicolon (;)
signifies the end of a row definition.
Sequential UDPs and Tasks
Sequential UDPs and tasks are functionally similar. Tasks are defined inside modules
and used inside the module of definition. They are not accessible to other modules. In
contrast, sequential UDPs are like other primitives and modules. They can be instantiated in
any other module of a design.
UDP Instantiation with Delays
Outputs of UDPs also can take on values with time delays. The delays can be
specified separately for the rising and falling transitions on the output. For example, an
instantiation as
udp_and_b #(1,2) g1 (out, inl, in2);
can be used to instantiate the UDF of Figure 9.25 for carry output generation. Here the output
transition to 1 (rising edge) takes effect with a time delay of 1 ns. The output transition to 0
(falling edge) takes effect with a time delay of 2 ns. If only one time delay were specified, the
same holds good for the rising as well as the falling edges of the output transition.
Vector-Type Instantiation of UDP
UDP definitions are scalar in nature. They can be used with vectors with proper
declarations. For example, the full-adder module fa in Figure 9.26 can be instantiated as an 8-
bit vector to form an 8-bit adder. The instantiation statement can be
fa [7:0] aa(co, s, a, b, {co[6:0],1’b0});
s (sum), co (carry output), a (first input), and b(second input) are all 8-bit vectors here. The
vector type of instantiation makes the design description compact; however, it may not be
supported by some simulators.