8
Advance Verilog Topics

8.1 Delay Modeling and Programming

In actual hardware, different delays exist and broadly, delays can be divided into two types i.e., gate delays and wire or interconnection delays. During the design of any circuit, delays must be considered in the programming to match with actual hardware timings. With advancement of technology, timing constraints become crucial and hence need to be taken care of while programming. Verilog also has the facility to introduce delay while designing the circuits [12].

8.1.1 Delay Modeling

Three different types of delay modeling are available in Verilog:

  1. Distributed-delay modeling
  2. Lumped-delay modeling
  3. Pin-to-Pin-delay modeling or Path-delay modeling.

8.1.2 Distributed-Delay Model

This type of delay is specified with each element of the circuit. In the case of combinational circuits, each gate has its propagation delay and is specified within the statement of all gates used in the gate-level modeling style of Verilog.

As an example in the following circuit diagram shown in Figure 8.1, the distributed delay is indicated inside the image of all the gates. The Verilog code for the same is shown in Program P8.1.

Figure 8.1 A simple combinational circuit indicating distributed delay.

//Program P8.1
module distributed_delay (F,A,B,C,D);
output F;
input A,B,C,D;
wire w1,w2;
or #3 x1(w1,A,B);
or #3 x2(w2,C,D);
and #2 x3(F,w1,w2);
endmodule

The distributed delay can also be specified in the dataflow modeling style within the assignment statement as shown in Program P8.2 which is a re-written program of Program P8.1 in dataflow style for the same circuit shown in Figure 8.1.

//Program P8.2
module distributed_delay (F,A,B,C,D);
output F;
input A,B,C,D;
wire w1,w2;
assign #3 w1 = A&B;
assign #3 w2 = C&D;
assign #2 F = w1&w2;
endmodule

8.1.3 Lumped-Delay Model

Lumped delay is the overall delay associated with a particular circuit or module. As shown in Figure 8.2, only one delay is specified in the gate whose output is the final output of the circuit, which is calculated based on the overall delay from input to output (see Figure 8.1). Lumped delay is normally specified on the output gate. The Verilog code for the same is specified in Program P8.3.

Figure 8.2 A simple combinational circuit indicating lumped delay.

//Program P8.3
module lumped_delay (F,A,B,C,D);
output F;
input A,B,C,D;
wire w1,w2;
assign w1 = A&B;
assign w2 = C&D;
assign #5 F = w1&w2;
endmodule

If we compare Program P8.2 and Program P8.3, it can easily be seen that the delay specified for the AND gate is the sum of delays associated with the OR gate and AND gate.

8.1.4 Pin-to-Pin-Delay Model

Delay can also be specified in the pattern of delays from individual input to output. This type of delay specification is known as pin-to-pin delay or path delay. Figure 8.3 represents the possible paths from individual inputs to the output of the circuit shown in Figure 8.2.

Figure 8.3 Possible path from individual input to output.

Let us assume that the associated delay with each path is as follows:

path A-w1-F, delay = 5
path B-w1-F, delay = 6
path C-w2-F, delay = 7
path D-w2-F, delay = 8

Pin-to-pin delay or path delay is specified in the Verilog module using specific blocks. The specify block in any module can be introduced by using keywords specify and endspecify.

The statements for pin-to-pin delays or path delays can be written within these keywords. Program P8.4 shows the format of specify block.

//Program P8.4
module path_delay (F,A,B,C,D);
output F;
input A,B,C,D;
wire w1,w2;
specify

(A = > F) = 5;
(B = > F) = 6;
(C = > F) = 7;
(D = > F) = 8;
endspecify

assign w1 = A&B;
assign w2 = C&D;
assign #5 F = w1&w2;
endmodule

8.2 User-Defined Primitive (UDP)

Verilog has a number of built-in primitives that can be illustrated in modules viz. gate type (AND, NAND, OR, NOR, XOR, XNOR, etc.) and switch type (NMOS, PMOS, CMOS, etc.). Verilog enables the user to create their own primitives called user-defined primitives (UDP). In UDP, the user describes any logic with the help of a truth table. The syntax for the same is shown in Program P8.5.

//Program P8.5
Primitive name_of_UDP (output, input1, input2);
Declaration_of_ports
reg output;//optional
initial

output = some_initial_value;//optional
table

truthtable
endtable

endprimitive

Any UDP should begin with the keyword primitive followed by its name (selected by the user). Only one output followed by the number of inputs should be provided in the bracket. The declaration of ports as output or input need to be declared in the port-declaration section. Defining output port as reg and its initialization with some value is optional. This needs to be done in the case of sequential UDPs. The programming architecture of UDPs is defined in the form of a truth table from which the value of output can be determined for all possible combinations of the inputs. This starts with a keyword table and ends with the keyword endtable. The format of the table will be discussed in the upcoming section. UDPs can be divided into two types: combinational and sequential UDP.

8.2.1 Combinational UDPs

Combinational UDPs are those UDPs in which the output is determined by a logical combination of the inputs as in any combinational circuit. The only difference is that the UDP has only one output but the combinational circuit can have more than one.

8.2.1.1 Truth-Table Format

To understand the format of writing a truth table between keywords table and endtable, let’s start by creating a UDP of a 2-input AND gate and give it the name my_and. The UDP is shown in Program P8.6.

//Program P8.6
primitive my_and (f, a, b);
output f;
input a, b;
table

//a b: f

0 0: 0;
0 1: 0;
1 0: 0;
1 1:1;
endtable

endprimitive

In the above UDP of an AND gate, it can be seen that the line next to the keyword table is a comment (indicated by//) which means the name of the ports a, b, and f are not allowed to write inside the table. A few important points that need to be remembered while writing the truth table are:

  1. The sequence in which the values are written should be in the same sequence in which the input ports are declared.
  2. Values assigned to input ports are separated by a space.
  3. The value assigned to output should be separated from input values by a semicolon “:”.

Also, note that if the output value is not defined in the truth table for any input combination and that input combination occurred during simulation, x will be assigned to the output.

8.2.1.2 Values Assigned to Input Ports

In section 8.2.1, we have learned how to write a truth table in a UDP. Until now, we have considered values “0” and “1” only for the input. We are now going to consider other values “x” and “z” that are allowed in Verilog coding. Let’s rewrite the AND gate program again named as my_and2.

//Program P8.7
primitive my_and2(f, a, b);
output f;
input a, b;
table

//a b: f
0 0: 0;
0 1: 0;
1 0: 0;
1 1:1;
0 x: 0;
x 0: 0;
endtable

endprimitive

We can see in Program 8.7, that some entries include “x” at the input, but the output for the same is “0”. This is because we know from the property of an AND gate that if any input is “0” output must be “0”. For other combinations where one input is “1” and other input is “x” or both inputs are “x,” the output will be “x,” that’s why this has not been included in the table, as we know that, for the input combinations not available in the table, output will be by-default “x.” Any “z” value will be considered as “x.”

A shorthand notation “?” is also available which we can use in UDP to make a truth table to reduce the size of the table. An example of a 2 × 1 multiplexer is shown in Program P8.4 using “?.” Here, the “?” represents all possible values “0”,”1” and “x.” So, it reduces four different entries in the table to just one.

//Program P8.8
primitive mux2x1 (f, a, b, s);
output f;
input a, b, s;
table

//a b s: y
0 ? 0: 0;//“?” can be “0” or “1” or “x”
1 ? 0: 1;//“?” can be “0” or “1” or “x”
? 0 1: 0;//“?” can be “0” or “1” or “x”
? 1 1:1;//“?” can be “0” or “1” or “x”
endtable

endprimitive

The functionality of a multiplexer is to connect one input (out of many inputs) to the output, one at a time. The input is selected according to the value fed to the select line. So, if s = “0” whatever the value on input, a goes to the output independent of the value at b. Thus “?” is best suited value for b in the table where s = “0.” Similarly “?” is the best-suited value for a in the table where s = “1” as indicated in Program P8.8.

8.2.1.3 Instantiation of a Combinational UDP

The UDP can be instantiated in any Verilog module like a keyword. It is not compulsory to give the instance any name as in the case of a keyword. Let’s write a module for a half- adder circuit using the UDP created in Program P8.7.

//Program P8.9
module half_adder (a,b,sum,carry);
input a,b;
output sum,carry;

xor (sum,a,b);
my_and2 (carry, a,b);
endmodule

8.2.2 Sequential UDPs

Sequential UDPs are those UDPs in which the next output is decided by the combination logic of the current inputs and current output. Sequential UDPs are different from combinational UDPs in the following terms:

  1. the output port needs to be declared as reg.
  2. the output needs to be initialized by some value, either “0” or “1.”
  3. the values of inputs, current output, and next output indicated in the table are separated by a semicolon.

The sequential UDPs can be further divided into two types: Level sensitive and edge sensitive.

8.2.2.1 Level-sensitive Sequential UDPs

Level-sensitive sequential UDPs are those UDPs in which the next output depends on the level of the clock. If the level of the clock is “1,” the next output is computed according to current inputs and output but if the clock is “0,” the next output retains the value of the current output. As an example, the level-sensitive sequential UDP of a D flip-flop (F/F) is presented below in Program P8.10.

//Program P8.10
primitive dff (q, d, clock, rst);
output q;
input d, clock, rst;
reg q;
initial

q = 0;
table

//d clock rst: current q: next q
? ? 1: ?: 0;//reset condition
0 1 0: ?: 0;//clk level high
1 1 0: ?: 1;//clk level high
? 0 0: ?: -;//clk level low
endtable

endprimitive

D-F/F UDP, named as dff, has one output port q and three input ports d, clock, rst. Here, we can see that output port q needs to be declared as reg as it has to store the current value of the output (current q). The output q is also initialized with the value “0” which becomes the value of current q. If the reset (rst) is “1,” then the value of the next output will be “0” independent of the values of d, clock (clock), and current output. This is called the reset condition. If rst is “0” then its behavior depends on the level of the clk. If clock = “1” whatever on d goes to the next output, otherwise the next output retains the value of the current output. “-” symbol is used to indicate retention of the current output as the next output.

8.2.2.2 Edge-sensitive Sequential UDPs

Edge sensitive means the next output depends on the edge of the clock pulse (either + ve edge 0→1 or –ve edge 1→0). These are called + ve edge triggered or –ve edge triggered depending on whether the next output appears on the + ve or –ve edge of the clock, respectively.

As an example of a –ve edge triggered D-F/F, the UDP is shown below in Program P8.11.

//Program P8.11
primitive EDff (q, d, clk, rst);
output q;
input d, clk, rst;
reg q;
initial q = 0;
table

//d clk rst: current q: next q
? ? 1: ?: 0; //reset condition
? (0?) 0: ?: -; //ignore + ve transition of the clk
? (x1) 0: ?: -; //ignore unknown + ve transition of the clk
? (1x) 0: ?: -; //ignore unknown –ve transition of the clk
1 (10) 0: ?: 1; //next output appears at –ve edge of the clk
0 (10) 0: ?: 0; //next output appears at –ve edge of the clk
(??) 0 0: ?: 0; //ignore change in d when clk is stable
endtable

endprimitive

The transition of any value can be represented as (v1v2) in Table 8.1, where v1 and v2 are the two different values out of “0,”1,” and “z.” EDff represents the UDP of a -ve edge triggered D-F/F in which all possible transitions in the clk are being considered in the table. When the clk is stable and transition occurs at d, no change in the output takes place and is hence ignored. It is also important to note that transition at two different ports is not allowed at the same time.

Table 8.1

Shorthand symbolMeaning
?0 or 1 or x
-Retention of current state
*(??)
B0 or 1
R(01)
F(10)
P(01) or (0x) or (x1)
N(10) or (1x) or (x0)

8.2.3 Shorthands in UDP

The different shorthands that can be used in creating the UDP are shown in Table 8.1. So, wherever we have used the shorthand symbol, the meaning can be obtained from this table (if not explained in the text, try to use these symbols in creating different UDPs).

8.3 Task and Function

While undertaking a design project in Verilog, a user may have to implement the same activity/steps at different places. It is therefore required to save each particular functionality at a particular location and invoke or call the same functionality whenever required in the main program instead of repeating the same code every time. These types of programs/codes are generally known as subroutines and are facilitated in almost all languages. In Verilog, task and function are available to fulfill the requirements of subroutines.

8.3.1 Difference between Task and Function

A task is defined as a set of instructions/statements for performing a particular functionality and that will be used in the design repeatedly. For example, a particular task includes shifting the contents from one memory location to another, performing some arithmetical operations and saving the result at a different memory location.

A function is normally used to evaluate an expression/formula which gives a single output for a particular set of inputs. For example, a function can be created for an equation 4 × 2 + 3y2 + xy which needs to be evaluated many times for the different values of x and y. That is why the function returns only one single value when invoked.

The differences between task and function are summarized in Table 8.2. Understanding the differences mentioned in Table 8.2 will be more effective when we consider the examples given in the upcoming sections.

Table 8.2 Differences between task and function.

TaskFunction
Task can enable other task or function.A function cannot enable any task but can enable another function.
Simulation time for the execution of task can be non-zero.Simulation time for the execution of a function is always zero.
Tasks may contain event, timing-control, or delay statements.Functions must not contain any event, timing-control, or delay statements.
Tasks may have no output, input or inout, or many of them.At least one input is mandatory in function. It can have more than one input. Output or inout are not allowed.
No return value is there in a task but multiple values can be passed.Functions always return one single value.

Some similarities between task and function are:

  1. Both function and task are defined in a module and belong to that particular module.
  2. Wires are not used in any task or function. They are constructed only from behavioral statements.
  3. Initial and always statements are not used in task and function.
  4. Invoking of task and function is done inside the initial and always block or via another task or function.

8.3.2 Syntax of Task and Function Declaration

//Program P8.12 Task_Declaration_Syntax
task <task_name>;

< input-declaration>;
< output-declaration>;
< inout-declaration>;
< parameter-declaration>;
< reg-declaration>;
< time-declaration>;
< integer-declaration>;
< real-declaration>;
< event-declaration>;
begin
<statement_or_null>;
end
endtask

Declaration of the task starts with the keyword task and ends with keyword endtask. Task declaration is described in detail via Program P8.12. The name of the task is declared just after the keyword task followed by a semicolon (;). Input, output, and inout are declared to pass the values to and from the task. The rest are declared as per the requirement in the task statements. All declarations in any task are optional including input, output, and inout. A sequence of statements describing the task are declared between begin and end.

//Program P8.13 Function_Declaration_Syntax
function <range_or_type> <function-name>;
< input-declaration>;
< parameter-declaration>;
< reg-declaration>;
< time-declaration>;
< integer-declaration>;
< real-declaration>;
<statement including function-name>
endfunction

Declaration of function starts with keyword function and ends with keyword endfunction. Function declaration is described in detail via Program P8.13. The name of the function is very important because the return value is assigned to the function-name. That is why range or type can also be declared with the name of the function. Only input declaration is there and there is no output or inout. The rest are declared as per the requirement in the function statements. The function statement must include “function-name=” followed by the expression of input combinations. At least one input is mandatory in any function. A sequence of statements describing the function are declared between begin and end.

8.3.3 Invoking Task and Function

Declared task and function can be invoked in any module using the format given in Programs P8.14 and P8.15, respectively.

//Program P8.14 Task invocation Syntax
task_name (< outputs_from_the_task>, < input_to_the_task>);


//Program P8.15 Function Invocation Syntax
name_of_function (<inputs_to_the_function>);

8.3.4 Examples of Task Declaration and Invocation

To understand the declaration and invocation of task examples of task bitwise_oper is shown in Program P8.16.

//Program P8.16
module operation(ab-and, ab-or, ab-xor,a,b);
input [15:0] a, b;
output [15:0] ab-and, ab-or, ab-xor;
reg [15:0] ab-and, ab-or, ab-xor;
always @(a or b)
begin
bitwise_oper(ab-and, ab-or, ab-xor, a, b);//Task Invocation
end
task bitwise_oper;//Task declaration
output [15:0] ab-and, ab-or, ab-xor;
input [15:0] a, b;
begin
#10 ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
endmodule

8.3.5 Examples of Function Declaration and Invocation

To understand the declaration and invocation of task and function, an example of function check_parity is shown in Program P8.17.

//Program P8.17
module parity(parity,address);
input [31:0] address;
output parity;
reg parity;
always @(address)
begin
parity = check_parity(address); //function invocation
$display(“Parity calculated = %b”, check_parity(address)); //function invocation
end
function check_parity; //function declaration
input [31:0] addr;
begin
check_parity = ^address;
end
endfunction
endmodule

Review Questions

Q1 Delay modeling is important in Verilog HDL, why?

Q2 UDPs are important, why? Give any two advantages of creating UDPs in Verilog HDL.

Q3 How does the UDP for sequential circuits differ from the combinational circuit? Explain the answer with a suitable example.

Q4 Write a Verilog program of full adder using multiplexer as UDP.

Q5 Write a Verilog program of full subtractor using UDP of NOT, AND, OR and Ex-OR gate.

Multiple Choice Questions

Q1 The correct statement for lumped delay is:

  1. the delay is specified per element basis
  2. the delay is specified per module
  3. the delay is specified for specific path
  4. none of the above

Q2 Path delays are assigned in Verilog within the keywords:

  1. table, endtable
  2. fork, join
  3. task, endtask
  4. specify, endspecify

Q3 The incorrect statement for combinational UDPs:

  1. It can be used to create a library of user-defined primitives
  2. The output in combinational UDPs must be declared on reg
  3. The table can be inserted in combination UDPs with keyword table, endtable
  4. UDPs can be declared as inside the keyword primitive, endprimitive

Q4 The correct syntax of writing a truth table in sequential UDPs is:

  1. in1 in2: Q;
  2. in1 in2 clk: Q:Q+;
  3. in1 in2 (10);Q;Q+;
  4. in1, in2, clk:Q:Q+;

Q5 The meaning of (1x) related to clock transition is:

  1. denotes a transition from 0 to 0, 1, or X. Potential positive-edge transition.
  2. denotes a transition from x to 0, 1. Potential negative-edge transition.
  3. denotes any transition in signal value 0, 1, or X to 0,1, or X.
  4. denotes a transition from logic 1 to unknown X state.

References

  1. [1] Palnitkar, S. (1996). Verilog HDL. Upper Saddle River, NJ: Sunsoft Press.
  2. [2] Bala Tripura Sundari, B. and Padmanabhan, T.R. (2003). Design through Verilog HDL. Hoboken, NJ: Wiley.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset