145 lines
6.0 KiB
VHDL
145 lines
6.0 KiB
VHDL
![]() |
library ieee;
|
||
|
use ieee.std_logic_1164.all;
|
||
|
use ieee.numeric_std.all;
|
||
|
|
||
|
package float is
|
||
|
constant SIGN : std_logic_vector( 31 downto 31 ) := ( others => '0' );
|
||
|
constant EXP : std_logic_vector( 30 downto 23 ) := ( others => '0' );
|
||
|
constant MANTISSA : std_logic_vector( 22 downto 0 ) := ( others => '0' );
|
||
|
|
||
|
function find_leftmost( arg : unsigned; value : std_ulogic ) return integer;
|
||
|
|
||
|
function count_leading_digits( arg : unsigned; value : std_ulogic ) return integer;
|
||
|
|
||
|
function to_float( arg : std_logic_vector ) return std_logic_vector;
|
||
|
|
||
|
function to_fixed( arg : std_logic_vector ) return std_logic_vector;
|
||
|
|
||
|
end package float;
|
||
|
|
||
|
package body float is
|
||
|
function find_leftmost( arg : unsigned; value : std_ulogic ) return integer is
|
||
|
begin
|
||
|
for i in arg'left downto arg'right loop
|
||
|
if ( arg( i ) = value ) then
|
||
|
return i;
|
||
|
end if;
|
||
|
end loop;
|
||
|
|
||
|
return -1;
|
||
|
end function find_leftmost;
|
||
|
|
||
|
function count_leading_digits( arg : unsigned; value : std_ulogic ) return integer is
|
||
|
variable left_most_value : integer range -1 to arg'high;
|
||
|
variable leading_values : integer range 0 to arg'high;
|
||
|
begin
|
||
|
left_most_value := find_leftmost( arg, not value );
|
||
|
leading_values := 0;
|
||
|
|
||
|
if ( left_most_value /= -1 ) then
|
||
|
leading_values := arg'high - left_most_value;
|
||
|
end if;
|
||
|
|
||
|
return leading_values;
|
||
|
end function count_leading_digits;
|
||
|
|
||
|
function to_float( arg : std_logic_vector ) return std_logic_vector is
|
||
|
variable y : std_logic_vector( 31 downto 0 );
|
||
|
variable s : std_logic;
|
||
|
variable e : unsigned( 7 downto 0 );
|
||
|
variable m : unsigned( 22 downto 0 );
|
||
|
variable value : unsigned( 30 downto 0 );
|
||
|
|
||
|
variable leading_sign_digits : integer range 0 to value'high;
|
||
|
variable reminding : integer range 0 to value'high;
|
||
|
begin
|
||
|
s := arg( 31 );
|
||
|
|
||
|
if ( s = '0' ) then
|
||
|
value := unsigned( arg( 30 downto 0 ) );
|
||
|
else
|
||
|
value := not unsigned( arg( 30 downto 0 ) );
|
||
|
value := value +1;
|
||
|
end if;
|
||
|
leading_sign_digits := count_leading_digits( value, '0' );
|
||
|
reminding := value'high - leading_sign_digits;
|
||
|
e := to_unsigned( 126 - leading_sign_digits, e'length );
|
||
|
|
||
|
if ( reminding > m'length ) then
|
||
|
m := value( reminding - 1 downto reminding - m'length );
|
||
|
elsif ( reminding > 1 ) then
|
||
|
m := ( others => '0' );
|
||
|
m( m'high downto m'high - reminding + 1 ) := value( reminding - 1 downto 0 );
|
||
|
else
|
||
|
m := ( others => '0' );
|
||
|
end if;
|
||
|
|
||
|
if (arg = x"00000000") then
|
||
|
y := (others => '0');
|
||
|
else
|
||
|
y := s & std_logic_vector( e ) & std_logic_vector( m );
|
||
|
end if;
|
||
|
|
||
|
return y;
|
||
|
end function to_float;
|
||
|
|
||
|
function to_fixed( arg : std_logic_vector ) return std_logic_vector is
|
||
|
variable y : unsigned( 31 downto 0 );
|
||
|
variable s : std_logic;
|
||
|
variable e : unsigned( 7 downto 0 );
|
||
|
variable m_index_max : integer range -127 to 128;
|
||
|
|
||
|
begin
|
||
|
s := arg( 31 );
|
||
|
e := unsigned(arg(30 downto 23));
|
||
|
m_index_max := to_integer(signed(30-(126-e)));
|
||
|
|
||
|
if (arg = x"00000000") then
|
||
|
y := (others => '0');
|
||
|
else
|
||
|
y := (others => '0');
|
||
|
case m_index_max is
|
||
|
when 30 => y(30 downto 7):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 29 => y(29 downto 6):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 28 => y(28 downto 5):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 27 => y(27 downto 4):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 26 => y(26 downto 3):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 25 => y(25 downto 2):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 24 => y(24 downto 1):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 23 => y(23 downto 0):= '1' & unsigned( arg(22 downto 0) );
|
||
|
when 22 => y(22 downto 0):= '1' & unsigned( arg(22 downto 1) );
|
||
|
when 21 => y(21 downto 0):= '1' & unsigned( arg(22 downto 2) );
|
||
|
when 20 => y(20 downto 0):= '1' & unsigned( arg(22 downto 3) );
|
||
|
when 19 => y(19 downto 0):= '1' & unsigned( arg(22 downto 4) );
|
||
|
when 18 => y(18 downto 0):= '1' & unsigned( arg(22 downto 5) );
|
||
|
when 17 => y(17 downto 0):= '1' & unsigned( arg(22 downto 6) );
|
||
|
when 16 => y(16 downto 0):= '1' & unsigned( arg(22 downto 7) );
|
||
|
when 15 => y(15 downto 0):= '1' & unsigned( arg(22 downto 8) );
|
||
|
when 14 => y(14 downto 0):= '1' & unsigned( arg(22 downto 9) );
|
||
|
when 13 => y(13 downto 0):= '1' & unsigned( arg(22 downto 10) );
|
||
|
when 12 => y(12 downto 0):= '1' & unsigned( arg(22 downto 11) );
|
||
|
when 11 => y(11 downto 0):= '1' & unsigned( arg(22 downto 12) );
|
||
|
when 10 => y(10 downto 0):= '1' & unsigned( arg(22 downto 13) );
|
||
|
when 9 => y(9 downto 0):= '1' & unsigned( arg(22 downto 14) );
|
||
|
when 8 => y(8 downto 0):= '1' & unsigned( arg(22 downto 15) );
|
||
|
when 7 => y(7 downto 0):= '1' & unsigned( arg(22 downto 16) );
|
||
|
when 6 => y(6 downto 0):= '1' & unsigned( arg(22 downto 17) );
|
||
|
when 5 => y(5 downto 0):= '1' & unsigned( arg(22 downto 18) );
|
||
|
when 4 => y(4 downto 0):= '1' & unsigned( arg(22 downto 19) );
|
||
|
when 3 => y(3 downto 0):= '1' & unsigned( arg(22 downto 20) );
|
||
|
when 2 => y(2 downto 0):= '1' & unsigned( arg(22 downto 21) );
|
||
|
when 1 => y(1 downto 0):= '1' & unsigned( arg(22 downto 22) );
|
||
|
when 0 => y(0):= '1';
|
||
|
when others => null;
|
||
|
end case;
|
||
|
if ( s = '1' ) then
|
||
|
y := not(y);
|
||
|
y:= y + x"00000001";
|
||
|
end if;
|
||
|
end if;
|
||
|
|
||
|
return std_logic_vector( y );
|
||
|
end function to_fixed;
|
||
|
|
||
|
end package body float;
|