0% found this document useful (0 votes)
1 views11 pages

Module 5b

Chapter 8 discusses tasks and functions in Verilog, highlighting their differences and usage in behavioral design. Tasks can have input, output, and inout arguments, may contain delays, and can be invoked from other tasks, while functions are limited to input arguments, execute in zero simulation time, and return a single value. The chapter also covers task and function declarations, examples, and the concept of automatic tasks and functions for concurrent calls.

Uploaded by

Rockstar gamer
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)
1 views11 pages

Module 5b

Chapter 8 discusses tasks and functions in Verilog, highlighting their differences and usage in behavioral design. Tasks can have input, output, and inout arguments, may contain delays, and can be invoked from other tasks, while functions are limited to input arguments, execute in zero simulation time, and return a single value. The chapter also covers task and function declarations, examples, and the concept of automatic tasks and functions for concurrent calls.

Uploaded by

Rockstar gamer
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
You are on page 1/ 11

Chapter 8.

Tasks and Functions


A designer is frequently required to implement the same functionality at many places in a
behavioral design. This means that the commonly used parts should be abstracted into
routines and the r outines must be invoked instead of repeating the code. Most
programming languages provide procedures or subroutines to accomplish this. Verilog
provides tasks and functions to break up large behavioral designs into smaller pieces.
Tasks and functions allow the designer to abstract Verilog code that is used at many
places in the design.

Tasks have input, output, and inout arguments; functions have input arguments. Thus,
values can be passed into and out from tasks and functions. Considering the analogy of
FORTRAN, tasks are similar to SUBROUTINE and functions are similar to
FUNCTION.

Tasks and functions are included in the design hierarchy. Like named blocks, tasks or
functions can be addressed by means of hierarchical names.

Learning Objectives

• Describe the differences between tasks and functions.

• Identify the conditions required for tasks to be defined. Understand task


declaration and invocation.

• Explain the conditions necessary for functions to be defined. Understand function


declaration and invocation.

175
8.1 Differences between Tasks and Functions

Tasks and functions serve different purposes in Verilog. We discuss tasks and functions
in greater detail in the following sections. However, first it is important to understand
differences between tasks and functions, as outlined in Table 8-1.

Table 8-1. Tasks and Functions


Functions Tasks
A function can enable another function A task can enable other tasks and functions.
but not another task.
Functions always execute in 0 Tasks may execute in non-zero simulation
simulation time. time.
Functions must not contain any delay, Tasks may contain delay, event, or timing
event, or timing control statements. control statements.
Functions must have at least one input Tasks may have zero or more arguments of
argument. They can have more than one type input, output, or inout.
input.
unctions always return a single value. Tasks do not return with a value, but can
They cannot have output or inout pass multiple values through output and
arguments. inout arguments.

Both tasks and functions must be defined in a module and are local to the module. Tasks
are used for common Verilog code that contains delays, timing, event constructs, or
multiple output arguments. Functions are used when common Verilog code is purely
combinational, executes in zero simulation time, and provides exactly one output.
Functions are typically used for conversions and commonly used calculations.

Tasks can have input, output, and inout arguments; functions can have input arguments.
In addition, they can have local variables, registers, time variables, integers, real, or
events. Tasks or functions cannot have wires. Tasks and functions contain behavioral
statements only. Tasks and functions do not contain always or initial statements but are
called from always blocks, initial blocks, or other tasks and functions.

176
8.2 Tasks

Tasks are declared with the keywords task and endtask. Tasks must be used if any one of
the following conditions is true for the procedure:

• There are delay, timing, or event control constructs in the procedure.

• The procedure has zero or more than one output arguments.

• The procedure has no input arguments.

8.2.1 Task Declaration and Invocation

Task declaration and task invocation syntax are as follows.

Example 8-1 Syntax for Tasks

task_declaration ::=
task [ automatic ] task_identifier ;
{ task_item_declaration }
statement
endtask
| task [ automatic ] task_identifier ( task_port_list ) ;
{ block_item_declaration }
statement
endtask

task_item_declaration ::=
block_item_declaration
| { attribute_instance } tf_input_declaration ;
| { attribute_instance } tf_output_declaration ;
| { attribute_instance } tf_inout_declaration ;
task_port_list ::= task_port_item { , task_port_item }
task_port_item ::=
{ attribute_instance } tf_input_declaration
| { attribute_instance } tf_output_declaration
| { attribute_instance } tf_inout_declaration
tf_input_declaration ::=
input [ reg ] [ signed ] [ range ] list_of_port_identifiers
| input [ task_port_type ] list_of_port_identifiers
tf_output_declaration ::=
output [ reg ] [ signed ] [ range ]
list_of_port_identifiers
| output [ task_port_type ] list_of_port_identifiers
tf_inout_declaration ::=
inout [ reg ] [ signed ] [ range ] list_of_port_identifiers
| inout [ task_port_type ] list_of_port_identifiers
task_port_type ::=
time | real | realtime | integer
177
I/O declarations use keywords input, output, or inout, based on the type of argument
declared. Input and inout arguments are passed into the task. Input arguments are
processed in the task statements. Output and inout argument values are passed back to the
variables in the task invocation statement when the task is completed. Tasks can invoke
other tasks or functions.

Although the keywords input, inout, and output used for I/O arguments in a task are the
same as the keywords used to declare ports in modules, there is a difference. Ports are
used to connect external signals to the module. I/O arguments in a task are used to pass
values to and from the task.

8.2.2 Task Examples

We discuss two examples of tasks. The first example illustrates the use of input and
output arguments in tasks. The second example models an asymmetric sequence
generator that generates an asymmetric sequence on the clock signal.

Use of input and output arguments

Example 8-2 illustrates the use of input and output arguments in tasks. Consider a task
called bitwise_oper, which computes the bitwise and, bitwise or, and bitwise ex-or of two
16-bit numbers. The two 16-bit numbers a and b are inputs and the three outputs are 16-
bit numbers ab_and, ab_or, ab_xor. A parameter delay is also used in the task.

Example 8-2 Input and Output Arguments in Tasks

//Define a module called operation that contains the task bitwise_oper


module operation;
...
...
parameter delay = 10;
reg [15:0] A, B;
reg [15:0] AB_AND, AB_OR, AB_XOR;

always @(A or B) //whenever A or B changes in value


begin
//invoke the task bitwise_oper. provide 2 input arguments A, B
//Expect 3 output arguments AB_AND, AB_OR, AB_XOR
//The arguments must be specified in the same order as they
//appear in the task declaration.
bitwise_oper(AB_AND, AB_OR, AB_XOR, A, B);
end
...
...
//define task bitwise_oper
task bitwise_oper;

178
output [15:0] ab_and, ab_or, ab_xor; //outputs from the task
input [15:0] a, b; //inputs to the task
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
...
endmodule

In the above task, the input values passed to the task are A and B. Hence, when the task is
entered, a = A and b = B. The three output values are computed after a delay. This delay
is specified by the parameter delay, which is 10 units for this example. When the task is
completed, the output values are passed back to the calling output arguments. Therefore,
AB_AND = ab_and, AB_OR = ab_or, and AB_XOR = ab_xor when the task is
completed.

Another method of declaring arguments for tasks is the ANSI C style. Example 8-3
shows the bitwise_oper task defined with an ANSI C style argument declaration.

Example 8-3 Task Definition using ANSI C Style Argument Declaration

//define task bitwise_oper


task bitwise_oper (output [15:0] ab_and, ab_or, ab_xor,
input [15:0] a, b);
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask

Asymmetric Sequence Generator

Tasks can directly operate on reg variables defined in the module. Example 8-4 directly
operates on the reg variable clock to continuously produce an asymmetric sequence. The
clock is initialized with an initialization sequence.

Example 8-4 Direct Operation on reg Variables

//Define a module that contains the task asymmetric_sequence


module sequence;
...
reg clock;
...
initial
init_sequence; //Invoke the task init_sequence
...
179
always
begin
asymmetric_sequence; //Invoke the task asymmetric_sequence
end
...
...
//Initialization sequence
task init_sequence;
begin
clock = 1'b0;
end
endtask

//define task to generate asymmetric sequence


//operate directly on the clock defined in the module.
task asymmetric_sequence;
begin
#12 clock = 1'b0;
#5 clock = 1'b1;
#3 clock = 1'b0;
#10 clock = 1'b1;
end
endtask
...
...
endmodule

8.2.3 Automatic (Re-entrant) Tasks

Tasks are normally static in nature. All declared items are statically allocated and they are
shared across all uses of the task executing concurrently. Therefore, if a task is called
concurrently from two places in the code, these task calls will operate on the same task
variables. It is highly likely that the results of such an operation will be incorrect.

To avoid this problem, a keyword automatic is added in front of the task keyword to
make the tasks re-entrant. Such tasks are called automatic tasks. All items declared inside
automatic tasks are allocated dynamically for each invocation. Each task call operates in
an independent space. Thus, the task calls operate on independent copies of the task
variables. This results in correct operation. It is recommended that automatic tasks be
used if there is a chance that a task might be called concurrently from two locations in the
code.

Example 8-5 shows how an automatic task is defined and used.

Example 8-5 Re-entrant (Automatic) Tasks

// Module that contains an automatic (re-entrant) task


// Only a small portion of the module that contains the task definition
// is shown in this example. There are two clocks.
180
// clk2 runs at twice the frequency of clk and is synchronous
// with clk.
module top;
reg [15:0] cd_xor, ef_xor; //variables in module top
reg [15:0] c, d, e, f; //variables in module top
-
task automatic bitwise_xor;
output [15:0] ab_xor; //output from the task
input [15:0] a, b; //inputs to the task
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
...
-
// These two always blocks will call the bitwise_xor task
// concurrently at each positive edge of clk. However, since
// the task is re-entrant, these concurrent calls will work correctly.
always @(posedge clk)
bitwise_xor(ef_xor, e, f);
-
always @(posedge clk2) // twice the frequency as the previous block
bitwise_xor(cd_xor, c, d);
-
-
endmodule

181
8.3 Functions

Functions are declared with the keywords function and endfunction. Functions are used if
all of the following conditions are true for the procedure:

• There are no delay, timing, or event control constructs in the procedure.

• The procedure returns a single value.

• There is at least one input argument.

• There are no output or inout arguments.

• There are no nonblocking assignments.

8.3.1 Function Declaration and Invocation

The syntax for functions is follows:

Example 8-6 Syntax for Functions

function_declaration ::=
function [ automatic ] [ signed ] [ range_or_type ]
function_identifier ;
function_item_declaration { function_item_declaration }
function_statement
endfunction
| function [ automatic ] [ signed ] [ range_or_type ]
function_identifier (function_port_list ) ;
block_item_declaration { block_item_declaration }
function_statement
endfunction
function_item_declaration ::=
block_item_declaration
| tf_input_declaration ;
function_port_list ::= { attribute_instance } tf_input_declaration {,
{ attribute_instance } tf_input_declaration }
range_or_type ::= range | integer | real | realtime | time

There are some peculiarities of functions. When a function is declared, a register with
name function_identifer is declared implicitly inside Verilog. The output of a function is
passed back by setting the value of the register function_identifer appropriately. The
function is invoked by specifying function name and input arguments. At the end of
function execution, the return value is placed where the function was invoked. The
optional range_or_type specifies the width of the internal register. If no range or type is
182
specified, the default bit width is 1. Functions are very similar to FUNCTION in
FORTRAN.

Notice that at least one input argument must be defined for a function. There are no
output arguments for functions because the implicit register function_identifer contains
the output value. Also, functions cannot invoke other tasks. They can invoke only other
functions.

8.3.2 Function Examples

We will discuss two examples. The first example models a parity calculator that returns a
1-bit value. The second example models a 32-bit left/right shift register that returns a 32-
bit shifted value.

Parity calculation

Let us discuss a function that calculates the parity of a 32-bit address and returns the
value. We assume even parity. Example 8-7 shows the definition and invocation of the
function calc_parity.

Example 8-7 Parity Calculation

//Define a module that contains the function calc_parity


module parity;
...
reg [31:0] addr;
reg parity;

//Compute new parity whenever address value changes


always @(addr)
begin
parity = calc_parity(addr); //First invocation of calc_parity
$display("Parity calculated = %b", calc_parity(addr) );
//Second invocation of calc_parity
end
...
...
//define the parity calculation function
function calc_parity;
input [31:0] address;
begin
//set the output value appropriately. Use the implicit
//internal register calc_parity.
calc_parity = ^address; //Return the xor of all address bits.
end
endfunction
...
...
endmodule

183
Note that in the first invocation of calc_parity, the returned value was used to set the reg
parity. In the second invocation, the value returned was directly used inside the $display
task. Thus, the returned value is placed wherever the function was invoked.

Another method of declaring arguments for functions is the ANSI C style. Example 8-8
shows the calc_parity function defined with an ANSI C style argument declaration.

Example 8-8 Function Definition using ANSI C Style Argument Declaration

//define the parity calculation function using ANSI C Style arguments


function calc_parity (input [31:0] address);
begin
//set the output value appropriately. Use the implicit
//internal register calc_parity.
calc_parity = ^address; //Return the xor of all address bits.
end
endfunction

Left/right shifter

To illustrate how a range for the output value of a function can be specified, let us
consider a function that shifts a 32-bit value to the left or right by one bit, based on a
control signal. Example 8-9 shows the implementation of the left/right shifter.

Example 8-9 Left/Right Shifter

//Define a module that contains the function shift


module shifter;
...
//Left/right shifter
`define LEFT_SHIFT 1'b0
`define RIGHT_SHIFT 1'b1
reg [31:0] addr, left_addr, right_addr;
reg control;

//Compute the right- and left-shifted values whenever


//a new address value appears
always @(addr)
begin
//call the function defined below to do left and right shift.
left_addr = shift(addr, `LEFT_SHIFT);
right_addr = shift(addr, `RIGHT_SHIFT);
end
...
...
//define shift function. The output is a 32-bit value.
function [31:0] shift;
input [31:0] address;
input control;
begin
//set the output value appropriately based on a control signal.
184
shift = (control == `LEFT_SHIFT) ?(address << 1) : (address >>
1);

end
endfunction
...
...
endmodule

8.3.3 Automatic (Recursive) Functions

Functions are normally used non-recursively . If a function is called concurrently from


two locations, the results are non-deterministic because both calls operate on the same
variable space.

However, the keyword automatic can be used to declare a recursive (automatic) function
where all function declarations are allocated dynamically for each recursive calls. Each
call to an automatic function operates in an independent variable space.Automatic
function items cannot be accessed by hierarchical references. Automatic functions can be
invoked through the use of their hierarchical name.

Example 8-10 shows how an automatic function is defined to compute a factorial.

Example 8-10 Recursive (Automatic) Functions

//Define a factorial with a recursive function


module top;
...
// Define the function
function automatic integer factorial;
input [31:0] oper;
integer i;
begin
if (operand >= 2)
factorial = factorial (oper -1) * oper; //recursive call
else
factorial = 1 ;
end
endfunction

// Call the function


integer result;
initial
begin
result = factorial(4); // Call the factorial of 7
$display("Factorial of 4 is %0d", result); //Displays 24
end
...
...
endmodule
185

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy