A function
is meant to do some processing on the input and return a single value, whereas a task
is more general and can calculate multiple result values and return them using output and inout type arguments. Tasks can contain simulation time consuming elements such as @, posedge and others.
Syntax
A task need not have a set of arguments in the port list, in which case it can be kept empty.
// Style 1
task [name];
input [port_list];
inout [port_list];
output [port_list];
begin
[statements]
end
endtask
// Style 2
task [name] (input [port_list], inout [port_list], output [port_list]);
begin
[statements]
end
endtask
// Empty port list
task [name] ();
begin
[statements]
end
endtask
Static Task
If a task is static, then all its member variables will be shared across different invocations of the same task that has been launched to run concurrently
task sum (input [7:0] a, b, output [7:0] c);
begin
c = a + b;
end
endtask
// or
task sum;
input [7:0] a, b;
output [7:0] c;
begin
c = a + b;
end
endtask
initial begin
reg [7:0] x, y , z;
sum (x, y, z);
end
The task-enabling arguments (x, y, z) correspond to the arguments (a, b, c) defined by the task. Since a and b are inputs, values of x and y will be placed in a and b respectively. Because c is declared as an output and connected with z during invocation, the sum will automatically be passed to the variable z from c.
Automatic Task
The keyword automatic
will make the task reentrant, otherwise it will be static by default. All items inside automatic tasks are allocated dynamically for each invocation and not shared between invocations of the same task running concurrently. Note that automatic
task items cannot be accessed by hierarchical references.
For illustration, consider the static task display which is called from different initial
blocks that run concurrently. In this case, the integer variable declared within the task is shared among all invocations of the task and hence thev displayed value should increment for each invocation.
module tb;
initial display();
initial display();
initial display();
initial display();
// This is a static task
task display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
Simulation Log xcelium> run i=1 i=2 i=3 i=4 xmsim: *W,RNQUIE: Simulation is complete.
If the task is made automatic, each invocation of the task is allocated a different space in simulation memory and behaves differently.
module tb;
initial display();
initial display();
initial display();
initial display();
// Note that the task is now automatic
task automatic display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
Simulation Log xcelium> run i=1 i=1 i=1 i=1 xmsim: *W,RNQUIE: Simulation is complete.
Global tasks
Tasks that are declared outside all modules are called global tasks as they have a global scope and can be called within any module.
// This task is outside all modules
task display();
$display("Hello World !");
endtask
module des;
initial begin
display();
end
endmodule
Simulation Log xcelium> run Hello World ! xmsim: *W,RNQUIE: Simulation is complete.
If the task was declared within the module des, it would have to be called in reference to the module instance name.
module tb;
des u0();
initial begin
u0.display(); // Task is not visible in the module 'tb'
end
endmodule
module des;
initial begin
display(); // Task definition is local to the module
end
task display();
$display("Hello World");
endtask
endmodule
Simulation Log xcelium> run Hello World Hello World xmsim: *W,RNQUIE: Simulation is complete.
Difference between function
and task
Although Verilog functions and tasks serve similar purposes, there are a few notable differences between them.
Function | Task |
---|---|
Cannot have time-controlling statements/delay, and hence executes in the same simulation time unit | Can contain time-controlling statements/delay and may only complete at some other time |
Cannot enable a task, because of the above rule | Can enable other tasks and functions |
Should have atleast one input argument and cannot have output or inout arguments | Can have zero or more arguments of any type |
Can return only a single value | Cannot return a value, but can achieve the same effect using output arguments |
When a function attempts to call a task
or contain a time consuming statement, the compiler reports an error.
module tb;
reg signal;
initial wait_for_1(signal);
function wait_for_1(reg signal);
#10;
endfunction
endmodule
Simulation Log
#10;
|
xmvlog: *E,BADFCN (testbench.sv,7|4): illegal time/event control statement within a function or final block or analog initial block [10.3.4(IEEE)].
Disable Task
Tasks can be disabled using the disable
keyword.
module tb;
initial display();
initial begin
// After 50 time units, disable a particular named
// block T_DISPLAY inside the task called 'display'
#50 disable display.T_DISPLAY;
end
task display();
begin : T_DISPLAY
$display("[%0t] T_Task started", $time);
#100;
$display("[%0t] T_Task ended", $time);
end
begin : S_DISPLAY
#10;
$display("[%0t] S_Task started", $time);
#20;
$display("[%0t] S_Task ended", $time);
end
endtask
endmodule
When display task was launched by the first initial
block, T_DISPLAY started and got disabled when time reached 50 units. Immediately the next block S_DISPLAY started and ran to completion by 80 units.
xcelium> run [0] T_Task started [60] S_Task started [80] S_Task ended xmsim: *W,RNQUIE: Simulation is complete.