------------------------------------------------------------------------------- -- Proposed package body for the VHDL-200x-FT fixed_pkg package -- (Fixed point math package) -- This package body supplies a recommended implementation of these functions -- Version : $Revision: 1.2 $ -- Date : $Date: 2006-08-24 09:22:31-04 $ -- -- Created for VHDL-200X-ft, David Bishop (dbishop@vhdl.org) ------------------------------------------------------------------------------- library IEEE; use IEEE.MATH_REAL.all; package body fixed_generic_pkg is -- Author David Bishop (dbishop@vhdl.org) -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton -- null array constants constant NAUF : UNRESOLVED_ufixed (0 downto 1) := (others => '0'); constant NASF : UNRESOLVED_sfixed (0 downto 1) := (others => '0'); constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); -- This differed constant will tell you if the package body is synthesizable -- or implemented as real numbers, set to "true" if synthesizable. constant fixedsynth_or_real : BOOLEAN := false; -- Special version of "minimum" to do some boundary checking without errors function mins (l, r : INTEGER) return INTEGER is begin -- function mins if (L = INTEGER'low or R = INTEGER'low) then return 0; -- error condition, silent end if; return minimum (L, R); end function mins; -- Special version of "minimum" to do some boundary checking with errors function mine (l, r : INTEGER) return INTEGER is begin -- function mine if (L = INTEGER'low or R = INTEGER'low) then report fixed_generic_pkg'instance_name & " Unbounded number passed, was a literal used?" severity error; return 0; end if; return minimum (L, R); end function mine; -- The following functions are used only internally. Every function -- calls "cleanvec" either directly or indirectly. -- purpose: Fixes "downto" problem and resolves meta states function cleanvec ( arg : UNRESOLVED_sfixed) -- input return UNRESOLVED_sfixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : UNRESOLVED_sfixed (arg'range); begin -- function cleanvec assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) report fixed_generic_pkg'instance_name & " Vector passed using a ""to"" range, expected is ""downto""" severity error; return arg; end function cleanvec; -- purpose: Fixes "downto" problem and resolves meta states function cleanvec ( arg : UNRESOLVED_ufixed) -- input return UNRESOLVED_ufixed is constant left_index : INTEGER := maximum(arg'left, arg'right); constant right_index : INTEGER := mins(arg'left, arg'right); variable result : UNRESOLVED_ufixed (arg'range); begin -- function cleanvec assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) report fixed_generic_pkg'instance_name & " Vector passed using a ""to"" range, expected is ""downto""" severity error; return arg; end function cleanvec; -- Type convert a "unsigned" into a "ufixed", used internally function to_fixed ( arg : UNRESOLVED_UNSIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (left_index downto right_index); begin -- function to_fixed result := UNRESOLVED_ufixed(arg); return result; end function to_fixed; -- Type convert a "signed" into an "sfixed", used internally function to_fixed ( arg : UNRESOLVED_SIGNED; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (left_index downto right_index); begin -- function to_fixed result := UNRESOLVED_sfixed(arg); return result; end function to_fixed; -- Type convert a "ufixed" into an "unsigned", used internally function to_uns ( arg : UNRESOLVED_ufixed) -- fp vector return UNRESOLVED_UNSIGNED is subtype t is UNRESOLVED_UNSIGNED(arg'high - arg'low downto 0); variable slv : t; begin -- function to_uns slv := t(arg); return UNRESOLVED_UNSIGNED(to_X01(STD_ULOGIC_VECTOR(slv))); end function to_uns; -- Type convert an "sfixed" into a "signed", used internally function to_s ( arg : UNRESOLVED_sfixed) -- fp vector return UNRESOLVED_SIGNED is subtype t is UNRESOLVED_SIGNED(arg'high - arg'low downto 0); variable slv : t; begin -- function to_s slv := t(arg); return UNRESOLVED_SIGNED(to_X01(STD_ULOGIC_VECTOR(slv))); end function to_s; -- adds 1 to the LSB of the number procedure round_up (arg : in UNRESOLVED_ufixed; result : out UNRESOLVED_ufixed; overflowx : out BOOLEAN) is variable arguns, resuns : UNRESOLVED_UNSIGNED (arg'high-arg'low+1 downto 0) := (others => '0'); begin -- round_up arguns (arguns'high-1 downto 0) := to_uns (arg); resuns := arguns + 1; result := to_fixed(resuns(arg'high-arg'low downto 0), arg'high, arg'low); overflowx := (resuns(resuns'high) = '1'); end procedure round_up; -- adds 1 to the LSB of the number procedure round_up (arg : in UNRESOLVED_sfixed; result : out UNRESOLVED_sfixed; overflowx : out BOOLEAN) is variable args, ress : UNRESOLVED_SIGNED (arg'high-arg'low+1 downto 0); begin -- round_up args (args'high-1 downto 0) := to_s (arg); args(args'high) := arg(arg'high); -- sign extend ress := args + 1; result := to_fixed(ress (ress'high-1 downto 0), arg'high, arg'low); overflowx := ((arg(arg'high) /= ress(ress'high-1)) and (or (STD_ULOGIC_VECTOR(ress)) /= '0')); end procedure round_up; -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up -- when the remainder is > 0.5. If the remainder IS 0.5 then if the -- bottom bit is a "1" it is rounded, otherwise it remains the same. function round_fixed (arg : UNRESOLVED_ufixed; remainder : UNRESOLVED_ufixed; overflow_style : fixed_overflow_style_type := fixed_overflow_style) return UNRESOLVED_ufixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : UNRESOLVED_ufixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or (to_suv(remainder(remainder'high-1 downto remainder'low))) = '1'); end if; else rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); end if; if rounds then round_up(arg => arg, result => result, overflowx => round_overflow); else result := arg; end if; if (overflow_style = fixed_saturate) and round_overflow then result := saturate (result'high, result'low); end if; return result; end function round_fixed; -- Rounding case statement function round_fixed (arg : UNRESOLVED_sfixed; remainder : UNRESOLVED_sfixed; overflow_style : fixed_overflow_style_type := fixed_overflow_style) return UNRESOLVED_sfixed is variable rounds : BOOLEAN; variable round_overflow : BOOLEAN; variable result : UNRESOLVED_sfixed (arg'range); begin rounds := false; if (remainder'length > 1) then if (remainder (remainder'high) = '1') then rounds := (arg(arg'low) = '1') or (or (to_suv(remainder(remainder'high-1 downto remainder'low))) = '1'); end if; else rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); end if; if rounds then round_up(arg => arg, result => result, overflowx => round_overflow); else result := arg; end if; if round_overflow then if (overflow_style = fixed_saturate) then if arg(arg'high) = '0' then result := saturate (result'high, result'low); else result := not saturate (result'high, result'low); end if; -- else -- result(result'high) := arg(arg'high); -- fix sign bit in wrap end if; end if; return result; end function round_fixed; ----------------------------------------------------------------------------- -- Visible functions ----------------------------------------------------------------------------- -- Conversion functions. These are needed for synthesis where typically -- the only input and output type is a std_logic_vector. function to_suv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_ULOGIC_VECTOR is subtype t is STD_ULOGIC_VECTOR (arg'high - arg'low downto 0); variable slv : t; begin if arg'length < 1 then return NSLV; end if; slv := t (arg); return slv; end function to_suv; function to_suv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_ULOGIC_VECTOR is subtype t is STD_ULOGIC_VECTOR (arg'high - arg'low downto 0); variable slv : t; begin if arg'length < 1 then return NSLV; end if; slv := t (arg); return slv; end function to_suv; function to_slv ( arg : UNRESOLVED_ufixed) -- fixed point vector return STD_LOGIC_VECTOR is begin return to_stdlogicvector (to_suv(arg)); end function to_slv; function to_slv ( arg : UNRESOLVED_sfixed) -- fixed point vector return STD_LOGIC_VECTOR is begin return to_stdlogicvector (to_suv(arg)); end function to_slv; function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return unresolved_ufixed is variable result : UNRESOLVED_ufixed (left_index downto right_index); begin if (arg'length < 1 or right_index > left_index) then return NAUF; end if; if (arg'length /= result'length) then report fixed_generic_pkg'instance_name & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NAUF; else result := to_fixed (arg => UNRESOLVED_UNSIGNED(arg), left_index => left_index, right_index => right_index); return result; end if; end function to_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector constant left_index : INTEGER; constant right_index : INTEGER) return unresolved_sfixed is variable result : UNRESOLVED_sfixed (left_index downto right_index); begin if (arg'length < 1 or right_index > left_index) then return NASF; end if; if (arg'length /= result'length) then report fixed_generic_pkg'instance_name & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NASF; else result := to_fixed (arg => UNRESOLVED_SIGNED(arg), left_index => left_index, right_index => right_index); return result; end if; end function to_sfixed; -- Two's complement number, Grows the vector by 1 bit. -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. function "abs" ( arg : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := mine(arg'low, arg'low); variable argreal, result : REAL; begin if (arg'length < 1) then return NASF; end if; argreal := to_real(arg); result := abs(argreal); return to_sfixed (result, left_index+1, right_index); end function "abs"; -- also grows the vector by 1 bit. function "-" ( arg : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is constant left_index : INTEGER := arg'high+1; constant right_index : INTEGER := mine(arg'low, arg'low); variable argreal, result : REAL; begin if (arg'length < 1) then return NASF; end if; argreal := to_real(arg); result := -(argreal); return to_sfixed (result, left_index+1, right_index); end function "-"; -- Addition function "+" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) + ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NAUF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal + rreal; return to_ufixed (result, left_index, right_index); end function "+"; function "+" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) + sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal + rreal; return to_sfixed (result, left_index, right_index); end function "+"; -- Subtraction function "-" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) - ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NAUF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal - rreal; return to_ufixed (result, left_index, right_index); end function "-"; function "-" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) - sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal - rreal; return to_sfixed (result, left_index, right_index); end function "-"; function "*" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) * ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(a+c+1 downto b+d) constant left_index : INTEGER := l'high + r'high+1; constant right_index : INTEGER := mine(l'low, l'low) + mine(r'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NAUF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal * rreal; return to_ufixed (result, left_index, right_index); end function "*"; function "*" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) * sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(a+c+1 downto b+d) constant left_index : INTEGER := l'high + r'high+1; constant right_index : INTEGER := mine(l'low, l'low) + mine(r'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); result := lreal * rreal; return to_sfixed (result, left_index, right_index); end function "*"; function "/" ( l, r : UNRESOLVED_ufixed) -- ufixed(a downto b) / ufixed(c downto d) = return UNRESOLVED_ufixed is -- ufixed(a-d downto b-c-1) begin return divide (l, r); end function "/"; function "/" ( l, r : UNRESOLVED_sfixed) -- sfixed(a downto b) / sfixed(c downto d) = return UNRESOLVED_sfixed is -- sfixed(a-d+1 downto b-c) begin return divide (l, r); end function "/"; -- This version of divide gives the user more control -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) function divide ( l, r : UNRESOLVED_ufixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is constant left_index : INTEGER := l'high - mine(r'low, r'low); constant right_index : INTEGER := mine (l'low, l'low) - r'high -1; variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NAUF; end if; lreal := to_real (l); rreal := to_real (r); if (rreal = 0.0) then report fixed_generic_pkg'instance_name & " DIVIDE uFixed point Division by zero" severity error; return saturate (left_index, right_index); -- saturate else result := lreal / rreal; return to_ufixed ( arg => result, left_index => left_index, right_index => right_index, round_style => round_style, guard_bits => guard_bits); end if; end function divide; -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) function divide ( l, r : UNRESOLVED_sfixed; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is constant left_index : INTEGER := l'high - mine(r'low, r'low)+1; constant right_index : INTEGER := mine (l'low, l'low) - r'high; variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); if (rreal = 0.0) then report fixed_generic_pkg'instance_name & " DIVIDE sFixed point Division by zero" severity error; return saturate (left_index, right_index); -- saturate else result := lreal / rreal; return to_sfixed ( arg => result, left_index => left_index, right_index => right_index, round_style => round_style, guard_bits => guard_bits); end if; end function divide; -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) function reciprocal ( arg : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is constant one : UNRESOLVED_ufixed (0 downto 0) := "1"; begin return divide (l => one, r => arg, round_style => round_style, guard_bits => guard_bits); end function reciprocal; -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) function reciprocal ( arg : UNRESOLVED_sfixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is constant one : UNRESOLVED_sfixed (1 downto 0) := "01"; -- extra bit. variable resultx : UNRESOLVED_sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); begin if (arg'length < 1 or resultx'length < 1) then return NASF; else resultx := divide (l => one, r => arg, round_style => round_style, guard_bits => guard_bits); return resultx (resultx'high-1 downto resultx'low); -- remove extra bit end if; end function reciprocal; -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function "rem" ( l, r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return remainder (l, r); end function "rem"; -- remainder -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function "rem" ( l, r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return remainder (l, r); end function "rem"; -- ufixed (a downto b) rem ufixed (c downto d) -- = ufixed (min(a,c) downto min(b,d)) function remainder ( l, r : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is constant left_index : INTEGER := minimum(l'high, r'high); constant right_index : INTEGER := mine(l'low, r'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NAUF; end if; lreal := to_real (l); rreal := to_real (r); if (rreal = 0.0) then report fixed_generic_pkg'instance_name & " rem uFixed point Division by zero" severity error; return saturate (left_index, right_index); -- saturate else result := (lreal / rreal) - (lreal mod rreal); return to_ufixed ( arg => result, left_index => left_index, right_index => right_index, round_style => round_style, guard_bits => guard_bits); end if; end function remainder; -- remainder -- sfixed (a downto b) rem sfixed (c downto d) -- = sfixed (min(a,c) downto min(b,d)) function remainder ( l, r : UNRESOLVED_sfixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is constant left_index : INTEGER := minimum(r'high, l'high); constant right_index : INTEGER := mine(r'low, l'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); if (rreal = 0.0) then report fixed_generic_pkg'instance_name & " rem uFixed point Division by zero" severity error; return saturate (left_index, right_index); -- saturate else result := (lreal / rreal) - (lreal mod rreal); return to_sfixed ( arg => result, left_index => left_index, right_index => right_index, round_style => round_style, guard_bits => guard_bits); end if; end function remainder; -- modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function "mod" ( l, r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return modulo (l, r); end function "mod"; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function "mod" ( l, r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return modulo(l, r); end function "mod"; -- modulo -- ufixed (a downto b) mod ufixed (c downto d) -- = ufixed (min(a,c) downto min(b, d)) function modulo ( l, r : UNRESOLVED_ufixed; -- fixed point input constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_ufixed is begin return remainder(l => l, r => r, round_style => round_style, guard_bits => guard_bits); end function modulo; -- sfixed (a downto b) mod sfixed (c downto d) -- = sfixed (c downto min(b, d)) function modulo ( l, r : UNRESOLVED_sfixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) return UNRESOLVED_sfixed is constant left_index : INTEGER := r'high; constant right_index : INTEGER := mine(r'low, l'low); variable lreal, rreal, result : REAL; begin if (l'length < 1 or r'length < 1 or mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then return NASF; end if; lreal := to_real (l); rreal := to_real (r); if (rreal = 0.0) then report fixed_generic_pkg'instance_name & " mod sFixed point Division by zero" severity error; return saturate (left_index, right_index); -- saturate else result := lreal mod rreal; return to_sfixed ( arg => result, left_index => left_index, right_index => right_index, round_style => round_style, guard_bits => guard_bits); end if; end function modulo; -- Procedure for those who need an "accumulator" function procedure add_carry ( L, R : in UNRESOLVED_ufixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_ufixed; c_out : out STD_ULOGIC) is constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable xresult : ufixed (left_index downto right_index); variable lreal, rreal, rresult : REAL; begin if (l'length < 1 or r'length < 1) then result := NAUF; c_out := '0'; else lreal := to_real (l); rreal := to_real (r); if c_in = '1' then rresult := lreal + rreal + 1.0; else rresult := lreal + rreal; end if; xresult := to_ufixed (rresult, left_index, right_index); c_out := xresult(left_index); result := xresult (left_index-1 downto right_index); end if; end procedure add_carry; procedure add_carry ( L, R : in UNRESOLVED_sfixed; c_in : in STD_ULOGIC; result : out UNRESOLVED_sfixed; c_out : out STD_ULOGIC) is constant left_index : INTEGER := maximum(l'high, r'high)+1; constant right_index : INTEGER := mins(l'low, r'low); variable xresult : sfixed (left_index downto right_index); variable lreal, rreal, rresult : REAL; begin if (l'length < 1 or r'length < 1) then result := NASF; c_out := '0'; else lreal := to_real (l); rreal := to_real (r); if c_in = '1' then rresult := lreal + rreal + 1.0; else rresult := lreal + rreal; end if; xresult := to_sfixed (rresult, left_index, right_index); c_out := xresult(left_index); result := xresult (left_index-1 downto right_index); end if; end procedure add_carry; -- Scales the result by a power of 2. Width of input = width of output with -- the decimal point moved. function scalb (y : UNRESOLVED_ufixed; N : INTEGER) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (y'high+N downto y'low+N); begin if y'length < 1 then return NAUF; else result := y; return result; end if; end function scalb; function scalb (y : UNRESOLVED_ufixed; N : SIGNED) return UNRESOLVED_ufixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function scalb (y : UNRESOLVED_sfixed; N : INTEGER) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (y'high+N downto y'low+N); begin if y'length < 1 then return NASF; else result := y; return result; end if; end function scalb; function scalb (y : UNRESOLVED_sfixed; N : SIGNED) return UNRESOLVED_sfixed is begin return scalb (y => y, N => to_integer(N)); end function scalb; function Is_Negative (arg : UNRESOLVED_sfixed) return BOOLEAN is begin if to_X01(arg(arg'high)) = '1' then return true; else return false; end if; end function Is_Negative; function find_rightmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'reverse_range loop if arg(i) ?= y then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_rightmost; function find_leftmost (arg : UNRESOLVED_ufixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'range loop if arg(i) ?= y then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_leftmost; function find_rightmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'reverse_range loop if arg(i) ?= y then return i; end if; end loop; return arg'high+1; -- return out of bounds 'high end function find_rightmost; function find_leftmost (arg : UNRESOLVED_sfixed; y : STD_ULOGIC) return INTEGER is begin for_loop : for i in arg'range loop if arg(i) ?= y then return i; end if; end loop; return arg'low-1; -- return out of bounds 'low end function find_leftmost; function "sll" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sll"; function "srl" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "srl"; function "rol" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv rol COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "rol"; function "ror" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); argslv := argslv ror COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "ror"; function "sla" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); -- Arithmetic shift on an unsigned is a logical shift argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sla"; function "sra" (ARG : UNRESOLVED_ufixed; COUNT : INTEGER) return UNRESOLVED_ufixed is variable argslv : UNRESOLVED_UNSIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_ufixed (arg'range); begin argslv := to_uns (arg); -- Arithmetic shift on an unsigned is a logical shift argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sra"; function "sll" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv sll COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "sll"; function "srl" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv srl COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "srl"; function "rol" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv rol COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "rol"; function "ror" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); argslv := argslv ror COUNT; result := to_fixed (argslv, result'high, result'low); return result; end function "ror"; function "sla" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); if COUNT > 0 then -- Arithmetic shift left on a 2's complement number is a logic shift argslv := argslv sll COUNT; else argslv := argslv sra -COUNT; end if; result := to_fixed (argslv, result'high, result'low); return result; end function "sla"; function "sra" (ARG : UNRESOLVED_sfixed; COUNT : INTEGER) return UNRESOLVED_sfixed is variable argslv : UNRESOLVED_SIGNED (arg'length-1 downto 0); variable result : UNRESOLVED_sfixed (arg'range); begin argslv := to_s (arg); if COUNT > 0 then argslv := argslv sra COUNT; else -- Arithmetic shift left on a 2's complement number is a logic shift argslv := argslv sll -COUNT; end if; result := to_fixed (argslv, result'high, result'low); return result; end function "sra"; -- Because some people want the older functions. function SHIFT_LEFT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : UNRESOLVED_ufixed; COUNT : NATURAL) return UNRESOLVED_ufixed is begin if (ARG'length < 1) then return NAUF; end if; return ARG sra COUNT; end function SHIFT_RIGHT; function SHIFT_LEFT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed is begin if (ARG'length < 1) then return NASF; end if; return ARG sla COUNT; end function SHIFT_LEFT; function SHIFT_RIGHT (ARG : UNRESOLVED_sfixed; COUNT : NATURAL) return UNRESOLVED_sfixed is begin if (ARG'length < 1) then return NASF; end if; return ARG sra COUNT; end function SHIFT_RIGHT; ---------------------------------------------------------------------------- -- logical functions ---------------------------------------------------------------------------- function "not" (L : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin RESULT := not to_suv(L); return to_ufixed(RESULT, L'high, L'low); end function "not"; function "and" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) and to_suv(R); else report fixed_generic_pkg'instance_name & " ""and"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "and"; function "or" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) or to_suv(R); else report fixed_generic_pkg'instance_name & " ""or"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "or"; function "nand" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) nand to_suv(R); else report fixed_generic_pkg'instance_name & " ""nand"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "nand"; function "nor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) nor to_suv(R); else report fixed_generic_pkg'instance_name & " ""nor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "nor"; function "xor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) xor to_suv(R); else report fixed_generic_pkg'instance_name & " ""xor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "xor"; function "xnor" (L, R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) xnor to_suv(R); else report fixed_generic_pkg'instance_name & " ""xnor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_ufixed(RESULT, L'high, L'low); end function "xnor"; function "not" (L : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin RESULT := not to_suv(L); return to_sfixed(RESULT, L'high, L'low); end function "not"; function "and" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) and to_suv(R); else report fixed_generic_pkg'instance_name & " ""and"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "and"; function "or" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) or to_suv(R); else report fixed_generic_pkg'instance_name & " ""or"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "or"; function "nand" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) nand to_suv(R); else report fixed_generic_pkg'instance_name & " ""nand"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "nand"; function "nor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) nor to_suv(R); else report fixed_generic_pkg'instance_name & " ""nor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "nor"; function "xor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) xor to_suv(R); else report fixed_generic_pkg'instance_name & " ""xor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "xor"; function "xnor" (L, R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto begin if (L'high = R'high and L'low = R'low) then RESULT := to_suv(L) xnor to_suv(R); else report fixed_generic_pkg'instance_name & " ""xnor"": Range error L'RANGE /= R'RANGE" severity warning; RESULT := (others => 'U'); end if; return to_sfixed(RESULT, L'high, L'low); end function "xnor"; -- Vector and std_ulogic functions, same as functions in numeric_std function "and" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L and R(i); end loop; return result; end function "and"; function "and" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) and R; end loop; return result; end function "and"; function "or" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L or R(i); end loop; return result; end function "or"; function "or" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) or R; end loop; return result; end function "or"; function "nand" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L nand R(i); end loop; return result; end function "nand"; function "nand" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) nand R; end loop; return result; end function "nand"; function "nor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L nor R(i); end loop; return result; end function "nor"; function "nor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) nor R; end loop; return result; end function "nor"; function "xor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L xor R(i); end loop; return result; end function "xor"; function "xor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) xor R; end loop; return result; end function "xor"; function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (R'range); begin for i in result'range loop result(i) := L xnor R(i); end loop; return result; end function "xnor"; function "xnor" (L : UNRESOLVED_ufixed; R : STD_ULOGIC) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (L'range); begin for i in result'range loop result(i) := L(i) xnor R; end loop; return result; end function "xnor"; function "and" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L and R(i); end loop; return result; end function "and"; function "and" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) and R; end loop; return result; end function "and"; function "or" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L or R(i); end loop; return result; end function "or"; function "or" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) or R; end loop; return result; end function "or"; function "nand" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L nand R(i); end loop; return result; end function "nand"; function "nand" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) nand R; end loop; return result; end function "nand"; function "nor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L nor R(i); end loop; return result; end function "nor"; function "nor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) nor R; end loop; return result; end function "nor"; function "xor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L xor R(i); end loop; return result; end function "xor"; function "xor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) xor R; end loop; return result; end function "xor"; function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (R'range); begin for i in result'range loop result(i) := L xnor R(i); end loop; return result; end function "xnor"; function "xnor" (L : UNRESOLVED_sfixed; R : STD_ULOGIC) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (L'range); begin for i in result'range loop result(i) := L(i) xnor R; end loop; return result; end function "xnor"; -- Reduction operators function "and" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return and to_suv(l); end function "and"; function "nand" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return nand to_suv(l); end function "nand"; function "or" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return or to_suv(l); end function "or"; function "nor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return nor to_suv(l); end function "nor"; function "xor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return xor to_suv(l); end function "xor"; function "xnor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is begin return xnor to_suv(l); end function "xnor"; function "and" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return and to_suv(l); end function "and"; function "nand" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return nand to_suv(l); end function "nand"; function "or" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return or to_suv(l); end function "or"; function "nor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return nor to_suv(l); end function "nor"; function "xor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return xor to_suv(l); end function "xor"; function "xnor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is begin return xnor to_suv(l); end function "xnor"; -- End reduction operators function "?=" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'length < 1) or (R'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '1'; for i in lresize'reverse_range loop result1 := lresize(i) ?= rresize(i); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result and result1; end if; end loop; return result; end if; end function "?="; function "?/=" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?/= if ((L'length < 1) or (R'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?/="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '0'; for i in lresize'reverse_range loop result1 := lresize(i) ?/= rresize(i); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result or result1; end if; end loop; return result; end if; end function "?/="; function "?>" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?> if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?>"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?>"": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l > r then return '1'; else return '0'; end if; end if; end function "?>"; function "?>=" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?>= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?>="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?>="": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l >= r then return '1'; else return '0'; end if; end if; end function "?>="; function "?<" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?< if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?<"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?<"": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l < r then return '1'; else return '0'; end if; end if; end function "?<"; function "?<=" (L, R : UNRESOLVED_ufixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?<= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?<="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?<="": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l <= r then return '1'; else return '0'; end if; end if; end function "?<="; function "?=" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?= if ((L'length < 1) or (R'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '1'; for i in lresize'reverse_range loop result1 := lresize(i) ?= rresize(i); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result and result1; end if; end loop; return result; end if; end function "?="; function "?/=" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); variable result, result1 : STD_ULOGIC; -- result begin -- ?/= if ((L'length < 1) or (R'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?/="": null detected, returning X" severity warning; return 'X'; else lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); result := '0'; for i in lresize'reverse_range loop result1 := lresize(i) ?/= rresize(i); if result1 = 'U' then return 'U'; elsif result1 = 'X' or result = 'X' then result := 'X'; else result := result or result1; end if; end loop; return result; end if; end function "?/="; function "?>" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?> if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?>"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?>"": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l > r then return '1'; else return '0'; end if; end if; end function "?>"; function "?>=" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?>= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?>="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?>="": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l >= r then return '1'; else return '0'; end if; end if; end function "?>="; function "?<" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?< if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?<"": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?<"": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l < r then return '1'; else return '0'; end if; end if; end function "?<"; function "?<=" (L, R : UNRESOLVED_sfixed) return STD_ULOGIC is variable founddash : BOOLEAN := false; begin -- ?<= if ((l'length < 1) or (r'length < 1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""?<="": null detected, returning X" severity warning; return 'X'; else for i in L'range loop if L(i) = '-' then founddash := true; end if; end loop; for i in R'range loop if R(i) = '-' then founddash := true; end if; end loop; if founddash then report fixed_generic_pkg'instance_name & " ""?<="": '-' found in compare string" severity error; return 'X'; elsif is_x(l) or is_x(r) then return 'X'; elsif l <= r then return '1'; else return '0'; end if; end if; end function "?<="; -- Match function, similar to "std_match" from numeric_std function std_match (L, R : UNRESOLVED_ufixed) return BOOLEAN is begin if (L'high = R'high and L'low = R'low) then return std_match(to_suv(L), to_suv(R)); else report fixed_generic_pkg'instance_name & " STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" severity warning; return false; end if; end function std_match; function std_match (L, R : UNRESOLVED_sfixed) return BOOLEAN is begin if (L'high = R'high and L'low = R'low) then return std_match(to_suv(L), to_suv(R)); else report fixed_generic_pkg'instance_name & " STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" severity warning; return false; end if; end function std_match; -- compare functions function "=" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal = rreal; end function "="; function "=" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal = rreal; end function "="; function "/=" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""/="": null argument detected, returning TRUE" severity warning; return true; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""/="": metavalue detected, returning TRUE" severity warning; return true; end if; lreal := to_real (l); rreal := to_real (r); return lreal /= rreal; end function "/="; function "/=" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""/="": null argument detected, returning TRUE" severity warning; return true; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""/="": metavalue detected, returning TRUE" severity warning; return true; end if; lreal := to_real (l); rreal := to_real (r); return lreal /= rreal; end function "/="; function ">" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">"": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal > rreal; end function ">"; function ">" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">"": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal > rreal; end function ">"; function "<" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<"": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal < rreal; end function "<"; function "<" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<"": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<"": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal < rreal; end function "<"; function ">=" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal >= rreal; end function ">="; function ">=" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " "">="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal >= rreal; end function ">="; function "<=" ( l, r : UNRESOLVED_ufixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal <= rreal; end function "<="; function "<=" ( l, r : UNRESOLVED_sfixed) -- fixed point input return BOOLEAN is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lreal, rreal : REAL; begin if (l'length < 1 or r'length < 1) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<="": null argument detected, returning FALSE" severity warning; return false; elsif (Is_X(l) or Is_X(r)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " ""<="": metavalue detected, returning FALSE" severity warning; return false; end if; lreal := to_real (l); rreal := to_real (r); return lreal <= rreal; end function "<="; -- overloads of the default maximum and minimum functions function maximum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); begin if (l'length < 1 or r'length < 1) then return NAUF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); if lresize > rresize then return lresize; else return rresize; end if; end function maximum; function maximum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); begin if (l'length < 1 or r'length < 1) then return NASF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); if lresize > rresize then return lresize; else return rresize; end if; end function maximum; function minimum (l, r : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index); begin if (l'length < 1 or r'length < 1) then return NAUF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); if lresize > rresize then return rresize; else return lresize; end if; end function minimum; function minimum (l, r : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is constant left_index : INTEGER := maximum(l'high, r'high); constant right_index : INTEGER := mins(l'low, r'low); variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index); begin if (l'length < 1 or r'length < 1) then return NASF; end if; lresize := resize (l, left_index, right_index); rresize := resize (r, left_index, right_index); if lresize > rresize then return rresize; else return lresize; end if; end function minimum; function to_ufixed ( arg : NATURAL; -- integer constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is variable argx : INTEGER; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_ufixed (left_index downto fw) := (others => '0'); variable sresult : UNRESOLVED_UNSIGNED (left_index downto 0); -- integer portion variable bound : NATURAL; -- find the numerical bounds begin if (left_index < fw) then return NAUF; end if; if left_index >= 0 then if (left_index < 30) then bound := 2**(left_index+1); else bound := INTEGER'high; end if; end if; if (arg /= 0) then if arg >= bound or left_index < 0 then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_UFIXED(NATURAL): vector truncated" severity warning; if (overflow_style = fixed_wrap) then -- wrap if bound = 0 then argx := 0; else argx := arg mod bound; end if; else -- saturate return saturate (result'high, result'low); end if; else argx := arg; end if; else return result; -- return zero end if; sresult := to_unsigned (argx, sresult'high+1); result := resize (arg => UNRESOLVED_ufixed (sresult), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_ufixed; function to_sfixed ( arg : INTEGER; -- integer constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is variable argx : INTEGER; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_sfixed (left_index downto fw) := (others => '0'); variable sresult : UNRESOLVED_SIGNED (left_index+1 downto 0); -- integer portion variable bound : NATURAL := 0; begin if (left_index < fw) then -- null range return NASF; end if; if left_index >= 0 then if (left_index < 30) then bound := 2**(left_index); else bound := INTEGER'high; end if; end if; if (arg /= 0) then if (arg >= bound or arg < -bound or left_index < 0) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_SFIXED(INTEGER): vector truncated" severity warning; if overflow_style = fixed_wrap then -- wrap if bound = 0 then -- negative integer_range trap argx := 0; else -- shift off the top bits argx := arg rem (bound*2); end if; else -- saturate if arg < 0 then result := not saturate (result'high, result'low); -- underflow else result := saturate (result'high, result'low); -- overflow end if; return result; end if; else argx := arg; end if; else return result; -- return zero end if; sresult := to_signed (argx, sresult'length); result := resize (arg => UNRESOLVED_sfixed (sresult), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_sfixed; function to_ufixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return UNRESOLVED_ufixed is constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_ufixed (left_index downto fw) := (others => '0'); variable Xresult : UNRESOLVED_ufixed (left_index downto fw-guard_bits) := (others => '0'); variable presult : REAL; variable overflow_needed : BOOLEAN; begin -- If negative or null range, return. if (left_index < fw) then return NAUF; end if; if (arg < 0.0) then report fixed_generic_pkg'instance_name & " TO_UFIXED: Negative argument passed " & REAL'image(arg) severity error; return result; end if; presult := arg; if presult >= (2.0**(left_index+1)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_UFIXED(REAL): vector truncated" severity warning; overflow_needed := (overflow_style = fixed_saturate); if overflow_style = fixed_wrap then presult := presult mod (2.0**(left_index+1)); -- wrap else return saturate (result'high, result'low); end if; end if; for i in Xresult'range loop if presult >= 2.0**i then Xresult(i) := '1'; presult := presult - 2.0**i; else Xresult(i) := '0'; end if; end loop; if guard_bits > 0 and round_style = fixed_round then result := round_fixed (arg => Xresult (left_index downto right_index), remainder => Xresult (right_index-1 downto right_index-guard_bits), overflow_style => overflow_style); else result := Xresult (result'range); end if; return result; end function to_ufixed; function to_sfixed ( arg : REAL; -- real constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return UNRESOLVED_sfixed is constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_sfixed (left_index downto fw) := (others => '0'); variable Xresult : UNRESOLVED_sfixed (left_index+1 downto fw-guard_bits) := (others => '0'); variable presult : REAL; begin if (left_index < fw) then -- null range return NASF; end if; if (arg >= (2.0**left_index) or arg < -(2.0**left_index)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_SFIXED(REAL): vector truncated" severity warning; if overflow_style = fixed_saturate then if arg < 0.0 then -- saturate result := not saturate (result'high, result'low); -- underflow else result := saturate (result'high, result'low); -- overflow end if; return result; else presult := abs(arg) mod (2.0**(left_index+1)); -- wrap end if; else presult := abs(arg); end if; for i in Xresult'range loop if presult >= 2.0**i then Xresult(i) := '1'; presult := presult - 2.0**i; else Xresult(i) := '0'; end if; end loop; if arg < 0.0 then Xresult := to_fixed(-to_s(Xresult), Xresult'high, Xresult'low); end if; if guard_bits > 0 and round_style = fixed_round then result := round_fixed (arg => Xresult (left_index downto right_index), remainder => Xresult (right_index-1 downto right_index-guard_bits), overflow_style => overflow_style); else result := Xresult (result'range); end if; return result; end function to_sfixed; function to_ufixed ( arg : UNRESOLVED_UNSIGNED; -- unsigned constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNRESOLVED_UNSIGNED(ARG_LEFT downto 0) is ARG; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_ufixed (left_index downto fw); begin if arg'length < 1 or (left_index < fw) then return NAUF; end if; result := resize (arg => UNRESOLVED_ufixed (XARG), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_ufixed; -- converted version function to_ufixed ( arg : UNRESOLVED_UNSIGNED) -- unsigned return UNRESOLVED_ufixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNRESOLVED_UNSIGNED(ARG_LEFT downto 0) is ARG; begin if arg'length < 1 then return NAUF; end if; return UNRESOLVED_ufixed(xarg); end function to_ufixed; function to_ufixed (arg : UNRESOLVED_sfixed) return UNRESOLVED_ufixed is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := mine(arg'low, arg'low); variable xarg : UNRESOLVED_sfixed(left_index+1 downto right_index); variable result : UNRESOLVED_ufixed(left_index downto right_index); begin if arg'length < 1 then return NAUF; end if; xarg := abs(arg); result := UNRESOLVED_ufixed (xarg (left_index downto right_index)); return result; end function to_ufixed; function to_sfixed ( arg : UNRESOLVED_SIGNED; -- signed constant left_index : INTEGER; -- size of integer portion constant right_index : INTEGER := 0; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNRESOLVED_SIGNED(ARG_LEFT downto 0) is ARG; constant fw : INTEGER := mine (right_index, right_index); -- catch literals variable result : UNRESOLVED_sfixed (left_index downto fw); begin if arg'length < 1 or (left_index < fw) then return NASF; end if; result := resize (arg => UNRESOLVED_sfixed (XARG), left_index => left_index, right_index => right_index, round_style => round_style, overflow_style => overflow_style); return result; end function to_sfixed; -- converted version function to_sfixed ( arg : UNRESOLVED_SIGNED) -- signed return UNRESOLVED_sfixed is constant ARG_LEFT : INTEGER := ARG'length-1; alias XARG : UNRESOLVED_SIGNED(ARG_LEFT downto 0) is ARG; begin if arg'length < 1 then return NASF; end if; return UNRESOLVED_sfixed(xarg); end function to_sfixed; function to_sfixed (arg : UNRESOLVED_ufixed) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (arg'high+1 downto arg'low); begin if arg'length < 1 then return NASF; end if; result (arg'high downto arg'low) := UNRESOLVED_sfixed(cleanvec(arg)); result (arg'high+1) := '0'; return result; end function to_sfixed; -- Because of the fairly complicated sizing rules in the fixed point -- packages these functions are provided to compute the result ranges -- Example: -- signal uf1 : ufixed (3 downto -3); -- signal uf2 : ufixed (4 downto -2); -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto -- ufixed_low (3, -3, '*', 4, -2)); -- uf1multuf2 <= uf1 * uf2; -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), -- '1' (reciprocal), 'A', 'a' (abs), 'N', 'n' (-sfixed) function ufixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return maximum (left_index, left_index2) + 1; when '*' => return left_index + left_index2 + 1; when '/' => return left_index - right_index2; when '1' => return -right_index; -- reciprocal when 'R'|'r' => return mins (left_index, left_index2); -- "rem" when 'M'|'m' => return mins (left_index, left_index2); -- "mod" when others => return left_index; -- For abs and default end case; end function ufixed_high; function ufixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return mins (right_index, right_index2); when '*' => return right_index + right_index2; when '/' => return right_index - left_index2 - 1; when '1' => return -left_index - 1; -- reciprocal when 'R'|'r' => return mins (right_index, right_index2); -- "rem" when 'M'|'m' => return mins (right_index, right_index2); -- "mod" when others => return right_index; -- for abs and default end case; end function ufixed_low; function sfixed_high (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return maximum (left_index, left_index2) + 1; when '*' => return left_index + left_index2 + 1; when '/' => return left_index - right_index2 + 1; when '1' => return -right_index + 1; -- reciprocal when 'R'|'r' => return mins (left_index, left_index2); -- "rem" when 'M'|'m' => return left_index2; -- "mod" when 'A'|'a' => return left_index + 1; -- "abs" when 'N'|'n' => return left_index + 1; -- -sfixed when others => return left_index; end case; end function sfixed_high; function sfixed_low (left_index, right_index : INTEGER; operation : CHARACTER := 'X'; left_index2, right_index2 : INTEGER := 0) return INTEGER is begin case operation is when '+'| '-' => return mins (right_index, right_index2); when '*' => return right_index + right_index2; when '/' => return right_index - left_index2; when '1' => return -left_index; -- reciprocal when 'R'|'r' => return mins (right_index, right_index2); -- "rem" when 'M'|'m' => return mins (right_index, right_index2); -- "mod" when others => return right_index; -- default for abs, neg and default end case; end function sfixed_low; -- Same as above, but using the "size_res" input only for their ranges: -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto -- ufixed_low (uf1, '*', uf2)); -- uf1multuf2 <= uf1 * uf2; function ufixed_high (size_res : UNRESOLVED_ufixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_ufixed) return INTEGER is begin return ufixed_high (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function ufixed_high; function ufixed_low (size_res : UNRESOLVED_ufixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_ufixed) return INTEGER is begin return ufixed_low (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function ufixed_low; function sfixed_high (size_res : UNRESOLVED_sfixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_sfixed) return INTEGER is begin return sfixed_high (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function sfixed_high; function sfixed_low (size_res : UNRESOLVED_sfixed; operation : CHARACTER := 'X'; size_res2 : UNRESOLVED_sfixed) return INTEGER is begin return sfixed_low (left_index => size_res'high, right_index => size_res'low, operation => operation, left_index2 => size_res2'high, right_index2 => size_res2'low); end function sfixed_low; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_ufixed is constant sat : UNRESOLVED_ufixed (left_index downto right_index) := (others => '1'); begin return sat; end function saturate; -- purpose: returns a saturated number function saturate ( constant left_index : INTEGER; constant right_index : INTEGER) return UNRESOLVED_sfixed is variable sat : UNRESOLVED_sfixed (left_index downto right_index) := (others => '1'); begin -- saturate positive, to saturate negative, just do "not saturate()" sat (left_index) := '0'; return sat; end function saturate; function saturate ( size_res : UNRESOLVED_ufixed) -- only the size of this is used return UNRESOLVED_ufixed is begin return saturate (size_res'high, size_res'low); end function saturate; function saturate ( size_res : UNRESOLVED_sfixed) -- only the size of this is used return UNRESOLVED_sfixed is begin return saturate (size_res'high, size_res'low); end function saturate; -- As a concession to those who use a graphical DSP environment, -- these functions take parameters in those tools format and create -- fixed point numbers. These functions are designed to convert from -- a std_logic_vector to the VHDL fixed point format using the conventions -- of these packages. In a pure VHDL environment you should use the -- "to_ufixed" and "to_sfixed" routines. -- Unsigned fixed point function to_UFix ( arg : STD_ULOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return ufixed is variable result : ufixed (width-fraction-1 downto -fraction); begin if (arg'length /= result'length) then report fixed_generic_pkg'instance_name & " TO_UFIX (STD_ULOGIC_VECTOR) " & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NAUF; else result := to_ufixed (arg, result'high, result'low); return result; end if; end function to_UFix; -- signed fixed point function to_SFix ( arg : STD_ULOGIC_VECTOR; width : NATURAL; -- width of vector fraction : NATURAL) -- width of fraction return sfixed is variable result : sfixed (width-fraction-1 downto -fraction); begin if (arg'length /= result'length) then report fixed_generic_pkg'instance_name & " TO_SFIX (STD_ULOGIC_VECTOR) " & "Vector lengths do not match. Input length is " & INTEGER'image(arg'length) & " and output will be " & INTEGER'image(result'length) & " wide." severity error; return NASF; else result := to_sfixed (arg, result'high, result'low); return result; end if; end function to_SFix; -- finding the bounds of a number. These functions can be used like this: -- signal xxx : ufixed (7 downto -3); -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) -- downto UFix_low(11, 3, "+", 11, 3)); -- Where "11" is the width of xxx (xxx'length), -- and 3 is the lower bound (abs (xxx'low)) -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" function ufix_high ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return ufixed_high (left_index => width - 1 - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - 1 - fraction2, right_index2 => -fraction2); end function ufix_high; function ufix_low ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return ufixed_low (left_index => width - 1 - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - 1 - fraction2, right_index2 => -fraction2); end function ufix_low; function sfix_high ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return sfixed_high (left_index => width - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - fraction2, right_index2 => -fraction2); end function sfix_high; function sfix_low ( width, fraction : NATURAL; operation : CHARACTER := 'X'; width2, fraction2 : NATURAL := 0) return INTEGER is begin return sfixed_low (left_index => width - fraction, right_index => -fraction, operation => operation, left_index2 => width2 - fraction2, right_index2 => -fraction2); end function sfix_low; function to_unsigned ( arg : UNRESOLVED_ufixed; -- ufixed point input constant size : NATURAL; -- length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_UNSIGNED is begin return to_uns(resize (arg => arg, left_index => size-1, right_index => 0, round_style => round_style, overflow_style => overflow_style)); end function to_unsigned; function to_unsigned ( arg : UNRESOLVED_ufixed; -- ufixed point input size_res : UNRESOLVED_UNSIGNED; -- length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_UNSIGNED is begin return to_unsigned (arg => arg, size => size_res'length, round_style => round_style, overflow_style => overflow_style); end function to_unsigned; function to_signed ( arg : UNRESOLVED_sfixed; -- sfixed point input constant size : NATURAL; -- length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_SIGNED is begin return to_s(resize (arg => arg, left_index => size-1, right_index => 0, round_style => round_style, overflow_style => overflow_style)); end function to_signed; function to_signed ( arg : UNRESOLVED_sfixed; -- sfixed point input size_res : UNRESOLVED_SIGNED; -- used for length of output constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_SIGNED is begin return to_signed (arg => arg, size => size_res'length, round_style => round_style, overflow_style => overflow_style); end function to_signed; function to_real ( arg : UNRESOLVED_ufixed) -- ufixed point input return REAL is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable result : REAL; -- result variable arg_int : UNRESOLVED_ufixed (left_index downto right_index); begin if (arg'length < 1) then return 0.0; end if; arg_int := cleanvec(arg); if (Is_X(arg_int)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_REAL: metavalue detected, returning 0.0" severity warning; return 0.0; end if; result := 0.0; for i in arg_int'range loop if (arg_int(i) = '1') then result := result + (2.0**i); end if; end loop; return result; end function to_real; function to_real ( arg : UNRESOLVED_sfixed) -- ufixed point input return REAL is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable result : REAL; -- result variable arg_int : UNRESOLVED_sfixed (left_index downto right_index); -- unsigned version of argument variable arg_uns : UNRESOLVED_ufixed (left_index downto right_index); -- absolute of argument begin if (arg'length < 1) then return 0.0; end if; arg_int := cleanvec(arg); if (Is_X(arg_int)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_REAL: metavalue detected, returning 0.0" severity warning; return 0.0; end if; arg_uns := to_ufixed (arg_int); result := to_real (arg_uns); if (arg_int(arg_int'high) = '1') then result := -result; end if; return result; end function to_real; function to_integer ( arg : UNRESOLVED_ufixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return NATURAL is constant left_index : INTEGER := arg'high; variable arg_uns : UNRESOLVED_UNSIGNED (minimum(31, left_index+1) downto 0) := (others => '0'); begin if (arg'length < 1) then return 0; end if; if (Is_X (arg)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_INTEGER: metavalue detected, returning 0" severity warning; return 0; end if; if (left_index < -1) then return 0; end if; arg_uns := to_uns(resize (arg => arg, left_index => arg_uns'high, right_index => 0, round_style => round_style, overflow_style => overflow_style)); return to_integer (arg_uns); end function to_integer; function to_integer ( arg : UNRESOLVED_sfixed; -- fixed point input constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return INTEGER is constant left_index : INTEGER := arg'high; constant right_index : INTEGER := arg'low; variable arg_s : UNRESOLVED_SIGNED (minimum(31, left_index+1) downto 0); begin if (arg'length < 1) then return 0; end if; if (Is_X (arg)) then assert NO_WARNING report fixed_generic_pkg'instance_name & " TO_INTEGER: metavalue detected, returning 0" severity warning; return 0; end if; if (left_index < -1) then return 0; end if; arg_s := to_s(resize (arg => arg, left_index => arg_s'high, right_index => 0, round_style => round_style, overflow_style => overflow_style)); return to_integer (arg_s); end function to_integer; function to_01 ( s : UNRESOLVED_ufixed; -- ufixed point input constant XMAP : STD_ULOGIC := '0') -- Map x to return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (s'range); -- result begin for i in s'range loop case s(i) is when '0' | 'L' => result(i) := '0'; when '1' | 'H' => result(i) := '1'; when others => result(i) := XMAP; end case; end loop; return result; end function to_01; function to_01 ( s : UNRESOLVED_sfixed; -- sfixed point input constant XMAP : STD_ULOGIC := '0') -- Map x to return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (s'range); begin for i in s'range loop case s(i) is when '0' | 'L' => result(i) := '0'; when '1' | 'H' => result(i) := '1'; when others => result(i) := XMAP; end case; end loop; return result; end function to_01; function Is_X ( arg : UNRESOLVED_ufixed) return BOOLEAN is variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv begin argslv := to_suv(arg); return Is_X (argslv); end function Is_X; function Is_X ( arg : UNRESOLVED_sfixed) return BOOLEAN is variable argslv : STD_ULOGIC_VECTOR (arg'length-1 downto 0); -- slv begin argslv := to_suv(arg); return Is_X (argslv); end function Is_X; function To_X01 ( arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is begin return to_ufixed (To_X01(to_suv(arg)), arg'high, arg'low); end function To_X01; function to_X01 ( arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is begin return to_sfixed (To_X01(to_suv(arg)), arg'high, arg'low); end function To_X01; function To_X01Z ( arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is begin return to_ufixed (To_X01Z(to_suv(arg)), arg'high, arg'low); end function To_X01Z; function to_X01Z ( arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is begin return to_sfixed (To_X01Z(to_suv(arg)), arg'high, arg'low); end function To_X01Z; function To_UX01 ( arg : UNRESOLVED_ufixed) return UNRESOLVED_ufixed is begin return to_ufixed (To_UX01(to_suv(arg)), arg'high, arg'low); end function To_UX01; function to_UX01 ( arg : UNRESOLVED_sfixed) return UNRESOLVED_sfixed is begin return to_sfixed (To_UX01(to_suv(arg)), arg'high, arg'low); end function To_UX01; function resize ( arg : UNRESOLVED_ufixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is constant arghigh : INTEGER := maximum (arg'high, arg'low); constant arglow : INTEGER := mine (arg'high, arg'low); variable invec : UNRESOLVED_ufixed (arghigh downto arglow); variable result : UNRESOLVED_ufixed(left_index downto right_index) := (others => '0'); variable needs_rounding : BOOLEAN := false; begin -- resize if (arg'length < 1) or (result'length < 1) then return NAUF; elsif (invec'length < 1) then return result; -- string literal value else invec := cleanvec(arg); if (right_index > arghigh) then -- return top zeros needs_rounding := (round_style = fixed_round) and (right_index = arghigh+1); elsif (left_index < arglow) then -- return overflow if (overflow_style = fixed_saturate) and (or(to_suv(invec)) = '1') then result := saturate (result'high, result'low); -- saturate end if; elsif (arghigh > left_index) then -- wrap or saturate? if (overflow_style = fixed_saturate and or (to_suv(invec(arghigh downto left_index+1))) = '1') then result := saturate (result'high, result'low); -- saturate else if (arglow >= right_index) then result (left_index downto arglow) := invec(left_index downto arglow); else result (left_index downto right_index) := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; end if; else -- arghigh <= integer width if (arglow >= right_index) then result (arghigh downto arglow) := invec; else result (arghigh downto right_index) := invec (arghigh downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; end if; -- Round result if needs_rounding then result := round_fixed (arg => result, remainder => invec (right_index-1 downto arglow), overflow_style => overflow_style); end if; return result; end if; end function resize; function resize ( arg : UNRESOLVED_sfixed; -- input constant left_index : INTEGER; -- integer portion constant right_index : INTEGER; -- size of fraction constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is constant arghigh : INTEGER := maximum (arg'high, arg'low); constant arglow : INTEGER := mine (arg'high, arg'low); variable invec : UNRESOLVED_sfixed (arghigh downto arglow); variable result : UNRESOLVED_sfixed(left_index downto right_index) := (others => '0'); variable reduced : STD_ULOGIC; variable needs_rounding : BOOLEAN := false; -- rounding begin -- resize if (arg'length < 1) or (result'length < 1) then return NASF; elsif (invec'length < 1) then return result; -- string literal value else invec := cleanvec(arg); if (right_index > arghigh) then -- return top zeros if (arg'low /= INTEGER'low) then -- check for a literal result := (others => arg(arghigh)); -- sign extend end if; needs_rounding := (round_style = fixed_round) and (right_index = arghigh+1); elsif (left_index < arglow) then -- return overflow if (overflow_style = fixed_saturate) then reduced := or (to_suv(invec)); if (reduced = '1') then if (invec(arghigh) = '0') then -- saturate POSITIVE result := saturate (result'high, result'low); else -- saturate negative result := not saturate (result'high, result'low); end if; -- else return 0 (input was 0) end if; -- else return 0 (wrap) end if; elsif (arghigh > left_index) then if (invec(arghigh) = '0') then reduced := or (to_suv(invec(arghigh-1 downto left_index))); if overflow_style = fixed_saturate and reduced = '1' then -- saturate positive result := saturate (result'high, result'low); else if (right_index > arglow) then result := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); else result (left_index downto arglow) := invec (left_index downto arglow); end if; end if; else reduced := and (to_suv(invec(arghigh-1 downto left_index))); if overflow_style = fixed_saturate and reduced = '0' then result := not saturate (result'high, result'low); else if (right_index > arglow) then result := invec (left_index downto right_index); needs_rounding := (round_style = fixed_round); else result (left_index downto arglow) := invec (left_index downto arglow); end if; end if; end if; else -- arghigh <= integer width if (arglow >= right_index) then result (arghigh downto arglow) := invec; else result (arghigh downto right_index) := invec (arghigh downto right_index); needs_rounding := (round_style = fixed_round); -- round end if; if (left_index > arghigh) then -- sign extend result(left_index downto arghigh+1) := (others => invec(arghigh)); end if; end if; -- Round result if (needs_rounding) then result := round_fixed (arg => result, remainder => invec (right_index-1 downto arglow), overflow_style => overflow_style); end if; return result; end if; end function resize; -- size_res functions -- These functions compute the size from a passed variable named "size_res" -- The only part of this variable used it it's size, it is never passed -- to a lower level routine. function to_ufixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_ufixed) -- for size only return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_ufixed; function to_sfixed ( arg : STD_ULOGIC_VECTOR; -- shifted vector size_res : UNRESOLVED_sfixed) -- for size only return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low); return result; end if; end function to_sfixed; function to_ufixed ( arg : NATURAL; -- integer size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : INTEGER; -- integer size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function to_ufixed ( arg : REAL; -- real size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, guard_bits => guard_bits, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : REAL; -- real size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style; constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, guard_bits => guard_bits, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function to_ufixed ( arg : UNRESOLVED_UNSIGNED; -- unsigned size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_ufixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_ufixed; function to_sfixed ( arg : UNRESOLVED_SIGNED; -- signed size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := to_sfixed (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function to_sfixed; function resize ( arg : UNRESOLVED_ufixed; -- input size_res : UNRESOLVED_ufixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_ufixed is variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := resize (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function resize; function resize ( arg : UNRESOLVED_sfixed; -- input size_res : UNRESOLVED_sfixed; -- for size only constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; constant round_style : fixed_round_style_type := fixed_round_style) return UNRESOLVED_sfixed is variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); begin if (result'length < 1) then return result; else result := resize (arg => arg, left_index => size_res'high, right_index => size_res'low, round_style => round_style, overflow_style => overflow_style); return result; end if; end function resize; -- Overloaded math functions for real function "+" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l + to_ufixed (r, l'high, l'low)); end function "+"; function "+" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) + r); end function "+"; function "+" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l + to_sfixed (r, l'high, l'low)); end function "+"; function "+" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) + r); end function "+"; function "-" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l - to_ufixed (r, l'high, l'low)); end function "-"; function "-" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) - r); end function "-"; function "-" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l - to_sfixed (r, l'high, l'low)); end function "-"; function "-" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) - r); end function "-"; function "*" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l * to_ufixed (r, l'high, l'low)); end function "*"; function "*" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) * r); end function "*"; function "*" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l * to_sfixed (r, l'high, l'low)); end function "*"; function "*" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) * r); end function "*"; function "/" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l / to_ufixed (r, l'high, l'low)); end function "/"; function "/" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) / r); end function "/"; function "/" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l / to_sfixed (r, l'high, l'low)); end function "/"; function "/" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) / r); end function "/"; function "rem" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l rem to_ufixed (r, l'high, l'low)); end function "rem"; function "rem" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) rem r); end function "rem"; function "rem" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l rem to_sfixed (r, l'high, l'low)); end function "rem"; function "rem" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) rem r); end function "rem"; function "mod" ( l : UNRESOLVED_ufixed; -- fixed point input r : REAL) return UNRESOLVED_ufixed is begin return (l mod to_ufixed (r, l'high, l'low)); end function "mod"; function "mod" ( l : REAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, r'low) mod r); end function "mod"; function "mod" ( l : UNRESOLVED_sfixed; -- fixed point input r : REAL) return UNRESOLVED_sfixed is begin return (l mod to_sfixed (r, l'high, l'low)); end function "mod"; function "mod" ( l : REAL; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, r'low) mod r); end function "mod"; -- Overloaded math functions for integers function "+" ( l : UNRESOLVED_ufixed; -- fixed point input r : NATURAL) return UNRESOLVED_ufixed is begin return (l + to_ufixed (r, l'high, 0)); end function "+"; function "+" ( l : NATURAL; r : UNRESOLVED_ufixed) -- fixed point input return UNRESOLVED_ufixed is begin return (to_ufixed (l, r'high, 0) + r); end function "+"; function "+" ( l : UNRESOLVED_sfixed; -- fixed point input r : INTEGER) return UNRESOLVED_sfixed is begin return (l + to_sfixed (r, l'high, 0)); end function "+"; function "+" ( l : INTEGER; r : UNRESOLVED_sfixed) -- fixed point input return UNRESOLVED_sfixed is begin return (to_sfixed (l, r'high, 0) + r); end function "+"; -- Overloaded functions function "-" ( l : UNRESOLVED_ufixed; -- fixed point input r : NATURAL) return UNRESOLVED_ufixed is begin return (l - to_ufixed (r, l'high, 0)); end function "-"; function "-" ( l : NATURAL; r : UNRESOLVED_ufixed)