Search code examples
floating-pointverilogsimulationsystem-verilogmodelsim

Simulation mismatch when using shortreal + shortrealtobits + bitstoshortreal combination in modelsim tool


Here is the minimal reproducible problem:

file: top.sv

module top(input [31:0] in1, output [31:0] out1);
    assign out1 = in1;
endmodule

file top_tb.sv

module top_tb;

shortreal in1_real;
shortreal out1_tb;
shortreal out_dut;

logic [31:0] in1_logic;
logic [31:0] out1_logic;
logic check;

initial in1_real = 2.1;
initial out1_tb = 2.1;


assign #5 in1_logic = $shortrealtobits(in1_real);

top inst_top(.in1(in1_logic),
          .out1(out1_logic));

assign #10 out_dut = $bitstoshortreal(out1_logic);
assign #30 check = 1;

always_comb begin
    if ((check == 1) && (out1_tb != out_dut)) begin
        $display("%t Not matching!!", $time);
    end
end

endmodule

When I run a simulation of this dut and tb in modelsim, I am not expecting any mismatch between out1_tb and out_dut, but I am seeing a mismatch. When I checked the waveform, both out1_tb and out_dut are shown as 2.1 only, still I am seeing a simulation mismatch.

Link to EDA Playground with the design and tesbench code: https://edaplayground.com/x/WDiC

When you click "run", you can see "Not matching" in the log.


Solution

  • When comparing real values, you should use a tolerance value. For example, I set the tolerance to 0.1 in the code below. If the absolute value of the difference between your numbers is greater than 0.1, then the numbers are considered different from each other.

    always_comb begin
        if ((check == 1) && compare(out1_tb, out_dut)) begin
        //if ((check == 1) && (out1_tb != out_dut)) begin
            $display("%t Not matching!! %g %g", $time, out1_tb, out_dut);
        end
    end
    
    function bit compare (shortreal r1, r2);
        shortreal diff;
        diff = (r1>=r2) ? r1-r2 : r2-r1; // Absolute value
        return (diff > 0.1) ? 1 : 0;
    endfunction
    

    There is uncertainty with all floating-point variable types. Sometimes, a direct comparison like != will work, and other times it will not work. It is not guaranteed to work, which is why a tolerance helps.

    This is a general issue with floating-point comparison.