| //`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 |