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.

FunctionTask
Cannot have time-controlling statements/delay, and hence executes in the same simulation time unitCan contain time-controlling statements/delay and may only complete at some other time
Cannot enable a task, because of the above ruleCan enable other tasks and functions
Should have atleast one input argument and cannot have output or inout argumentsCan have zero or more arguments of any type
Can return only a single valueCannot 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.

 Simulation Log
xcelium> run
[0] T_Task started
[60] S_Task started
[80] S_Task ended
xmsim: *W,RNQUIE: Simulation is complete.