📄 fpu_lth.vhd
字号:
-------------------------------------------------------------------------------
-- 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 + -