verilog 中函数调用的输出不清楚.请帮助我理解输出


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

而如果将输出位更改为 [7:0],则输出是不同的。

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

另外我的理解是,在非自动函数中,所有调用之间共享相同的函数,那么在第一个程序中,为什么不同调用的值不同呢?

我认为您在这里遇到了未定义行为的情况。模块中定义的所有函数默认为static。这意味着函数参数a对于函数的所有调用都是静态的。因此,每个递归都会修改同一变量的值a。从所有递归返回后,它将始终1

现在,根据计算a * factorial(a-1)的顺序,参数将传递到函数或1。看起来vcs首先为[7:0]执行递归。因此,a总是在乘法之前1节奏的做法不同。

修复它的方法是将函数声明为automatic

function automatic [7:0] factorial

通常,应避免在可合成代码中使用递归。在这种情况下,您可以使用循环。

您是正确的,即非自动函数只有一个函数参数和输出的副本。在表达式a * factorial(a-1)中,语言规则表示,在计算所有操作数之前,实现可以自由地以任何顺序调用factorial函数。请注意,幕后正在进行一些隐式转换,这些强制转换可以在评估中添加额外的步骤并更改顺序。这可以在SystemVerilog中使用以下等效代码显式表示。

factorial= 32'(a)*factorial(32'(a)-32'd1);

这可能是为什么根据声明的结果宽度获得不同结果的原因factorial.

当然,递归函数或重入任务都应该声明为自动的,以便它们每次出现都有其变量的本地副本。

最新更新