07.Functions - vineethkumarv/SystemVerilog_Course GitHub Wiki

Functions

The main usage of a function is to write a piece of code that can be called at any time and n number of times by simply calling the function name which doesn't take any simulation time to execute.
Functions are return type that will return only a single value mentioned in the function declaration, if not mentioned then return a one-bit value

syntax :
initial
begin
function_name(arguments);
end

function <return_type(optional)> function_name(arguments);
statement1;
statement2;
.
.
statementN;
endfunction

limitations:

  • The code inside the functions is not allowed to have time-consuming statements like #, @, wait
  • can only return one value
  • cannot call a task from the function as the task is allowed to have time-consuming statements

There are a lot of variations to call a function

Calling a function with values as arguments

Example:

      int result;  
      initial  
      begin  
      result=sum(5,6);  
      $display("\treturned from function and");  
      $display("\tstored the value of sum in result");    
      $display("\n\t@ %0t ns, value of sum is %0d",$time,result);     
      end  
      function int sum(int var1,var2);    
      $display("entered into function");   
      return var1+var2;  
      endfunction   

Here in the above example function name is sum which is of return type int i.e., it has return a one int value only.

Flowchart:

01 (1)

                Flowchart.1- functions passing values  

output:

func pass by val1

          Fig.1- output for function with passing values as arguments  

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_val/func_pass_by_val.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_val/func_pass_by_val_log.log

In the above example, the result is a variable declared as int to store the result of the function sum.
when the sum function is executed, the simulator checks for the function named sum is present or not, if yes then compares the arguments and return the type of function if all match then it proceeds with statements of the function. Then the value 5 is stored in var1, and 6 is stored in var2 After entering into the function it will display entered into function, and next, it will return the value of var1+var2 which will be caught by the variable result and displayed in the next line.

Calling a function with variables as arguments

Example:

      int result,a=5,b=6;    
      initial  
      begin  
      $display("\tcalling the function");  
      result=sum(a,b);  
      $display("\treturned from function and");  
      $display("\tstored the value of sum in result");  
      $display("\n\t@ %0t ns, value of sum is %0d",$time,result);    
      end  
      function int sum(input int a,b);  
      $display("entered into function");   
      return a+b;  
      endfunction  

Flowchart:

02

                Flowchart.2- functions passing arguments as variables   

output:

func pass by variables1

          Fig.2- output for function with passing values as variables  

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_variables/func_pass_by_variables.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_variables/func_pass_by_variables_log.log

This is almost similar to the example of passing by values but here will just pass the values by storing the values in variables so that the same line can be reusable if needed and here the variables called in initial module a&b are different than the a&b in function i.e., they have separate memory if any change is made in function on variables a&b then it won't be reflected with values of main modules a&b until a&b are declared as global. Here in the functional declaration we also mentioned input for variables whereas in the first example we didn't mention it, so we can give the directions of arguments if necessary and only one output is possible for functions.

Calling a function with values from an expression

Example:

      initial  
      begin   
      $display("\n\t@ %0t ns, value of sum is %0d",$time,sum(5,6));    
      end  
      function int sum(int var1,var2);  
      $display("entered into function");   
      return var1+var2;  
      endfunction  

output:

func call from display1

          Fig.3- output for function call from an expression    

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_call_from_display/func_call_from_display.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_call_from_display/func_call_from_display_log.log

In the above example, we didn't use any variables to store the values of the return type of the function, function is called directly from the display statement where the return value is passed to the display statement or else can be used in any expression i.e., function can be called as part of an expression (if we want to add 3 values of 4,5,6 then we can use as 4+sum(5,6).)

Calling a function with variables with positional arguments

Example:

      initial  
      begin   
      result=sum(.var1(5),.var2(6));  
      $display("\treturned from function and");  
      $display("\tstored the value of sum in result");  
      $display("\n\t@ %0t ns, value of sum is %0d",$time,result);      
      end  
      function int sum(int var1,var2); 
      $display("entered into function");   
      return var1+var2;  
      endfunction  

output:

func pass by positional1

          Fig.4- output for function call passing positional arguments   

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_positonal/func_pass_by_positional.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_positonal/func_pass_by_positional_log.log

In the above example, we are calling the function using positional arguments i.e., value 5 is pointed to var1 of the function and 6 to var2 and then after works as a normal function only.

calling an automatic function

syntax:
function automatic function_name(arguments);

Example:

      module func_automatic();
          int result1,result2;
          function int factorial_static(int var1);
          if(var1>=2)
            result1=factorial_static(var1-1)*var1;
          else
            begin
              result1=1;
            end
            return result1;
          endfunction

          function automatic int factorial_automatic(int var1);
            if(var1>=2)
              result2=factorial_automatic(var1-1)*var1;
            else
            begin
              result2=1;
            end
            return result2;
          endfunction
        initial
        begin
          
            result1=factorial_static(5);
            result2=factorial_automatic(5);
          
          $display("factorial_static:%0d",result1);
          $display("factorial_automatic:%0d",result2);
        end
      endmodule: func_automatic  

Here we are using the function with an automatic keyword which means whenever the function is called the new memory is created whereas in static the same memory is used whenever the function is called.

output:

func fact static automatic

          Fig.5- output for automatic function     

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_automatic/func_automatic.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_automatic/func_automatic_log.log

In the above example, we created two functions one is static & other is automatic and calling the sum function twice in the fork so runs parallel and runs concurrently so in the static function the previous memory is overwritten with the old values so that's why lost the data of sum which is 5 but in automatic, it was showing as expected, so whenever automatic is used new memory is allocated for every call.

calling a function with variables with reference of variables

syntax:
function automatic data_type function_name(ref arguments);

Flowchart:

03

                Flowchart.3- functions passing arguments as variables with reference  

Example:

      int result,addend,augend;  
      initial  
      begin   
      addend=5;  
      augend=6;  
      $display("\tBefore calling function -> addend = %0d , augend = %0d",addend,augend);  
      $display("\tcalling the functions");  
      result=sum_without_ref(addend,augend);  
      $display("\tafter calling function without ref -> addend = %0d, augend =%0d",addend,augend);  
      result=sum_with_ref(addend,augend);  
      $display("\tafter calling function with ref -> addend = %0d, augend =%0d",addend,augend);  
      end  
      function automatic int sum_with_ref(ref int var1,var2);  
      int temp;  
      $display("\n\tentered into with ref function");  
      temp=var1;  
      var1=var2;  
      var2=temp;  
      $display("\tswapped variables by using ref ");  
      return var1+var2;  
      endfunction : sum_with_ref  

      function int sum_without_ref(input int var1,var2);  
      int temp;  
      $display("\n\tentered into without ref function");  
      temp=var1;  
      var1=var2;  
      var2=temp;  
      $display("\tswapped variables by without using ref ");  
      return var1+var2;  
      endfunction : sum_without_ref  

when calling the function by passing variables reference, need to mention the keywords automatic and as well as ref for the arguments as shown in the above example.

output:

func pass by ref1

          Fig.6- output for function call passing arguments with reference   

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_ref/func_pass_by_ref.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_pass_by_ref/func_pass_by_ref_log.log

In the above example, here trying to call the function by passing the variables reference which means the values addend and augend in the main module and in the automatic function both share the same space of memory. In the example mentioned both static and automatic were given the sum and swapped the variables which are performed in automatic but not in static function.

calling a function with a void return type

syntax:
//type casting
void'(function_name(arguments));
or
//declaring the function as void type which doesn't return any value.
function void function_name(arguments);

Example:

      initial  
      begin  
      display("\t ----output for function void return type-----");  
      display("\t passing string to function for displaying");  
      end  
      function void display(string str);  
      $display("%s",str);    
      endfunction: display  

output:

func return void1

          Fig.7- output for void function type     

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_return_void/func_return_void.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_return_void/func_return_void_log.log

In the example, we are calling the function but don't care about the return value of the function, but if we don't mention then the compiler will through warning so in that case will use the convert the function data type to void or else can ignore at function calling point by using the type conversion

Calling a function by passing an array

syntax:
data_type array_name[size];
function automatic return_type function_name(ref data_type array_name);

Example:

      int array[5];  
      void'(fun_arr(array));  
      $display("\treturned from function");  
      $display("\n\t@ %0t ns, Array elements = %0p",$time,array);  
      end  
      function automatic int fun_arr(ref int arr[5]);  
      $display("\tEntered the function");  
      foreach(arr[i])begin  
      arr[i]=i+1;  
      end  
      $display("\t values assigned to array elements starts from 1");  
      return 0;  
      endfunction  

In general, we can't return an array from a function, but can pass an array using pass-by-reference and can manipulate that array in the function as shown in this example. output:

func return arr1

          Fig.8- output for function passing an array through refrence 

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_return_arr/func_return_arr.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/func_return_arr/func_return_arr_log.log

In this example, calling the function which passes an array, initially took an empty array of int type so will have all 0's initially and in function assigning the values starting from 1 and incrementing by 1 value and assigning for each index of the array with help of foreach loop, here we used reference to pass the array so all the array elements can be manipulated in the function

Calling a function with variables that had default values

syntax:
function_name() function <return_type> function_name(varable1=deafult_value,variable2=default_value)

Example:

      initial
        begin
          $display("\t ----output for function passing by values through variables-----");
          $display("\tcalling the function");
          result=sum();
          $display("\treturned from function and");
          $display("\tstored the value of sum in result");
          $display("\n\t@ %0t ns, value of sum is %0d",$time,result);
        end

        function int sum(input int var1=2,var2=3);
          $display("\n\tentered into function ");
          return var1+var2;
        endfunction: sum

In this example, calling the function but not passing any values or variables, then in that case the two variables required for the function will take the default values assigned to them i.e., in this case 2 & 3 gives the sum as 5.

output:

02

          Fig.9- output for function which have default values for variables 

If the function is called without values and variables and the function does not have any default values then the simulator will throw an error as shown below.

03

          Fig.10- output for error for not mentioning default values    

Calling a task from a function

In general, calling a task from a function is illegal, the compiler will through an array but there is an exceptional case for that, the task can be called from a function by using a fork join_none as sown in the following example.

Example:

      initial  
      begin
      $display("\t@ %0t ns, In the initial block",$time);  
      $display("\tcalling function");  
      #1 void'(function_call);  
      end  

      function function_call;  
      fork  
      $display( "\t@ %0t ns I'm in function",$time);  
      $display("\t@ %0t ns, calling task from func",$time);  
      task_call;  
      join_none  
      endfunction  

      task task_call;  
      #1 $display( "\t@ %0t ns , I'm in task",$time);  
      #1 $display("\t@ %0t ns,leaving from task",$time);  
      endtask  

Flowchart:

05

                Flowchart.4- calling a task from the function  

output:

task from func1

          Fig.10- output for calling a task from function      

Github lab code link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/task_from_func/task_from_func.sv
Github lab output link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_SiliconCrew/functions/task_from_func/task_from_func_log.log

In the initial block, called a function that has some statements and calls a task inside the fork join_none so that the task from a function can be accomplished, here at 0 ns the simulator is in the initial block and a func is called, then @1 ns it printed that I'm in function and task is called @1ns in func and from there simulator goes to task, @2ns it prints I'm in task and waits for 1ns more and leaving the task.