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

📄 fpu_lth.vhd

📁 sparc org, vhdl rtl code
💻 VHD
📖 第 1 页 / 共 3 页
字号:
-------------------------------------------------------------------------------
--  Copyright (C) 2002 Martin Kasprzyk <m_kasprzyk@altavista.com>
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
-------------------------------------------------------------------------------
-- File       : fpu.vhd
-- Author     : Martin Kasprzyk <e00mk@efd.lth.se>
-------------------------------------------------------------------------------
-- Description: A IEEE754 floating point unit for the LEON SPARC processor
-------------------------------------------------------------------------------
-- Modfied by Jiri Gaisler to:
-- * be VHDL-87 compatible 
-- * remove ambiguity for std_logic +,-, and > operands.
-- * supress 'X' warnings from std_logic_arith packages
-- * added bug fixes from Albert Wang (5 Dec 2002)
-- * added bug fixes from Albert Wang (16 Dec 2002)
-------------------------------------------------------------------------------
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned."-";
use ieee.std_logic_unsigned."+";
use ieee.std_logic_unsigned.">";
use work.leon_iface.all;
use work.sparcv8.all;

entity fpu_lth is
  port(
    ss_clock        : in  std_logic;
    FpInst          : in  std_logic_vector(9 downto 0);
    FpOp            : in  std_logic;
    FpLd            : in  std_logic;
    Reset           : in  std_logic;
    fprf_dout1      : in  std_logic_vector(63 downto 0);
    fprf_dout2      : in  std_logic_vector(63 downto 0);
    RoundingMode    : in  std_logic_vector(1 downto 0);
    FpBusy          : out std_logic;
    FracResult      : out std_logic_vector(54 downto 3);
    ExpResult       : out std_logic_vector(10 downto 0);
    SignResult      : out std_logic;
    SNnotDB         : out std_logic;                            -- Not used
    Excep           : out std_logic_vector(5 downto 0);
    ConditionCodes  : out std_logic_vector(1 downto 0);
    ss_scan_mode    : in  std_logic;                            -- Not used
    fp_ctl_scan_in  : in  std_logic;                            -- Not used
    fp_ctl_scan_out : out std_logic                             -- Not used
  );
end;

architecture rtl of fpu_lth is

  constant zero : std_logic_vector(63 downto 0) := (others => '0');

-------------------------------------------------------------------------------
-- Leading zero counter.
-------------------------------------------------------------------------------
  procedure lz_counter (
    in_vect       : in  std_logic_vector(55 downto 0);
    leading_zeros : out std_logic_vector(5 downto 0)) is 
    variable pos_mask : std_logic_vector(55 downto 0);
    variable neg_mask : std_logic_vector(55 downto 0);
    variable leading_one : std_logic_vector(55 downto 0);
    variable nr_zeros : std_logic_vector(5 downto 0);
  begin
    -- Find leading one e.g. if in_vect = 00101101 then pos_mask = 00111111
    -- and neg_mask = "11100000, performing and gives leading_one = 00100000
    pos_mask(55) := in_vect(55);
    for i in 54 downto 0 loop
      pos_mask(i) := pos_mask(i+1) or in_vect(i);
    end loop;
    neg_mask := "1" & (not pos_mask(55 downto 1));
    leading_one := pos_mask and neg_mask;

    -- Get number of leading zeros from the leading_one vector
    nr_zeros := "000000";
 
    for i in 1 to 55 loop
      if (i / 32) /= 0 then
        nr_zeros(5) := nr_zeros(5) or leading_one(55-i);
      end if;

      if ((i mod 32) / 16) /= 0  then
        nr_zeros(4) := nr_zeros(4) or leading_one(55-i);
      end if;

      if (((i mod 32) mod 16) / 8) /= 0 then
        nr_zeros(3) := nr_zeros(3) or leading_one(55-i);
      end if;

      if ((((i mod 32) mod 16) mod 8) / 4) /= 0 then
        nr_zeros(2) := nr_zeros(2) or leading_one(55-i);
      end if;

      if (((((i mod 32) mod 16) mod 8) mod 4) / 2) /= 0 then
        nr_zeros(1) := nr_zeros(1) or leading_one(55-i);
      end if;
      
      if (i mod 2) /= 0 then
        nr_zeros(0) := nr_zeros(0) or leading_one(55-i);
      end if;
    end loop;

    -- Return result
    leading_zeros := nr_zeros;
  end lz_counter;
  
-------------------------------------------------------------------------------
-- Variable amount right shifter with sticky bit calculation.
-------------------------------------------------------------------------------
  procedure right_shifter_sticky (
    in_vect    : in  std_logic_vector(54 downto 0);
    amount     : in  std_logic_vector(5 downto 0);
    out_vect   : out std_logic_vector(54 downto 0);
    sticky_bit : out std_logic) is
    variable after32  : std_logic_vector(54 downto 0);
    variable after16  : std_logic_vector(54 downto 0);
    variable after8   : std_logic_vector(54 downto 0);
    variable after4   : std_logic_vector(54 downto 0);
    variable after2   : std_logic_vector(54 downto 0);
    variable after1   : std_logic_vector(54 downto 0);
    variable sticky32 : std_logic;
    variable sticky16 : std_logic;
    variable sticky8  : std_logic;
    variable sticky4  : std_logic;
    variable sticky2  : std_logic;
    variable sticky1  : std_logic;
  begin
    -- If amount(5) = '1' then shift vector 32 positions right
    if amount(5) = '1' then
      after32 := zero(31 downto 0) & in_vect(54 downto 32);
      if in_vect(31 downto 0) /= zero(31 downto 0) then
        sticky32 := '1';
      else
        sticky32 := '0';
      end if;
    else
      after32 := in_vect;
      sticky32 := '0';
    end if;

    -- If amount(4) = '1' then shift vector 16 positions right
    if amount(4) = '1' then
      after16 := zero(15 downto 0) & after32(54 downto 16);
      if after32(15 downto 0) /= zero(15 downto 0) then
        sticky16 := '1';
      else
        sticky16 := '0';
      end if;
    else
      after16 := after32;
      sticky16 := '0';
    end if;

    -- If amount(3) = '1' then shift vector 8 positions right
    if amount(3) = '1' then
      after8 := zero(7 downto 0) & after16(54 downto 8);
      if after16(7 downto 0) /= zero(7 downto 0) then
        sticky8 := '1';
      else
        sticky8 := '0';
      end if;
    else
      after8 := after16;
      sticky8 := '0';
    end if;

    -- If amount(2) = '1' then shift vector 4 positions right
    if amount(2) = '1' then
      after4 := zero(3 downto 0) & after8(54 downto 4);
      if after8(3 downto 0) /= zero(3 downto 0) then
        sticky4 := '1';
      else
        sticky4 := '0';
      end if;
    else
      after4 := after8;
      sticky4 := '0';
    end if;

    -- If amount(1) = '1' then shift vector 2 positions right
    if amount(1) = '1' then
      after2 := "00" & after4(54 downto 2);
      if after4(1 downto 0) /= "00" then
        sticky2 := '1';
      else
        sticky2 := '0';
      end if;
    else
      after2 := after4;
      sticky2 := '0';
    end if;

    -- If amount(0) = '1' then shift vector 1 positions right
    if amount(0) = '1' then
      after1 := "0" & after2(54 downto 1);
      sticky1 := after2(0);
    else
      after1 := after2;
      sticky1 := '0';
    end if;

    -- Return values
    out_vect := after1;
    sticky_bit := sticky32 or sticky16 or sticky8 or sticky4 or sticky2 or
                 sticky1;
  end right_shifter_sticky;

-------------------------------------------------------------------------------
-- Variable amount left shifter
-------------------------------------------------------------------------------
  procedure left_shifter (
    in_vect  : in  std_logic_vector(56 downto 0);
    amount   : in  std_logic_vector(5 downto 0);
    out_vect : out std_logic_vector(56 downto 0)) is
    variable after32 : std_logic_vector(56 downto 0);
    variable after16 : std_logic_vector(56 downto 0);
    variable after8  : std_logic_vector(56 downto 0);
    variable after4  : std_logic_vector(56 downto 0);
    variable after2  : std_logic_vector(56 downto 0);
    variable after1  : std_logic_vector(56 downto 0);
  begin
    -- If amount(5) = '1' then shift vector 32 positions left
    if amount(5) = '1' then
      after32 := in_vect(24 downto 0) & zero(31 downto 0);
    else
      after32 := in_vect;
    end if;

    -- If amount(4) = '1' then shift vector 16 positions left
    if amount(4) = '1' then
      after16 :=  after32(40 downto 0) & zero(15 downto 0);
    else
      after16 := after32;
    end if;

    -- If amount(3) = '1' then shift vector 8 positions left
    if amount(3) = '1' then
      after8 := after16(48 downto 0) & zero(7 downto 0);
    else
      after8 := after16;
    end if;

    -- If amount(2) = '1' then shift vector 4 positions left
    if amount(2) = '1' then
      after4 := after8(52 downto 0) & zero(3 downto 0);
    else
      after4 := after8;
    end if;

    -- If amount(1) = '1' then shift vector 2 positions left
    if amount(1) = '1' then
      after2 := after4(54 downto 0) & "00";
    else
      after2 := after4;
    end if;

    -- If amount(0) = '1' then shift vector 1 positions left
    if amount(0) = '1' then
      after1 := after2(55 downto 0) & "0";
    else
      after1 := after2;
    end if;

    -- Return value
    out_vect := after1;
  end left_shifter;
  
-------------------------------------------------------------------------------
-- Declaration of record types used to pass signals between pipeline stages.
-------------------------------------------------------------------------------
type op_decode_stage_type is record     -- input <-> op_decode
  opcode : std_logic_vector(9 downto 0);
end record;

type prenorm_stage_type is record       -- op_decode <-> prenorm
  sign1      : std_logic;
  exp1       : std_logic_vector(10 downto 0);
  frac1     : std_logic_vector(51 downto 0);
  sign2      : std_logic;
  exp2       : std_logic_vector(10 downto 0);
  frac2     : std_logic_vector(51 downto 0);
  single     : std_logic;               -- Single precision
  comp       : std_logic;               -- Compare and set cc
  gen_ex     : std_logic;               -- Generate exception if unordered 
  op1_denorm : std_logic;
  op2_denorm : std_logic;
  op1_inf    : std_logic;
  op2_inf    : std_logic;
  op1_NaN    : std_logic;
  op2_NaN    : std_logic;
  op1_SNaN   : std_logic;
  op2_SNaN   : std_logic;
end record;

type addsub_stage_type is record        -- prenorm <-> addsub
  sign_a   : std_logic;
  a        : std_logic_vector(56 downto 0);
  sign_b   : std_logic;
  b        : std_logic_vector(56 downto 0);
  exp      : std_logic_vector(10 downto 0);
  single   : std_logic;                 -- Single precision
  comp     : std_logic;                 -- Compare and set cc
  gen_ex   : std_logic;                 -- Generate exception if unordered 
  swaped   : std_logic;                 -- Operands swaped during pre_norm
  op1_inf  : std_logic;
  op2_inf  : std_logic;
  op1_NaN  : std_logic;
  op2_NaN  : std_logic;
  op1_SNaN : std_logic;
  op2_SNaN : std_logic;
end record;

type postnorm_stage_type is record      -- addsub <-> postnorm
  frac     : std_logic_vector(56 downto 0);
  exp      : std_logic_vector(10 downto 0);
  sign     : std_logic;
  single   : std_logic;                         -- Single precision
  comp     : std_logic;                         -- Compare and set cc  
  cc       : std_logic_vector(1 downto 0);      -- Condition codes
  exc      : std_logic_vector(4 downto 0);      -- Exceptions
  res_inf  : std_logic;
  res_NaN  : std_logic;
  res_SNaN : std_logic;
  res_zero : std_logic;
end record;

type roundnorm_stage_type is record     -- postnorm <-> roundnorm
  frac     : std_logic_vector(56 downto 0);
  exp      : std_logic_vector(10 downto 0);
  sign     : std_logic;
  single   : std_logic;                         -- Single precision
  comp     : std_logic;                         -- Compare and set cc  
  cc       : std_logic_vector(1 downto 0);      -- Condition codes
  exc      : std_logic_vector(4 downto 0);      -- Exceptions
  res_inf  : std_logic;
  res_NaN  : std_logic;
  res_SNaN : std_logic;
end record;

⌨️ 快捷键说明

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