我有一个实数
delay
,我想将其转换为 10 的第一个倍数。例如,如果延迟 = 0.0024,我希望输出为 240。
在以下代码片段中,
delay
= 1.52e-6。在 while
循环执行之后,我预计 delay
为 1520。但是,在 delay
循环之后,我看到 while
= 1.52e17。我检查了波形,看起来delay
的值是1.5200000000000001e-6。为什么会这样呢?我是不是做错了什么?
这是代码:
real delay = 1.52e-6;
function real mod (real a, real b);
mod = a - b*$floor(a/b);
endfunction
initial begin
while (mod(delay, 10) != 0) delay = delay*10;
end
为什么会这样?
如果您在运行模拟时使用中间值,您就会明白为什么会发生这种情况。这比查看波形更明显,波形只会显示
$display
循环完成后的最终值。这是一个可运行的代码示例:while
输出:
module tb;
real delay = 1.52e-6;
function real mod (real a, real b);
mod = a - b*$floor(a/b);
$display("a=%g, floor=%g, mod=%g", a, $floor(a/b), mod);
endfunction
initial begin
$display(delay);
while (mod(delay, 10) != 0) delay = delay*10;
$display(delay);
end
endmodule
是的。问题是您在
1.52e-06
a=1.52e-06, floor=0, mod=1.52e-06
a=1.52e-05, floor=0, mod=1.52e-05
a=0.000152, floor=0, mod=0.000152
a=0.00152, floor=0, mod=0.00152
a=0.0152, floor=0, mod=0.0152
a=0.152, floor=0, mod=0.152
a=1.52, floor=0, mod=1.52
a=15.2, floor=1, mod=5.2
a=152, floor=15, mod=2
a=1520, floor=152, mod=2.27374e-13
a=15200, floor=1520, mod=1.81899e-12
a=152000, floor=15200, mod=2.91038e-11
a=1.52e+06, floor=152000, mod=2.32831e-10
a=1.52e+07, floor=1.52e+06, mod=1.86265e-09
a=1.52e+08, floor=1.52e+07, mod=2.98023e-08
a=1.52e+09, floor=1.52e+08, mod=2.38419e-07
a=1.52e+10, floor=1.52e+09, mod=1.90735e-06
a=1.52e+11, floor=1.52e+10, mod=3.05176e-05
a=1.52e+12, floor=1.52e+11, mod=0.000244141
a=1.52e+13, floor=1.52e+12, mod=0.00195312
a=1.52e+14, floor=1.52e+13, mod=0.03125
a=1.52e+15, floor=1.52e+14, mod=0.25
a=1.52e+16, floor=1.52e+15, mod=2
a=1.52e+17, floor=1.52e+16, mod=0
1.52e+17
循环中的比较检查没有按照您期望的方式工作。您不应该像这样将
while
值与 0 进行比较。相反,您需要将其与某个相当小的值进行比较。例如:real
这将为您提供所需的输出:
while (mod(delay, 10) > 1e-12) delay = delay*10;
这是完整的输出:
1520
这是浮点比较