`timescale 1ns / 1ps
module factorial(
input i_n,
output reg res,
input i_clk
);
integer j;
initial
begin:a
for (j=1;j<=i_n;j=j+1)begin
res<=res*j;
end
res<='d3;
$display("res is %f",res);//as res is 'd3,should display 3.0
end
endmodule
module u_f;
reg i_n;
wire res;
reg i_clk;
initial
begin
i_n<=3;
i_clk=1'b0;
end
always
begin
#10 i_clk<=~i_clk;
end
factorial u2(
.i_n(i_n),
.i_clk(i_clk),
.res(res)
);
endmodule
Above verilog script output:
Time resolution is 1 ps
res is 0.000000
The correct output should be res is 3.000000
but display res is 0.000000
,where is the problem?
The output of 0.000 is correct. res
has not be initialized so its value is X
and the %f
casts the print to floating-point which becomes 0.000.
res<='d3;
is a non-blocking assignment (NBA). It does not updated res
immediately. It schedules res
to be assigned to 3 at the end of the time-step. $display("res is %f",res);
will print res
current value; not its scheduled value.
Using blocking assignment (ie: res='d3
) will make $display("res is %f",res);
print 3.00000.
Alternatively you can use keep the non-blocking and replaces $display
with $strobe
. $strobe
is similar to $display
but prints after the NBA.
res<='d3;
$stobe("res is %f from strobe",res);
$display("res is %f from display",res);
Outputs: (display is printed before strobe even though strobe was scheduled first)
res is 0.000000 from display
res is 3.000000 from strobe
FYI this initial block and for-loop will not work as you intend:
initial begin:a
for (j=1;j<=i_n;j=j+1)begin
res<=res*j;
end
end
res<=res*j;
updates LHS in the NBA region, but the RHS is evaluated immediately. res*j
will always use the initial value of res
and not it scheduled value.
i_n
is one bit
initial
blocks can trigger before inputs are initialized
res
is not initialized it is X
. X
times any value is X
To be synthesizable all for-loops must be able to static-unroll.