📄 fpu_div.vhd
字号:
--SINGLE_FILE_TAG--------------------------------------------------------------------------------- $Id: fpu_div.vhd,v 1.1 2007/10/12 09:11:36 stefana Exp $--------------------------------------------------------------------------------- FPU_DIV - 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_div.vhd-- Version: v2.00a-- Description: Implements a divider for the FPU-- --------------------------------------------------------------------------------- Structure: -- fpu_div.vhd----------------------------------------------------------------------------------- Author: stassart-- History:-- BJS 2005-10-19 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_DIV is generic ( C_TARGET : TARGET_FAMILY_TYPE ); port ( Clk : in std_logic; -- Clock Reset : in std_logic; -- Reset EX_MantA_1 : in FPU_MANT_TYPE; -- Operand A mantissa EX_MantB_1 : in FPU_MANT_TYPE; -- Operand B mantissa EX_Start_FPU : in boolean; -- Start the FPU EX_Div_Op : in boolean; -- Is division operation? EX_PipeRun : in boolean; -- Move the execute stage Mem_Not_Div_Op : in boolean; MEM_Div_Done : out boolean; -- FPU divider is done the next cycle MEM_Div_Res_4 : out FPU_MANT_IGRS_TYPE; -- FPU mantissa multiplicaiton result MEM_Div_Dec_Exp_4 : out boolean -- Div decrement exponent );end FPU_DIV;--------------------------------------------------------------------------------- Architecture section-------------------------------------------------------------------------------architecture IMP of FPU_DIV is subtype Mant_OverImpl_T is std_logic_vector(FPU_MANT_TYPE'left-2 to FPU_MANT_TYPE'right); signal mem_div_iterate : boolean; signal mem_div_end : boolean; signal mem_div_delay : std_logic_vector(0 to 2); signal mem_div_done_i : boolean; signal mem_reset_Q : std_logic; signal mem_diff_cmb : Mant_OverImpl_T; signal mem_res_neg_cmb : std_logic; signal mem_R : Mant_OverImpl_T := (others => '0'); signal mem_D : Mant_OverImpl_T := (others => '0'); signal mem_Q : Mant_OverImpl_T; signal mem_next_sub : std_logic; signal mem_div_sticky_bit_cmb : std_logic; signal mem_start_div : boolean;begin ----------------------------------------------------------------------------- -- Decode logic ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- MEM_Div_Iterate_DFF -- Old name: Div_Count_Handle ----------------------------------------------------------------------------- MEM_Div_Iterate_DFF : process (Clk) is begin -- process MEM_Div_Iterate_DFF if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then -- synchronous reset (active high) mem_div_iterate <= false; elsif EX_Start_FPU and EX_PipeRun then mem_div_iterate <= EX_Div_Op; elsif mem_div_end then mem_div_iterate <= false; end if; end if; end process MEM_Div_Iterate_DFF; ----------------------------------------------------------------------------- -- MEM_Div_Delay_REG -- Delay till done with divide operation -- Shift to the right ----------------------------------------------------------------------------- MEM_Div_Delay_REG : process (Clk) is begin -- process MEM_Div_Delay_REG if Clk'event and Clk = '1' then -- rising clock edge if (mem_div_iterate and mem_Q(mem_Q'left+2) = '1') then mem_div_end <= true; elsif mem_reset_Q = '1' then mem_div_end <= false; end if; if (mem_div_end and mem_div_iterate) then mem_div_delay(0) <= '1'; else mem_div_delay(0) <= '0'; end if; mem_div_delay(1 to mem_div_delay'right) <= mem_div_delay(0 to mem_div_delay'right-1); end if; end process MEM_Div_Delay_REG; mem_div_done_i <= mem_div_delay(mem_div_delay'right) = '1'; -- Reset Q? mem_reset_Q <= '1' when Reset = '1' else '1' when mem_div_done_i else '0'; ----------------------------------------------------------------------------- -- Data logic ----------------------------------------------------------------------------- -- Add/Subtract operation per iteration mem_diff_cmb <= std_logic_vector(unsigned(mem_R) - unsigned(mem_D)) when mem_next_sub = '1' else std_logic_vector(unsigned(mem_R) + unsigned(mem_D)); -- Is the result negative? mem_res_neg_cmb <= mem_diff_cmb(mem_diff_cmb'left); ----------------------------------------------------------------------------- -- MEM_R_DFF -- The R register -- Is loaded with EX_MantA_1 (Op2) on start of division -- "01" adds positive sign bit and implicit bit -- During the iteration, the add/sub result is left shifted one bit -- '0' is shifted in because the mantissa is always positive ----------------------------------------------------------------------------- MEM_R_DFF : process (Clk) is begin -- process MEM_R_DFF if Clk'event and Clk = '1' then -- rising clock edge if EX_PipeRun and EX_Start_FPU then mem_R <= "01" & EX_MantA_1; elsif mem_div_iterate then mem_R <= mem_diff_cmb(mem_diff_cmb'left+1 to mem_diff_cmb'right) & '0'; end if; end if; end process MEM_R_DFF; ----------------------------------------------------------------------------- -- MEM_D_DFF -- The D register -- Just loaded with EX_MantB_1 (Op1), never changes during the iteration -- "01" adds positive sign bit and implicit bit ----------------------------------------------------------------------------- MEM_D_DFF : process (Clk) is begin -- process MEM_D_DFF if Clk'event and Clk = '1' then -- rising clock edge if EX_PipeRun and EX_Start_FPU then mem_D <= "01" & EX_MantB_1; end if; end if; end process MEM_D_DFF; ----------------------------------------------------------------------------- -- MEM_Q_DFF -- Left shift Q each iteration -- Shift in 1 if the previous operation was positive -- Shift in 0 if the previous operation was negative ----------------------------------------------------------------------------- MEM_Q_DFF : process (Clk) is begin -- process MEM_Q_DFF if Clk'event and Clk = '1' then -- rising clock edge if (mem_reset_Q = '1') then mem_Q <= (others => '0'); elsif (mem_div_iterate) then mem_Q <= mem_Q(mem_Q'left+1 to mem_Q'right) & not mem_res_neg_cmb; end if; end if; end process MEM_Q_DFF; ----------------------------------------------------------------------------- -- MEM_Next_Sub_DFF -- Is the next operation subtraction? ----------------------------------------------------------------------------- MEM_Next_Sub_DFF : process (Clk) is begin -- process MEM_Next_Sub_DFF if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then -- synchronous reset (active high) mem_next_sub <= '1'; else if EX_PipeRun and EX_Start_FPU then -- Start with a subtraction mem_next_sub <= '1'; elsif (mem_div_iterate) then mem_next_sub <= not mem_res_neg_cmb; end if; end if; end if; end process MEM_Next_Sub_DFF; ---------------------------------------- -- MEM_Div_Sticky -- Calculate the sticky bit -- Old name: div_carry_or_I1 ---------------------------------------- MEM_Div_Sticky : process (mem_R) is variable temp_sticky : std_logic; begin -- process MEM_Div_Sticky temp_sticky := '0'; -- mem_R'left is the round bit -- start at the following bit for I in mem_R'left+1 to mem_R'right loop temp_sticky := temp_sticky or mem_R(I); end loop; -- I mem_div_sticky_bit_cmb <= temp_sticky; end process MEM_Div_Sticky; ----------------------------------------------------------------------------- -- MEM_Start_Div_DFF -- Signal indicating start of divider ----------------------------------------------------------------------------- MEM_Start_Div_DFF : process (Clk) is begin if Clk'event and Clk = '1' then -- rising clock edge if Reset = '1' then -- synchronous reset (active high) mem_start_div <= false; else if EX_PipeRun then mem_start_div <= EX_Start_FPU and ex_div_op; else mem_start_div <= false; end if; end if; end if; end process MEM_Start_Div_DFF; ----------------------------------------------------------------------------- -- Outputs ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- MEM_Dec_Exp_DFF -- Need to decrement the exponent? -- This is not pipelined -- Old name: detect_adjust ----------------------------------------------------------------------------- MEM_Dec_Exp_DFF : process (Clk) is variable start_div_1 : boolean; begin -- process MEM_Dec_Exp_DFF if Clk'event and Clk = '1' then -- rising clock edge if (Reset = '1') or (Mem_Not_Div_Op) then -- synchronous reset (active high) MEM_Div_Dec_Exp_4 <= false; else if mem_start_div then if (mem_res_neg_cmb = '1') then MEM_Div_Dec_Exp_4 <= true; else MEM_Div_Dec_Exp_4 <= false; end if; end if; end if; end if; end process MEM_Dec_Exp_DFF; ----------------------------------------------------------------------------- -- MEM_Div_Res_4_DFF -- Divider result ----------------------------------------------------------------------------- MEM_Div_Res_4_DFF : process (Clk) is begin -- process MEM_Div_Res_4_DFF if Clk'event and Clk = '1' then -- rising clock edge if (Reset = '1') or (Mem_Not_Div_Op) then -- synchronous reset (active high) MEM_Div_Res_4 <= (others => '0'); else -- Implicit through guard bit MEM_Div_Res_4(MEM_Div_Res_4'left to MEM_Div_Res_4'right-2) <= mem_Q; MEM_Div_Res_4(FPU_MANT_ROUND_POS) <= mem_R(mem_R'left); MEM_Div_Res_4(FPU_MANT_STICKY_POS) <= mem_div_sticky_bit_cmb; end if; end if; end process MEM_Div_Res_4_DFF; -- Divider is done MEM_Div_Done <= mem_div_done_i;end IMP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -