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

📄 fpu_lth.vhd

📁 sparc org, vhdl rtl code
💻 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 + -