0% found this document useful (0 votes)
93 views8 pages

User Defined Primitives in Verilog

Verilog user-defined primitives (UDPs) allow designers to define custom logic elements. UDPs are defined using a primitive keyword and specify logic behavior through a state table. UDPs can model both combinational and sequential logic, such as latches and flip-flops. Sequential UDPs include the current state as an input and use it to determine the next state value. UDPs provide an efficient way to model custom elements and sequential circuits.

Uploaded by

Surya Prakash
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
93 views8 pages

User Defined Primitives in Verilog

Verilog user-defined primitives (UDPs) allow designers to define custom logic elements. UDPs are defined using a primitive keyword and specify logic behavior through a state table. UDPs can model both combinational and sequential logic, such as latches and flip-flops. Sequential UDPs include the current state as an input and use it to determine the next state value. UDPs provide an efficient way to model custom elements and sequential circuits.

Uploaded by

Surya Prakash
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

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 [Link] Video

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:

1. Combinational UDP
2. 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.

1. primitive UDP_name (output, input, ...);


2. port_declaration
3. [ reg output; ]
4. [ initial output = initial_value; ]
5. table
6. truth_table
7. endtable
8. endprimitive

UDP Rules

o UDP takes only scalar input terminals (1 bit).


o UDP can have only one scalar output. The output terminal must always appear
first in the terminal list.
o The state in a sequential UDP is initialized with an initial statement.
o State table entries can contain values of 0, 1 or X. Z values passed to a UDP are
treated as X values.
o UDPs are defined at the same level as modules.
o UDPs are instantiated exactly like gate primitives.
o 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.

1. // Output should always be the first signal in the port list


2. primitive mux (out, sel, a, b);
3. output out;
4. input sel, a, b;
5.
6. table
7. // sel a b out
8. 0 1 ? : 1;
9. 0 0 ? : 0;
10. 1 ? 0 : 0;
11. 1 ? 1 : 1;
12. x 0 0 : 0;
13. x 1 1 : 1;
14. endtable
15. endprimitive

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.

1. module tb;
2. reg sel, a, b;
3. reg [2:0] dly;
4. wire out;
5. integer i;
6.
7. // Instantiate the UDP
8. // UDPs cannot be instantiated with port name connection
9. mux u_mux ( out, sel, a, b);
10. initial begin
11. a <= 0;
12. b <= 0;
13.
14. $monitor("[T=%0t] a=%0b b=%0b sel=%0b out=%0b", $time, a, b, sel, out);
15.
16. // Drive a, b, and sel after different random delays
17. for (i = 0; i < 10; i = i + 1) begin
18. dly = $random;
19. #(dly) a <= $random;
20. dly = $random;
21. #(dly) b <= $random;
22. dly = $random;
23. #(dly) sel <= $random;
24. end
25. end
26. endmodule

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.

1. primitive d_latch (q, clk, d);


2. output q;
3. input clk, d;
4. reg q;
5.
6. table
7. // clk d q q+
8. 1 1 : ? : 1;
9. 1 0 : ? : 0;
10. 0 ? : ? : -;
11. endtable
12.
13. endprimitive

In the above code, a hyphen "-" on the last row of the table indicates no change in value
for q+.

1. module tb;
2. reg clk, d;
3. reg [1:0] dly;
4. wire q;
5. integer i;
6. d_latch u_latch (q, clk, d);
7. always #10 clk = ~clk;
8. initial begin
9. clk = 0;
10.
11. $monitor ("[T=%0t] clk=%0b d=%0b q=%0b", $time, clk, d, q);
12. #10; // To see the effect of X
13. for (i = 0; i < 50; i = i+1) begin
14. dly = $random;
15. #(dly) d <= $random;
16. end
17.
18. #20 $finish;
19. end
20. endmodule

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?

1. primitive d_flop (q, clk, d);


2. output q;
3. input clk, d;
4. reg q;
5. table
6. // clk d q q+
7. // obtain output on rising edge of clk
8. (01) 0 : ? : 0;
9. (01) 1 : ? : 1;
10. (0?) 1 : 1 : 1;
11. (0?) 0 : 0 : 0;
12.
13. // ignore negative edge of clk
14. (?0) ? : ? : -;
15.
16. // ignore data changes on steady clk
17. ? (??): ? : -;
18. endtable
19. endprimitive

The UDP is instantiated and driven with random d input values in the testbench after a
random number of clocks.

1. module tb;
2. reg clk, d;
3. reg [1:0] dly;
4. wire q;
5. integer i;
6. d_flop u_flop (q, clk, d);
7. always #10 clk = ~clk;
8. initial begin
9. clk = 0;
10. $monitor ("[T=%0t] clk=%0b d=%0b q=%0b", $time, clk, d, q);
11. #10; // To see the effect of X
12. for (i = 0; i < 20; i = i+1) begin
13. dly = $random;
14. repeat(dly) @(posedge clk);
15. d <= $random;
16. end
17. #20 $finish;
18. end
19. endmodule

The output q follows the input d after 1 clock delay, which is the D flip-flop's desired
behavior.

Common questions

Powered by AI

Combinational UDPs in Verilog determine their output solely based on the current input values, and do not maintain any internal state . This means that each input combination directly maps to a specific output as outlined in a truth table. Sequential UDPs, however, also consider the current output value as part of their state. They require an internal state representation, which makes them capable of modeling memory elements like latches or flip-flops. Consequently, sequential UDPs have a current state field in their state table entries and can respond to edge-sensitive input changes .

Sequential UDPs in Verilog model level-sensitive behavior by using a state table where the output reacts to the static values of inputs and can hold its state across input changes . A level-sensitive UDP, like a latch, continuously monitors its inputs and updates its output when conditions are met . In contrast, edge-sensitive behavior is modeled by making the output react specifically to changes or transitions in input values, such as rising or falling edges. This is typical in modeling devices like flip-flops, where the transition from one clock state to another triggers output changes . The key difference lies in continuous monitoring versus being responsive to specific state changes at the input .

To instantiate a Verilog primitive within a module, the primitive name is used followed by a list of output and input signals in order. For example, using a UDP named 'mux' would look like: mux u_mux (out, sel, a, b). Importantly, UDPs cannot be instantiated using named port connections, which means the ports must follow sequence rather than name mapping . Also, because UDPs do not support bi-directional inout ports, designs must be planned so that output is indeed meant as a one-way data flow .

User-defined primitives (UDPs) in Verilog allow users to create custom primitive elements that function similarly to Verilog's built-in primitives like AND, OR, and NOT gates . Unlike built-in primitives, UDPs enable designers to represent additional logic that may not be available in the standard library, improving simulation performance and reducing memory usage. UDPs can either be combinational, where the output is determined solely by the input, or sequential, where the output depends on both the input and the prior output state .

The '?' symbol in a Verilog UDP's state table represents an indeterminate logic value, which can be 0, 1, or x . It is used to indicate that a particular input condition does not affect the output or can be treated as any value without impacting the decision logic of the UDP. In state tables, this allows the designer to specify outputs for a range of input scenarios without explicitly listing each permutation, thus providing a level of abstraction and flexibility .

Using Verilog user-defined primitives (UDPs) can reduce the complexity of gate logic in circuits by allowing designers to encapsulate complex logic into simpler elements . This abstraction reduces the overall memory usage and enhances simulation performance, as the underlying primitive logic can be evaluated more quickly than more intricate gate-based module instantiations . Additionally, UDPs can be optimized at the implementation level, making them more efficient for certain applications than re-creating equivalent logic from multiple standard gates each time they are needed .

Using a sequential UDP can be more advantageous in scenarios where a simple memory element, like a latch or a flip-flop, needs to be represented with minimal overhead. These UDPs offer a more efficient modeling approach than complex module definitions where simplicity, reduced debugging complexity, and simulation speed are prioritized . Complex module definitions for these elements might introduce unnecessary complexity where sequential UDPs can represent the required behavior concisely with proper state management within the UDP itself .

In Verilog UDPs, the tri-state value 'z' is not supported because UDPs are designed for simpler logic states that do not include floating or disconnected states . When a 'z' value is encountered as an input to a UDP, it is treated as an unknown state 'x'. This simplifies the logic design by focusing on definite states and ensuring predictable simulation behavior .

Combinational UDPs in Verilog can have a maximum of 10 scalar inputs, while sequential UDPs are limited to 9 inputs due to the internal state counting as an additional input . These limitations exist to ensure that the state table size remains manageable and that the logic remains tractable for efficient performance during simulations. Larger numbers of inputs would exponentially increase the number of potential logic states, complicating the design and potentially degrading performance .

A Verilog UDP definition must begin with the reserved word 'primitive' and end with 'endprimitive' . The output port should be declared first in the terminal list and must be scalar (1-bit). Inputs to a UDP must also be scalar, with a maximum of 10 inputs for combinational UDPs and 9 for sequential UDPs due to the inclusion of an internal state . UDPs do not support inout ports, and any use of the tri-state 'z' value in inputs is automatically converted to 'x' .

You might also like