⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpu_addsub.vhd

📁 Xilinx软核microblaze源码(VHDL)版本7.10
💻 VHD
📖 第 1 页 / 共 2 页
字号:
--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 + -