Anjali_287
Anjali_287

Reputation: 133

Output of the function call is unexpected

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

Answers (3)

Santhosh Prasad
Santhosh Prasad

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

dave_59
dave_59

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

Serge
Serge

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

Related Questions