Verilog User Defined Primitives
A modeling technique whereby the user can virtually argument predefined gate primitives by designing and specifying new primitive elements called user-defined primitives (UDPs). These primitives are self-contained and do not instantiate other primitives or modules.
Verilog provides a standard set of primitives, such as AND, NAND, NOT, OR, and NOR, as a part of the language. These are also known as built-in primitives.
Instances of these new UDPs can be used in the same manner as the gate primitives to represent the circuit being modeled. This technique can reduce the amount of memory and improve simulation performance. The Verilog-XL algorithm accelerates the evaluation of these UDPs.
However, designers occasionally like to use their custom-built primitives when developing a design.
Each UDP has exactly one output, which can be in one of these states: 0, 1, or x. The tri-state value z is not supported. Any input that has the value Z will be treated as X.
These two types of behavior can be represented in user-defined primitives:
- Combinational UDP
- Sequential UDP
A sequential UDP uses the value of its inputs and the current value of its output to determine the next value of output.
Sequential UDPs provide an efficient and easy way to model sequential circuits such as latches and flip-flops.
A sequential UDP can model both level-sensitive and edge-sensitive behavior. The maximum number of inputs to a combinational UDP is 10. The maximum number of inputs to a sequential UDP is limited to 9 because the internal state counts as an input.
Syntax
UDP begins with the reserved word primitive and ends with endprimitive. Ports/terminals of primitive should follow. UDPs should be defined outside the module and endmodule.
UDP Rules
- UDP takes only scalar input terminals (1 bit).
- UDP can have only one scalar output. The output terminal must always appear first in the terminal list.
- The state in a sequential UDP is initialized with an initial statement.
- State table entries can contain values of 0, 1 or X. Z values passed to a UDP are treated as X values.
- UDPs are defined at the same level as modules.
- UDPs are instantiated exactly like gate primitives.
- UDPs do not support inout ports.
Verilog UDP Symbols
Verilog user-defined primitives can be written at the same level as module definitions, but never between module and endmodule. They can have many input ports but always one output port, and bi-directional ports are not valid. All port signals have to be scalar, which means they have to be 1-bit wide.
Hardware behavior is described as a primitive state table that lists out a different possible combination of inputs and their corresponding output within the table and endtable. Values of input and output signals are indicated using the following symbols.
Symbol | Comments |
---|---|
0 | Logic 0 |
1 | Logic 1 |
x | Unknown, can be either logic 0 or 1. It can be used as input/output or current state of sequential UDPs |
? | Logic 0, 1 or x. It cannot be the output of any UDP |
– | No change, only allowed in the output of a UDP |
ab | Change in value from a to b where a or b is either 0, 1, or x |
* | Same as ??, indicates any change in the input value |
r | Same as 01 -> rising edge on input |
f | Same as 10 -> falling edge on input |
p | Potential positive edge on input; either 0->1, 0->x, or x->1 |
n | Potential falling edge on input; either 1->0, x->0, 1->x |
Combinational UDP
In combinational UDPs, the output state is determined solely as a function of the current input states. Whenever an input changes state, the UDP is evaluated, and one of the state table rows is matched. The output state is set to the value indicated by that row. The maximum number of inputs to a Combinational UDP is 10.
Consider the following example, which defines a multiplexer with two data inputs, a control input. But there can only be a single output.
A ? indicates that the signal can be either 0, 1 or x and does not matter in deciding the final output.
Example
Below is a testbench module that instantiates the UDP and applies input stimuli to it.
Sequential UDP
Sequential UDP allows the mixing of the level-sensitive and edge-sensitive constructs in the same description. The output port should also be declared as reg type within the UDP definition and can be optionally initialized within an initial statement.
Sequential UDP takes the value of its inputs and the current value of its output to determine the next value of its output. The value of the output is also the internal state of the UDP.
Sequential UDPs have an additional field in between the input and output field, which is delimited by a “:” representing the current state.
Sequential UDP provides an easy and efficient way to model sequential circuits such as latches and flip-flops. The maximum number of inputs to a Sequential UDP is limited to 9 because the internal state counts as an input. There are two kinds of sequential UDPs.
1. Level-Sensitive UDPs
Level-sensitive sequential behavior is represented the same way as combinational behavior, except that the output is declared to be reg type, and there is an additional field in each table entry.
This new field represents the current state of the UDP. The output field in a sequential UDP represents the next state.
In the above code, a hyphen “-” on the last row of the table indicates no change in value for q+.
2. Edge-Sensitive UDPs
In level-sensitive behavior, the inputs and the current state’s values are sufficient to determine the output value.
Edge sensitive behavior differs in that changes in the output are triggered by specific transitions of the inputs.
A D flip-flop is modeled as a Verilog user-defined primitive in the example shown below. Note that the rising edge of the clock is specified by 01 or 0?
The UDP is instantiated and driven with random d input values in the testbench after a random number of clocks.
The output q follows the input d after 1 clock delay, which is the D flip-flop’s desired behavior.