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.
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
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 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
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
xcelium> run i=1 i=1 i=1 i=1 xmsim: *W,RNQUIE: Simulation is complete.
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
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
xcelium> run Hello World Hello World xmsim: *W,RNQUIE: Simulation is complete.
Although Verilog functions and tasks serve similar purposes, there are a few notable differences between them.
|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
#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)].
Tasks can be disabled using the
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  T_Task started  S_Task started  S_Task ended xmsim: *W,RNQUIE: Simulation is complete.