📄 fpu_arch.vhd
字号:
ELSIF fracta_mul(22 DOWNTO 7) = "0000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(16,5); ELSIF fracta_mul(22 DOWNTO 6) = "00000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(17,5); ELSIF fracta_mul(22 DOWNTO 5) = "000000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(18,5); ELSIF fracta_mul(22 DOWNTO 4) = "0000000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(19,5); ELSIF fracta_mul(22 DOWNTO 3) = "00000000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(20,5); ELSIF fracta_mul(22 DOWNTO 2) = "000000000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(21,5); ELSIF fracta_mul(22 DOWNTO 1) = "0000000000000000000001" THEN div_opa_ldz_d <= conv_std_logic_vector(22,5); ELSIF fracta_mul(22 DOWNTO 1) = "0000000000000000000000" THEN div_opa_ldz_d <= conv_std_logic_vector(23,5); ELSE div_opa_ldz_d <= (OTHERS => 'X'); END IF;END PROCESS; fdiv_opa <= ((SHL(fracta_mul,div_opa_ldz_d)) & "00" & X"000000") WHEN ((or_reduce(opa_r(30 DOWNTO 23)))='0') ELSE (fracta_mul & "00" & X"000000"); u6 : div_r2 PORT MAP (clk => clk, opa => fdiv_opa, opb => fractb_mul, quo => quo, remainder => remainder); remainder_00 <= NOT or_reduce(remainder); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN div_opa_ldz_r1 <= div_opa_ldz_d; div_opa_ldz_r2 <= div_opa_ldz_r1; END IF; END PROCESS;---------------------------------------------------------------------------- Normalize Result-- PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN CASE fpu_op_r2 IS WHEN "000" => exp_r <= exp_fasu; WHEN "001" => exp_r <= exp_fasu; WHEN "010" => exp_r <= exp_mul; WHEN "011" => exp_r <= exp_mul; WHEN "100" => exp_r <= (others => '0'); WHEN "101" => exp_r <= opa_r1(30 downto 23); WHEN OTHERS => exp_r <= (others => '0'); END case; END IF; END PROCESS; fract_div <= quo(49 DOWNTO 2) WHEN (opb_dn = '1') ELSE (quo(26 DOWNTO 0) & '0' & X"00000"); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN opa_r1 <= opa_r(30 DOWNTO 0); IF fpu_op_r2="101" THEN IF sign_d = '1' THEN fract_i2f <= conv_std_logic_vector(1,48)-(X"000000" & (or_reduce(opa_r1(30 downto 23))) & opa_r1(22 DOWNTO 0))-conv_std_logic_vector(1,48); ELSE fract_i2f <= (X"000000" & (or_reduce(opa_r1(30 downto 23))) & opa_r1(22 DOWNTO 0)); END IF; ELSE IF sign_d = '1' THEN fract_i2f <= conv_std_logic_vector(1,48) - (opa_r1 & X"0000" & '1'); ELSE fract_i2f <= (opa_r1 & '0' & X"0000"); END IF; END IF; END IF; END PROCESS; PROCESS (fpu_op_r3,fract_out_q,prod,fract_div,fract_i2f) BEGIN CASE fpu_op_r3 IS WHEN "000" => fract_denorm <= (fract_out_q & X"00000"); WHEN "001" => fract_denorm <= (fract_out_q & X"00000"); WHEN "010" => fract_denorm <= prod; WHEN "011" => fract_denorm <= fract_div; WHEN "100" => fract_denorm <= fract_i2f; WHEN "101" => fract_denorm <= fract_i2f; WHEN OTHERS => fract_denorm <= (others => '0'); END case; END PROCESS; PROCESS (clk, opa_r(31),opas_r1,rmode_r2,sign_d) BEGIN IF clk'event AND clk = '1' THEN opas_r1 <= opa_r(31); opas_r2 <= opas_r1; IF rmode_r2="11" THEN sign <= NOT sign_d; ELSE sign <= sign_d; END IF; END if; END PROCESS; sign_d <= sign_mul WHEN (fpu_op_r2(1) = '1') ELSE sign_fasu; post_norm_output_zero <= mul_00 or div_00; u4 : post_norm PORT MAP ( clk => clk, -- System Clock fpu_op => fpu_op_r3, -- Floating Point Operation opas => opas_r2, -- OPA Sign sign => sign, -- Sign of the result rmode => rmode_r3, -- Rounding mode fract_in => fract_denorm, -- Fraction Input exp_ovf => exp_ovf_r, -- Exponent Overflow exp_in => exp_r, -- Exponent Input opa_dn => opa_dn, -- Operand A Denormalized opb_dn => opb_dn, -- Operand A Denormalized rem_00 => remainder_00, -- Diveide Remainder is zero div_opa_ldz => div_opa_ldz_r2, -- Divide opa leading zeros count output_zero => post_norm_output_zero, -- Force output to Zero fpout => out_d, -- Normalized output (un-registered) ine => ine_d, -- Result Inexact output (un-registered) overflow => overflow_d, -- Overflow output (un-registered) underflow => underflow_d, -- Underflow output (un-registered) f2i_out_sign => f2i_out_sign -- F2I Output Sign );---------------------------------------------------------------------------- FPU Outputs-- PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN fasu_op_r1 <= fasu_op; fasu_op_r2 <= fasu_op_r1; IF exp_mul = X"ff" THEN inf_mul2 <= '1'; ELSE inf_mul2 <= '0'; END IF; END IF; END PROCESS; -- Force pre-set values for non numerical output mul_inf <= '1' WHEN ((fpu_op_r3="010") and ((inf_mul_r or inf_mul2)='1') and (rmode_r3="00")) else '0'; div_inf <= '1' WHEN ((fpu_op_r3="011") and ((opb_00 or opa_inf)='1')) ELSE '0'; mul_00 <= '1' WHEN ((fpu_op_r3="010") and ((opa_00 or opb_00)='1')) ELSE '0'; div_00 <= '1' WHEN ((fpu_op_r3="011") and ((opa_00 or opb_inf)='1')) else '0'; out_fixed <= QNAN_VAL(30 DOWNTO 0) WHEN (((qnan_d OR snan_d) OR (ind_d AND NOT fasu_op_r2) OR ((NOT fpu_op_r3(2) AND fpu_op_r3(1) AND fpu_op_r3(0)) AND opb_00 AND opa_00) OR (((opa_inf AND opb_00) OR (opb_inf AND opa_00 )) AND (NOT fpu_op_r3(2) AND fpu_op_r3(1) AND NOT fpu_op_r3(0))) )='1') ELSE INF_VAL(30 DOWNTO 0); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF ( ((mul_inf='1') or (div_inf='1') or ((inf_d='1') and (fpu_op_r3/="011") and (fpu_op_r3/="101")) or (snan_d='1') or (qnan_d='1')) and (fpu_op_r3/="100")) THEN fpout(30 DOWNTO 0) <= out_fixed; ELSE fpout(30 DOWNTO 0) <= out_d; END IF; END IF; END PROCESS; out_d_00 <= NOT or_reduce(out_d); sign_mul_final <= NOT sign_mul_r WHEN ((sign_exe_r AND ((opa_00 AND opb_inf) OR (opb_00 AND opa_inf)))='1') ELSE sign_mul_r; sign_div_final <= NOT sign_mul_r WHEN ((sign_exe_r and (opa_inf and opb_inf))='1') ELSE (sign_mul_r or (opa_00 and opb_00)); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN If ((fpu_op_r3="101") and (out_d_00='1')) THEN fpout(31) <= (f2i_out_sign and not(qnan_d OR snan_d) ); ELSIF ((fpu_op_r3="010") and ((snan_d or qnan_d)='0')) THEN fpout(31) <= sign_mul_final; ELSIF ((fpu_op_r3="011") and ((snan_d or qnan_d)='0')) THEN fpout(31) <= sign_div_final; ELSIF ((snan_d or qnan_d or ind_d) = '1') THEN fpout(31) <= nan_sign_d; ELSIF (output_zero_fasu = '1') THEN fpout(31) <= result_zero_sign_d; ELSE fpout(31) <= sign_fasu_r; END IF; END IF; END PROCESS;-- Exception Outputs ine_mula <= ((inf_mul_r OR inf_mul2 OR opa_inf OR opb_inf) AND (NOT rmode_r3(1) AND rmode_r3(0)) and NOT ((opa_inf AND opb_00) OR (opb_inf AND opa_00 )) AND fpu_op_r3(1)); ine_mul <= (ine_mula OR ine_d OR inf_fmul OR out_d_00 OR overflow_d OR underflow_d) AND NOT opa_00 and NOT opb_00 and NOT (snan_d OR qnan_d OR inf_d); ine_div <= (ine_d OR overflow_d OR underflow_d) AND NOT (opb_00 OR snan_d OR qnan_d OR inf_d); ine_fasu <= (ine_d OR overflow_d OR underflow_d) AND NOT (snan_d OR qnan_d OR inf_d); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF fpu_op_r3(2) = '1' THEN ine <= ine_d; ELSIF fpu_op_r3(1) = '0' THEN ine <= ine_fasu; ELSIF fpu_op_r3(0)='1' THEN ine <= ine_div; ELSE ine <= ine_mul; END IF; END IF; END PROCESS; overflow_fasu <= overflow_d AND NOT (snan_d OR qnan_d OR inf_d); overflow_fmul <= NOT inf_d AND (inf_mul_r OR inf_mul2 OR overflow_d) AND NOT (snan_d OR qnan_d); overflow_fdiv <= (overflow_d AND NOT (opb_00 OR inf_d OR snan_d OR qnan_d)); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN underflow_fmul_r <= underflow_fmul_d; IF fpu_op_r3(2) ='1' THEN overflow <= '0'; ELSIF fpu_op_r3(1) = '0' THEN overflow <= overflow_fasu; ELSIF fpu_op_r3(0) = '1' THEN overflow <= overflow_fdiv; ELSE overflow <= overflow_fmul; END IF; END IF; END PROCESS; underflow_fmul1_p1 <= '1' WHEN (out_d(30 DOWNTO 23) = X"00") else '0'; underflow_fmul1_p2 <= '1' WHEN (out_d(22 DOWNTO 0) = ("000" & X"00000")) else '0'; underflow_fmul1_p3 <= '1' WHEN (prod/=conv_std_logic_vector(0,48)) else '0'; underflow_fmul1 <= underflow_fmul_r(0) or (underflow_fmul_r(1) and underflow_d ) or ((opa_dn or opb_dn) and out_d_00 and (underflow_fmul1_p3) and sign) or (underflow_fmul_r(2) AND ((underflow_fmul1_p1) or (underflow_fmul1_p2))); underflow_fasu <= underflow_d AND NOT (inf_d or snan_d or qnan_d); underflow_fmul <= underflow_fmul1 AND NOT (snan_d or qnan_d or inf_mul_r); underflow_fdiv <= underflow_fasu AND NOT opb_00; PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF fpu_op_r3(2) = '1' THEN underflow <= '0'; ELSIF fpu_op_r3(1) = '0' THEN underflow <= underflow_fasu; ELSIF fpu_op_r3(0) = '1' THEN underflow <= underflow_fdiv; ELSE underflow <= underflow_fmul; END IF; snan <= snan_d; END IF; END PROCESS;-- Status Outputs PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF fpu_op_r3(2)='1' THEN qnan <= '0'; ELSE qnan <= snan_d OR qnan_d OR (ind_d AND NOT fasu_op_r2) OR (opa_00 AND opb_00 AND (NOT fpu_op_r3(2) AND fpu_op_r3(1) AND fpu_op_r3(0))) OR (((opa_inf AND opb_00) OR (opb_inf AND opa_00 )) AND (NOT fpu_op_r3(2) AND fpu_op_r3(1) AND NOT fpu_op_r3(0))); END IF; END IF; END PROCESS; inf_fmul <= (((inf_mul_r OR inf_mul2) AND (NOT rmode_r3(1) AND NOT rmode_r3(0))) OR opa_inf OR opb_inf) AND NOT ((opa_inf AND opb_00) OR (opb_inf AND opa_00)) AND (NOT fpu_op_r3(2) AND fpu_op_r3(1) AND NOT fpu_op_r3(0)); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF fpu_op_r3(2) = '1' THEN inf <= '0'; ELSE inf <= (NOT (qnan_d OR snan_d) AND (((and_reduce(out_d(30 DOWNTO 23))) AND NOT (or_reduce(out_d(22 downto 0))) AND NOT(opb_00 AND NOT fpu_op_r3(2) AND fpu_op_r3(1) AND fpu_op_r3(0))) OR (inf_d AND NOT (ind_d AND NOT fasu_op_r2) AND NOT fpu_op_r3(1)) OR inf_fmul OR (NOT opa_00 AND opb_00 AND NOT fpu_op_r3(2) AND fpu_op_r3(1) AND fpu_op_r3(0)) or (NOT fpu_op_r3(2) AND fpu_op_r3(1) AND fpu_op_r3(0) AND opa_inf AND NOT opb_inf) ) ); END IF; END IF; END PROCESS; output_zero_fasu <= out_d_00 AND NOT (inf_d OR snan_d OR qnan_d); output_zero_fdiv <= (div_00 OR (out_d_00 AND NOT opb_00)) AND NOT (opa_inf AND opb_inf) AND NOT (opa_00 AND opb_00) AND NOT (qnan_d OR snan_d); output_zero_fmul <= (out_d_00 OR opa_00 OR opb_00) AND NOT (inf_mul_r OR inf_mul2 OR opa_inf OR opb_inf OR snan_d OR qnan_d) AND NOT (opa_inf AND opb_00) AND NOT (opb_inf AND opa_00); PROCESS (clk) BEGIN IF clk'event AND clk = '1' THEN IF fpu_op_r3="101" THEN zero <= out_d_00 and NOT (snan_d or qnan_d); ELSIF fpu_op_r3="011" THEN zero <= output_zero_fdiv; ELSIF fpu_op_r3="010" THEN zero <= output_zero_fmul; ELSE zero <= output_zero_fasu; END IF; IF (opa_nan = '0') AND (fpu_op_r2="011") THEN opa_nan_r <= '1'; ELSE opa_nan_r <= '0'; END IF; div_by_zero <= opa_nan_r AND NOT opa_00 AND NOT opa_inf AND opb_00; END IF; END PROCESS;END arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -