📄 fpu.vhd
字号:
---------------------------------------------------------------------- -- NaN ---------------------------------------------------------------------- -- A NaN has an exponent of 255, an a non-zero mantissa -- The MSb of the mantissa determines quiet or signaling mem_NanA_2 <= ex_A_NaN_2_cmb; mem_NanB_2 <= ex_B_NaN_2_cmb; -- For quiet if the MSb of the mantissa is 1, -- then by definition the mantissa is non-zero mem_QNanA_2 <= ex_ExpA_Ones_2_cmb and (ex_a(FPU_NAN_POS) = FPU_NAN_QUIET); mem_QNanB_2 <= ex_ExpB_Ones_2_cmb and (ex_b(FPU_NAN_POS) = FPU_NAN_QUIET); mem_SNanA_2 <= ex_A_NaN_2_cmb and (ex_a(FPU_NAN_POS) = FPU_NAN_SIG); mem_SNanB_2 <= ex_B_NaN_2_cmb and (ex_b(FPU_NAN_POS) = FPU_NAN_SIG); ---------------------------------------------------------------------- -- Denormalized ---------------------------------------------------------------------- -- Exponent is physical zero/logical -127 (our reserved value) -- Mantissa is non-zero -- The implicit MSb of the mantissa is zero mem_DeNormA_2 <= ex_ExpA_Zero_2_cmb and not ex_MantA_Zero_2_cmb; mem_DeNormB_2 <= ex_ExpB_Zero_2_cmb and not ex_MantB_Zero_2_cmb; ---------------------------------------------------------------------- -- Infinity ---------------------------------------------------------------------- -- Exponent is 255 -- Mantissa is zero mem_InfA_2 <= ex_ExpA_Ones_2_cmb and ex_MantA_Zero_2_cmb; mem_InfB_2 <= ex_ExpB_Ones_2_cmb and ex_MantB_Zero_2_cmb; ---------------------------------------------------------------------- -- Zero ---------------------------------------------------------------------- -- Exponent is zero -- Mantissa is zero mem_ZeroA_2 <= ex_A_Zero_2_cmb; mem_ZeroB_2 <= ex_B_Zero_2_cmb; end if; end if; end process Stage2_Input_Types; ---------------------------------------- -- MEM_Abs_AgtB_2_REG -- Which abs(OpA) or abs(OpB) is greater -- old name: Op1_Is_A ---------------------------------------- MEM_Abs_AgtB_2_REG : process (Clk) is begin -- process MEM_Abs_AgtB_2_REG if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_absAgtB_2 <= false; elsif (EX_PipeRun) then if (ex_absBgtA_2_cmb) then -- B is greater mem_absAgtB_2 <= false; else -- A is greater mem_absAgtB_2 <= true; end if; end if; end if; end process MEM_Abs_AgtB_2_REG; ---------------------------------------- -- MEM_Exp_Res_2_PROC -- Select the exponent for the result -- For add or subtract use the larger exponent -- For mul, add the exponents -- For div, subtract the exponents -- cmp does not care -- flt, int, sqrt are not implemented ---------------------------------------- MEM_Exp_Res_2_REG : process (Clk) is variable temp_1 : Exp_Plus2_T; variable temp_2 : Exp_Plus2_T; begin -- process MEM_Exp_Res_2_PROC if Clk'event and Clk = '1' then -- rising clock edge temp_1 := "00" & ex_ExpA_1; temp_2 := "00" & ex_ExpB_1; if Reset = '1' then mem_Exp_Res_2 <= (others => '0'); elsif (EX_PipeRun) then if (ex_add_op or ex_sub_op) then if (not ex_Exp_Equal_2_cmb and ex_Exp_BgtA_2_cmb) then -- Exponent for B is greater mem_Exp_Res_2 <= temp_2; else -- Exponent for A is greater or equal mem_Exp_Res_2 <= temp_1; end if; elsif (ex_mul_op) then mem_Exp_Res_2 <= std_logic_vector(unsigned(temp_1) + unsigned(temp_2)); else -- ex_div_op mem_Exp_Res_2 <= ex_Exp_AsubB_2_i; end if; end if; end if; end process MEM_Exp_Res_2_REG; ---------------------------------------- -- MEM_Add_Mant_2_REG -- Add or subtract mantissa -- (old name: Add_2) ---------------------------------------- MEM_Add_Mant_2_REG : process (Clk) is begin -- process MEM_Add_Mant_2_REG if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_add_mant_2 <= false; elsif (EX_PipeRun) then -- FPU_OP_ADDSUB_POS: 1 for subtract -- SignA: 1 for negative -- SignB: 1 for negative -- If 1 or 3 of these conditions are true, subtract -- Otherwise add (0 or 2) if ((ex_fpu_op_1(FPU_OP_ADDSUB_POS) xor ex_SignA_1 xor ex_SignB_1) = '1') then mem_add_mant_2 <= false; else mem_add_mant_2 <= true; end if; end if; end if; end process MEM_Add_Mant_2_REG; ---------------------------------------- -- MEM_Res_Sign_2_REG -- Calculate the result sign -- Old name: Res_Sign_2 ---------------------------------------- MEM_Res_Sign_2_REG : process (Clk) is begin -- process MEM_Res_Sign_2_REG if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_Res_Sign_2 <= '0'; elsif (EX_PipeRun) then if (ex_add_op or ex_sub_op) then if (ex_absBgtA_2_cmb) then -- B is greater -- If B is positive: adding positive, subtracting negative -- If B is negative: adding negative, subtracting positive mem_Res_Sign_2 <= ex_fpu_op_1(FPU_OP_ADDSUB_POS) xor ex_SignB_1; else -- A is greater -- Use the sign of A mem_Res_Sign_2 <= ex_SignA_1; end if; else -- ex_mul_op or ex_div_op i -- For multiply or divide, opposite signs is negative -- Otherwise positive mem_Res_Sign_2 <= ex_SignA_1 xor ex_SignB_1; if ((C_USE_FPU = 2) and ex_sqrt_op) then mem_Res_Sign_2 <= '0'; end if; if ((C_USE_FPU = 2) and ex_flt_op) then mem_Res_Sign_2 <= ex_signB_1; end if; end if; end if; end if; end process MEM_Res_Sign_2_REG; ---------------------------------------- -- MEM_Stage2_Cmp_REG -- Evaluate comparisons ---------------------------------------- MEM_Stage2_Cmp_REG : process (Clk) is begin -- process MEM_Stage2_Cmp_REG if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_cmp_eq_2 <= false; mem_cmp_lt_2 <= false; mem_cmp_gt_2 <= false; mem_cmp_un_2 <= false; elsif (EX_PipeRun) then -- Default assignments mem_cmp_eq_2 <= false; mem_cmp_lt_2 <= false; mem_cmp_gt_2 <= false; mem_cmp_un_2 <= false; if (ex_cmp_op) then if (ex_SignA_1 = '0' and ex_SignB_1 = '1') then -- A positive, B negative -- A > B mem_cmp_gt_2 <= true; elsif (ex_SignA_1 = '1' and ex_SignB_1 = '0') then -- A negative, B positive -- A < B mem_cmp_lt_2 <= true; -- Signs are the same at this point -- ex_SignA_1 = ex_SignB_1 elsif (ex_Exp_Mant_Equal_2_cmb) then -- Numbers are equal mem_cmp_eq_2 <= true; elsif (ex_absBgtA_2_cmb) then -- abs(A) < abs(B) mem_cmp_lt_2 <= (ex_SignA_1 = '0'); mem_cmp_gt_2 <= (ex_SignA_1 = '1'); else -- abs(A) > abs(B) mem_cmp_lt_2 <= (ex_SignA_1 = '1'); mem_cmp_gt_2 <= (ex_SignA_1 = '0'); end if; -- Handle both zero (equal) -- This overrides the above logic if (ex_A_Zero_2_cmb and ex_B_Zero_2_cmb) then mem_cmp_eq_2 <= true; mem_cmp_lt_2 <= false; mem_cmp_gt_2 <= false; end if; -- If either operand is a NaN if (ex_A_NaN_2_cmb or ex_B_NaN_2_cmb) then -- Comparison is unordered mem_cmp_eq_2 <= false; mem_cmp_lt_2 <= false; mem_cmp_gt_2 <= false; mem_cmp_un_2 <= true; end if; end if; end if; end if; end process MEM_Stage2_Cmp_REG; ----------------------------------------------------------------------------- -- Stage 3 -- Addition/Subtraction and Multiplication/Division ----------------------------------------------------------------------------- ---------------------------------------- -- MEM_MUL_Op_3_REG -- Stage 3 is multiply operation? ---------------------------------------- MEM_MUL_Op_3_REG : process (Clk) is begin -- process MEM_MUL_Op_3_REG if Clk'event and Clk = '1' then mem_mul_op_3 <= mem_mul_op_2; end if; end process MEM_MUL_Op_3_REG; ---------------------------------------- -- MEM_DIV_Op_3_REG -- Stage 3 is division operation? ---------------------------------------- MEM_DIV_Op_3_REG : process (Clk) is begin -- process MEM_DIV_Op_3_REG if Clk'event and Clk = '1' then mem_div_op_3 <= mem_div_op_2; mem_sqrt_op_3 <= mem_sqrt_op_2; mem_flt_op_3 <= mem_flt_op_2; mem_int_op_3 <= mem_int_op_2; end if; end process MEM_DIV_Op_3_REG; ---------------------------------------- -- MEM_ADDSUB_Op_3_REG -- Stage 3 is add/subtract operation? ---------------------------------------- MEM_ADDSUB_Op_3_REG : process (Clk) is begin -- process MEM_ADDSUB_Op_3_REG if Clk'event and Clk = '1' then mem_addsub_op_3 <= mem_add_op_2 or mem_sub_op_2; end if; end process MEM_ADDSUB_Op_3_REG; ---------------------------------------- -- FPU_ADDSUB_I -- Add/Subtract mantissas ---------------------------------------- FPU_ADDSUB_I : FPU_ADDSUB generic map ( C_TARGET => C_TARGET -- [TARGET_FAMILY_TYPE] ) port map ( Clk => Clk, -- [in std_logic] Reset => Reset, -- [in std_logic] MEM_Add_Op_2 => mem_add_op_2, -- [in boolean] MEM_Sub_Op_2 => mem_sub_op_2, -- [in boolean] MEM_Add_Mant_2 => mem_add_mant_2, -- [in boolean] MEM_MantA_2 => mem_MantA_2, -- [in FPU_MANT_I_TYPE] MEM_MantB_2 => mem_MantB_2, -- [in FPU_MANT_I_TYPE] MEM_absAgtB_2 => mem_absAgtB_2, -- [in boolean] MEM_Exp_absAsubB_2 => mem_Exp_absAsubB_2, -- [in FPU_EXP_TYPE] MEM_AddSub_Zero_4 => mem_addsub_zero_4, -- [out boolean] MEM_AddSub_Inc_Exp_4 => mem_addsub_inc_exp_4, -- [out boolean] MEM_AddSub_Sub_Exp_4 => mem_addsub_sub_exp_4, -- [out FPU_EXP_LS_TYPE] MEM_Mant_LS16_4 => mem_mant_ls16_5_cmb, -- [out std_logic] MEM_Mant_AddSub_Res_4 => mem_mant_addsub_res_5_cmb -- [out FPU_MANT_IGRS_TYPE] ); ---------------------------------------- -- Stage3_Add_Sub_With_Const_PROC -- Adjust Exponent Result -- -127 for multiplication -- -128 for division -- Old name: Res_Exp_3_AddSub ---------------------------------------- Stage3_Add_Sub_With_Const : block is signal addsub_sel : Exp_Plus2_T; signal addsub_di : Exp_Plus2_T; signal addsub_carry : std_logic_vector(addsub_sel'left to addsub_sel'right + 1); signal addsub : std_logic; signal add : std_logic; signal temp : Exp_Plus2_T; begin -- block Stage3_Add_Sub_With_Const temp(temp'left to temp'right-7) <= (others => '0'); temp(temp'right-6 to temp'right) <= (others => '1'); addsub <= '1' when mem_mul_op_2 or mem_div_op_2 else '0'; add <= '1' when mem_div_op_2 else '0'; addsub_carry(addsub_carry'right) <= '1' when mem_mul_op_2 else '0'; AddSub_Pass : for I in addsub_sel'right downto addsub_sel'left generate ------------------------------------------------------------------------- -- bit 1 0 -- bit 3 2 addsub,Exp_Res -- temp(I), add 00 01 11 10 -- 00 0 1 0 1 = 0110 -- 01 - - 1 0 = 1010 -- 11 - - 0 1 = 0110 -- 10 0 1 1 0 = 1010 -- Init = 0110 1010 1010 0110 = 6AA6 ------------------------------------------------------------------------- I_ALU_LUT : LUT4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -