Reputation: 133
module func();
function [31:0]factorial;
input [7:0]a;
if (a==1)
factorial=1;
else
factorial= a*factorial(a-1);
endfunction
initial
begin
$dumpfile("file.vcd");
$dumpvars(1);
$display("Factorial of 1 = %0d", factorial(1));
$display("Factorial of 2 = %0d", factorial(2));
$display("Factorial of 3 = %0d", factorial(3));
$display("Factorial of 4 = %0d", factorial(4));
$display("Factorial of 5 = %0d", factorial(5));
end
endmodule
Output:
Factorial of 1 = 1
Factorial of 2 = 2
Factorial of 3 = 6
Factorial of 4 = 24
Factorial of 5 = 120
If I change the output bit to [7:0]
, then the output is different.
module func();
function [7:0]factorial;
input [7:0]a;
if (a==1)
factorial=1;
else
factorial= a*factorial(a-1);
endfunction
initial
begin
$dumpfile("file.vcd");
$dumpvars(1);
$display("Factorial of 1 = %0d", factorial(1));
$display("Factorial of 2 = %0d", factorial(2));
$display("Factorial of 3 = %0d", factorial(3));
$display("Factorial of 4 = %0d", factorial(4));
$display("Factorial of 5 = %0d", factorial(5));
end
endmodule
Output:
Factorial of 1 = 1
Factorial of 2 = 1
Factorial of 3 = 1
Factorial of 4 = 1
Factorial of 5 = 1
Also, my understanding is that in non-automatic function, the same functions are being shared between all calls. Then in first program, why are the values of different calls different?
Upvotes: 1
Views: 699
Reputation: 1
Use the below code to Generate the Factorial of any number
module test;
function int factorial(int n);
int result =1 ;
for (int i = 1; i <= n; i++)begin
result *= i;
$display("result %d %d",result, i); end
return result;
endfunction
initial begin
int n = 5; // Replace 5 with your desired number
int result;
// Calculate factorial
result = factorial(n);
$display("Factorial of %0d is %0d", n, result);
end
endmodule
Upvotes: 0
Reputation: 42788
You are correct about the fact that there is only one copy of function arguments and output for non-automatic functions. In the expression a * factorial(a-1)
the language rules say the implementation is free to call the factorial
function in any order before evaluating all operands. Note there is some implicit casting going on behind the scenes that can add extra steps the the evaluation and change the ordering. This can be represented using the following equivalent code explicitly in SystemVerilog.
factorial= 32'(a)*factorial(32'(a)-32'd1);
This could be the reason behind why you are getting different results depending on the declared resulting width of factorial
.
Of course, recursive functions or re-entrant tasks should all be declared automatic so they each occurrence has a local copy of their variables.
Upvotes: 0
Reputation: 12384
I think that you hit a case of an undefined behavior here. All functions defined in modules are by default static
. That means that the function parameter a
is static for all invocations of the function. So, every recursion modifies value of the same variable a
. It will always be 1
after returning from all recursions.
Now, depending on the order of evaluation a * factorial(a-1)
the argument will either be as passed to the function or 1
. It looks like vcs executes recursion first for [7:0]
. As a result a
is always 1
before multiplication. Cadence does it differently.
The way to fix it is to declare the function as automatic
:
function automatic [7:0] factorial
In general you should avoid recursion in synthesizable code. You can use a loop in this case.
Upvotes: 2