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

📄 fpu_lth.vhd

📁 ARM7的源代码
💻 VHD
📖 第 1 页 / 共 3 页
字号:
        -- Calculate condition codes.    cc_bit1 := ((not zero_fraction) and (not neg_value) and (not as.swaped)) or               unordered;    cc_bit0 := ((not zero_fraction) and                (as.swaped or (neg_value and (not as.swaped)))) or unordered;    -- Set condition codes if comp signal is 1.    if as.comp = '1' then      posn_in.cc <= cc_bit1 & cc_bit0;    else      posn_in.cc <= (others => '0');    end if;    -- Set exceptions    posn_in.exc <= SNaN & inf & "000";        -- Check if operation results in specal value    posn_in.res_SNaN <= SNaN;    posn_in.res_NaN <= NaN;    posn_in.res_inf <= inf;    posn_in.single <= as.single;    posn_in.res_zero <= zero_fraction;    posn_in.comp <= as.comp;  end process addsub_stage;--------------------------------------------------------------------------------- Postnorm stage-------------------------------------------------------------------------------  posnorm_stage: process (posn)    variable mask : std_logic_vector(55 downto 0);    variable leading_one : std_logic_vector(55 downto 0);    variable leading_zeros : std_logic_vector(55 downto 0);    variable shifts_needed : std_logic_vector(5 downto 0);    variable shift_amount : std_logic_vector(5 downto 0);    variable exp : std_logic_vector(10 downto 0);    variable frac : std_logic_vector(56 downto 0);    variable overflow : std_logic;    variable underflow : std_logic;  begin    -- If supernormal (overflow bit set) shift left by one step and inc exp    if ((posn.single = '1') and (posn.frac(27) = '1')) or       (posn.frac(56) = '1') then      frac := "0" & posn.frac(56 downto 1);-- pragma translate_off      if not is_x(posn.exp) then-- pragma translate_on        exp := posn.exp + 1;-- pragma translate_off      end if;-- pragma translate_on      underflow := '0';    else      -- Get number of leading zeros, if single precision is used don't count      -- leading 29 zeroes. (Overflow bit is not counted)      if posn.single = '1' then        lz_counter((posn.frac(26 downto 0) & "0" & zero(27 downto 0)),shifts_needed);      else        lz_counter(posn.frac(55 downto 0),shifts_needed);      end if;      -- If the shift amount needed is larger then the exponent then underflow      -- has occured, check that fraction is not zero.-- pragma translate_off      if not is_x(shifts_needed & posn.exp) then-- pragma translate_on        if (unsigned(shifts_needed) > unsigned(posn.exp)) and (posn.res_zero = '0') then            shift_amount := posn.exp(5 downto 0);          exp := (others => '0');          underflow := '1';        else          shift_amount := shifts_needed;-- pragma translate_off          if not is_x( posn.exp & shift_amount) then-- pragma translate_on            exp := posn.exp - shift_amount;-- pragma translate_off          end if;-- pragma translate_on          underflow := '0';        end if;-- pragma translate_off      end if;-- pragma translate_on      -- Perform left shift      left_shifter(posn.frac,shift_amount,frac);    end if;    -- Check if overflow has occured, also check that result is not any NaN    if (exp(7 downto 0) = "11111111") and       ((posn.single = '1') or (exp(10 downto 8) = "111")) and       (posn.res_SNaN = '0') and (posn.res_NaN = '0') then      overflow := '1';    else      overflow := '0';    end if;    -- If operation is not some sort of compare set overflow/underflow    -- exceptions caused in this pipeline stage    if (posn.comp = '0') then      rnd_in.exc <= posn.exc(4) & overflow & underflow & posn.exc(1 downto 0);    else      rnd_in.exc <= posn.exc(4) & "00" & posn.exc(1 downto 0);    end if;        rnd_in.frac <= frac;    rnd_in.exp <= exp;    rnd_in.cc <= posn.cc;    rnd_in.res_NaN <= posn.res_NaN;    rnd_in.res_SNaN <= posn.res_SNaN;    rnd_in.res_inf <= posn.res_inf or overflow;    rnd_in.single <= posn.single;    rnd_in.comp <= posn.comp;    rnd_in.sign <= posn.sign;  end process posnorm_stage;  --------------------------------------------------------------------------------- Round and normalize stage-------------------------------------------------------------------------------  roundnorm_stage: process (rnd, RoundingMode)    variable rounded_value : std_logic_vector(53 downto 0);    variable rounded_norm_value : std_logic_vector(52 downto 0);    variable exp_norm : std_logic_vector(10 downto 0);    variable exp : std_logic_vector(10 downto 0);    variable fraction : std_logic_vector(51 downto 0);    variable all_zero : std_logic_vector(51 downto 0);    variable overflow : std_logic;    variable inexact : std_logic;    variable NaNs : std_logic;  begin    all_zero := (others => '0');    -- Perform rounding according to selected rounding mode    case RoundingMode is      when "00" => if rnd.frac(2) = '1' and                      rnd.frac(3 downto 0) /=  "0000" then-- pragma translate_off      		     if not is_x(rnd.frac(56 downto 3)) then-- pragma translate_on                       rounded_value := rnd.frac(56 downto 3) + 1;-- pragma translate_off      		     end if;-- pragma translate_on                   else                     rounded_value := rnd.frac(56 downto 3);                   end if;      when "01" => rounded_value := rnd.frac(56 downto 3);      when "10" => if rnd.sign = '0' and rnd.frac(2) = '1' then-- pragma translate_off      		     if not is_x(rnd.frac(56 downto 3)) then-- pragma translate_on                       rounded_value := rnd.frac(56 downto 3) + 1;-- pragma translate_off      		     end if;-- pragma translate_on                   else                     rounded_value := rnd.frac(56 downto 3);                   end if;      when "11" => if rnd.sign = '1' and rnd.frac(2) = '1' then-- pragma translate_off      		     if not is_x(rnd.frac(56 downto 3)) then-- pragma translate_on                       rounded_value := rnd.frac(56 downto 3) + 1;-- pragma translate_off      		     end if;-- pragma translate_on                   else                     rounded_value := rnd.frac(56 downto 3);                   end if;      when others => null;    end case;    -- Normalize if needed i.e. if overflow bit set shift fraction one step    -- left and inc exp.    if (rnd.single = '1' and rounded_value(24) = '1') or       rounded_value(36) = '1' then      rounded_norm_value := rounded_value(53 downto 1);-- pragma translate_off      if not is_x(rnd.exp) then-- pragma translate_on        exp_norm := rnd.exp + 1;-- pragma translate_off      end if;-- pragma translate_on    else      rounded_norm_value := rounded_value(52 downto 0);      exp_norm := rnd.exp;    end if;    -- Check if overflow has occured    if (exp_norm(7 downto 0) = "11111111") and       ((rnd.single = '1') or (exp_norm(10 downto 8) = "111")) and       (rnd.res_SNaN = '0') and (rnd.res_NaN = '0') then      overflow := '1';    else      overflow := '0';    end if;    -- Check if result is inexact    inexact := (rnd.frac(2) or rnd.frac(1) or rnd.frac(0)) and (not rnd.comp);    -- Check if result is some sort of NaN    NaNs := rnd.res_NaN or rnd.res_SNaN;        -- Set fraction and exponent.    if NaNs = '1' then      fraction := rnd.res_NaN & "1" & all_zero(49 downto 0);      exp := (others => '1');    elsif overflow = '1' or rnd.res_inf = '1' then      fraction := (others => '0');      exp := (others => '1');    else      fraction := rounded_norm_value(51 downto 0);      exp := exp_norm;    end if;    -- Set exception bits. If operaration is some sort of compare then    -- overflow, underflow and inexact interrupt can not occure.     if rnd.comp = '1' then      rnd_out.exc <= "0" & rnd.exc(4) & "0000";    else      rnd_out.exc <= "0" & rnd.exc(4) & (overflow or rnd.exc(3)) &                     rnd.exc(2 downto 1) & inexact;    end if;        -- Put out result    if rnd.single = '1' then      rnd_out.frac <= fraction(22 downto 0) & "0" & zero(27 downto 0);     else      rnd_out.frac <= fraction;    end if;    rnd_out.exp <= exp;    rnd_out.sign <= rnd.sign;    rnd_out.cc <= rnd.cc;  end process roundnorm_stage;--------------------------------------------------------------------------------- FPU busy signal generation process-------------------------------------------------------------------------------  gen_busy: process (state, FpOp, FpLd)  begin    -- Default assignments    FpBusy <= '0';    next_state <= state;    result_ready <= '0';    -- Calculate nextstate and output    case state is      when start       => if FpOp = '1' then                            next_state <= get_operand;                          end if;      when get_operand => FpBusy <= '1';                          if FpLd = '1' then                            next_state <= pre_norm;                          end if;      when pre_norm    => FpBusy <= '1';                          next_state <= add_sub;      when add_sub     => FpBusy <= '1';                          next_state <= post_norm;      when post_norm   => FpBusy <= '1';                          next_state <= rnd_norm;      when rnd_norm    => result_ready <= '1';                          if FpOp = '1' then                            next_state <= get_operand;                          else                            next_state <= hold_val;                          end if;      when hold_val    => if FpOp = '1' then                            next_state <= get_operand;                          end if;      when others      => null;    end case;  end process gen_busy;  process (ss_clock, Reset)  begin    if Reset = '1' then      state <= start;    elsif ss_clock = '1' and ss_clock'event then      state <= next_state;    end if;  end process;--------------------------------------------------------------------------------- Pipeline registers-------------------------------------------------------------------------------  -- Gated ff holding opcode  de_gated : process (ss_clock, FpOp)    begin    if ss_clock = '1' and ss_clock'event then      if FpOp = '1' then        de <= de_in;      end if;    end if;  end process de_gated;  -- Gated ff holding unpacked operands and control signals  pren_gated : process (ss_clock, FpLd)  begin    if ss_clock = '1' and ss_clock'event then      if FpLd = '1' then        pren <= pren_in;      end if;    end if;  end process pren_gated;  -- Normal ff for the other pipeline stages  pipe_regs: process (ss_clock)  begin  -- process pipe_regs    if ss_clock = '1' and ss_clock'event then      as <= as_in;      posn <= posn_in;      rnd <= rnd_in;    end if;  end process pipe_regs;  -- Gated ff with asynchronous reset holding the FPU output values  out_gated_reset: process (ss_clock, Reset, result_ready)  begin  -- process out_gated_reset    if Reset = '1' then      FracResult <= (others => '0');      ExpResult <= (others => '0');      SignResult <= '0';      Excep <= (others => '0');      ConditionCodes <= (others => '0');    elsif ss_clock = '1' and ss_clock'event then      if result_ready = '1' then        FracResult <= rnd_out.frac;        ExpResult <= rnd_out.exp;        SignResult <= rnd_out.sign;        Excep <= rnd_out.exc;        ConditionCodes <= rnd_out.cc;      end if;    end if;  end process out_gated_reset;  end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -