wk_sbs_hdl/hw/beh/pkg_ufp.vhd

100 lines
3.3 KiB
VHDL
Raw Normal View History

-- 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<R_MIN then -- If too small, set to zero
ee := (others => '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;