Tutorials

A task that may or may not consume simulation time, returns values as output or inout argument type, and may or may not take arguments.

Syntax:

``````// Style 1
...

// Style 2
input <port_list>;
inout <port_list>;
output <port_list>;
...

### A Basic Example with arguments and directions

``````module task_example;

task compare(input int a, b, output done);
if(a>b)
\$display("a is greater than b");
else if(a<b)
\$display("a is less than b");
else
\$display("a is equal to b");

#10;
done = 1;

initial begin
bit done;
compare(10,10, done);
if(done) \$display("comparison completed at time = %0t", \$time);
compare(5,9, done);
if(done) \$display("comparison completed at time = %0t", \$time);
compare(9,5, done);
if(done) \$display("comparison completed at time = %0t", \$time);
end
endmodule``````

Output:

``````a is equal to b
comparison completed at time = 10
a is less than b
comparison completed at time = 20
a is greater than b
comparison completed at time = 30``````

``````module task_example;

task compare(input int a, b, output bit [1:0] done);
if(a>b) begin
done = 2'h1;
return;
\$display("a > b comparison completed");
end

if(a<b) begin
done = 2'h2;
return;
\$display("a < b comparison completed");
end

if(a == b) begin
done = 2'h3;
return;
\$display("a == b comparison completed");
end

initial begin
bit [1:0] done;
int a, b;

repeat(5) begin
a = \$urandom_range(5, 20);
b = \$urandom_range(5, 20);
\$display("input a = %0d, input b = %0d", a, b);
compare(a,b, done);
if(done == 2'h1) \$display("a is greater than b");
if(done == 2'h2) \$display("a is less than b");
if(done == 2'h3) \$display("a is equal to b");
\$display("------------------------");
end
end
endmodule``````

Output:

``````input a = 11, input b = 5
a is greater than b
------------------------
input a = 15, input b = 10
a is greater than b
------------------------
input a = 8, input b = 12
a is less than b
------------------------
input a = 6, input b = 17
a is less than b
------------------------
input a = 9, input b = 9
a is equal to b
------------------------``````

1. By default, tasks declared are static except they are declared inside a class scope. If the task is declared within class scope, they behave like an automatic task by default unless they are specifically mentioned as static tasks. We will discuss more on this concept in class (OOP) concepts.
2. All variables declared in a static task are static variables unless they are specifically mentioned as an automatic variable.
3. All variables declared in an automatic task are automatic variables unless they are specifically mentioned as a static variable.

To understand the scope of variables in tasks, static and automatic variables are declared in each static, automatic, and normal task.

``````module task_example;

static int count_A;
automatic int count_B;
int count_C;

count_A++;
count_B++;
count_C++;
\$display("Static: count_A = %0d, count_B = %0d, count_C = %0d", count_A, count_B, count_C);

static int count_A;
automatic int count_B;
int count_C;

count_A++;
count_B++;
count_C++;
\$display("Automatic: count_A = %0d, count_B = %0d, count_C = %0d", count_A, count_B, count_C);

static int count_A;
automatic int count_B;
int count_C;

count_A++;
count_B++;
count_C++;
\$display("Normal: count_A = %0d, count_B = %0d, count_C = %0d", count_A, count_B, count_C);

initial begin
increment_static();
increment_static();
increment_static();
increment_automatic();
increment_automatic();
increment_automatic();
\$display("\nCalling normal tasks: without static/automatic keyword");
increment();
increment();
increment();

// count_A
\$display("\nStatic: count_A = %0d", increment_static.count_A);
\$display("Automatic: count_A = %0d", increment_automatic.count_A);
\$display("Normal: count_A = %0d", increment.count_A);

// count_B: Hierarchical reference to automatic variable is not legal.
/*
\$display("\nStatic: count_B = %0d", increment_static.count_B);
\$display("Automatic: count_B = %0d", increment_automatic.count_B);
\$display("Normal: count_B = %0d", increment.count_B);
*/

// count_C
\$display("\nStatic: count_C = %0d", increment_static.count_C);
//\$display("Automatic: count_C = %0d", increment_automatic.count_C); // illegal reference to automatic variable
\$display("Normal: count_C = %0d", increment.count_C);
end
endmodule``````

Output:

``````Calling static tasks
Static: count_A = 1, count_B = 1, count_C = 1
Static: count_A = 2, count_B = 1, count_C = 2
Static: count_A = 3, count_B = 1, count_C = 3

Automatic: count_A = 1, count_B = 1, count_C = 1
Automatic: count_A = 2, count_B = 1, count_C = 1
Automatic: count_A = 3, count_B = 1, count_C = 1

Calling normal tasks: without static/automatic keyword
Normal: count_A = 1, count_B = 1, count_C = 1
Normal: count_A = 2, count_B = 1, count_C = 2
Normal: count_A = 3, count_B = 1, count_C = 3

Static: count_A = 3
Automatic: count_A = 3
Normal: count_A = 3

Static: count_C = 3
Normal: count_C = 3``````

A pass by value argument passing mechanism does copy arguments locally and operate on those variables. Any changes in variables in the task will not be visible outside of the task.

``````module task_example;
int a, b;
int out;

task tk_multiply(int a, b, output int out);
a = a*b; //value of a is updated, it won't update global variables a and b
out = a;

initial begin
a = 5;
b = 6;

tk_multiply(a,b, out);
\$display("Task: out = %0d for a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

``Task: out = 30 for a = 5 and b = 6``

Default values in the argument:

If no arguments are passed, default values are considered in the function/ task otherwise, default values will be overridden in case of passing any arguments

``````module task_example;
int a, b;
int out;

task tk_multiply(int a = 5, b = 6, output int out);
a = a*b; //value of a is updated, it won't update global variables a and b
out = a;

initial begin
a = 5;
b = 6;

tk_multiply(a,b, out);
\$display("Task: out = %0d for a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

``Task: out = 30 for a = 5 and b = 6``

A pass by reference argument passing mechanism does not copy arguments locally but reference to the original arguments is passed. This also means that any change in values for the argument inside the subroutine will affect the original values of the variables,

The ref keyword is used to denote pass by reference arguments.

``````module task_example;
int a, b;
int out;

task automatic multiply(ref int a, b, output int out);
a = a*b; //value of a is updated, it won't update global variables a and b
out = a;

initial begin
a = 5;
b = 6;
multiply(a,b, out);
\$display("Multiplication: out = %0d, a = %0d and b = %0d", out, a, b); //observe value of a is updated
end
endmodule``````

Output:

``Multiplication: out = 30, a = 30 and b = 6``

### With const ref keyword

To ensure that the subroutine should not update any values, the ‘const ref’ keyword is used.

``````module task_example;
int a, b;
int out;

task automatic tk_multiply(const ref int a, b, output int out);
a = a*b; // expects compilation error when subroutine tries to modify argument value.
out = a;

initial begin
a = 5;
b = 6;

tk_multiply(a,b, out);
\$display("Function: out = %0d, a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

`````` a = a*b; // expects compilation error when subroutine tries to modify argument value.
|
*E,CONASN (testbench.sv,9|4): Constant variable cannot be assigned outside of an initialization.``````

It is illegal to use pass by reference argument for static tasks.

``````module task_example;
int a, b;
int out;

task tk_multiply(ref int a, b, output int out);
a = a*b; // static task
out = a;

initial begin
a = 5;
b = 6;

tk_multiply(a,b, out);
\$display("Task: out = %0d, a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

``````  task tk_multiply(ref int a, b, output int out);
|
*E,REFANA (testbench.sv,8|27): reference argument is illegal inside static task-function declaration.
task tk_multiply(ref int a, b, output int out);
|
*E,REFANA (testbench.sv,8|30): reference argument is illegal inside static task-function declaration.``````

## Similarities between function and task

1. Can declare a static variable in automatic function
2. Can declare an automatic variable in a static function
3. Both support default arguments and arguments have input direction by default unless it is specified.
4. Multiple statements can be written without using a begin .. end block.
5. The default argument data type is logic unless it is specified.
6. Passing value by name, reference, value, and position is allowed.
7. The “return” keyword is used to premature return from a task or function. The only difference is that function can return a value and a task can not return any value when the “return” keyword is used.
8. By default tasks and functions are automatic in classes and they are commonly known as class methods.

## Difference between function and task

 Function Task Can not contain simulation delay, so execute in the same time unit. can or can not contain a simulation time delay. Can return a single value Can return multiple values as output or inout argument. Can not call another task Can call another function or task

System Verilog Tutorials