📄 fpu_addsub.vhd
字号:
mem_rot_mux2 <= mem_rot_mux1(mem_rot_mux1'right-3 to mem_rot_mux1'right) & mem_rot_mux1(mem_rot_mux1'left to mem_rot_mux1'right-4); else -- "11" -- Rotate 6 mem_rot_mux2 <= mem_rot_mux1(mem_rot_mux1'right-5 to mem_rot_mux1'right) & mem_rot_mux1(mem_rot_mux1'left to mem_rot_mux1'right-6); end if; end process Stage3_Rotate_Mux2; -- Select rotate 0, 8, 16, 24 mem_rot_mux3_sel <= MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-4 to MEM_Exp_absAsubB_2'right-3); ---------------------------------------- -- Stage3_Rotate_Mux3 -- Rotate 0, 8, 16, 24 -- Old name: mux3_3 ---------------------------------------- Stage3_Rotate_Mux3 : process (mem_rot_mux3_sel, mem_rot_mux2) is begin -- process Stage3_Rotate_Mux3 if (mem_rot_mux3_sel = "00") then -- Rotate 0 mem_rot_mux3 <= mem_rot_mux2; elsif (mem_rot_mux3_sel = "01") then -- Rotate 8 mem_rot_mux3 <= mem_rot_mux2(mem_rot_mux2'right-7 to mem_rot_mux2'right) & mem_rot_mux2(mem_rot_mux2'left to mem_rot_mux2'right-8); elsif (mem_rot_mux3_sel = "10") then -- Rotate 16 mem_rot_mux3 <= mem_rot_mux2(mem_rot_mux2'right-15 to mem_rot_mux2'right) & mem_rot_mux2(mem_rot_mux2'left to mem_rot_mux2'right-16); else -- "11" -- Rotate 24 mem_rot_mux3 <= mem_rot_mux2(mem_rot_mux2'right-23 to mem_rot_mux2'right) & mem_rot_mux2(mem_rot_mux2'left to mem_rot_mux2'right-24); end if; end process Stage3_Rotate_Mux3; -- Get the mask of bits to use for the mantissa -- This mask is used to convert rotated mantissa into shifted mantissa mem_mant_mask_3_cmb <= get_mant_mask(MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-4 to MEM_Exp_absAsubB_2'right)); -- Get the mask of bits required to calculate the sticky bits mem_sticky_mask_3_cmb <= get_sticky_mask(MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-4 to MEM_Exp_absAsubB_2'right)); ---------------------------------------- -- Stage3_Sticky -- Calculate the sticky bit -- This is an OR of the bits that have been rotated around past the round bit -- carry_and_or ---------------------------------------- Stage3_Sticky : process (mem_rot_mux3, mem_sticky_mask_3_cmb) is variable temp_mant_sticky_or : FPU_MANT_I_TYPE; variable temp_sticky : std_logic; begin -- Stage3_Sticky temp_mant_sticky_or := mem_rot_mux3(mem_sticky_mask_3_cmb'left to mem_sticky_mask_3_cmb'right) and mem_sticky_mask_3_cmb; temp_sticky := '0'; for I in temp_mant_sticky_or'left to temp_mant_sticky_or'right loop temp_sticky := temp_sticky or temp_mant_sticky_or(I); end loop; -- I mem_mant_sticky_3_cmb <= temp_sticky; end process Stage3_Sticky; -- If the shift is 26 or larger, it is a large shift and does not even have any rounding left -- 1 for implicit bit -- 23 bits for mantissa -- 1 for guard bit -- 1 for round bit mem_large_shift_3_cmb <= ( (MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-7) = '1') or -- 128 (MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-6) = '1') or -- 64 (MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-5) = '1') or -- 32 -- 26-31 ((MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-4 to MEM_Exp_absAsubB_2'right-3) = "11") and -- 24 ((MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-2) = '1') or -- +4 (MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-1) = '1')))); -- or +2 ---------------------------------------- -- MEM_AddOrSub_3_REG -- Add or Subtract operation in stage 3 ---------------------------------------- MEM_AddOrSub_3_REG : process (Clk) is begin -- process MEM_AddOrSub_3_REG if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_AddOrSub_3 <= false; else mem_AddOrSub_3 <= MEM_Add_Op_2 or MEM_Sub_Op_2; end if; end if; end process MEM_AddOrSub_3_REG; ---------------------------------------- -- Stage3_Mant_Sticky -- Add the sticky bit -- mem_MantA_3 is the larger operand's mantissa (with GRS) -- mem_MantB_3 is the smaller operand's mantissa shifted (with GRS) ---------------------------------------- Stage3_Mant_Sticky : process (Clk) is variable temp_A : FPU_MANT_I_TYPE; begin -- process Stage3_Mant_Sticky if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then mem_MantA_3 <= (others => '0'); mem_MantB_3 <= (others => '0'); else ------------ -- A ------------ -- Select larger operand's mantissa if (MEM_absAgtB_2) then temp_A := MEM_MantA_2; else temp_A := MEM_MantB_2; end if; -- Take the larger operand's mantissa mem_MantA_3(mem_MantA_3'left to temp_A'right) <= temp_A; -- Add guard, round, and sticky bits mem_MantA_3(temp_A'right+1 to mem_MantA_3'right) <= "000"; ------------ -- B ------------ -- Set sticky bit MEM_MantB_3(FPU_MANT_STICKY_POS) <= mem_mant_sticky_3_cmb; if (mem_large_shift_3_cmb) then -- Above only looks at the right 5 bits of the difference in exponents -- This check is used if there is a large difference in exponents MEM_MantB_3(mem_MantB_3'left to mem_MantB_3'right-3) <= (others => '0'); -- Guard and rounding bits MEM_MantB_3(FPU_MANT_GUARD_POS) <= '0'; MEM_MantB_3(FPU_MANT_ROUND_POS) <= '0'; else -- Take the rotated result without the guard and rounding bits and mask it -- to produce shifted mantissa MEM_MantB_3(mem_MantB_3'left to mem_MantB_3'right-3) <= mem_rot_mux3(mem_rot_mux3'left to mem_rot_mux3'right-2) and mem_mant_mask_3_cmb; -- Guard and rounding bits MEM_MantB_3(FPU_MANT_GUARD_POS) <= mem_rot_mux3(FPU_MANT_GUARD_POS); MEM_MantB_3(FPU_MANT_ROUND_POS) <= mem_rot_mux3(FPU_MANT_ROUND_POS); end if; end if; end if; end process Stage3_Mant_Sticky; ---------------------------------------- -- MEM_Add_Mant_3_REG -- Add or subtract mantissas? -- Old name: Add_3 ---------------------------------------- MEM_Add_Mant_3_REG : process (Clk) is begin -- process MEM_Add_Mant_REG if Clk'event and Clk = '1' then -- rising clock edge -- if Reset = '1' then -- mem_add_mant_3 <= false; -- else mem_add_mant_3 <= mem_add_mant_2; -- end if; end if; end process MEM_Add_Mant_3_REG; ----------------------------------------------------------------------------- -- Stage 4 ----------------------------------------------------------------------------- ---------------------------------------- -- MEM_AddSub_Res_4_PROC -- Perform addition or subtraction on mantissa -- Old name: Mant_AddSub_Res ---------------------------------------- MEM_AddSub_Res_4_PROC : process (mem_add_mant_3, mem_MantA_3, mem_MantB_3) is variable mem_MantA_4_cmb : Mant_OIGRS_T; variable mem_MantB_4_cmb : Mant_OIGRS_T; variable mem_add_mant_4_cmb : boolean; begin -- process MEM_AddSub_Res_4_PROC mem_MantA_4_cmb := '0' & mem_MantA_3; mem_MantB_4_cmb := '0' & mem_MantB_3; mem_add_mant_4_cmb := mem_add_mant_3; if (mem_add_mant_4_cmb) then -- Add mem_AddSub_Res_4_cmb <= std_logic_vector(unsigned(mem_MantA_4_cmb) + unsigned(mem_MantB_4_cmb)); else -- Subtract mem_AddSub_Res_4_cmb <= std_logic_vector(unsigned(mem_MantA_4_cmb) - unsigned(mem_MantB_4_cmb)); end if; end process MEM_AddSub_Res_4_PROC; -- Remove overflow bit, rounding bit, and sticky bit -- Implicit and guard bits are left mem_AddSub_IG_4_cmb <= mem_AddSub_Res_4_cmb(mem_AddSub_IG_4_cmb'left to mem_AddSub_IG_4_cmb'right); ---------------------------------------- -- MEM_Res_4_REG -- Mantissa addition/subtraction result -- Deal with overflow bit -- Old Name: Res_4 ---------------------------------------- MEM_Res_4_REG : process (Clk) is variable temp_sticky : std_logic; begin -- process MEM_Res_4_REG if Clk'event and Clk = '1' then if (mem_AddSub_Res_4_cmb(Mant_Over_POS) = '1') then -- Overflow bit set -- Can only happen when adding two mant and the result is >= 2.0 -- Calculate the new sticky bit by ORing old rounding bit with old sticky bit temp_sticky := mem_AddSub_Res_4_cmb(FPU_MANT_ROUND_POS) or mem_AddSub_Res_4_cmb(FPU_MANT_STICKY_POS); -- Old overflow bit becomes implicit bit -- Old guard bit becomes rounding bit mem_res_4 <= mem_AddSub_Res_4_cmb(Mant_Over_POS to FPU_MANT_GUARD_POS) & temp_sticky; else -- Overflow bit not set -- Drop the overflow bit mem_res_4 <= mem_AddSub_Res_4_cmb(FPU_MANT_IMPL_POS to FPU_MANT_STICKY_POS); end if; end if; end process MEM_Res_4_REG; ---------------------------------------- -- Find_First_Bit_I ---------------------------------------- Find_First_Bit_I: find_first_bit port map ( MEM_Mant => mem_AddSub_IG_4_cmb, MEM_Mant_One_Pos => mem_left_shift_4_cmb, MEM_Mant_One_Found => mem_possible_zero_n_4_cmb ); ---------------------------------------- -- Stage_4_Left_Shift_REG -- Clock the left shift ---------------------------------------- Stage_4_Left_Shift_REG : process (Clk) is begin -- process Stage_4_Left_Shift_REG if Clk'event and Clk = '1' then mem_left_shift_4 <= (others => '0'); mem_possible_zero_4 <= false; if (mem_AddOrSub_3) then -- This is used later to subtract the exponent -- Must be zero for non add/sub operations if (mem_AddSub_Res_4_cmb(Mant_Over_POS) = '1') then -- Overflow -- Can only happen when adding two mant and the result is >= 2.0 -- Mant does not need to be shifted because the MSb is set mem_left_shift_4 <= (others => '0'); else mem_left_shift_4 <= mem_left_shift_4_cmb; mem_possible_zero_4 <= mem_possible_zero_n_4_cmb = '0'; end if; end if; end if; end process Stage_4_Left_Shift_Reg; ---------------------------------------- -- Stage_4_Inc_Exp_REG -- Increment the exponent on overflow ---------------------------------------- Stage_4_Inc_Exp_REG : process (Clk) is begin -- process Stage_4_Inc_Exp_REG if Clk'event and Clk = '1' then MEM_AddSub_Inc_Exp_4 <= false; if (mem_AddOrSub_3) then if (mem_AddSub_Res_4_cmb(Mant_Over_POS) = '1') then -- Overflow -- Can only happen when adding two mant and the result is >= 2.0 -- Mant does not need to be shifted because the MSb is set MEM_AddSub_Inc_Exp_4 <= true; end if; end if; end if; end process Stage_4_Inc_Exp_REG; ----------------------------------------------------------------------------- -- Stage 5 ----------------------------------------------------------------------------- -- Left shift selects -- Shift 0, 1, 2, 3 mem_ls_sel1_5_cmb <= mem_left_shift_4(mem_left_shift_4'right-1 to mem_left_shift_4'right); -- Shift 0, 4, 8, 12 mem_ls_sel2_5_cmb <= mem_left_shift_4(mem_left_shift_4'right-3 to mem_left_shift_4'right-2); -- Shift 0, 16 mem_ls_sel3_5_cmb <= mem_left_shift_4(mem_left_shift_4'right-4); ---------------------------------------- -- Left_Shift_Zero_Three -- This mux selects between 0, 1, 2, and 3 bits shifted -- Old name: mux5_1 ---------------------------------------- Left_Shift_Zero_Three : process (mem_res_4, mem_ls_sel1_5_cmb) is begin -- process Left_Shift_Zero_Three if (mem_ls_sel1_5_cmb = "00") then -- Shift 0 mem_ls_mux1_5_cmb <= mem_res_4; elsif (mem_ls_sel1_5_cmb = "01") then -- Shift 1 mem_ls_mux1_5_cmb <= mem_res_4(mem_res_4'left+1 to mem_res_4'right) & '0'; elsif (mem_ls_sel1_5_cmb = "10") then -- Shift 2 mem_ls_mux1_5_cmb <= mem_res_4(mem_res_4'left+2 to mem_res_4'right) & "00"; else -- "11" -- Shift 3 mem_ls_mux1_5_cmb <= mem_res_4(mem_res_4'left+3 to mem_res_4'right) & "000"; end if; end process Left_Shift_Zero_Three; ---------------------------------------- -- Left_Shift_Zero_Twelve -- This mux selects between 0, 4, 8, 12 bits shifted -- Old name: mux5_2 ---------------------------------------- Left_Shift_Zero_Twelve : process (mem_ls_mux1_5_cmb, mem_ls_sel2_5_cmb) is begin -- process Left_Shift_Zero_Twelve if (mem_ls_sel2_5_cmb = "00") then -- Shift 0 mem_ls_mux2_5_cmb <= mem_ls_mux1_5_cmb; elsif (mem_ls_sel2_5_cmb = "01") then -- Shift 4 mem_ls_mux2_5_cmb <= mem_ls_mux1_5_cmb(mem_ls_mux1_5_cmb'left+4 to mem_ls_mux1_5_cmb'right) & "0000"; elsif (mem_ls_sel2_5_cmb = "10") then -- Shift 8 mem_ls_mux2_5_cmb <= mem_ls_mux1_5_cmb(mem_ls_mux1_5_cmb'left+8 to mem_ls_mux1_5_cmb'right) & "00000000"; else -- "11" -- Shift 12 mem_ls_mux2_5_cmb <= mem_ls_mux1_5_cmb(mem_ls_mux1_5_cmb'left+12 to mem_ls_mux1_5_cmb'right) & "000000000000"; end if; end process Left_Shift_Zero_Twelve; ---------------------------------------- -- Registered outputs ---------------------------------------- MEM_AddSub_Zero_4 <= mem_possible_zero_4; MEM_AddSub_Sub_Exp_4 <= mem_left_shift_4; ---------------------------------------- -- Non-registered outputs ---------------------------------------- MEM_Mant_LS16_4 <= mem_ls_sel3_5_cmb; MEM_Mant_AddSub_Res_4 <= mem_ls_mux2_5_cmb;end IMP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -