Pass by value is the default method through which arguments are passed into functions and tasks. Each subroutine retains a local copy of the argument. If the arguments are changed within the subroutine declaration, the changes do not affect the caller.
In pass by reference functions and tasks directly access the specified variables passed as arguments.Its like passing pointer of the variable.
example:
task pass(int i) // task pass(var int i) pass by reference
{
delay(10);
i = 1;
printf(" i is changed to %d at %d\n",i,get_time(LO) );
delay(10);
i = 2;
printf(" i is changed to %d at %d\n",i,get_time(LO) );
}
In verilog,method arguments takes as pass by value.The inputs are copyed when the method is called and the outputs are assigned to outputs when exiting the method.In SystemVerilog ,methods can have pass by reference.Arguments passed by reference are not copied into the subroutine area, rather, a reference to the original argument is passed to the subroutine. The subroutine can then access the argument data via the reference.
In the following example, variable a is changed at time 10,20 and 30. The method pass_by_val , copies only the value of the variable a, so the changes in variable a which are occurred after the task pass_by_val call, are not visible to pass_by_val. Method pass_by_ref is directly referring to the variable a. So the changes in variable a are visible inside pass_by_ref.
EXAMPLE:
program main();
int a;
initial begin
#10 a = 10;
#10 a = 20;
#10 a = 30;
#10 $finish;
end
task pass_by_val(int i);
forever
@i $display("pass_by_val: I is %0d",i);
endtask
task pass_by_ref(ref int i);
forever begin
@i $display("pass_by_ref: I is %0d",i);
end
endtask
initial begin
pass_by_val(a);
end
initial begin
pass_by_ref(a);
end
endprogram
RESULT:
pass_by_ref: I is 10
pass_by_ref: I is 20
pass_by_ref: I is 30
By default, SystemVerilog passes arrays by value, copying the entire array.
It is recommended to pass arrays by reference whenever possible for performance reasons.
If you want your function to modify the array, use ref.
If you want your function to read the array, use const ref.
Example:
module automatic test;
initial run();
function void run();
// Create some SystemVerilog arrays and populate them
int array[5];
int queue[$];
int assoc[int];
for (int i = 0; i < 5; i++) begin
array[i] = i;
queue[i] = i;
assoc[i] = i;
end
pass_by_value(array, queue, assoc);
$display("After pass by value:");
for (int i = 0; i < 5; i++) begin
$display("array[%0d]:%0d", i, array[i]);
$display("queue[%0d]:%0d", i, queue[i]);
$display("assoc[%0d]:%0d", i, assoc[i]);
end
pass_by_ref(array, queue, assoc);
$display("After pass by reference:");
for (int i = 0; i < 5; i++) begin
$display("array[%0d]:%0d", i, array[i]);
$display("queue[%0d]:%0d", i, queue[i]);
$display("assoc[%0d]:%0d", i, assoc[i]);
end
endfunction
// These functions try to modify the arrays.
// Default.
// A copy of the arrays is made in this function
function void pass_by_value(int array[5], int queue[$], int assoc[int]);
array[2] = 100;
queue[2] = 100;
assoc[2] = 100;
endfunction
// Original arrays are being referenced
function void pass_by_ref(ref int array[5], ref int queue[$], ref int assoc[int]);
array[3] = 100;
queue[3] = 100;
assoc[3] = 100;
endfunction
// Original arrays are being referenced
// And they can be read but cannot be modified in this function
function void pass_by_const_ref(const ref int array[5],
const ref int queue[$],
const ref int assoc[int]);
// Arrays cannot be modified in this function
// array[3] = 100;
// queue[3] = 100;
// assoc[3] = 100;
endfunction
endmodule
In pass by reference functions and tasks directly access the specified variables passed as arguments.Its like passing pointer of the variable.
example:
task pass(int i) // task pass(var int i) pass by reference
{
delay(10);
i = 1;
printf(" i is changed to %d at %d\n",i,get_time(LO) );
delay(10);
i = 2;
printf(" i is changed to %d at %d\n",i,get_time(LO) );
}
In verilog,method arguments takes as pass by value.The inputs are copyed when the method is called and the outputs are assigned to outputs when exiting the method.In SystemVerilog ,methods can have pass by reference.Arguments passed by reference are not copied into the subroutine area, rather, a reference to the original argument is passed to the subroutine. The subroutine can then access the argument data via the reference.
In the following example, variable a is changed at time 10,20 and 30. The method pass_by_val , copies only the value of the variable a, so the changes in variable a which are occurred after the task pass_by_val call, are not visible to pass_by_val. Method pass_by_ref is directly referring to the variable a. So the changes in variable a are visible inside pass_by_ref.
EXAMPLE:
program main();
int a;
initial begin
#10 a = 10;
#10 a = 20;
#10 a = 30;
#10 $finish;
end
task pass_by_val(int i);
forever
@i $display("pass_by_val: I is %0d",i);
endtask
task pass_by_ref(ref int i);
forever begin
@i $display("pass_by_ref: I is %0d",i);
end
endtask
initial begin
pass_by_val(a);
end
initial begin
pass_by_ref(a);
end
endprogram
RESULT:
pass_by_ref: I is 10
pass_by_ref: I is 20
pass_by_ref: I is 30
By default, SystemVerilog passes arrays by value, copying the entire array.
It is recommended to pass arrays by reference whenever possible for performance reasons.
If you want your function to modify the array, use ref.
If you want your function to read the array, use const ref.
Example:
module automatic test;
initial run();
function void run();
// Create some SystemVerilog arrays and populate them
int array[5];
int queue[$];
int assoc[int];
for (int i = 0; i < 5; i++) begin
array[i] = i;
queue[i] = i;
assoc[i] = i;
end
pass_by_value(array, queue, assoc);
$display("After pass by value:");
for (int i = 0; i < 5; i++) begin
$display("array[%0d]:%0d", i, array[i]);
$display("queue[%0d]:%0d", i, queue[i]);
$display("assoc[%0d]:%0d", i, assoc[i]);
end
pass_by_ref(array, queue, assoc);
$display("After pass by reference:");
for (int i = 0; i < 5; i++) begin
$display("array[%0d]:%0d", i, array[i]);
$display("queue[%0d]:%0d", i, queue[i]);
$display("assoc[%0d]:%0d", i, assoc[i]);
end
endfunction
// These functions try to modify the arrays.
// Default.
// A copy of the arrays is made in this function
function void pass_by_value(int array[5], int queue[$], int assoc[int]);
array[2] = 100;
queue[2] = 100;
assoc[2] = 100;
endfunction
// Original arrays are being referenced
function void pass_by_ref(ref int array[5], ref int queue[$], ref int assoc[int]);
array[3] = 100;
queue[3] = 100;
assoc[3] = 100;
endfunction
// Original arrays are being referenced
// And they can be read but cannot be modified in this function
function void pass_by_const_ref(const ref int array[5],
const ref int queue[$],
const ref int assoc[int]);
// Arrays cannot be modified in this function
// array[3] = 100;
// queue[3] = 100;
// assoc[3] = 100;
endfunction
endmodule