-- Library of functions to work with unsigned FP numbers library ieee; use ieee.std_logic_1164.all; package pkg_ufp is -- Format -- [ ee ][ mm ] -- with total BW bits, and BE exponent bits and offset of exponent EO -- b(ee) in EO-[0..2**BE-1] -- b(mm) in [0..2**(BW-BE)-1]/2**(BW-BE) -- Convert a number if unsigned floating point to real function ufp_to_real ( ee_mm : std_logic_vector; -- Data in format exponent_mantissa as bits BW : natural; -- Bit width BE : natural; -- Number of bits used for exponent EO : natural) -- Offset of exponent return real; -- Convert a real number to unsigned floating point function real_to_ufp ( r : real; -- Real number to convert BW : natural; -- Bit width BE : natural; -- Number of bits used for exponent EO : natural) -- Offset of exponent return std_logic_vector; end package pkg_ufp; library ieee; use ieee.numeric_std.all; use ieee.math_real.all; package body pkg_ufp is function ufp_to_real ( ee_mm : std_logic_vector; -- Data in format exponent_mantissa as bits BW : natural; -- Bit width BE : natural; -- Number of bits used for exponent EO : natural) -- Offset of exponent return real is variable mm : unsigned(BW-BE-1 downto 0); variable ee : unsigned(BE-1 downto 0); variable d : real; begin ee := unsigned(ee_mm(BW-1 downto BW-BE)); mm := unsigned(ee_mm(BW-BE-1 downto 0)); d := real(to_integer(mm)) * 2.0**real(EO-to_integer(ee)-(BW-BE)); return d; end function ufp_to_real; function real_to_ufp ( r : real; -- Real number to convert BW : natural; -- Bit width BE : natural; -- Number of bits used for exponent EO : natural) -- Offset of exponent return std_logic_vector is variable BO, MAX_EXP, BM : integer; variable R_MIN, BM_LIM : real; variable mm : unsigned(BW-BE-1 downto 0); variable ee : unsigned(BE-1 downto 0); variable aa : integer; -- Scaling to normalize r into ufp representation variable mm_id : integer; begin BO := BW-BE-EO; -- Exponent of Scaling factor BM := BW - BE; -- Bits for mantissa BM_lim := log2(2.0**BM-1.0); -- A bit less than BM MAX_EXP := 2**BE-1; -- Max exponent R_MIN := 2.0**(-MAX_EXP-BO); -- Min value (not equal zero) if r '1'); mm := (others => '0'); else --aa := BM - integer(ceil(log2(r))); aa := integer(floor(BM_LIM - log2(r))); if aa < BO then aa := BO; end if; if aa > MAX_EXP+BO then aa := MAX_EXP+BO; end if; --report "[TST] aa=" & integer'image(aa) severity note; --report "[TST] rr=" & real'image( r * 2.0**aa ) severity note; mm_id := integer(round(r * 2.0**aa)); --mm_id := integer(floor(r * 2.0**aa)); -- ???? ee := to_unsigned(aa-BO, ee'length); mm := to_unsigned(mm_id, mm'length); end if; return std_logic_vector(ee) & std_logic_vector(mm); end function real_to_ufp; end package body pkg_ufp;