blob: 3c747001887c97bc27b50fc862b334d6202a0e60 [file] [log] [blame]
//`include "fpu_lib.sv"
module compare#(parameter exp_width = 8, parameter mant_width = 24)
(
input wire [(exp_width + mant_width)-1:0] a,
input wire [(exp_width + mant_width)-1:0] b,
input wire [1:0] op,
output wire [(exp_width + mant_width)-1:0] out,
output wire [4:0] exceptions
);
wire lt, gt, eq, unordered;
wire sign_a, sign_b;
wire [exp_width-1:0] exp_a, exp_b;
wire [mant_width-2:0] mant_a, mant_b;
wire is_a_zero, is_a_inf, is_a_qNaN, is_a_sNaN;
wire is_b_zero, is_b_inf, is_b_qNaN, is_b_sNaN;
wire both_inf, both_zero;
wire ordered, exp_equal;
wire lt_mag, eq_mag, ordered_eq, ordered_lt;
wire invalid, div_by_zero, overflow, underflow, inexact;
wire [9:0] spec_value_chk_a, spec_value_chk_b;
// extracting sign,exponent and mantissa of numbers
assign {sign_a,exp_a,mant_a} = a;
assign {sign_b,exp_b,mant_b} = b;
// module to check for special values
special_check #(exp_width,mant_width) special_check_a (.in (a), .result(spec_value_chk_a));
special_check #(exp_width,mant_width) special_check_b (.in (b), .result(spec_value_chk_b));
assign is_a_zero = spec_value_chk_a[3] | spec_value_chk_a[4];
assign is_a_inf = spec_value_chk_a[0] | spec_value_chk_a[7];
assign is_a_qNaN = spec_value_chk_a[9];
assign is_a_sNaN = spec_value_chk_a[8];
assign is_b_zero = spec_value_chk_b[3] | spec_value_chk_b[4];
assign is_b_inf = spec_value_chk_b[0] | spec_value_chk_b[7];
assign is_b_qNaN = spec_value_chk_b[9];
assign is_b_sNaN = spec_value_chk_b[8];
// check if inputs are valid or not
assign ordered = !(is_a_qNaN || is_b_qNaN) && !(is_a_sNaN || is_b_sNaN);
assign both_inf = is_a_inf && is_b_inf;
assign both_zero = is_a_zero && is_b_zero;
// comparison of exponents
assign exp_equal = (exp_a == exp_b);
// comparison of mantissas
assign lt_mag = (exp_a < exp_b) || (exp_equal && (mant_a < mant_b));
assign eq_mag = exp_equal && (mant_a == mant_b);
// valid inputs and equal
assign ordered_eq = both_zero || (sign_a == sign_b) && (both_inf || eq_mag);
// valid inputs and a is less than b
assign ordered_lt = !both_zero && ((sign_a && !sign_b) || (!both_inf && ((sign_a && !lt_mag && ! eq_mag)
|| (!sign_b && lt_mag))));
assign lt = ordered && ordered_lt;
assign eq = ordered && ordered_eq;
assign gt = ordered && !ordered_eq && !ordered_lt;
// invalid exception would be generated if any or both numbers are NaN
assign invalid = is_a_sNaN || is_b_sNaN || ((is_a_qNaN || is_b_qNaN) && !(op == 3'b010));
// unordered flag is set to high if any or both inputs are NaN
assign unordered = !ordered;
// hardwired exceptions that cannot be flagged in comparator
assign div_by_zero = 1'b0;
assign overflow = 1'b0;
assign underflow = 1'b0;
assign inexact = 1'b0;
assign exceptions = {invalid, div_by_zero, overflow, underflow, inexact};
assign out = ({32{op == 3'b10}} & {31'b0,eq}) |
({32{op == 3'b01}} & {31'b0,lt}) |
({32{op == 3'b00}} & ({31'b0,lt} | {31'b0,eq}));
endmodule