blob: b511f337e17d161c5d1a7a7e506be283c1a0ef57 [file] [log] [blame]
//`include "fpu_lib.sv"
module sqrt #( parameter exp_width = 8, parameter mant_width = 24, parameter options = 0)
(
input wire clk,
input wire rst_l,
input wire in_valid,
input wire [(exp_width + mant_width)-1:0] a,
input wire [2:0] round_mode,
input wire cancel,
output wire in_ready,
output wire out_valid,
output wire [(exp_width + mant_width)-1:0] out,
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
wire is_a_qNaN, is_a_inf, is_a_zero, is_a_sNaN, sign_a;
wire signed [(exp_width + 1):0] sexp_a;
wire [mant_width:0] mant_a;
wire not_sNaN_inval_excep, major_excep;
wire is_res_NaN, is_res_inf, is_res_zero, sign_res;
wire special_case_a, normal_case_sqrt, normal_case_s;
wire even_sqrt, odd_sqrt;
wire [(clog2(mant_width + 3) - 1):0] cycle_num, cycle_num_in;
wire major_exc_z, not_zero_rem_z;
wire is_NaN_z, is_inf_z, is_zero_z, sign_z;
wire signed [(exp_width + 1):0] sexp_z, sexp_z_in;
wire [(mant_width - 2):0] mant_b_z;
wire [2:0] round_mode_z;
wire [(mant_width + 1):0] rem_z, rem_z_in;
wire [(mant_width + 1):0] mantx_z, mantx_z_in;
wire idle, entering, entering_norm_case, skip_cycle_2;
wire [1:0] dec_hi_mant_a;
wire [(mant_width + 2):0] rem;
wire [mant_width:0] bit_mask;
wire [(mant_width + 1):0] trail_term;
wire signed [(mant_width + 3):0] trail_rem;
wire new_bit;
wire [2:0] round_mode_out;
wire invalid_excep;
wire infinite_excep;
wire is_out_NaN;
wire is_out_inf;
wire is_out_zero;
wire out_sign;
wire signed [(exp_width + 1):0] out_sexp;
wire [(mant_width + 2):0] out_mant;
wire [(exp_width + mant_width):0] num;
wire cancel_reset;
assign cancel_reset = rst_l & !cancel;
exponent #(exp_width, mant_width) exp_a (.in(a), .out(num));
mac_spec_check #(exp_width,mant_width ) mac_spec_check (.in(num), .is_qNaN (is_a_qNaN), .is_inf(is_a_inf), .is_zero(is_a_zero),
.is_sNaN(is_a_sNaN),.sign(sign_a), .s_exp(sexp_a), .sig(mant_a) );
assign not_sNaN_inval_excep = !is_a_qNaN && !is_a_zero && sign_a;
assign major_excep = is_a_sNaN || not_sNaN_inval_excep;
assign is_res_NaN = is_a_qNaN || not_sNaN_inval_excep;
assign is_res_inf = is_a_inf;
assign is_res_zero = is_a_zero;
assign sign_res = sign_a;
assign special_case_a = is_a_qNaN || is_a_inf || is_a_zero;
assign normal_case_sqrt = !special_case_a && !sign_a;
assign normal_case_s = normal_case_sqrt;
assign even_sqrt = !sexp_a[0];
assign odd_sqrt = sexp_a[0];
assign idle = (cycle_num == 0);
assign in_ready = (cycle_num <= 1);
assign entering = in_ready && in_valid;
assign entering_norm_case = entering && normal_case_s;
assign skip_cycle_2 = (cycle_num == 3) && mantx_z[mant_width + 1];
assign cycle_num_in = (entering && !normal_case_s ? 1 : 0)
| (entering_norm_case ? ((sexp_a[0] ? mant_width : mant_width + 1)) : 0)
| (!idle && !skip_cycle_2 ? cycle_num - 1 : 0)
| (!idle && skip_cycle_2 ? 1 : 0);
rvdffe #(clog2(mant_width + 3)) cycle_num_ff (.clk(clk), .rst_l(cancel_reset), .din(cycle_num_in), .en(!idle || in_valid), .dout(cycle_num));
rvdffe #(1) major_exc_z_ff (.clk(clk), .rst_l(cancel_reset), .din(major_excep), .en(entering), .dout(major_exc_z));
rvdffe #(1) is_NaN_z_ff (.clk(clk), .rst_l(cancel_reset), .din(is_res_NaN), .en(entering), .dout(is_NaN_z));
rvdffe #(1) is_inf_z_ff (.clk(clk), .rst_l(cancel_reset), .din(is_res_inf), .en(entering), .dout(is_inf_z));
rvdffe #(1) is_zero_z_ff (.clk(clk), .rst_l(cancel_reset), .din(is_res_zero), .en(entering), .dout(is_zero_z));
rvdffe #(1) sign_z_ff (.clk(clk), .rst_l(cancel_reset), .din(sign_res), .en(entering), .dout(sign_z));
assign sexp_z_in = (sexp_a>>>1) + (1<<(exp_width - 1));
rvdffe #((exp_width + 2)) sexp_z_ff (.clk(clk), .rst_l(cancel_reset), .din(sexp_z_in), .en(entering_norm_case), .dout(sexp_z));
rvdffe #(3) round_mode_z_ff (.clk(clk), .rst_l(cancel_reset), .din(round_mode), .en(entering_norm_case), .dout(round_mode_z));
assign dec_hi_mant_a = mant_a[(mant_width - 1):(mant_width - 2)] - 1;
assign rem = (in_ready && !odd_sqrt ? mant_a<<1 : 0) | (in_ready && odd_sqrt
? {dec_hi_mant_a, mant_a[(mant_width - 3):0], 3'b0} : 0) | (!in_ready ? rem_z<<1 : 0);
assign bit_mask = ({{(mant_width + 2){1'b0}}, 1'b1}<<cycle_num)>>2;
assign trail_term = (in_ready && even_sqrt ? 1<<mant_width : 0)
| (in_ready && odd_sqrt ? 5<<(mant_width - 1) : 0)
| (!in_ready ? mantx_z<<1 | bit_mask : 0);
assign trail_rem = rem - trail_term;
assign new_bit = (0 <= trail_rem);
assign rem_z_in = new_bit ? trail_rem : rem;
rvdffe #((mant_width + 2)) rem_z_ff (.clk(clk), .rst_l(cancel_reset), .din(rem_z_in), .en(entering_norm_case || (cycle_num > 2)), .dout(rem_z));
rvdffe #(1) not_zero_rem_z_ff (.clk(clk), .rst_l(cancel_reset), .din((trail_rem != 0)), .en(entering_norm_case || (!in_ready && new_bit)), .dout(not_zero_rem_z));
assign mantx_z_in = ( in_ready ? 1<<mant_width : 0)
|( in_ready && odd_sqrt ? new_bit<<(mant_width - 1) : 0)
|(!in_ready ? mantx_z | bit_mask : 0);
rvdffe #((mant_width + 2)) mantx_z_ff (.clk(clk), .rst_l(cancel_reset), .din(mantx_z_in), .en(entering_norm_case || (!in_ready && new_bit)), .dout(mantx_z));
assign out_valid = (cycle_num == 1);
assign round_mode_out = round_mode_z;
assign invalid_excep = major_exc_z && is_NaN_z;
assign infinite_excep = 1'b0;
assign is_out_NaN = is_NaN_z;
assign is_out_inf = is_inf_z;
assign is_out_zero = is_zero_z;
assign out_sign = sign_z;
assign out_sexp = sexp_z;
assign out_mant = {mantx_z, not_zero_rem_z};
round_excep #(exp_width, mant_width+2, exp_width,mant_width,0) round_exception
( .invalid_excep(invalid_excep), .infinite_excep(infinite_excep), .in_is_NaN(is_out_NaN),
.in_is_inf(is_out_inf), .in_is_zero(is_out_zero),.in_sign(out_sign),.in_sexp(out_sexp),
.in_mant(out_mant),.round_mode(round_mode), .result(out), .exceptions(exceptions));
endmodule