com
https://schaumont.dyn.wpi.edu/ece4530f19/lectures/lecture13-notes.html
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -------------------------------------------------------------------------------- package float32 is -------------------------------------------------------------------------------- type fp32 is record sign : std_logic; exponent : unsigned(7 downto 0); mantissa : unsigned(22 downto 0); end record fp32; type fp32_array is array(natural range<>) of fp32; -------------------------------------------------------------------------------- constant fp32_EXPONENT_OFFSET : unsigned(7 downto 0) := "01111111"; constant fp32_EXPONENT_OFFSET_INT : integer := 127; constant fp32_ZERO : fp32 := ( sign => '0', exponent => (others => '0'), mantissa => (others => '0') ); constant fp32_INF : fp32 := ( sign => '0', exponent => (others => '1'), mantissa => (others => '0') ); -------------------------------------------------------------------------------- function fp32_abs_eq (first, second : in fp32) return boolean; function fp32_is_nan (first, second : in fp32) return boolean; function fp32_gt (first, second: in fp32) return boolean; -------------------------------------------------------------------------------- function fp32_from_slv (src : in std_logic_vector(31 downto 0)) return fp32; function slv_from_fp32 (src : in fp32) return std_logic_vector; function fp32_add (first, second: in fp32) return fp32; function fp32_sub (first, second: in fp32) return fp32; function fp32_mul (first, second: in fp32) return fp32; --function fp32_div (first, second: in fp32) return fp32; -------------------------------------------------------------------------------- end float32; -------------------------------------------------------------------------------- package body float32 is -------------------------------------------------------------------------------- function fp32_abs_eq (first, second : in fp32) return boolean is begin return (first.exponent = second.exponent and first.mantissa = second.mantissa); end function fp32_abs_eq; function fp32_is_nan (first, second : in fp32) return boolean is begin return (first.exponent = fp32_INF.exponent and first.mantissa /= fp32_INF.mantissa); end function fp32_is_nan; -------------------------------------------------------------------------------- function fp32_gt (first, second: in fp32) return boolean is variable result : boolean := false; begin if first.exponent = fp32_ZERO.exponent and second.exponent = fp32_ZERO.exponent then -- zero > zero result := false; elsif first.exponent = fp32_ZERO.exponent and second.exponent /= fp32_ZERO.exponent then -- zero > nonzero result := second.sign /= '0'; elsif first.exponent /= fp32_ZERO.exponent and second.exponent = fp32_ZERO.exponent then -- nonzero > zero result := first.sign = '0'; else -- if first.exponent /= 0 and second.exponent /= 0 then -- both nonzero if first.sign = '1' and second.sign = '0' then -- negative > positive result := false; elsif first.sign = '0' and second.sign = '1' then -- positive > negative result := true; else -- same sign if first.exponent > second.exponent then result := true; elsif first.exponent < second.exponent then result := false; else result := first.mantissa > second.mantissa; end if; if first.sign = '1' then -- both negative result := not result; end if; end if; end if; return result; end function fp32_gt; -------------------------------------------------------------------------------- function fp32_from_slv (src : in std_logic_vector(31 downto 0)) return fp32 is begin return (sign => src(31), exponent => unsigned(src(30 downto 23)), mantissa => unsigned(src(22 downto 0))); end function fp32_from_slv; function slv_from_fp32 (src : in fp32) return std_logic_vector is begin return src.sign & std_logic_vector(src.exponent) & std_logic_vector(src.mantissa); end function slv_from_fp32; function fp32_mul (first, second: in fp32) return fp32 is variable result : fp32 := fp32_ZERO; variable buf : unsigned(47 downto 0) := (others => '0'); variable start : integer := 46; begin if first.exponent /= 0 and second.exponent /= 0 then result.sign := first.sign xor second.sign; result.exponent := first.exponent + second.exponent - fp32_EXPONENT_OFFSET; buf := unsigned('1' & first.mantissa) * unsigned('1' & second.mantissa); -- normalize for i in 47 downto 46 loop if buf(i) = '1' then start := i - 1; exit; end if; end loop; result.exponent := to_unsigned(to_integer(result.exponent) + start - 45, 8); result.mantissa := buf(start downto start-22); end if; return result; end function fp32_mul; -------------------------------------------------------------------------------- function fp32_sum (first, second: in fp32) return fp32 is variable result : fp32 := fp32_ZERO; variable buf : unsigned (24 downto 0) := (others => '0'); variable buf1 : unsigned (24 downto 0) := (others => '0'); variable buf2 : unsigned (24 downto 0) := (others => '0'); variable delta : integer := 0; variable start : integer := 22; variable zero : boolean := true; begin result.sign := first.sign; result.exponent := first.exponent; buf1 := unsigned("01" & first.mantissa); buf2 := unsigned("01" & second.mantissa); delta := to_integer(first.exponent) - to_integer (second.exponent); if delta < 24 then if delta /= 0 then buf2 (24-delta downto 0) := buf2 (24 downto delta); buf2 (24 downto 24-delta+1) := (others => '0'); end if; if first.sign = second.sign then buf := buf1 + buf2; else buf := buf1 - buf2; end if; end if; -- normalize for i in 24 downto 0 loop if buf(i) = '1' then start := i; zero := false; exit; end if; end loop; if not zero then result.exponent := result.exponent + start - 1 - 22; if start = 24 then result.mantissa(22 downto 0) := buf(23 downto 1); -- elsif start = 23 then -- result.mantissa(22 downto 0) := buf(22 downto 0); elsif start > 0 result.mantissa(22 downto 23-start) := buf(start-1 downto 0); end if; end if; return result; end function fp32_sum; function fp32_add (first, second: in fp32) return fp32 is begin if first.exponent = 0 then return second; elsif second.exponent = 0 then return first; elsif first.exponent > second.exponent then return fp32_sum (first, second); elsif first.exponent < second.exponent then return fp32_sum (second, first); elsif first.mantissa >= second.mantissa then return fp32_sum (first, second); else return fp32_sum (second, first); end if; end function fp32_add; function fp32_sub (first, second: in fp32) return fp32 is variable temp : fp32 := second; begin temp.sign := not temp.sign; return fp32_add (first, temp); end function fp32_sub; -------------------------------------------------------------------------------- end float32; --------------------------------------------------------------------------------
com.txt · Last modified: 2025/02/19 19:28 by 147.32.8.110