Quartus compiler parameter expression evaluation with power operator (A**) faulty?
Hi
I have encountered a discrepancy between Quartus and ModelSim compilation of parameter expressions containing a power operator (A**B):
module quartus_pow_op_test #( parameter F_S_HZ = 100000000, parameter F_C_HZ = 300000, parameter N_BITS = 34 ) ( input wire clk, input wire reset ); localparam POW_2_N_BITS_INT = 2**N_BITS; // valid for N_BITS = 0...30 localparam POW_2_N_BITS_REAL = 2.0**N_BITS; localparam PHASE_RATE_0 = ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**N_BITS); localparam PHASE_RATE_1 = ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**34); localparam PHASE_RATE_2 = ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**34)); localparam PHASE_RATE_3 = ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**N_BITS)); localparam PHASE_RATE_4 = ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * POW_2_N_BITS_REAL; initial begin $display("DEBUG: F_S_HZ = %0f", F_S_HZ); $display("DEBUG: F_C_HZ = %0f", F_C_HZ); $display("DEBUG: N_BITS = %0f", N_BITS); $display("DEBUG: 2**N_BITS = %0f", POW_2_N_BITS_INT); $display("DEBUG: 2.0**N_BITS = %0f (POW_2_N_BITS_REAL)", POW_2_N_BITS_REAL); $display("DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**N_BITS) = %0f", PHASE_RATE_0); $display("DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**34) = %0f", PHASE_RATE_1); $display("DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**34)) = %0f", PHASE_RATE_2); $display("DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**N_BITS)) = %0f", PHASE_RATE_3); $display("DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * POW_2_N_BITS_REAL = %0f", PHASE_RATE_4); end endmodule
Result is:
DEBUG: F_S_HZ = 100000000.000000 DEBUG: F_C_HZ = 300000.000000 DEBUG: N_BITS = 34.000000 DEBUG: 2**N_BITS = 0.000000 DEBUG: 2.0**N_BITS = 17179869184.000000 (POW_2_N_BITS_REAL) DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**N_BITS) = 0.000000 DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (2.0**34) = 0.000000 DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**34)) = 51539607.552000 DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * (1.0*(2.0**N_BITS)) = 0.000000 DEBUG: ((1.0*F_C_HZ)/(1.0*F_S_HZ)) * POW_2_N_BITS_REAL = 51539607.552000
Note that some forms of the expression evaluate to (incorrect) zero - whereas ModelSim compiler evaluates all forms correctly.
Am I missing something here? Also is there a better way of produces info messages during Quartus compile than the above use of $display() in an initial section?
Thanks
Steve
Hi,
Verilog LRM says
"Implementations may limit the maximum size of integer variables, but it shall be at least 32 bits."You see that Quartus apparently uses 32 bit integer but Modelsim most likely 64 bit. That's completely legal but must be considered.
Quartus gives an overflow warning for line 10, by the way.
The rest shouldn't happen according to Verilog language reference, I think. Looks a bug in parameter calculation, ignoring type proagation rules for real parameters.
This worked for me in Quartus 19.1localparam PHASE_RATE_5 = real'(F_C_HZ)/real'(F_S_HZ) * real'(2.0**N_BITS);