Search code examples
verilogsystem-verilog

Verilog truncates fixed point numbers


I'm writing this below function that takes bit[5:0] data, calculates floating point number (positive/negative) and then converts it to fixed point number with 5 decimal places. But somehow it doesn't output fixed point number in format 1.xxxxx or 0.xxxxx

function convert2fixfp(bit[5:0] data);
   real a;
  int  b;
  real c;
     a = (data[5] * -1.0) + (data[4] * 0.5) + (data[3] * 0.25) + (data[2] * 0.125) + (data[1] * 0.0625) + (data[0] * 0.03125);
    $display("input is: 6'b%b, output is: %.6f", data, a);

    b = a * (2**5);
    c = $itor(b) * (2.0**-5);
        $display("input is: %.6f, intermittent is: %d, output is: %.6f", a, $itor(b), c)

  return c;
endfunction

Then I call this function in a task

task calculate_weights();
bit[5:0] data;
real [5:0] weights[16];
foreach(weights[i])
     weights[i] = convert2real(data);
end
$display("weights: %p", weights); // here trailing 0s in decimal part are truncated and it doesn't show fixed point number. 

values for data can be:
6'b101100
fixed point should be `-0.625000` but with %p only `-0.625` is printed.

I need these trailing 0s as will be passing weights[16] array to C++ code via DPI-C call which absolutely need numbers to be fixed point.

Was expecting that it would handle both positive and negative floating-point numbers i.e a But when I print array of multiple values calculated, it doesn't print fixed point numbers instead prints truncated point numbers only like below (and those are truncated too):

For example, 0.375 should have been 0.37500 0.5625 should have been 0.56250

{0.53125, -0.0625, 0.375, 0.78125, 0.84375, 0.75, 0.75, 0.84375, 0.46875, -0.84375, 0.125, 0.625, 0.5625, -0.09375, 0.5625, -0.25, -0.3125, -0.03125, 0.21875, -0.375, 0.375, 0.375, -0.34375, 0.1875, -0.15625, 0.40625, 0.84375, 0.21875, -0.90625, -0.25, 0.9375, -0.90625, -0.3125, 0.71875, -0.25, -0.90625, -0.71875, -0.28125, 0.5, 0.5, -0.6875, -0.84375, 0.71875, 0.4375, 0.75, 0.125, -1, 0.78125, 0.6875, -0.40625, -0.65625, 0.5625, 0.03125, 0.78125, -0.5, -0.46875, 0.40625, -0.03125, -0.0625, 0.03125, 0.34375, -0.125, -0.5, 0.34375, 0.28125, -0.4375, 0.28125, 0.5, 0.71875, 0.3125, 0.78125, 0.125}

Do you know what's wrong here?

I tried taking 2's complement but didn't work either.


Solution

  • This is a string formatting issue—your numbers are all stored in floating-point representation. Do not use %p if you need very specific formatting. Use a foreach loop

    $write("weights:"); 
    foreach(weights[i]) $write(" %.6f",weights[i]);
    $display; // newline
    

    If you need to print this as a single line for the UVM, you can concatenate the numbers into a string first

    string sw;
    
    foreach(weights[i]) $sformat(sw, "%s %.6f",sw,weights[i]);
    `uvm_info("ID",$sformatf("weights:%s",sw),UVM_LOW)