Tutorials

A function that does not consume simulation time, returns a single value or an expression, and may or may not take arguments.

## Function types

1. Automatic functions
2. Static functions

Syntax:

``````// Style 1
function <return_type> <function_name> (input <port_list>,inout <port_list>, output <port_list>);
...
return <value or expression>
endfunction

// Style 2
function <return_type> <function_name> ();
input <port_list>;
inout <port_list>;
output <port_list>;
...
return <value or expression>
endfunction
``````

## Function Examples

### A Basic Example with arguments and directions

``````module function_example;

function compare(input int a, b);
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");
return 1; // Not mandatory to write
endfunction

initial begin
compare(10,10);
compare(5, 9);
compare(9, 5);
end
endmodule``````

Output:

``````a is equal to b
a is less than b
a is greater than b``````

### Premature Function Return Example

``````module function_example;

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

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

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

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);
done = compare(a,b);
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 = 10, input b = 17
a is less than b
------------------------
input a = 20, input b = 11
a is greater than b
------------------------
input a = 6, input b = 20
a is less than b
------------------------
input a = 7, input b = 15
a is less than b
------------------------
input a = 15, input b = 14
a is greater than b
------------------------``````

## Static and Automatic Functions

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

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

``````module function_example;

function static increment_static();
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);
endfunction

function automatic increment_automatic();
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);
endfunction

function increment();
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);
endfunction

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

//Accessing variables using function
// 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 functions
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

Calling automatic functions
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 functions: 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``````

## Void Functions

A function that returns no value is called a void function. The ‘void’ keyword is used in a function definition.

``````module function_example;

function void compare(input int a, b);
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");
endfunction

initial begin
compare(10,10);
compare(5, 9);
compare(9, 5);
end
endmodule``````

Output:

``````a is equal to b
a is less than b
a is greater than b``````

## Pass by value Functions

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

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

function int fn_multiply(int a, b);
a = a*b; //value of a is updated, it won't update global variables a and b
return a;
endfunction

initial begin
a = 5;
b = 6;
out = fn_multiply(a,b);
\$display("Function: out = %0d for a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

``Function: 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 function_example;
int a, b;
int out;

function int multiply(int a = 5, b = 6);
a = a*b; //value of a is updated, it won't update global variables a and b
return a;
endfunction

initial begin
out = multiply(); // Note: No arguments are passed
\$display("argument passed: out = %0d, a = %0d and b = %0d", out, a, b); //a and b values will be 0 since their values are not updated

a = 2;
b = 3;
out = multiply(a, b);
\$display("No arguments passed: out = %0d for a = %0d and b = %0d", out, a, b);
end
endmodule``````

Output:

``````argument passed: out = 30, a = 0 and b = 0
No arguments passed: out = 6 for a = 2 and b = 3``````

## Pass by Reference Functions

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 function_example;
int a, b;
int out;

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

initial begin
a = 5;
b = 6;
out = multiply(a,b);
\$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 function_example;
int a, b;
int out;

function automatic int fn_multiply(const ref int a, b);
a = a*b; // expects compilation error when subroutine tries to modify argument value.
return a;
endfunction

initial begin
a = 5;
b = 6;
out = fn_multiply(a,b);
\$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.``````

### With static function

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

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

function int multiply(ref int a, b); // static function
a = a*b;
return a;
endfunction

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

Output:

``````  function int multiply(ref int a, b); // static function
|
*E,REFANA (testbench.sv,8|32): reference argument is illegal inside static task-function declaration.
function int multiply(ref int a, b); // static function
|
*E,REFANA (testbench.sv,8|35): reference argument is illegal inside static task-function declaration.``````

## Pass by name and position

By default, SystemVerilog allows passing values in the same order which is specified in function.

But, passing a value by name and position allows arguments to be passed by name irrespective of their position mentioned in the function definition.

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

function void fn_pass(string name, int val);
\$display("Function: Values passed by name: %s, %0d", name, val);
endfunction

initial begin
fn_pass(.val(100), .name("Alex"));
end
endmodule``````

Output:

``Function: Values passed by name: Alex, 100``

System Verilog Tutorials