[ Team LiB ]
12.1 UDP basics
In this section, we describe parts of a UDP definition and rules for UDPs.
12.1.1 Parts of UDP Definition
Figure 12-1
shows the distinct parts of a basic UDP definition in pseudo syntax form. For
details, see the formal syntax definition described in Appendix , Formal Syntax
Definition.
Figure 12-1 Parts of UDP Definition
//UDP name and terminal list
primitive <udp_name> (
<output_terminal_name>(only one allowed)
<input_terminal_names> );
//Terminal declarations
output <output_terminal_name>;
input <input_terminal_names>;
reg <output_terminal_name>;(optional; only for sequential
UDP)
// UDP initialization (optional; only for sequential UDP
initial <output_terminal_name> = <value>;
//UDP state table
table
<table entries>
endtable
//End of UDP definition
endprimitive
A UDP definition starts with the keyword primitive. The primitive name, output terminal,
and input terminals are specified. Terminals are declared as output or input in the
terminal declarations section. For a sequential UDP, the output terminal is declared as a
reg. For sequential UDPs, there is an optional initial statement that initializes the output
terminal of the UDP. The UDP state table is most important part of the UDP. It begins
with the keyword table and ends with the keyword endtable. The table defines how the
output will be computed from the inputs and current state. The table is modeled as a
lookup table. and the table entries resemble entries in a logic truth table. Primitive
definition is completed with the keyword endprimitive.
12.1.2 UDP Rules
UDP definitions follow certain rules:
1. UDPs can take only scalar input terminals (1 bit). Multiple input terminals are
permitted.
2. UDPs can have only one scalar output terminal (1 bit). The output terminal must
always appear first in the terminal list. Multiple output terminals are not allowed.
3. In the declarations section, the output terminal is declared with the keyword
output. Since sequential UDPs store state, the output terminal must also be
declared as a reg.
4. The inputs are declared with the keyword input.
5. The state in a sequential UDP can be initialized with an initial statement. This
statement is optional. A 1-bit value is assigned to the output, which is declared as
reg.
6. The state table entries can contain values 0, 1, or x. UDPs do not handle z values.
z values passed to a UDP are treated as x values.
7. UDPs are defined at the same level as modules. UDPs cannot be defined inside
modules. They can be instantiated only inside modules. UDPs are instantiated
exactly like gate primitives.
8. UDPs do not support inout ports.
Both combinational and sequential UDPs must follow the above rules. In the following
sections, we will discuss the details of combinational and sequential UDPs.
[ Team LiB ]
[ Team LiB ]
12.2 Combinational UDPs
Combinational UDPs take the inputs and produce the output value by looking up the
corresponding entry in the state table.
12.2.1 Combinational UDP Definition
The state table is the most important part of the UDP definition. The best way to explain
a state table is to take the example of an and gate modeled as a UDP. Instead of using the
and gate provided by Verilog, let us define our own and gate primitive and call it
udp_and.
Example 12-1 Primitive udp_and
//Primitive name and terminal list
primitive udp_and(out, a, b);
//Declarations
output out; //must not be declared as reg for combinational UDP
input a, b; //declarations for inputs.
//State table definition; starts with keyword table
table
//The following comment is for readability only
//Input entries of the state table must be in the
//same order as the input terminal list.
// a b : out;
0 0 : 0;
0 1 : 0;
1 0 : 0;
11 : 1;
endtable //end state table definition
endprimitive //end of udp_and definition
Compare parts of udp_and defined above with the parts discussed in Figure 12-1
. The
missing parts are that the output is not declared as reg and the initial statement is absent.
N
ote that these missing parts are used only for sequential UDPs, which are discussed
later in the chapter.
ANSI C style declarations for UDPs are also supported. This style allows the declarations
of a primitive port to be combined with the port list. Example 12-2
shows an example of
an ANSI C style UDP declaration.
Example 12-2 ANSI C Style UDP Declaration
//Primitive name and terminal list
primitive udp_and(output out,
input a,
input b);
endprimitive //end of udp_and definition
12.2.2 State Table Entries
In order to understand how state table entries are specified, let us take a closer look at the
state table for udp_and. Each entry in the state table in a combinational UDP has the
following pseudosyntax:
<input1> <input2> <inputN> : <output>;
N
ote the following points about state table entries:
1. The <input#> values in a state table entry must appear in the same order as they
appear in the input terminal list. It is important to keep this in mind while
designing UDPs, because designers frequently make mistakes in the input order
and get incorrect results.
2. Inputs and output are separated by a ":".
3. A state table entry ends with a ";".
4. All possible combinations of inputs, where the output produces a known value,
must be explicitly specified. Otherwise, if a certain combination occurs and the
corresponding entry is not in the table, the output is x. Use of default x output is
frequently used in commercial models. Note that the table for udp_and does not
handle the case when a or b is x.
In the Verilog and gate, if a = x and b = 0, the result should be 0, but udp_and will give
an x as output because the corresponding entry was not found in the state table, that is,
the state table was incompletely specified. To understand how to completely specify all
possible combinations in a UDP, let us define our own or gate udp_or, which completely
specifies all possible cases. The UDP definition for udp_or is shown in Example 12-3
.
Example 12-3 Primitive udp_or
primitive udp_or(out, a, b);
output out;
input a, b;
table
// a b : out;
0 0 : 0;
0 1 : 1;
1 0 : 1;
11 : 1;
x 1 : 1;
1 x : 1;
endtable
endprimitive
N
otice that the above example covers all possible combinations of a and b where the
output is not x. The value z is not allowed in a UDP. The z values on inputs are treated as
x values.
12.2.3 Shorthand Notation for Don't Cares
In the above example, whenever one input is 1, the result of the OR operation is 1,
regardless of the value of the other input. The ? symbol is used for a don't care condition.
A ? symbol is automatically expanded to 0, 1, or x. The or gate described above can be
rewritten with the ? symbol.
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
12.2.4 Instantiating UDP Primitives
Having discussed how to define combinational UDPs, let us take a look at how UDPs are
instantiated. UDPs are instantiated exactly like Verilog gate primitives. Let us design a 1-
bit full adder with the udp_and and udp_or primitivesdefined earlier. The 1-
b
it full adder
code shown in Example 12-4
is identical to Example 5-7 on page 75 except that the
standard Verilog primitives and and or primitives are replaced with udp_and and upd_or
primitives.
Example 12-4 Instantiation of udp Primitives
// Define a 1-bit full adder
module fulladd(sum, c_out, a, b, c_in);
// I/O port declarations
output sum, c_out;
input a, b, c_in;
// Internal nets
wire s1, c1, c2;
// Instantiate logic gate primitives
xor (s1, a, b);//use Verilog primitive
udp_and (c1, a, b); //use UDP
xor (sum, s1, c_in); //use Verilog primitive
udp_and (c2, s1, c_in); //use UDP
udp_or (c_out, c2, c1);//use UDP
endmodule
12.2.5 Example of a Combinational UDP
We discussed two small examples of combinational UDPs: udp_and and udp_or. Let us
design a bigger combinational UDP, a 4-to-1 multiplexer. A 4-to-1 multiplexer was
designed with gates in Section 5.1.4
, Examples. In this section, we describe the
multiplexer as a UDP. Note that the multiplexer is ideal because it has only one output
terminal. The block diagram and truth table for the multiplexer are shown in Figure 12-2
.
Figure 12-2. 4-to-1 Multiplexer with UDP
The multiplexer has six inputs and one output. The Verilog UDP description for the
multiplexer is shown in Example 12-5
.
Example 12-5 Verilog Description of 4-to-1 Multiplexer with UDP
// 4-to-1 multiplexer. Define it as a primitive
primitive mux4_to_1 ( output out,
input i0, i1, i2, i3, s1, s0);
table
// i0 i1 i2 i3, s1 s0 : out
1 ? ? ? 0 0 : 1 ;
0 ? ? ? 0 0 : 0 ;
? 1 ? ? 0 1 : 1 ;
? 0 ? ? 0 1 : 0 ;
? ? 1 ? 1 0 : 1 ;
? ? 0 ? 1 0 : 0 ;
? ? ? 111 : 1 ;
? ? ? 0 11 : 0 ;
? ? ? ? x ? : x ;
? ? ? ? ? x : x ;
endtable
endprimitive
It is important to note that the state table becomes large very quickly as the number of
inputs increases. Memory requirements to simulate UDPs increase exponentially with the
number of inputs to the UDP. However, UDPs offer a convenient feature to implement an
arbitrary function whose truth table is known, without extracting actual logic and by
using logic gates to implement the circuit.
The stimulus shown in Example 12-6
is applied to test the multiplexer.
Example 12-6 Stimulus for 4-to-1 Multiplexer with UDP
// Define the stimulus module (no ports)
module stimulus;
// Declare variables to be connected
// to inputs
reg IN0, IN1, IN2, IN3;
reg S1, S0;
// Declare output wire
wire OUTPUT;
// Instantiate the multiplexer
mux4_to_1 mymux(OUTPUT, IN0, IN1, IN2, IN3, S1, S0);
// Stimulate the inputs
initial
begin
// set input lines
IN0 = 1; IN1 = 0; IN2 = 1; IN3 = 0;
#1 $display("IN0= %b, IN1= %b, IN2= %b, IN3= %b\n",IN0,IN1,IN2,IN3);
// choose IN0
S1 = 0; S0 = 0;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
// choose IN1
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
The output of the simulation is shown below.
IN0= 1, IN1= 0, IN2= 1, IN3= 0
S1 = 0, S0 = 0, OUTPUT = 1
S1 = 0, S0 = 1, OUTPUT = 0
S1 = 1, S0 = 0, OUTPUT = 1
S1 = 1, S0 = 1, OUTPUT = 0
[ Team LiB ]
. below.
IN0= 1, IN1= 0, IN2= 1, IN3= 0
S1 = 0, S0 = 0, OUTPUT = 1
S1 = 0, S0 = 1, OUTPUT = 0
S1 = 1, S0 = 0, OUTPUT = 1
S1 = 1, S0 = 1, OUTPUT. i0, i1, i2, i3, s1, s0);
table
// i0 i1 i2 i3, s1 s0 : out
1 ? ? ? 0 0 : 1 ;
0 ? ? ? 0 0 : 0 ;
? 1 ? ? 0 1 : 1 ;
? 0 ? ? 0 1 : 0 ;
? ? 1 ? 1