Search code examples
verilogsystem-verilog

Real value printed with %f is 0.0000, but condition '>0' does not apply (after using $floor in a task)


I declare my variable:

real meas_diff_div;

I have a task, where I use this variable:

measure_task(meas_diff_div);

After that I filter for an error based on the value of this real:

  if(meas_diff_div > 0)`error("error message. %f", meas_diff_div);

Sometimes the error is triggered, even if the printed value is 0.000000

At the task declaration, the 1st line looks like this:

task measure_task(output real output_value); 

In the task this real is 'filled' up with (I use $floor in this context to get around the % 'modulo' operator applied to 'real' problemtype):

 output_value = realtime_val1 - realtime_val2 * $floor(realtime_val1/realtime_val2);

Solution

  • The problem is how you $display the real value.

    %f shows only zeroes because it does not have enough digits of precision to show very small floating point values. Use %g to show the number in scientific format to see it really is non-zero. Similarly, use %f and specify a large enough precision value.

    module tb;
        real meas_diff_div;
     
    initial begin
        meas_diff_div = 0.0000001;
        if (meas_diff_div > 0) $display("%f"   , meas_diff_div);
        if (meas_diff_div > 0) $display("%1.7f", meas_diff_div);
        if (meas_diff_div > 0) $display("%g"   , meas_diff_div);
    end
    endmodule
    

    Outputs:

    0.000000
    0.0000001
    1e-07
    

    As you can see, when the signal has a small non-zero value, like 0.0000001, the if evaluates to true since it is larger than 0.

    Although not explicitly stated in the IEEE Std 1800-2017, %f seems to behave like %.6f (the default number of digits after the decimal point is 6). Since this syntax was borrowed from C, see also: What is c printf %f default precision?

    For your filter you could do something like:

    if (meas_diff_div > 0.001) `error("error message. %f", meas_diff_div);
    

    In your code, the problem is not $floor. The difference of 2 real values can produce a non-zero value.