Most programming languages usually use tasks and
functions to execute common procedures from different places in a
description. Considering the analogy of FORTRAN, tasks are similar to
subroutines and functions are similar to function. Verilog provides
tasks and functions to break up large behavioral designs into smaller
pieces. Tasks and functions allow a designer to abstract Verilog
codes 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.
Differences of Tasks and Functions
Tasks and functions serve different purpose in
Verilog, and the following table describes differences between tasks and functions in Verilog.
Functions | Tasks |
---|---|
can enable another function but not another task | can call or enable other tasks and functions |
always execute in 0 simulation time | may execute in non-zero simulation time |
must not contain delay, event, or timing control statements | may contain delay, event, wait or timing control statements |
must have at least 1 input argument, or many inputs | may have no or more arguments of type input, output, or inout |
always return a single value, cannot have output or inout arguments | do not return a value, but can pass multiple values through output and inout arguments |
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 Verilog code is purely combinational, executes in 0 simulation time, and provides exactly 1 output. Function are typically used for conversions and commonly used for calculations.
In addition, they can have local variables, registers, time variables, integers, real, or events. Tasks or functions cannot have wires, and 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.
Tasks
Tasks are generally known as procedures or subroutines. Tasks are declared with keywords task and end task. Data is passed into the
task, the processing done, and the result returned. Tasks have to be
specifically called, with data ins and outs, rather than just wired
in to the general netlist. Included in the main body of code, they
can be called many times, reducing code repetition.
- It is possible to define a task in a separate file and use the compile directive 'include to include the task in the file which instantiates the task.
- The variables declared within the task are local to that task. The order of declaration within the task defines how the variables passed to the task by the caller are used.
- tasks can take, drive and source global variables, when no local variables are used. When local variables are used, basically output is assigned only at the end of task execution.
- tasks can be used for modeling both combinational and sequential logic.
- A task must be specifically called with a statement, it cannot be used within an expression as a function can.
Syntax of a task begins with keyword task and
ends with keyword endtask
- Inputs and outputs are declared after the keyword task.
- Local variables are declared after input and output declaration.
Task must be used if any one of the following conditions is true for the procedure:
- There are delay, timing, or event control construct in the procedure.
- The procedure has zero or more than one output arguments.
- The procedure has no input arguments.
Examples of Task
[1]. A simple Task---------------------
module simple_task();
task convert;
input [7:0] temp_in;
output [7:0] temp_out;
begin
temp_out = (9/5) *( temp_in + 32);
end
endtask
endmodule
[2]. Task Using Global Variable
-------------------------------
module task_global();
reg [7:0] temp_in;
reg [7:0] temp_out;
task covert;
begin
temp_out = (9/5) *( temp_in + 32);
end
endtask
endmodule
[3]. Calling a Task---------------------
Let's assume that the task in example 1 is stored in a file called mytask.v. Advantage of coding a task in a separate file, is that it can be used in multiple modules.
module task_calling (temp_a, temp_b, temp_c, temp_d);
input [7:0] temp_a, temp_c;
output [7:0] temp_b, temp_d;
reg [7:0] temp_b, temp_d;
`include "mytask.v"
always @ (temp_a)
begin
convert (temp_a, temp_b);
end
always @ (temp_c)
begin
convert (temp_c, temp_d);
end
endmodule
Functions
Functions are declared with 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.
Example of Functions
[1] Simple Function
-------------------------module simple_function(); unction myfunction;
input [7:0] a, b, c, d;
begin
myfunction = ((a+b) + (c-d));
end
endfunction
endmodule
[2]. Calling a Function
-----------------------
Let's assume that the function in example 1 is stored in a file called myfunction.v.
module function_calling (a, b, c, d, e, f);
input a, b, c, d, e;
output f;
wireg f;
`include "myfunction.v"
assign f = (myfunction (a, b, c, d)) ? e:0;
endmodule
Reference:
- Verilog HDL, A guide to Digital Design and Synthesis, 2nd edtion, Samir Palnitkar, SunSoft Press - A Prentice Hall Title.
- http://www.asic-world.com/verilog/task_func1.html
No comments:
Post a Comment