Line 310... |
Line 310... |
variable op_m_all_zero_v, op_e_all_zero_v, op_e_all_one_v : std_ulogic;
|
variable op_m_all_zero_v, op_e_all_zero_v, op_e_all_one_v : std_ulogic;
|
variable op_is_zero_v, op_is_inf_v, op_is_denorm_v, op_is_nan_v : std_ulogic;
|
variable op_is_zero_v, op_is_inf_v, op_is_denorm_v, op_is_nan_v : std_ulogic;
|
begin
|
begin
|
for i in 0 to 1 loop -- for rs1 and rs2 inputs
|
for i in 0 to 1 loop -- for rs1 and rs2 inputs
|
-- check for all-zero/all-one --
|
-- check for all-zero/all-one --
|
op_m_all_zero_v := not or_reduce_f(op_data(i)(22 downto 00));
|
op_m_all_zero_v := '0';
|
op_e_all_zero_v := not or_reduce_f(op_data(i)(30 downto 23));
|
op_e_all_zero_v := '0';
|
op_e_all_one_v := and_reduce_f(op_data(i)(30 downto 23));
|
op_e_all_one_v := '0';
|
|
if (or_reduce_f(op_data(i)(22 downto 00)) = '0') then
|
|
op_m_all_zero_v := '1';
|
|
end if;
|
|
if (or_reduce_f(op_data(i)(30 downto 23)) = '0') then
|
|
op_e_all_zero_v := '1';
|
|
end if;
|
|
if (and_reduce_f(op_data(i)(30 downto 23)) = '1') then
|
|
op_e_all_one_v := '1';
|
|
end if;
|
|
|
-- check special cases --
|
-- check special cases --
|
op_is_zero_v := op_e_all_zero_v and op_m_all_zero_v; -- zero
|
op_is_zero_v := op_e_all_zero_v and op_m_all_zero_v; -- zero
|
op_is_inf_v := op_e_all_one_v and op_m_all_zero_v; -- infinity
|
op_is_inf_v := op_e_all_one_v and op_m_all_zero_v; -- infinity
|
op_is_denorm_v := '0'; -- FIXME / TODO -- op_e_all_zero_v and (not op_m_all_zero_v); -- subnormal
|
op_is_denorm_v := '0'; -- FIXME / TODO -- op_e_all_zero_v and (not op_m_all_zero_v); -- subnormal
|
Line 341... |
Line 350... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
control_engine_fsm: process(rstn_i, clk_i)
|
control_engine_fsm: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
ctrl_engine.state <= S_IDLE;
|
ctrl_engine.state <= S_IDLE;
|
|
ctrl_engine.valid <= '0';
|
ctrl_engine.start <= '0';
|
ctrl_engine.start <= '0';
|
fpu_operands.frm <= (others => def_rst_val_c);
|
fpu_operands.frm <= (others => def_rst_val_c);
|
fpu_operands.rs1 <= (others => def_rst_val_c);
|
fpu_operands.rs1 <= (others => def_rst_val_c);
|
fpu_operands.rs1_class <= (others => def_rst_val_c);
|
fpu_operands.rs1_class <= (others => def_rst_val_c);
|
fpu_operands.rs2 <= (others => def_rst_val_c);
|
fpu_operands.rs2 <= (others => def_rst_val_c);
|
Line 669... |
Line 679... |
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic;
|
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic;
|
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic;
|
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic;
|
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic;
|
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic;
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
multiplier.res_class(fp_class_pos_norm_c) <= def_rst_val_c;
|
multiplier.res_class <= (others => def_rst_val_c);
|
multiplier.res_class(fp_class_neg_norm_c) <= def_rst_val_c;
|
|
multiplier.res_class(fp_class_pos_inf_c) <= def_rst_val_c;
|
|
multiplier.res_class(fp_class_neg_inf_c) <= def_rst_val_c;
|
|
multiplier.res_class(fp_class_pos_zero_c) <= def_rst_val_c;
|
|
multiplier.res_class(fp_class_neg_zero_c) <= def_rst_val_c;
|
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- minions --
|
-- minions --
|
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c);
|
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c);
|
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c);
|
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c);
|
a_pos_subn_v := fpu_operands.rs1_class(fp_class_pos_denorm_c); b_pos_subn_v := fpu_operands.rs2_class(fp_class_pos_denorm_c);
|
a_pos_subn_v := fpu_operands.rs1_class(fp_class_pos_denorm_c); b_pos_subn_v := fpu_operands.rs2_class(fp_class_pos_denorm_c);
|
Line 754... |
Line 759... |
multiplier.res_class(fp_class_qnan_c) <=
|
multiplier.res_class(fp_class_qnan_c) <=
|
(a_snan_v or b_snan_v) or -- any input is sNaN
|
(a_snan_v or b_snan_v) or -- any input is sNaN
|
(a_qnan_v or b_qnan_v) or -- nay input is qNaN
|
(a_qnan_v or b_qnan_v) or -- nay input is qNaN
|
((a_pos_inf_v or a_neg_inf_v) and (b_pos_zero_v or b_neg_zero_v)) or -- +/-inf * +/-zero
|
((a_pos_inf_v or a_neg_inf_v) and (b_pos_zero_v or b_neg_zero_v)) or -- +/-inf * +/-zero
|
((a_pos_zero_v or a_neg_zero_v) and (b_pos_inf_v or b_neg_inf_v)); -- +/-zero * +/-inf
|
((a_pos_zero_v or a_neg_zero_v) and (b_pos_inf_v or b_neg_inf_v)); -- +/-zero * +/-inf
|
end if;
|
|
end process multiplier_class_core;
|
|
|
|
-- subnormal result --
|
-- subnormal result --
|
multiplier.res_class(fp_class_pos_denorm_c) <= '0'; -- is evaluated by the normalizer
|
multiplier.res_class(fp_class_pos_denorm_c) <= '0'; -- is evaluated by the normalizer
|
multiplier.res_class(fp_class_neg_denorm_c) <= '0'; -- is evaluated by the normalizer
|
multiplier.res_class(fp_class_neg_denorm_c) <= '0'; -- is evaluated by the normalizer
|
|
end if;
|
|
end process multiplier_class_core;
|
|
|
-- unused --
|
-- unused --
|
fu_mul.result <= (others => '0');
|
fu_mul.result <= (others => '0');
|
fu_mul.flags <= (others => '0');
|
fu_mul.flags <= (others => '0');
|
|
|
Line 908... |
Line 913... |
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic;
|
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic;
|
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic;
|
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic;
|
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic;
|
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic;
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
addsub.res_class(fp_class_pos_inf_c) <= def_rst_val_c;
|
addsub.res_class <= (others => def_rst_val_c);
|
addsub.res_class(fp_class_neg_inf_c) <= def_rst_val_c;
|
|
addsub.res_class(fp_class_pos_zero_c) <= def_rst_val_c;
|
|
addsub.res_class(fp_class_neg_zero_c) <= def_rst_val_c;
|
|
addsub.res_class(fp_class_qnan_c) <= def_rst_val_c;
|
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- minions --
|
-- minions --
|
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c);
|
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c);
|
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c);
|
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c);
|
a_pos_subn_v := fpu_operands.rs1_class(fp_class_pos_denorm_c); b_pos_subn_v := fpu_operands.rs2_class(fp_class_pos_denorm_c);
|
a_pos_subn_v := fpu_operands.rs1_class(fp_class_pos_denorm_c); b_pos_subn_v := fpu_operands.rs2_class(fp_class_pos_denorm_c);
|
Line 1037... |
Line 1038... |
addsub.res_class(fp_class_pos_norm_c) <= (a_pos_norm_v or a_neg_norm_v) and (b_pos_norm_v or b_neg_norm_v); -- +/-norm +/- +-/norm [sign is irrelevant here]
|
addsub.res_class(fp_class_pos_norm_c) <= (a_pos_norm_v or a_neg_norm_v) and (b_pos_norm_v or b_neg_norm_v); -- +/-norm +/- +-/norm [sign is irrelevant here]
|
addsub.res_class(fp_class_neg_norm_c) <= (a_pos_norm_v or a_neg_norm_v) and (b_pos_norm_v or b_neg_norm_v); -- +/-norm +/- +-/norm [sign is irrelevant here]
|
addsub.res_class(fp_class_neg_norm_c) <= (a_pos_norm_v or a_neg_norm_v) and (b_pos_norm_v or b_neg_norm_v); -- +/-norm +/- +-/norm [sign is irrelevant here]
|
|
|
-- sNaN --
|
-- sNaN --
|
addsub.res_class(fp_class_snan_c) <= (a_snan_v or b_snan_v); -- any input is sNaN
|
addsub.res_class(fp_class_snan_c) <= (a_snan_v or b_snan_v); -- any input is sNaN
|
end if;
|
|
end process adder_subtractor_class_core;
|
|
|
|
-- subnormal result --
|
-- subnormal result --
|
addsub.res_class(fp_class_pos_denorm_c) <= '0'; -- is evaluated by the normalizer
|
addsub.res_class(fp_class_pos_denorm_c) <= '0'; -- is evaluated by the normalizer
|
addsub.res_class(fp_class_neg_denorm_c) <= '0'; -- is evaluated by the normalizer
|
addsub.res_class(fp_class_neg_denorm_c) <= '0'; -- is evaluated by the normalizer
|
|
end if;
|
|
end process adder_subtractor_class_core;
|
|
|
-- unused --
|
-- unused --
|
fu_addsub.result <= (others => '0');
|
fu_addsub.result <= (others => '0');
|
fu_addsub.flags <= (others => '0');
|
fu_addsub.flags <= (others => '0');
|
|
|
Line 1357... |
Line 1358... |
sreg.upper(31 downto 02) <= (others => '0');
|
sreg.upper(31 downto 02) <= (others => '0');
|
sreg.upper(01 downto 00) <= mantissa_i(47 downto 46);
|
sreg.upper(01 downto 00) <= mantissa_i(47 downto 46);
|
sreg.lower <= mantissa_i(45 downto 23);
|
sreg.lower <= mantissa_i(45 downto 23);
|
sreg.ext_g <= mantissa_i(22);
|
sreg.ext_g <= mantissa_i(22);
|
sreg.ext_r <= mantissa_i(21);
|
sreg.ext_r <= mantissa_i(21);
|
sreg.ext_s <= or_reduce_f(mantissa_i(20 downto 0));
|
if (or_reduce_f(mantissa_i(20 downto 0)) = '1') then
|
|
sreg.ext_s <= '1';
|
|
else
|
|
sreg.ext_s <= '0';
|
|
end if;
|
-- check for special cases --
|
-- check for special cases --
|
if ((ctrl.class(fp_class_snan_c) or ctrl.class(fp_class_qnan_c) or -- NaN
|
if ((ctrl.class(fp_class_snan_c) or ctrl.class(fp_class_qnan_c) or -- NaN
|
ctrl.class(fp_class_neg_zero_c) or ctrl.class(fp_class_pos_zero_c) or -- zero
|
ctrl.class(fp_class_neg_zero_c) or ctrl.class(fp_class_pos_zero_c) or -- zero
|
ctrl.class(fp_class_neg_denorm_c) or ctrl.class(fp_class_pos_denorm_c) or -- subnormal
|
ctrl.class(fp_class_neg_denorm_c) or ctrl.class(fp_class_pos_denorm_c) or -- subnormal
|
ctrl.class(fp_class_neg_inf_c) or ctrl.class(fp_class_pos_inf_c) or -- infinity
|
ctrl.class(fp_class_neg_inf_c) or ctrl.class(fp_class_pos_inf_c) or -- infinity
|
Line 1472... |
Line 1477... |
end case;
|
end case;
|
end if;
|
end if;
|
end process ctrl_engine;
|
end process ctrl_engine;
|
|
|
-- stop shifting when normalized --
|
-- stop shifting when normalized --
|
sreg.done <= (not or_reduce_f(sreg.upper(sreg.upper'left downto 1))) and sreg.upper(0); -- input is zero, hidden one is set
|
sreg.done <= '1' when (or_reduce_f(sreg.upper(sreg.upper'left downto 1)) = '0') and (sreg.upper(0) = '1') else '0'; -- input is zero, hidden one is set
|
|
|
-- all-zero including hidden bit --
|
-- all-zero including hidden bit --
|
sreg.zero <= not or_reduce_f(sreg.upper);
|
sreg.zero <= '1' when (or_reduce_f(sreg.upper) = '0') else '0';
|
|
|
-- result --
|
-- result --
|
result_o(31) <= ctrl.res_sgn;
|
result_o(31) <= ctrl.res_sgn;
|
result_o(30 downto 23) <= ctrl.res_exp;
|
result_o(30 downto 23) <= ctrl.res_exp;
|
result_o(22 downto 0) <= ctrl.res_man;
|
result_o(22 downto 0) <= ctrl.res_man;
|
Line 1714... |
Line 1719... |
ctrl.state <= S_NORMALIZE_BUSY;
|
ctrl.state <= S_NORMALIZE_BUSY;
|
end if;
|
end if;
|
|
|
when S_NORMALIZE_BUSY => -- running normalization cycle
|
when S_NORMALIZE_BUSY => -- running normalization cycle
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
sreg.ext_s <= sreg.ext_s or or_reduce_f(sreg.mant(sreg.mant'left-2 downto 0)); -- sticky bit
|
if (or_reduce_f(sreg.mant(sreg.mant'left-2 downto 0)) = '1') then
|
|
sreg.ext_s <= '1'; -- sticky bit
|
|
end if;
|
if (or_reduce_f(ctrl.cnt(ctrl.cnt'left-1 downto 0)) = '0') then
|
if (or_reduce_f(ctrl.cnt(ctrl.cnt'left-1 downto 0)) = '0') then
|
if (ctrl.unsign = '0') then -- signed conversion
|
if (ctrl.unsign = '0') then -- signed conversion
|
ctrl.over <= ctrl.over or sreg.int(sreg.int'left); -- update overrun flag again to check for numerical overflow into sign bit
|
ctrl.over <= ctrl.over or sreg.int(sreg.int'left); -- update overrun flag again to check for numerical overflow into sign bit
|
end if;
|
end if;
|
ctrl.state <= S_ROUND;
|
ctrl.state <= S_ROUND;
|