📄 fpu_addsub.vhd
字号:
--SINGLE_FILE_TAG--------------------------------------------------------------------------------- $Id: fpu_addsub.vhd,v 1.1 2007/10/12 09:11:36 stefana Exp $--------------------------------------------------------------------------------- FPU_MUL - entity/architecture----------------------------------------------------------------------------------- ****************************************************************************-- ** Copyright(C) 2005 by Xilinx, Inc. All rights reserved.-- **-- ** This text contains proprietary, confidential information of-- ** Xilinx, Inc. , is distributed by under license from Xilinx, Inc.,-- ** and may be used, copied and/or disclosed only pursuant to the-- ** terms of a valid license agreement with Xilinx, Inc. -- **-- ** Unmodified source code is guaranteed to place and route, -- ** function and run at speed according to the datasheet-- ** specification. Source code is provided "as-is", with no-- ** obligation on the part of Xilinx to provide support.-- **-- ** Xilinx Hotline support of source code IP shall only include-- ** standard level Xilinx Hotline support, and will only address-- ** issues and questions related to the standard released Netlist-- ** version of the core (and thus indirectly, the original core source-- **-- ** The Xilinx Support Hotline does not have access to source-- ** code and therefore cannot answer specific questions related-- ** to source HDL. The Xilinx Support Hotline will only be able-- ** to confirm the problem in the Netlist version of the core.-- **-- ** This copyright and support notice must be retained as part-- ** of this text at all times.-- ****************************************************************************----------------------------------------------------------------------------------- Filename: fpu_addsub.vhd-- Version: v2.00a-- Description: Add or subtract mantissas-- --------------------------------------------------------------------------------- Structure: -- fpu_addsub.vhd----------------------------------------------------------------------------------- Author: stassart-- History:-- BJS 2005-10-06 First Version----------------------------------------------------------------------------------- Naming Conventions:-- active low signals: "*_n"-- clock signals: "clk", "*_clk"-- reset signals: "rst", "*_rst", "reset"-- generics: All uppercase, starting with: "C_"-- constants: All uppercase, not starting with: "C_"-- state machine next state: "*_next_state"-- state machine current state: "*_curr_state"-- pipelined signals: "*_d#"-- counter signals: "*_cnt_*" , "*_counter_*", "*_count_*"-- internal version of output port: "*_i"-- ports: Names begin with uppercase-- component instantiations: "<ENTITY_>I_<#|FUNC>" , "ENTITY>_I#" ---- Signals starting with IF, OF, EX, MEM, or WB indicate that they start in that-- stage:---- IF -- instruction fetch-- OF -- operand fetch-- EX -- execute-- MEM -- memory-- WB -- write back-------------------------------------------------------------------------------library IEEE;use IEEE.std_logic_1164.all;use IEEE.numeric_std.all;---------------------------------------------------------------------------- Include MicroBlaze package for data types and ISA constants--------------------------------------------------------------------------library Microblaze_v7_10_a;use Microblaze_v7_10_a.MicroBlaze_ISA.all;use Microblaze_v7_10_a.MicroBlaze_Types.all;-- pragma xilinx_rtl_offlibrary unisim;use unisim.vcomponents.all;-- pragma xilinx_rtl_on--------------------------------------------------------------------------------- Port declarations-------------------------------------------------------------------------------entity FPU_ADDSUB is generic ( C_TARGET : TARGET_FAMILY_TYPE ); port ( Clk : in std_logic; -- Clock Reset : in std_logic; -- Reset MEM_Add_Op_2 : in boolean; -- Add operation MEM_Sub_Op_2 : in boolean; -- Subtract operation MEM_Add_Mant_2 : in boolean; -- Add or Subtract mantissa MEM_MantA_2 : in FPU_MANT_I_TYPE; -- Operand's A mantissa (with I) MEM_MantB_2 : in FPU_MANT_I_TYPE; -- Operand's A mantissa (with I) MEM_absAgtB_2 : in boolean; -- abs(OpA) > abs(OpB) MEM_Exp_absAsubB_2 : in FPU_EXP_TYPE; -- exponents abs(A - B) MEM_AddSub_Zero_4 : out boolean; -- Mantissa is zero unless there is rounding MEM_AddSub_Inc_Exp_4 : out boolean; -- Mul increment exponent MEM_AddSub_Sub_Exp_4 : out FPU_EXP_LS_TYPE; -- Mantissa needed left shift, subtract exponent MEM_Mant_LS16_4 : out std_logic; -- Result still needs to be shifted 16 MEM_Mant_AddSub_Res_4 : out FPU_MANT_IGRS_TYPE -- Result of addition/subtraction );end FPU_ADDSUB;--------------------------------------------------------------------------------- Architecture section-------------------------------------------------------------------------------architecture IMP of FPU_ADDSUB is ---------------------------------------- -- find_first_bit -- Find the first bit that is 1 -- Pos contains the position of the first 1: 0-24 -- Found will be 1 if there is a 1. -- If there is no 1 then Found will be 0 and Pos will be 0. ---------------------------------------- component find_first_bit is port ( MEM_Mant : in std_logic_vector(FPU_MANT_TYPE'left-1 to FPU_MANT_TYPE'right+1); MEM_Mant_One_Pos : out std_logic_vector(FPU_MANT_BIT_POS); MEM_MANT_One_Found : out std_logic); end component find_first_bit; ---------------------------------------- -- get_mant_mask -- The mantissa is supposed to be shifted by the difference in exponents -- -- As an area optimization, this FPU rotates rather than shifting to -- preserve the bits for calculating the sticky bit -- -- This function masks out the bits that were rotated and should be 0 -- (because it should be a shift not a rotate) -- Bits set to 1 in this mask are used -- Bits set to 0 in this mask are zero ---------------------------------------- function get_mant_mask (s : std_logic_vector(0 to 4)) return FPU_MANT_I_TYPE is variable r : FPU_MANT_I_TYPE; begin -- function get_mant_mask r := (others => '1'); case s is when "00000" => null; when "00001" => r(r'left) := '0'; when "00010" => r(r'left to r'left+1) := (others => '0'); when "00011" => r(r'left to r'left+2) := (others => '0'); when "00100" => r(r'left to r'left+3) := (others => '0'); when "00101" => r(r'left to r'left+4) := (others => '0'); when "00110" => r(r'left to r'left+5) := (others => '0'); when "00111" => r(r'left to r'left+6) := (others => '0'); when "01000" => r(r'left to r'left+7) := (others => '0'); when "01001" => r(r'left to r'left+8) := (others => '0'); when "01010" => r(r'left to r'left+9) := (others => '0'); when "01011" => r(r'left to r'left+10) := (others => '0'); when "01100" => r(r'left to r'left+11) := (others => '0'); when "01101" => r(r'left to r'left+12) := (others => '0'); when "01110" => r(r'left to r'left+13) := (others => '0'); when "01111" => r(r'left to r'left+14) := (others => '0'); when "10000" => r(r'left to r'left+15) := (others => '0'); when "10001" => r(r'left to r'left+16) := (others => '0'); when "10010" => r(r'left to r'left+17) := (others => '0'); when "10011" => r(r'left to r'left+18) := (others => '0'); when "10100" => r(r'left to r'left+19) := (others => '0'); when "10101" => r(r'left to r'left+20) := (others => '0'); when "10110" => r(r'left to r'left+21) := (others => '0'); when "10111" => r(r'left to r'left+22) := (others => '0'); when others => r(r'left to r'left+23) := (others => '0'); end case; return r; end function get_mant_mask; ---------------------------------------- -- get_sticky_mask -- The sticky bit is an OR of all bits that have been shifted past -- the rounding bit position -- -- As an area optimization, this FPU rotates rather than shifting to -- preserve the bits for calculating the sticky bit -- -- This mask sets the bits that need to be or'd together in the -- mantissa to get the sticky bit -- ---------------------------------------- function get_sticky_mask (s : std_logic_vector(0 to 4)) return FPU_MANT_I_TYPE is variable r : FPU_MANT_I_TYPE; begin -- function get_sticky_mask r := (others => '0'); case s is when "00000" => null; when "00001" => null; when "00010" => null; when "00011" => r(r'left) := '1'; when "00100" => r(r'left to r'left+1) := (others => '1'); when "00101" => r(r'left to r'left+2) := (others => '1'); when "00110" => r(r'left to r'left+3) := (others => '1'); when "00111" => r(r'left to r'left+4) := (others => '1'); when "01000" => r(r'left to r'left+5) := (others => '1'); when "01001" => r(r'left to r'left+6) := (others => '1'); when "01010" => r(r'left to r'left+7) := (others => '1'); when "01011" => r(r'left to r'left+8) := (others => '1'); when "01100" => r(r'left to r'left+9) := (others => '1'); when "01101" => r(r'left to r'left+10) := (others => '1'); when "01110" => r(r'left to r'left+11) := (others => '1'); when "01111" => r(r'left to r'left+12) := (others => '1'); when "10000" => r(r'left to r'left+13) := (others => '1'); when "10001" => r(r'left to r'left+14) := (others => '1'); when "10010" => r(r'left to r'left+15) := (others => '1'); when "10011" => r(r'left to r'left+16) := (others => '1'); when "10100" => r(r'left to r'left+17) := (others => '1'); when "10101" => r(r'left to r'left+18) := (others => '1'); when "10110" => r(r'left to r'left+19) := (others => '1'); when "10111" => r(r'left to r'left+20) := (others => '1'); when "11000" => r(r'left to r'left+21) := (others => '1'); when "11001" => r(r'left to r'left+22) := (others => '1'); when others => r(r'left to r'left+23) := (others => '1'); end case; return r; end function get_sticky_mask; -- Mantissa with implicit and guard bits -- The guard bit is to retain more precision subtype Mant_ImplG_T is std_logic_vector(FPU_MANT_TYPE'left-1 to FPU_MANT_TYPE'right+1); -- Mantissa with implicit, guard, and rounding bits -- The rounding bit is used for rounding to nearest subtype Mant_ImplGR_T is std_logic_vector(FPU_MANT_TYPE'left-1 to FPU_MANT_TYPE'right+2); -- Mantissa with overflow (addition), implicit, guard, rounding, and sticky bits subtype Mant_OIGRS_T is std_logic_vector(FPU_MANT_TYPE'left-2 to FPU_MANT_TYPE'right+3); -- Overflow bit constant Mant_Over_POS : natural := Mant_OIGRS_T'left; signal mem_rot_mux1_sel : std_logic_vector(0 to 1); signal mem_rot_mux1 : Mant_ImplGR_T; signal mem_rot_mux2_sel : std_logic_vector(0 to 1); signal mem_rot_mux2 : Mant_ImplGR_T; signal mem_rot_mux3_sel : std_logic_vector(0 to 1); signal mem_rot_mux3 : Mant_ImplGR_T; signal mem_mant_mask_3_cmb : FPU_MANT_I_TYPE; signal mem_sticky_mask_3_cmb : FPU_MANT_I_TYPE; signal mem_mant_sticky_3_cmb : std_logic; signal mem_large_shift_3_cmb : boolean; signal mem_AddOrSub_3 : boolean; signal mem_MantA_3 : FPU_MANT_IGRS_TYPE; signal mem_MantB_3 : FPU_MANT_IGRS_TYPE; signal mem_add_mant_3 : boolean; signal mem_AddSub_IG_4_cmb : Mant_ImplG_T; signal mem_AddSub_Res_4_cmb : Mant_OIGRS_T; signal mem_res_4 : FPU_MANT_IGRS_TYPE; signal mem_left_shift_4_cmb : FPU_EXP_LS_TYPE; signal mem_possible_zero_n_4_cmb : std_logic; signal mem_left_shift_4 : FPU_EXP_LS_TYPE; signal mem_possible_zero_4 : boolean; signal mem_ls_sel1_5_cmb : std_logic_vector(0 to 1); signal mem_ls_sel2_5_cmb : std_logic_vector(0 to 1); signal mem_ls_sel3_5_cmb : std_logic; signal mem_ls_mux1_5_cmb : FPU_MANT_IGRS_TYPE; signal mem_ls_mux2_5_cmb : FPU_MANT_IGRS_TYPE;begin --------------------------------------------------------------------------------- -- -- In this file OIGRS is used to refer to bits -- -- O: Overflow (set when adding two operands with equal exponents) -- I: Implicit (the implicit 1 bit leading the mantissa) -- [fraction part] -- G: Guard (extra bit for precision) -- R: Round (extra bit to the right of guard for rounding) -- S: Sticky (extra bit which is an OR of all bits shifted past the round bit) -- -- 1) Add the guard and rounding bits to MantA and MantB -- 2) Select the smaller operand's mantissa -- 3) Rotate by the difference in the mantissa -- (Rotation is used rather than shifting to preserve the bits for calculating -- the sticky bit) -- 4) Mask out the rotated bits to obtain shifted result -- 5) Create mask for sticky bit -- 6) Or rotated bits to find sticky bit -- 7) Add sticky bit and create operand A with the larger operand's mantissa (with GRS) -- operand B with the smaller operand's mantissa (with GRS) -- 8) Perform addition or subtraction -- 9) Find the MSb that is 1 -- 10) Detect overflow bit and if shifting is necessary -- 11) Left shift the result as necessary to make the MSb 1 --------------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- Stage 3 ----------------------------------------------------------------------------- -- Select between OpA and OpB, whichever is larger mem_rot_mux1_sel(mem_rot_mux1_sel'right) <= '1' when MEM_absAgtB_2 else '0'; -- Rotate 1? mem_rot_mux1_sel(mem_rot_mux1_sel'left) <= MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right); ---------------------------------------- -- Stage3_Rotate_Mux1 -- Adds the guard and rounding bits "00" -- Selects the smaller operand's mantissa -- Rotate 0 or 1 -- Old name: mux3_1 ---------------------------------------- Stage3_Rotate_Mux1 : process (mem_rot_mux1_sel, MEM_MantA_2, MEM_MantB_2) is begin -- process Stage3_Rotate_Mux1 if (mem_rot_mux1_sel = "00") then -- A rotated 0 mem_rot_mux1 <= MEM_MantA_2 & "00"; elsif (mem_rot_mux1_sel = "01") then -- B rotated 0 mem_rot_mux1 <= MEM_MantB_2 & "00"; elsif (mem_rot_mux1_sel = "10") then -- A rotated 1 mem_rot_mux1 <= '0' & MEM_MantA_2 & '0'; else -- "11" -- B rotated 1 mem_rot_mux1 <= '0' & MEM_MantB_2 & '0'; end if; end process Stage3_Rotate_Mux1; -- Select rotate 0, 2, 4, or 6 mem_rot_mux2_sel <= MEM_Exp_absAsubB_2(MEM_Exp_absAsubB_2'right-2 to MEM_Exp_absAsubB_2'right-1); ---------------------------------------- -- Stage3_Rotate_Mux2 -- Rotate 0, 2, 4, or 6 -- Old name: mux3_2 ---------------------------------------- Stage3_Rotate_Mux2 : process (mem_rot_mux2_sel, mem_rot_mux1) is begin -- process Stage3_Rotate_Mux2 if (mem_rot_mux2_sel = "00") then -- Rotate 0 mem_rot_mux2 <= mem_rot_mux1; elsif (mem_rot_mux2_sel = "01") then -- Rotate 2 mem_rot_mux2 <= mem_rot_mux1(mem_rot_mux1'right-1 to mem_rot_mux1'right) & mem_rot_mux1(mem_rot_mux1'left to mem_rot_mux1'right-2); elsif (mem_rot_mux2_sel = "10") then -- Rotate 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -