| `include "defs.vi" |
| |
| module special_check #(parameter exp_width = 8, parameter mant_width = 24) |
| ( |
| input wire [(exp_width + mant_width-1):0] in, |
| |
| output wire [9:0] result |
| ); |
| |
| wire is_pos_zero; |
| wire is_neg_zero; |
| wire is_pos_inf; |
| wire is_neg_inf; |
| wire is_pos_subnorm; |
| wire is_neg_subnorm; |
| wire is_pos_norm; |
| wire is_neg_norm; |
| wire is_qNaN; |
| wire is_sNaN; |
| |
| wire sign; |
| wire [exp_width-1:0] exp; |
| wire [(mant_width-2):0] sig; |
| |
| wire exp_zero, exp_one, sig_zero; |
| |
| |
| assign {sign, exp, sig} = in; |
| |
| assign exp_zero = |exp ? 1'b0 : 1'b1; |
| assign sig_zero = |sig ? 1'b0 : 1'b1; |
| assign exp_one = &exp ? 1'b1 : 1'b0; |
| |
| assign is_pos_zero = !sign & exp_zero & sig_zero; |
| assign is_neg_zero = sign & exp_zero & sig_zero; |
| assign is_pos_subnorm = !sign & exp_zero & !sig_zero; |
| assign is_neg_subnorm = sign & exp_zero & !sig_zero; |
| assign is_pos_inf = !sign & exp_one & sig_zero; |
| assign is_neg_inf = sign & exp_one & sig_zero; |
| assign is_qNaN = exp_one & !sig_zero & sig[22]; |
| assign is_sNaN = exp_one & !sig_zero & !sig[22]; |
| |
| assign is_pos_norm = (is_pos_zero | is_neg_zero | is_pos_subnorm | is_neg_subnorm | is_pos_inf | is_neg_inf | |
| is_qNaN | is_sNaN) ? 1'b0 : ~sign ? 1'b1 : 1'b0; |
| |
| assign is_neg_norm = (is_pos_zero | is_neg_zero | is_pos_subnorm | is_neg_subnorm | is_pos_inf | is_neg_inf | |
| is_qNaN | is_sNaN) ? 1'b0 : sign ? 1'b1 : 1'b0; |
| |
| assign result = {is_qNaN, is_sNaN, is_pos_inf, is_pos_norm, is_pos_subnorm, is_pos_zero, is_neg_zero, |
| is_neg_subnorm, is_neg_norm, is_neg_inf}; |
| endmodule |
| |
| module mac_spec_check #(parameter exp_width = 3, parameter mant_width = 3) |
| ( |
| input wire [(exp_width + mant_width):0] in, |
| |
| output wire is_qNaN, |
| output wire is_inf, |
| output wire is_zero, |
| output wire is_sNaN, |
| output wire sign, |
| output wire signed [(exp_width+1):0] s_exp, |
| output wire [mant_width:0] sig |
| ); |
| |
| wire [exp_width:0] exp; |
| wire [(mant_width - 2):0] mant; |
| wire is_ssNaN; |
| wire is_spec; |
| |
| assign {sign, exp, mant} = in; |
| |
| assign is_ssNaN = (in[(exp_width + mant_width - 1):(exp_width + mant_width - 3)] == 'b111); |
| assign is_spec = (exp>>(exp_width - 1) == 'b11); |
| assign is_qNaN = is_spec && exp[exp_width - 2]; |
| assign is_inf = is_spec && !exp[exp_width - 2]; |
| assign is_zero = (exp>>(exp_width - 2) == 'b000); |
| assign is_sNaN = is_ssNaN && !in[mant_width - 2]; |
| |
| assign s_exp = exp; |
| assign sig = {1'b0, !is_zero, mant}; |
| |
| endmodule |
| |
| module rounding |
| ( |
| input wire sign, |
| input wire [26:0] mantisa, |
| input wire [2:0] round_mode, |
| |
| output wire [23:0] rounded_mantisa, |
| output wire rounding_overflow |
| ); |
| |
| wire [23:0] rne, rtz, rdn, rup, rmm; |
| wire rne_overflow, rtz_overflow, rdn_overflow, rup_overflow, rmm_overflow; |
| |
| assign {rne_overflow, rne} = mantisa[2] ? (|mantisa[1:0] ? ({1'b0, mantisa[26:3]} + 1'b1) |
| : ({1'b0, mantisa[26:3]} + mantisa[3])) : {1'b0, mantisa[26:3]}; |
| |
| assign {rtz_overflow, rtz} = {1'b0, mantisa[26:3]}; |
| |
| assign {rdn_overflow, rdn} = |mantisa[2:0] ? (sign ? ({1'b0, mantisa[26:3]} + 1'b1) |
| : {1'b0, mantisa[26:3]}) : {1'b0, mantisa[26:3]}; |
| |
| assign {rup_overflow, rup} = |mantisa[2:0] ? (sign ? {1'b0, mantisa[26:3]} |
| : ({1'b0, mantisa[26:3]} + 1'b1)) : {1'b0, mantisa[26:3]}; |
| assign {rmm_overflow, rmm} = mantisa[2] ? ({1'b0, mantisa[26:3]} + 1'b1) : {1'b0, mantisa[26:3]}; |
| |
| assign rounded_mantisa = ({24{round_mode == 3'b000}} & rne) | |
| ({24{round_mode == 3'b001}} & rtz) | |
| ({24{round_mode == 3'b010}} & rdn) | |
| ({24{round_mode == 3'b011}} & rup) | |
| ({24{round_mode == 3'b100}} & rmm); |
| |
| assign rounding_overflow = ((round_mode == 3'b000) & rne_overflow) | |
| ((round_mode == 3'b001) & rtz_overflow) | |
| ((round_mode == 3'b010) & rdn_overflow) | |
| ((round_mode == 3'b011) & rup_overflow) | |
| ((round_mode == 3'b100) & rmm_overflow); |
| |
| endmodule |
| |
| |
| module leading_zero |
| ( |
| input wire [23:0] in, |
| |
| output wire [4:0] out |
| ); |
| assign out[4:0] = ({5{(in[22] & (&(~(in[23]))))}} & 5'd1) | |
| ({5{(in[21] & (&(~(in[23:22]))))}} & 5'd2) | |
| ({5{(in[20] & (&(~(in[23:21]))))}} & 5'd3) | |
| ({5{(in[19] & (&(~(in[23:20]))))}} & 5'd4) | |
| ({5{(in[18] & (&(~(in[23:19]))))}} & 5'd5) | |
| ({5{(in[17] & (&(~(in[23:18]))))}} & 5'd6) | |
| ({5{(in[16] & (&(~(in[23:17]))))}} & 5'd7) | |
| ({5{(in[15] & (&(~(in[23:16]))))}} & 5'd8) | |
| ({5{(in[14] & (&(~(in[23:15]))))}} & 5'd9) | |
| ({5{(in[13] & (&(~(in[23:14]))))}} & 5'd10) | |
| ({5{(in[12] & (&(~(in[23:13]))))}} & 5'd11) | |
| ({5{(in[11] & (&(~(in[23:12]))))}} & 5'd12) | |
| ({5{(in[10] & (&(~(in[23:11]))))}} & 5'd13) | |
| ({5{(in[9] & (&(~(in[23:10]))))}} & 5'd14) | |
| ({5{(in[8] & (&(~(in[23: 9]))))}} & 5'd15) | |
| ({5{(in[7] & (&(~(in[23: 8]))))}} & 5'd16) | |
| ({5{(in[6] & (&(~(in[23: 7]))))}} & 5'd17) | |
| ({5{(in[5] & (&(~(in[23: 6]))))}} & 5'd18) | |
| ({5{(in[4] & (&(~(in[23: 5]))))}} & 5'd19) | |
| ({5{(in[3] & (&(~(in[23: 4]))))}} & 5'd20) | |
| ({5{(in[2] & (&(~(in[23: 3]))))}} & 5'd21) | |
| ({5{(in[1] & (&(~(in[23: 2]))))}} & 5'd22) | |
| ({5{(in[0] & (&(~(in[23: 1]))))}} & 5'd23); |
| |
| endmodule |
| |
| |
| module leading_ones |
| ( |
| input wire [31:0] in, |
| output wire [4:0] out |
| ); |
| |
| assign out [4:0] = ({5{(in[31])}} & 5'd31) | |
| ({5{(in[30] & (&(~(in[31]))))}} & 5'd30) | |
| ({5{(in[29] & (&(~(in[31:30]))))}} & 5'd29) | |
| ({5{(in[28] & (&(~(in[31:29]))))}} & 5'd28) | |
| ({5{(in[27] & (&(~(in[31:28]))))}} & 5'd27) | |
| ({5{(in[26] & (&(~(in[31:27]))))}} & 5'd26) | |
| ({5{(in[25] & (&(~(in[31:26]))))}} & 5'd25) | |
| ({5{(in[24] & (&(~(in[31:25]))))}} & 5'd24) | |
| ({5{(in[23] & (&(~(in[31:24]))))}} & 5'd23) | |
| ({5{(in[22] & (&(~(in[31:23]))))}} & 5'd22) | |
| ({5{(in[21] & (&(~(in[31:22]))))}} & 5'd21) | |
| ({5{(in[20] & (&(~(in[31:21]))))}} & 5'd20) | |
| ({5{(in[19] & (&(~(in[31:20]))))}} & 5'd19) | |
| ({5{(in[18] & (&(~(in[31:19]))))}} & 5'd18) | |
| ({5{(in[17] & (&(~(in[31:18]))))}} & 5'd17) | |
| ({5{(in[16] & (&(~(in[31:17]))))}} & 5'd16) | |
| ({5{(in[15] & (&(~(in[31:16]))))}} & 5'd15) | |
| ({5{(in[14] & (&(~(in[31:15]))))}} & 5'd14) | |
| ({5{(in[13] & (&(~(in[31:14]))))}} & 5'd13) | |
| ({5{(in[12] & (&(~(in[31:13]))))}} & 5'd12) | |
| ({5{(in[11] & (&(~(in[31:12]))))}} & 5'd11) | |
| ({5{(in[10] & (&(~(in[31:11]))))}} & 5'd10) | |
| ({5{(in[9] & (&(~(in[31:10]))))}} & 5'd9) | |
| ({5{(in[8] & (&(~(in[31:9]))))}} & 5'd8) | |
| ({5{(in[7] & (&(~(in[31:8]))))}} & 5'd7) | |
| ({5{(in[6] & (&(~(in[31:7]))))}} & 5'd6) | |
| ({5{(in[5] & (&(~(in[31:6]))))}} & 5'd5) | |
| ({5{(in[4] & (&(~(in[31:5]))))}} & 5'd4) | |
| ({5{(in[3] & (&(~(in[31:4]))))}} & 5'd3) | |
| ({5{(in[2] & (&(~(in[31:3]))))}} & 5'd2) | |
| ({5{(in[1] & (&(~(in[31:2]))))}} & 5'd1) | |
| ({5{(in[0] & (&(~(in[31:1]))))}} & 5'd0); |
| endmodule |
| |
| module left_shifter #(parameter mant = 24) |
| ( |
| input wire [mant-1:0] mantisa, |
| input wire [7:0] shift_amount, |
| |
| output wire [mant-1:0] out |
| ); |
| |
| wire [mant-1:0] temp; |
| |
| assign temp = mantisa << shift_amount; |
| assign out = {temp[mant-1:1], mantisa[0]}; |
| |
| endmodule |
| |
| module right_shifter |
| ( |
| input wire [26:0] mantisa, |
| input wire [7:0] shift_amount, |
| |
| output wire [26:0] out |
| ); |
| |
| assign out = ({27{(shift_amount[7:0]==8'd0)}} & mantisa) | |
| ({27{(shift_amount[7:0]==8'd1)}} & {1'd0, mantisa[26:2], |mantisa[1:0]}) | |
| ({27{(shift_amount[7:0]==8'd2)}} & {2'd0, mantisa[26:3], |mantisa[2:0]}) | |
| ({27{(shift_amount[7:0]==8'd3)}} & {3'd0, mantisa[26:4], |mantisa[3:0]}) | |
| ({27{(shift_amount[7:0]==8'd4)}} & {4'd0, mantisa[26:5], |mantisa[4:0]}) | |
| ({27{(shift_amount[7:0]==8'd5)}} & {5'd0, mantisa[26:6], |mantisa[5:0]}) | |
| ({27{(shift_amount[7:0]==8'd6)}} & {6'd0, mantisa[26:7], |mantisa[6:0]}) | |
| ({27{(shift_amount[7:0]==8'd7)}} & {7'd0, mantisa[26:8], |mantisa[7:0]}) | |
| ({27{(shift_amount[7:0]==8'd8)}} & {8'd0, mantisa[26:9], |mantisa[8:0]}) | |
| ({27{(shift_amount[7:0]==8'd9)}} & {9'd0, mantisa[26:10], |mantisa[9:0]}) | |
| ({27{(shift_amount[7:0]==8'd10)}} & {10'd0, mantisa[26:11], |mantisa[10:0]}) | |
| ({27{(shift_amount[7:0]==8'd11)}} & {11'd0, mantisa[26:12], |mantisa[11:0]}) | |
| ({27{(shift_amount[7:0]==8'd12)}} & {12'd0, mantisa[26:13], |mantisa[12:0]}) | |
| ({27{(shift_amount[7:0]==8'd13)}} & {13'd0, mantisa[26:14], |mantisa[13:0]}) | |
| ({27{(shift_amount[7:0]==8'd14)}} & {14'd0, mantisa[26:15], |mantisa[14:0]}) | |
| ({27{(shift_amount[7:0]==8'd15)}} & {15'd0, mantisa[26:16], |mantisa[15:0]}) | |
| ({27{(shift_amount[7:0]==8'd16)}} & {16'd0, mantisa[26:17], |mantisa[16:0]}) | |
| ({27{(shift_amount[7:0]==8'd17)}} & {17'd0, mantisa[26:18], |mantisa[17:0]}) | |
| ({27{(shift_amount[7:0]==8'd18)}} & {18'd0, mantisa[26:19], |mantisa[18:0]}) | |
| ({27{(shift_amount[7:0]==8'd19)}} & {19'd0, mantisa[26:20], |mantisa[19:0]}) | |
| ({27{(shift_amount[7:0]==8'd20)}} & {20'd0, mantisa[26:21], |mantisa[20:0]}) | |
| ({27{(shift_amount[7:0]==8'd21)}} & {21'd0, mantisa[26:22], |mantisa[21:0]}) | |
| ({27{(shift_amount[7:0]==8'd22)}} & {22'd0, mantisa[26:23], |mantisa[22:0]}) | |
| ({27{(shift_amount[7:0]==8'd23)}} & {23'd0, mantisa[26:24], |mantisa[23:0]}) | |
| ({27{(shift_amount[7:0]==8'd24)}} & {24'd0, mantisa[26:25], |mantisa[24:0]}) | |
| ({27{(shift_amount[7:0]==8'd25)}} & {25'd0, mantisa[26], |mantisa[25:0]}) | |
| ({27{(shift_amount[7:0]>=8'd26)}} & {26'd0, |mantisa[26:0]}); |
| endmodule |
| |
| module int_excep #(parameter width = 1) |
| ( |
| input wire signed_out, |
| input wire is_qNaN, |
| input wire is_sNaN, |
| input wire sign, |
| |
| output wire [(width - 1):0] execp_out |
| ); |
| wire max_int; |
| |
| assign max_int = is_qNaN || is_sNaN || !sign; |
| assign execp_out = {signed_out ^ max_int, {(width - 1){max_int}}}; |
| |
| endmodule |
| |
| module rvdff #( parameter WIDTH=1, SHORT=0 ) |
| ( input wire [(WIDTH-1):0] din, |
| input wire clk, |
| input wire rst_l, |
| |
| output reg [(WIDTH-1):0] dout |
| ); |
| |
| if (SHORT == 1) begin |
| assign dout = din; |
| end |
| else begin |
| `ifdef RV_CLOCKGATE |
| always @(posedge tb_top.clk) begin |
| #0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH); |
| end |
| `endif |
| |
| always @(posedge clk or negedge rst_l) begin |
| if (rst_l == 0) |
| dout[WIDTH-1:0] <= 0; |
| else |
| dout[WIDTH-1:0] <= din[WIDTH-1:0]; |
| end |
| |
| end |
| endmodule |
| |
| module rvdffe #( parameter WIDTH=1, SHORT=0, OVERRIDE=0 ) |
| ( |
| input wire [WIDTH-1:0] din, |
| input wire en, |
| input wire clk, |
| input wire rst_l, |
| output wire [WIDTH-1:0] dout |
| ); |
| |
| wire [WIDTH-1:0] in; |
| |
| if (SHORT == 1) begin : genblock |
| if (1) begin : genblock |
| assign dout = din; |
| end |
| end |
| else begin : genblock |
| |
| // `ifndef RV_PHYSICAL |
| // if (WIDTH >= 8 || OVERRIDE==1) begin: genblock |
| // `endif |
| |
| assign in = en ? din : dout; |
| |
| rvdff #(WIDTH) dff (.din(in), .dout(dout), .rst_l(rst_l), .clk(clk)); |
| |
| // `ifndef RV_PHYSICAL |
| // end |
| // // else |
| // // $error("%m: rvdffe must be WIDTH >= 8"); |
| // `endif |
| end // else: !if(SHORT == 1) |
| |
| endmodule // rvdffe |
| |
| module exponent #(parameter exp_width = 8, parameter mant_width = 24) |
| ( |
| input wire [(exp_width + mant_width - 1):0] in, |
| output wire [(exp_width + mant_width):0] out |
| ); |
| |
| function integer clog2; |
| input integer a; |
| |
| begin |
| a = a - 1; |
| for (clog2 = 0; a > 0; clog2 = clog2 + 1) a = a>>1; |
| end |
| |
| endfunction |
| |
| localparam norm_dist_width = clog2(mant_width); |
| |
| wire sign; |
| wire exp_in_zero, is_special, mant_in_zero, is_zero; |
| wire [(exp_width - 1):0] exp_in; |
| wire [(mant_width - 2):0] mant_in, sbnorm_mant; |
| wire [exp_width:0] exp_adjusted, exp; |
| wire [(norm_dist_width - 1):0] norm_dist; |
| |
| assign {sign, exp_in, mant_in} = in; |
| assign exp_in_zero = (exp_in == 0); |
| assign mant_in_zero = (mant_in == 0); |
| |
| lead_zero_param#(mant_width - 1, norm_dist_width) countLeadingZeros(mant_in, norm_dist); |
| |
| assign sbnorm_mant = (mant_in<<norm_dist)<<1; |
| assign exp_adjusted = (exp_in_zero ? norm_dist ^ ((1<<(exp_width + 1)) - 1) : exp_in) + ((1<<(exp_width - 1)) | (exp_in_zero ? 2 : 1)); |
| assign is_zero = exp_in_zero && mant_in_zero; |
| assign is_special = (exp_adjusted[exp_width:(exp_width - 1)] == 'b11); |
| |
| assign exp[exp_width:(exp_width - 2)] = is_special ? {2'b11, !mant_in_zero} : is_zero ? 3'b000 : exp_adjusted[exp_width:(exp_width - 2)]; |
| assign exp[(exp_width - 3):0] = exp_adjusted; |
| assign out = {sign, exp, exp_in_zero ? sbnorm_mant : mant_in}; |
| |
| endmodule |
| |
| module invert#(parameter width = 1) |
| ( |
| input wire [(width - 1):0] in, |
| output wire [(width - 1):0] out |
| ); |
| genvar ix; |
| generate |
| for (ix = 0; ix < width; ix = ix + 1) begin :bt |
| assign out[ix] = in[width - 1 - ix]; |
| end |
| endgenerate |
| |
| endmodule |
| |
| module low_mask_hi_lo#( parameter in_width = 1, parameter top_bound = 1, parameter bottom_bound = 0 ) |
| ( |
| input wire [(in_width - 1):0] in, |
| output wire [(top_bound - bottom_bound - 1):0] out |
| ); |
| localparam num_in_vals = 1<<in_width; |
| wire signed [num_in_vals:0] c; |
| wire [(top_bound - bottom_bound - 1):0] reverse_out; |
| |
| assign c[num_in_vals] = 1; |
| assign c[(num_in_vals - 1):0] = 0; |
| assign reverse_out = (c>>>in)>>(num_in_vals - top_bound); |
| invert #(top_bound - bottom_bound) reverse_hi(reverse_out, out); |
| endmodule |
| |
| module low_mask_lo_hi#( parameter in_width = 1, parameter top_bound = 0, parameter bottom_bound = 1) |
| ( |
| input wire [(in_width - 1):0] in, |
| output wire [(bottom_bound - top_bound - 1):0] out |
| ); |
| |
| localparam num_in_vals = 1<<in_width; |
| wire signed [num_in_vals:0] c; |
| wire [(bottom_bound - top_bound - 1):0] reverse_out; |
| |
| assign c[num_in_vals] = 1; |
| assign c[(num_in_vals - 1):0] = 0; |
| assign reverse_out = (c>>>~in)>>(top_bound + 1); |
| invert #(bottom_bound - top_bound) reverse_lo(reverse_out, out); |
| |
| endmodule |
| |
| module compress_by2#(parameter in_width = 1) |
| ( |
| input wire [(in_width - 1):0] in, |
| output wire [((in_width - 1)/2):0] out |
| ); |
| |
| localparam bit_num_reduced = (in_width - 1)/2; |
| |
| genvar ix; |
| generate |
| for (ix = 0; ix < bit_num_reduced; ix = ix + 1) begin :bt |
| assign out[ix] = |in[(ix*2 + 1):ix*2]; |
| end |
| endgenerate |
| |
| assign out[bit_num_reduced] = |in[(in_width - 1):bit_num_reduced*2]; |
| endmodule |
| |
| module compress_by4#(parameter in_width = 1) |
| ( |
| input wire [(in_width - 1):0] in, |
| output wire [(in_width - 1)/4:0] out |
| ); |
| |
| localparam bit_num_reduced = (in_width - 1)/4; |
| genvar ix; |
| generate |
| for (ix = 0; ix < bit_num_reduced; ix = ix + 1) begin :bt |
| assign out[ix] = |in[(ix*4 + 3):ix*4]; |
| end |
| endgenerate |
| |
| assign out[bit_num_reduced] = |in[(in_width - 1):bit_num_reduced*4]; |
| endmodule |
| |
| module lead_zero_param#(parameter in_width = 1, parameter count_width = 1) |
| ( |
| input wire [(in_width - 1):0] in, |
| output wire [(count_width - 1):0] count |
| ); |
| |
| wire [(in_width - 1):0] reverse_in; |
| wire [in_width:0] one_least_reverse_in; |
| |
| invert #(in_width) reverse_num(in, reverse_in); |
| assign one_least_reverse_in = {1'b1, reverse_in} & ({1'b0, ~reverse_in} + 1); |
| |
| genvar ix; |
| generate |
| for (ix = 0; ix <= in_width; ix = ix + 1) begin :bt |
| wire [(count_width - 1):0] count_so_far; |
| if (ix == 0) begin |
| assign count_so_far = 0; |
| end |
| else begin |
| assign count_so_far = bt[ix - 1].count_so_far | (one_least_reverse_in[ix] ? ix : 0); |
| if (ix == in_width) |
| assign count = count_so_far; |
| end |
| end |
| endgenerate |
| endmodule |
| |
| module round_excep#( parameter in_exp_width = 8, parameter in_mant_width = 24, parameter out_exp_width = 8, |
| parameter out_mant_width = 24, parameter options = 0 ) |
| ( |
| input wire invalid_excep, |
| input wire infinite_excep, |
| input wire in_is_NaN, |
| input wire in_is_inf, |
| input wire in_is_zero, |
| input wire in_sign, |
| input wire signed [(in_exp_width + 1):0] in_sexp, |
| input wire [in_mant_width:0] in_mant, |
| input wire [2:0] round_mode, |
| |
| output wire [(out_exp_width + out_mant_width)-1:0] result, |
| output wire [4:0] exceptions |
| ); |
| |
| function integer clog2; |
| input integer a; |
| |
| begin |
| a = a - 1; |
| for (clog2 = 0; a > 0; clog2 = clog2 + 1) a = a>>1; |
| end |
| |
| endfunction |
| |
| localparam sigMSBitAlwaysZero = ((options & `flRoundOpt_sigMSBitAlwaysZero) != 0); |
| localparam effectiveInSigWidth = sigMSBitAlwaysZero ? in_mant_width : in_mant_width + 1; |
| localparam neverUnderflows = ((options & (`flRoundOpt_neverUnderflows | `flRoundOpt_subnormsAlwaysExact))!= 0) |
| || (in_exp_width < out_exp_width); |
| localparam neverOverflows = ((options & `flRoundOpt_neverOverflows) != 0) || (in_exp_width < out_exp_width); |
| localparam adjustedExpWidth = (in_exp_width < out_exp_width) ? out_exp_width + 1 : (in_exp_width == out_exp_width)? |
| in_exp_width + 2 : in_exp_width + 3; |
| localparam outNaNExp = 7<<(out_exp_width - 2); |
| localparam outInfExp = 6<<(out_exp_width - 2); |
| localparam outMaxFiniteExp = outInfExp - 1; |
| localparam outMinNormExp = (1<<(out_exp_width - 1)) + 2; |
| localparam outMinNonzeroExp = outMinNormExp - out_mant_width + 1; |
| localparam [out_exp_width:0] min_norm_exp = (1<<(out_exp_width - 1)) + 2; |
| localparam norm_dist_width = clog2(in_mant_width); |
| |
| wire roundmode_near_even, roundmode_min_mag, roundmode_min, roundmode_max, roundmode_max_mag, round_mag_up; |
| wire is_out_NaN; |
| wire signed [(adjustedExpWidth - 1):0] adjusted_sexp; |
| wire [(out_mant_width + 2):0] adjusted_mant; |
| wire notNaN_is_special_inf_out, common_case, overflow, underflow, inexact, sign_out; |
| wire overflow_round_magup, peg_min_nonzero_mag_out, peg_max_finite_mag_out, notNaN_is_inf_out; |
| wire [out_exp_width:0] exp_out; |
| wire [(out_mant_width - 2):0] mant_out; |
| wire [(out_exp_width+out_mant_width):0] out; |
| wire is_NaN, is_inf, is_zero, sign_res, is_subnorm; |
| wire signed [(out_exp_width+1):0] s_exp; |
| wire [out_mant_width:0] mant; |
| wire [(norm_dist_width - 1):0] subnorm_shift_dist; |
| wire [(out_exp_width - 1):0] exp_res; |
| wire [(out_mant_width - 2):0] mant_res; |
| wire [out_exp_width:0] common_exp_out; |
| wire [(out_mant_width - 2):0] common_mant_out; |
| wire common_overflow, common_total_underflow, common_underflow; |
| wire common_inexact; |
| wire do_shift_mant_down1; |
| |
| assign roundmode_near_even = (round_mode == `round_near_even); |
| assign roundmode_min_mag = (round_mode == `round_minMag); |
| assign roundmode_min = (round_mode == `round_min); |
| assign roundmode_max = (round_mode == `round_max); |
| assign roundmode_max_mag = (round_mode == `round_near_maxMag); |
| assign round_mag_up = (roundmode_min && in_sign) || (roundmode_max && !in_sign); |
| |
| assign is_out_NaN = invalid_excep || (!infinite_excep && in_is_NaN); |
| assign adjusted_sexp = in_sexp + ((1<<out_exp_width) - (1<<in_exp_width)); |
| |
| assign adjusted_mant = in_mant; |
| |
| assign do_shift_mant_down1 = sigMSBitAlwaysZero ? 0 : adjusted_mant[out_mant_width + 2]; |
| |
| generate |
| if ( neverOverflows && neverUnderflows && (effectiveInSigWidth <= out_mant_width) ) begin |
| assign common_exp_out = adjusted_sexp + do_shift_mant_down1; |
| assign common_mant_out = do_shift_mant_down1 ? adjusted_mant>>3 : adjusted_mant>>2; |
| end |
| else begin |
| |
| wire [(out_mant_width + 2):0] roundMask; |
| |
| if (neverUnderflows) begin |
| assign roundMask = {do_shift_mant_down1, 2'b11}; |
| end |
| else begin |
| wire [out_mant_width:0] roundMask_main; |
| |
| low_mask_lo_hi#(out_exp_width + 1,outMinNormExp-out_mant_width-1,outMinNormExp) lowmask_roundmask |
| ( adjusted_sexp[out_exp_width:0], roundMask_main ); |
| assign roundMask = {roundMask_main | do_shift_mant_down1, 2'b11}; |
| end |
| |
| wire [(out_mant_width + 2):0] shifted_round_mask, round_pos_mask; |
| wire round_pos_bit , any_round_extra, any_round, round_incr; |
| |
| assign shifted_round_mask = roundMask>>1; |
| assign round_pos_mask = ~shifted_round_mask & roundMask; |
| assign round_pos_bit = (|(adjusted_mant[(out_mant_width + 2):3] & round_pos_mask[(out_mant_width + 2):3])) || ((|(adjusted_mant[2:0] & round_pos_mask[2:0]))); |
| assign any_round_extra = (|(adjusted_mant[(out_mant_width + 2):3] & shifted_round_mask[(out_mant_width + 2):3])) || ((|(adjusted_mant[2:0] & shifted_round_mask[2:0]))); |
| assign any_round = round_pos_bit || any_round_extra; |
| |
| wire [(out_mant_width + 1):0] rounded_mant; |
| wire signed [adjustedExpWidth:0] sext_adjusted_exp,s_rounded_exp; |
| |
| assign round_incr = ((roundmode_near_even || roundmode_max_mag) && round_pos_bit) || (round_mag_up && any_round); |
| assign rounded_mant = round_incr ? (((adjusted_mant | roundMask)>>2) + 1) & ~(roundmode_near_even && round_pos_bit && !any_round_extra |
| ? roundMask>>1 : 0) : (adjusted_mant & ~roundMask)>>2; |
| assign sext_adjusted_exp = adjusted_sexp; |
| assign s_rounded_exp = sext_adjusted_exp + (rounded_mant>>out_mant_width); |
| |
| |
| assign common_exp_out = s_rounded_exp; |
| assign common_mant_out = do_shift_mant_down1 ? rounded_mant>>1 : rounded_mant; |
| assign common_overflow = neverOverflows ? 0 : (s_rounded_exp>>>(out_exp_width - 1) >= 3); |
| assign common_total_underflow = neverUnderflows ? 0 : (s_rounded_exp < outMinNonzeroExp); |
| |
| wire unbound_range_round_posbit, unbound_range_any_round, unbound_range_round_incr, round_carry ; |
| |
| assign unbound_range_round_posbit = do_shift_mant_down1 ? adjusted_mant[2] : adjusted_mant[1]; |
| assign unbound_range_any_round = (do_shift_mant_down1 && adjusted_mant[2]) || (|adjusted_mant[1:0]); |
| assign unbound_range_round_incr = ((roundmode_near_even || roundmode_max_mag) && unbound_range_round_posbit) |
| || (round_mag_up && unbound_range_any_round); |
| |
| assign round_carry = do_shift_mant_down1 ? rounded_mant[out_mant_width + 1] : rounded_mant[out_mant_width]; |
| assign common_underflow = neverUnderflows ? 0 : common_total_underflow || (any_round && (adjusted_sexp>>>out_exp_width <= 0) |
| && (do_shift_mant_down1 ? roundMask[3] : roundMask[2]) && !(((`flControl_tininessAfterRounding) != 0) |
| && !(do_shift_mant_down1 ? roundMask[4] : roundMask[3]) && round_carry && round_pos_bit |
| && unbound_range_round_incr)); |
| assign common_inexact = common_total_underflow || any_round; |
| end |
| endgenerate |
| |
| assign notNaN_is_special_inf_out = infinite_excep || in_is_inf; |
| assign common_case = !is_out_NaN && !notNaN_is_special_inf_out && !in_is_zero; |
| assign overflow = common_case && common_overflow; |
| assign underflow = common_case && common_underflow; |
| assign inexact = overflow || (common_case && common_inexact); |
| |
| assign overflow_round_magup = roundmode_near_even || roundmode_max_mag || round_mag_up; |
| assign peg_min_nonzero_mag_out = common_case && common_total_underflow && (round_mag_up); |
| assign peg_max_finite_mag_out = overflow && !overflow_round_magup; |
| assign notNaN_is_inf_out = notNaN_is_special_inf_out || (overflow && overflow_round_magup); |
| |
| assign sign_out = is_out_NaN ? `HardFloat_signDefaultNaN : in_sign; |
| |
| assign exp_out = (common_exp_out & ~(in_is_zero || common_total_underflow ? 7<<(out_exp_width - 2) : 0) |
| & ~(peg_min_nonzero_mag_out ? ~outMinNonzeroExp : 0) |
| & ~(peg_max_finite_mag_out ? 1<<(out_exp_width - 1) : 0) |
| & ~(notNaN_is_inf_out ? 1<<(out_exp_width - 2) : 0)) |
| | (peg_min_nonzero_mag_out ? outMinNonzeroExp : 0) |
| | (peg_max_finite_mag_out ? outMaxFiniteExp : 0) |
| | (notNaN_is_inf_out ? outInfExp : 0) |
| | (is_out_NaN ? outNaNExp : 0); |
| |
| |
| assign mant_out = (is_out_NaN ? `HardFloat_fractDefaultNaN(out_mant_width) : 0) |
| | (!in_is_zero && !common_total_underflow |
| ? common_mant_out & `HardFloat_fractDefaultNaN(out_mant_width) : 0) |
| | (!is_out_NaN && !in_is_zero && !common_total_underflow |
| ? common_mant_out & ~`HardFloat_fractDefaultNaN(out_mant_width): 0) |
| | {(out_mant_width - 1){peg_max_finite_mag_out}}; |
| |
| |
| assign out = {sign_out, exp_out, mant_out}; |
| assign exceptions = {invalid_excep, infinite_excep, overflow, underflow, inexact}; |
| |
| mac_spec_check #(out_exp_width, out_mant_width) mac_spec_check_out(.in(out), .is_qNaN(is_NaN), .is_inf(is_inf), .is_zero(is_zero), |
| .is_sNaN(), .sign(sign_res), .s_exp(s_exp), .sig(mant)); |
| assign is_subnorm = (s_exp < min_norm_exp); |
| |
| assign subnorm_shift_dist = min_norm_exp - 1 - s_exp; |
| assign exp_res = (is_subnorm ? 0 : s_exp - min_norm_exp + 1) | (is_NaN || is_inf ? {out_exp_width{1'b1}} : 0); |
| assign mant_res = is_subnorm ? (mant>>1)>>subnorm_shift_dist : is_inf ? 0 : mant; |
| assign result = {sign_res, exp_res, mant_res}; |
| |
| endmodule |