FIXED_GENERIC_PKG package body

Bit-level reference implementation of generic binary fixed-point arithmetic.

Use clause
library IEEE;
use IEEE.FIXED_GENERIC_PKG.all;
Source
ieee/fixed_generic_pkg-body.vhdl in the IEEE 1076 OSR, tag 1076-2019
Apache License 2.0, © 2019 IEEE P1076 WG Authors
Length
6360 lines
Declaration
View package declaration ›

Overview

This is the reference implementation of FIXED_GENERIC_PKG, published with IEEE Std 1076-2019. The body represents the formal semantics of the package per §16.10: implementers may compile it as-is or substitute a more efficient implementation, but the resulting behaviour shall not differ from the semantics defined here. The interface lives on the declaration page.

The body is large because the operators are implemented from first principles - bit-by-bit add/multiply, alignment of binary points across operand widths, and explicit rounding/overflow handling that obeys the package’s generic parameters. Use your browser’s find (Ctrl/Cmd+F) to locate a specific function within this listing.

VHDL source listing

ieee/fixed_generic_pkg-body.vhdl: package body (6360 lines)
License: Apache License 2.0 Download

Package preamble and local constants

NAUF NASF NSLV fixedsynth_or_real
-- -----------------------------------------------------------------
-- 
-- Copyright 2019 IEEE P1076 WG Authors
-- 
-- See the LICENSE file distributed with this work for copyright and
-- licensing information and the AUTHORS file.
-- 
-- This file to you under the Apache License, Version 2.0 (the "License").
-- You may obtain a copy of the License at
-- 
--     http://www.apache.org/licenses/LICENSE-2.0
-- 
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-- implied.  See the License for the specific language governing
-- permissions and limitations under the License.
--
--   Title     :  Fixed-point package (Generic package body)
--             :
--   Library   :  This package shall be compiled into a library
--             :  symbolically named IEEE.
--             :
--   Developers:  Accellera VHDL-TC and IEEE P1076 Working Group
--             :
--   Purpose   :  This packages defines basic binary fixed point arithmetic
--             :  arithmetic functions
--             :
--   Note      :  This package may be modified to include additional data
--             :  required by tools, but it must in no way change the
--             :  external interfaces or simulation behavior of the
--             :  description. It is permissible to add comments and/or
--             :  attributes to the package declarations, but not to change
--             :  or delete any original lines of the package declaration.
--             :  The package body may be changed only in accordance with
--             :  the terms of Clause 16 of this standard.
--             :
-- --------------------------------------------------------------------
-- $Revision: 1220 $
-- $Date: 2008-04-10 17:16:09 +0930 (Thu, 10 Apr 2008) $
-- --------------------------------------------------------------------

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 := true;

Local helper functions

mins mine cleanvec to_fixed to_uns to_s round_fixed to_ufixed
round_up
  -- 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
  begin  -- function cleanvec
    assert not (arg'ascending 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
  begin  -- function cleanvec
    assert not (arg'ascending 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 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 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_sulv(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_sulv(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;
        -- Sign bit not fixed when wrapping
      end if;
    end if;
    return result;
  end function round_fixed;

  -- converts an sfixed into a ufixed.  The output is the same length as the
  -- input, because abs("1000") = "1000" = 8.
  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;

Vector and explicit-bound conversion functions

to_sulv to_slv to_ufixed to_sfixed
-----------------------------------------------------------------------------
-- Visible functions
-----------------------------------------------------------------------------
  -- Conversion functions.  These are needed for synthesis where typically
  -- the only input and output type is a std_logic_vector.
  function to_sulv (
    arg : UNRESOLVED_ufixed)            -- fixed point vector
    return STD_ULOGIC_VECTOR
  is
    variable intermediate_result : UNRESOLVED_ufixed(arg'length-1 downto 0);
  begin
    if arg'length < 1 then
      return NSLV;
    end if;
    intermediate_result := arg;
    return STD_ULOGIC_VECTOR (intermediate_result);
  end function to_sulv;

  function to_sulv (
    arg : UNRESOLVED_sfixed)            -- fixed point vector
    return STD_ULOGIC_VECTOR
  is
    variable intermediate_result : UNRESOLVED_sfixed(arg'length-1 downto 0);
  begin
    if arg'length < 1 then
      return NSLV;
    end if;
    intermediate_result := arg;
    return STD_ULOGIC_VECTOR (intermediate_result);
  end function to_sulv;

  function to_slv (
    arg : UNRESOLVED_ufixed)            -- fixed point vector
    return STD_LOGIC_VECTOR is
  begin
    return to_sulv(arg);
  end function to_slv;

  function to_slv (
    arg : UNRESOLVED_sfixed)            -- fixed point vector
    return STD_LOGIC_VECTOR is
  begin
    return to_sulv(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 & "TO_UFIXED(SLV) "
        & "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 & "TO_SFIXED(SLV) "
        & "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;

Arithmetic operators and functions

"abs" "-" "+" "*" "/" divide reciprocal "rem" remainder "mod" modulo scalb Is_Negative
add_carry
  -- 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 ressns      : UNRESOLVED_SIGNED (arg'length downto 0);
    variable result      : UNRESOLVED_sfixed (left_index+1 downto right_index);
  begin
    if (arg'length < 1 or result'length < 1) then
      return NASF;
    end if;
    ressns (arg'length-1 downto 0) := to_s (cleanvec (arg));
    ressns (arg'length)            := ressns (arg'length-1);  -- expand sign bit
    result                         := to_fixed (abs(ressns), left_index+1, right_index);
    return result;
  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 ressns      : UNRESOLVED_SIGNED (arg'length downto 0);
    variable result      : UNRESOLVED_sfixed (left_index downto right_index);
  begin
    if (arg'length < 1 or result'length < 1) then
      return NASF;
    end if;
    ressns (arg'length-1 downto 0) := to_s (cleanvec(arg));
    ressns (arg'length)            := ressns (arg'length-1);  -- expand sign bit
    result                         := to_fixed (-ressns, left_index, right_index);
    return result;
  end function "-";

  -- Addition
  function "+" (
    l, r : UNRESOLVED_ufixed)    -- ufixed(a downto b) + ufixed(c downto d) =
    return UNRESOLVED_ufixed     -- ufixed(max(a,c)+1 downto min(b,d))
  is
    constant left_index       : INTEGER := maximum(l'high, r'high)+1;
    constant right_index      : INTEGER := mine(l'low, r'low);
    variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable result           : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
  begin
    if (l'length < 1 or r'length < 1 or result'length < 1) then
      return NAUF;
    end if;
    lresize    := resize (l, left_index, right_index);
    rresize    := resize (r, left_index, right_index);
    lslv       := to_uns (lresize);
    rslv       := to_uns (rresize);
    result_slv := lslv + rslv;
    result     := to_fixed(result_slv, left_index, right_index);
    return result;
  end function "+";

  function "+" (
    l, r : UNRESOLVED_sfixed)    -- sfixed(a downto b) + sfixed(c downto d) =
    return UNRESOLVED_sfixed     -- sfixed(max(a,c)+1 downto min(b,d))
  is
    constant left_index       : INTEGER := maximum(l'high, r'high)+1;
    constant right_index      : INTEGER := mine(l'low, r'low);
    variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable result           : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (left_index-right_index downto 0);
    variable result_slv       : UNRESOLVED_SIGNED (left_index-right_index downto 0);
  begin
    if (l'length < 1 or r'length < 1 or result'length < 1) then
      return NASF;
    end if;
    lresize    := resize (l, left_index, right_index);
    rresize    := resize (r, left_index, right_index);
    lslv       := to_s (lresize);
    rslv       := to_s (rresize);
    result_slv := lslv + rslv;
    result     := to_fixed(result_slv, left_index, right_index);
    return result;
  end function "+";

  -- Subtraction
  function "-" (
    l, r : UNRESOLVED_ufixed)    -- ufixed(a downto b) - ufixed(c downto d) =
    return UNRESOLVED_ufixed     -- ufixed(max(a,c)+1 downto min(b,d))
  is
    constant left_index       : INTEGER := maximum(l'high, r'high)+1;
    constant right_index      : INTEGER := mine(l'low, r'low);
    variable lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable result           : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
  begin
    if (l'length < 1 or r'length < 1 or result'length < 1) then
      return NAUF;
    end if;
    lresize    := resize (l, left_index, right_index);
    rresize    := resize (r, left_index, right_index);
    lslv       := to_uns (lresize);
    rslv       := to_uns (rresize);
    result_slv := lslv - rslv;
    result     := to_fixed(result_slv, left_index, right_index);
    return result;
  end function "-";

  function "-" (
    l, r : UNRESOLVED_sfixed)    -- sfixed(a downto b) - sfixed(c downto d) =
    return UNRESOLVED_sfixed     -- sfixed(max(a,c)+1 downto min(b,d))
  is
    constant left_index       : INTEGER := maximum(l'high, r'high)+1;
    constant right_index      : INTEGER := mine(l'low, r'low);
    variable lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable result           : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (left_index-right_index downto 0);
    variable result_slv       : UNRESOLVED_SIGNED (left_index-right_index downto 0);
  begin
    if (l'length < 1 or r'length < 1 or result'length < 1) then
      return NASF;
    end if;
    lresize    := resize (l, left_index, right_index);
    rresize    := resize (r, left_index, right_index);
    lslv       := to_s (lresize);
    rslv       := to_s (rresize);
    result_slv := lslv - rslv;
    result     := to_fixed(result_slv, left_index, right_index);
    return result;
  end function "-";

  function "*" (
    l, r : UNRESOLVED_ufixed)    -- ufixed(a downto b) * ufixed(c downto d) =
    return UNRESOLVED_ufixed     -- ufixed(a+c+1 downto b+d)
  is
    variable lslv       : UNRESOLVED_UNSIGNED (l'length-1 downto 0);
    variable rslv       : UNRESOLVED_UNSIGNED (r'length-1 downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (r'length+l'length-1 downto 0);
    variable result     : UNRESOLVED_ufixed (l'high + r'high+1 downto
                                             mine(l'low, l'low) + mine(r'low, r'low));
  begin
    if (l'length < 1 or r'length < 1 or
        result'length /= result_slv'length) then
      return NAUF;
    end if;
    lslv       := to_uns (cleanvec(l));
    rslv       := to_uns (cleanvec(r));
    result_slv := lslv * rslv;
    result     := to_fixed (result_slv, result'high, result'low);
    return result;
  end function "*";

  function "*" (
    l, r : UNRESOLVED_sfixed)    -- sfixed(a downto b) * sfixed(c downto d) =
    return UNRESOLVED_sfixed     -- sfixed(a+c+1 downto b+d)
  is
    variable lslv       : UNRESOLVED_SIGNED (l'length-1 downto 0);
    variable rslv       : UNRESOLVED_SIGNED (r'length-1 downto 0);
    variable result_slv : UNRESOLVED_SIGNED (r'length+l'length-1 downto 0);
    variable result     : UNRESOLVED_sfixed (l'high + r'high+1 downto
                                             mine(l'low, l'low) + mine(r'low, r'low));
  begin
    if (l'length < 1 or r'length < 1 or
        result'length /= result_slv'length) then
      return NASF;
    end if;
    lslv       := to_s (cleanvec(l));
    rslv       := to_s (cleanvec(r));
    result_slv := lslv * rslv;
    result     := to_fixed (result_slv, result'high, result'low);
    return result;
  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
    variable result     : UNRESOLVED_ufixed (l'high - mine(r'low, r'low) downto
                                         mine (l'low, l'low) - r'high -1);
    variable dresult    : UNRESOLVED_ufixed (result'high downto result'low -guard_bits);
    variable lresize    : UNRESOLVED_ufixed (l'high downto l'high - dresult'length+1);
    variable lslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
    variable rslv       : UNRESOLVED_UNSIGNED (r'length-1 downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (arg            => l,
                       left_index     => lresize'high,
                       right_index    => lresize'low,
                       overflow_style => fixed_wrap,   -- vector only grows
                       round_style    => fixed_truncate);
    lslv := to_uns (cleanvec (lresize));
    rslv := to_uns (cleanvec (r));
    if (rslv = 0) then
      report fixed_generic_pkg'instance_name
        & "DIVIDE(ufixed) Division by zero" severity error;
      result := saturate (result'high, result'low);    -- saturate
    else
      result_slv := lslv / rslv;
      dresult    := to_fixed (result_slv, dresult'high, dresult'low);
      result := resize (arg            => dresult,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => fixed_wrap,  -- overflow impossible
                        round_style    => round_style);
    end if;
    return result;
  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
    variable result     : UNRESOLVED_sfixed (l'high - mine(r'low, r'low) + 1 downto
                                             mine (l'low, l'low) - r'high);
    variable dresult    : UNRESOLVED_sfixed (result'high downto result'low-guard_bits);
    variable lresize    : UNRESOLVED_sfixed (l'high+1 downto l'high+1 -dresult'length+1);
    variable lslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
    variable rslv       : UNRESOLVED_SIGNED (r'length-1 downto 0);
    variable result_slv : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (arg            => l,
                       left_index     => lresize'high,
                       right_index    => lresize'low,
                       overflow_style => fixed_wrap,   -- vector only grows
                       round_style    => fixed_truncate);
    lslv := to_s (cleanvec (lresize));
    rslv := to_s (cleanvec (r));
    if (rslv = 0) then
      report fixed_generic_pkg'instance_name
        & "DIVIDE(sfixed) Division by zero" severity error;
      result := saturate (result'high, result'low);
    else
      result_slv := lslv / rslv;
      dresult    := to_fixed (result_slv, dresult'high, dresult'low);
      result := resize (arg            => dresult,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => fixed_wrap,  -- overflow impossible
                        round_style    => round_style);
    end if;
    return result;
  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
    variable result     : UNRESOLVED_ufixed (minimum(l'high, r'high) downto
                                             mine(l'low, r'low));
    variable lresize    : UNRESOLVED_ufixed (maximum(l'high, r'low) downto
                                             mins(r'low, r'low)-guard_bits);
    variable rresize    : UNRESOLVED_ufixed (r'high downto r'low-guard_bits);
    variable dresult    : UNRESOLVED_ufixed (rresize'range);
    variable lslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
    variable rslv       : UNRESOLVED_UNSIGNED (rresize'length-1 downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (rslv'range);
  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;
    lresize := resize (arg            => l,
                       left_index     => lresize'high,
                       right_index    => lresize'low,
                       overflow_style => fixed_wrap,     -- vector only grows
                       round_style    => fixed_truncate);
    lslv := to_uns (lresize);
    rresize := resize (arg            => r,
                       left_index     => rresize'high,
                       right_index    => rresize'low,
                       overflow_style => fixed_wrap,     -- vector only grows
                       round_style    => fixed_truncate);
    rslv := to_uns (rresize);
    if (rslv = 0) then
      report fixed_generic_pkg'instance_name
        & "remainder(ufixed) Division by zero" severity error;
      result := saturate (result'high, result'low);      -- saturate
    else
      if (r'low <= l'high) then
        result_slv := lslv rem rslv;
        dresult    := to_fixed (result_slv, dresult'high, dresult'low);
        result := resize (arg            => dresult,
                          left_index     => result'high,
                          right_index    => result'low,
                          overflow_style => fixed_wrap,  -- can't overflow
                          round_style    => round_style);
      end if;
      if l'low < r'low then
        result(mins(r'low-1, l'high) downto l'low) :=
          cleanvec(l(mins(r'low-1, l'high) downto l'low));
      end if;
    end if;
    return result;
  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
    variable l_abs      : UNRESOLVED_ufixed (l'range);
    variable r_abs      : UNRESOLVED_ufixed (r'range);
    variable result     : UNRESOLVED_sfixed (minimum(r'high, l'high) downto
                                             mine(r'low, l'low));
    variable neg_result : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto
                                             mins(r'low, l'low));
  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;
    l_abs := to_ufixed (l);
    r_abs := to_ufixed (r);
    result := UNRESOLVED_sfixed (remainder (
      l           => l_abs,
      r           => r_abs,
      round_style => round_style));
    neg_result := -result;
    if l(l'high) = '1' then
      result := neg_result(result'range);
    end if;
    return result;
  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
    variable l_abs : UNRESOLVED_ufixed (l'range);
    variable r_abs : UNRESOLVED_ufixed (r'range);
    variable result : UNRESOLVED_sfixed (r'high downto
                                         mine(r'low, l'low));
    variable dresult : UNRESOLVED_sfixed (minimum(r'high, l'high)+1 downto
                                          mins(r'low, l'low));
    variable dresult_not_zero : BOOLEAN;
  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;
    l_abs := to_ufixed (l);
    r_abs := to_ufixed (r);
    dresult := "0" & UNRESOLVED_sfixed(remainder (l           => l_abs,
                                                  r           => r_abs,
                                                  round_style => round_style));
    if (to_s(dresult) = 0) then
      dresult_not_zero := false;
    else
      dresult_not_zero := true;
    end if;
    if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0'
      and dresult_not_zero then
      result := resize (arg            => r - dresult,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => overflow_style,
                        round_style    => round_style);
    elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then
      result := resize (arg            => -dresult,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => overflow_style,
                        round_style    => round_style);
    elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1'
      and dresult_not_zero then
      result := resize (arg            => dresult + r,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => overflow_style,
                        round_style    => round_style);
    else
      result := resize (arg            => dresult,
                        left_index     => result'high,
                        right_index    => result'low,
                        overflow_style => overflow_style,
                        round_style    => round_style);
    end if;
    return result;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
    variable result_slv : UNRESOLVED_UNSIGNED (left_index-right_index
                                               downto 0);
    variable cx : UNRESOLVED_UNSIGNED (0 downto 0);  -- Carry in
  begin
    if (L'length < 1 or R'length < 1) then
      result := NAUF;
      c_out  := '0';
    else
      cx (0)     := c_in;
      lresize    := resize (L, left_index, right_index);
      rresize    := resize (R, left_index, right_index);
      lslv       := to_uns (lresize);
      rslv       := to_uns (rresize);
      result_slv := lslv + rslv + cx;
      c_out      := result_slv(left_index-right_index);
      result := to_fixed(result_slv (left_index-right_index-1 downto 0),
                         left_index-1, 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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv : UNRESOLVED_SIGNED (left_index-right_index
                                             downto 0);
    variable result_slv : UNRESOLVED_SIGNED (left_index-right_index
                                             downto 0);
    variable cx : UNRESOLVED_SIGNED (1 downto 0);  -- Carry in
  begin
    if (L'length < 1 or R'length < 1) then
      result := NASF;
      c_out  := '0';
    else
      cx (1)     := '0';
      cx (0)     := c_in;
      lresize    := resize (L, left_index, right_index);
      rresize    := resize (R, left_index, right_index);
      lslv       := to_s (lresize);
      rslv       := to_s (rresize);
      result_slv := lslv + rslv + cx;
      c_out      := result_slv(left_index-right_index);
      result := to_fixed(result_slv (left_index-right_index-1 downto 0),
                         left_index-1, 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 : UNRESOLVED_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 : UNRESOLVED_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;

Find leftmost and rightmost functions

find_rightmost find_leftmost
  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;

Shift and rotate operators and functions

"sll" "srl" "rol" "ror" "sla" "sra" SHIFT_LEFT SHIFT_RIGHT
  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 and reduction operators

"not" "and" "or" "nand" "nor" "xor" "xnor"

Vector logical operators

"not" "and" "or" "nand" "nor" "xor" "xnor"
  ----------------------------------------------------------------------------
  -- 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_sulv(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_sulv(L) and to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """and"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) or to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """or"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) nand to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """nand"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) nor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """nor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) xor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """xor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) xnor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """xnor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(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_sulv(L) and to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """and"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) or to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """or"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) nand to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """nand"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) nor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """nor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) xor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """xor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    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_sulv(L) xnor to_sulv(R);
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & """xnor"": Range error L'RANGE /= R'RANGE"
        severity warning;
      RESULT := (others => 'X');
    end if;
    return to_sfixed(RESULT, L'high, L'low);
  end function "xnor";

Scalar-vector mixed logical operators

"and" "or" "nand" "nor" "xor" "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 logical operators

"and" "nand" "or" "nor" "xor" "xnor"
  -- Reduction operators
  function "and" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return and to_sulv(l);
  end function "and";

  function "nand" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return nand to_sulv(l);
  end function "nand";

  function "or" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return or to_sulv(l);
  end function "or";

  function "nor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return nor to_sulv(l);
  end function "nor";

  function "xor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return xor to_sulv(l);
  end function "xor";

  function "xnor" (l : UNRESOLVED_ufixed) return STD_ULOGIC is
  begin
    return xnor to_sulv(l);
  end function "xnor";

  function "and" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return and to_sulv(l);
  end function "and";

  function "nand" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return nand to_sulv(l);
  end function "nand";

  function "or" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return or to_sulv(l);
  end function "or";

  function "nor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return nor to_sulv(l);
  end function "nor";

  function "xor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return xor to_sulv(l);
  end function "xor";

  function "xnor" (l : UNRESOLVED_sfixed) return STD_ULOGIC is
  begin
    return xnor to_sulv(l);
  end function "xnor";
  -- End reduction operators

Comparison, matching, and min/max functions

"?=" "?/=" "?>" "?>=" "?<" "?<=" std_match "=" "/=" ">" "<" ">=" "<=" maximum minimum

Matching relational and std_match

"?=" "?/=" "?>" "?>=" "?<" "?<=" std_match
  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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?= rslv;
    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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?/= rslv;
    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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?> rslv;
    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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?>= rslv;
    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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?< rslv;
    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 lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_uns (lresize);
      rslv    := to_uns (rresize);
      return lslv ?<= rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?= rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?/= rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?> rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?>= rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?< rslv;
    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 lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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);
      lslv    := to_s (lresize);
      rslv    := to_s (rresize);
      return lslv ?<= rslv;
    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_sulv(L), to_sulv(R));
    else
      assert no_warning
        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_sulv(L), to_sulv(R));
    else
      assert no_warning
        report fixed_generic_pkg'instance_name
        & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE"
        severity warning;
      return false;
    end if;
  end function std_match;

Boolean relational operators

"=" "/=" ">" "<" ">=" "<="
  -- 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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_uns (lresize);
    rslv    := to_uns (rresize);
    return lslv = rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_s (lresize);
    rslv    := to_s (rresize);
    return lslv = rslv;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_uns (lresize);
    rslv    := to_uns (rresize);
    return lslv /= rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_s (lresize);
    rslv    := to_s (rresize);
    return lslv /= rslv;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_uns (lresize);
    rslv    := to_uns (rresize);
    return lslv > rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_s (lresize);
    rslv    := to_s (rresize);
    return lslv > rslv;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_uns (lresize);
    rslv    := to_uns (rresize);
    return lslv < rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_s (lresize);
    rslv    := to_s (rresize);
    return lslv < rslv;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_uns (lresize);
    rslv    := to_uns (rresize);
    return lslv >= rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize := resize (l, left_index, right_index);
    rresize := resize (r, left_index, right_index);
    lslv    := to_s (lresize);
    rslv    := to_s (rresize);
    return lslv >= rslv;
  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 lresize, rresize : UNRESOLVED_ufixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_UNSIGNED (lresize'length-1 downto 0);
  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;
    lresize     := resize (l, left_index, right_index);
    rresize     := resize (r, left_index, right_index);
    lslv        := to_uns (lresize);
    rslv        := to_uns (rresize);
    return lslv <= rslv;
  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 lresize, rresize : UNRESOLVED_sfixed (left_index downto right_index);
    variable lslv, rslv       : UNRESOLVED_SIGNED (lresize'length-1 downto 0);
  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;
    lresize     := resize (l, left_index, right_index);
    rresize     := resize (r, left_index, right_index);
    lslv        := to_s (lresize);
    rslv        := to_s (rresize);
    return lslv <= rslv;
  end function "<=";

Minimum and maximum functions

maximum minimum
  -- 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);
    return to_fixed(maximum(to_uns(lresize), to_uns(rresize)),
                    left_index, right_index);
  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);
    return to_fixed(maximum(to_s(lresize), to_s(rresize)),
                    left_index, right_index);
  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);
    return to_fixed(minimum(to_uns(lresize), to_uns(rresize)),
                    left_index, right_index);
  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);
    return to_fixed(minimum(to_s(lresize), to_s(rresize)),
                    left_index, right_index);
  end function minimum;

Conversion and helper functions

to_ufixed to_sfixed ufixed_high ufixed_low sfixed_high sfixed_low saturate to_UFix to_SFix ufix_high ufix_low sfix_high sfix_low to_unsigned to_signed to_real to_integer

Conversion to ufixed and sfixed

to_ufixed to_sfixed
  function to_ufixed (
    arg                     : NATURAL;  -- integer
    constant left_index     : INTEGER;  -- left index (high index)
    constant right_index    : INTEGER                   := 0;  -- right index
    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 fw      : INTEGER := mins (right_index, right_index);  -- catch literals
    variable result  : UNRESOLVED_ufixed (left_index downto fw);
    variable sresult : UNRESOLVED_ufixed (left_index downto 0) :=
      (others => '0');  -- integer portion
    variable argx    : NATURAL;         -- internal version of arg
  begin
    if (result'length < 1) then
      return NAUF;
    end if;
    if arg /= 0 then
      argx := arg;
      for I in 0 to sresult'left loop
        if (argx mod 2) = 0 then
          sresult(I) := '0';
        else
          sresult(I) := '1';
        end if;
        argx := argx/2;
      end loop;
      if argx /= 0 then
        assert no_warning
          report fixed_generic_pkg'instance_name
          & "TO_UFIXED(NATURAL): vector truncated"
          severity warning;
        if overflow_style = fixed_saturate then
          return saturate (left_index, right_index);
        end if;
      end if;
      result := resize (arg            => sresult,
                        left_index     => left_index,
                        right_index    => right_index,
                        round_style    => round_style,
                        overflow_style => overflow_style);
    else
      result := (others => '0');
    end if;
    return result;
  end function to_ufixed;

  function to_sfixed (
    arg                     : INTEGER;  -- integer
    constant left_index     : INTEGER;  -- left index (high index)
    constant right_index    : INTEGER                   := 0;  -- right index
    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 fw      : INTEGER := mins (right_index, right_index);  -- catch literals
    variable result  : UNRESOLVED_sfixed (left_index downto fw);
    variable sresult : UNRESOLVED_sfixed (left_index downto 0) :=
      (others => '0');  -- integer portion
    variable argx    : INTEGER;         -- internal version of arg
    variable sign    : STD_ULOGIC;      -- sign of input
  begin
    if (result'length < 1) then         -- null range
      return NASF;
    end if;
    if arg /= 0 then
      if (arg < 0) then
        sign := '1';
        argx := -(arg + 1);
      else
        sign := '0';
        argx := arg;
      end if;
      for I in 0 to sresult'left loop
        if (argx mod 2) = 0 then
          sresult(I) := sign;
        else
          sresult(I) := not sign;
        end if;
        argx := argx/2;
      end loop;
      if argx /= 0 or left_index < 0 or sign /= sresult(sresult'left) then
        assert no_warning
          report fixed_generic_pkg'instance_name
          & "TO_SFIXED(INTEGER): vector truncated"
          severity warning;
        if overflow_style = fixed_saturate then                -- 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;
      end if;
      result := resize (arg            => sresult,
                        left_index     => left_index,
                        right_index    => right_index,
                        round_style    => round_style,
                        overflow_style => overflow_style);
    else
      result := (others => '0');
    end if;
    return result;
  end function to_sfixed;

  function to_ufixed (
    arg                     : REAL;     -- real
    constant left_index     : INTEGER;  -- left index (high index)
    constant right_index    : INTEGER;  -- right index
    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 := mins (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;
  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;
      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;  -- left index (high index)
    constant right_index    : INTEGER;  -- right index
    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 := mins (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;  -- left index (high index)
    constant right_index    : INTEGER                   := 0;  -- right index
    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;
    variable result   : UNRESOLVED_ufixed (left_index downto right_index);
  begin
    if arg'length < 1 or (left_index < right_index) 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_sfixed (
    arg                     : UNRESOLVED_SIGNED;               -- signed
    constant left_index     : INTEGER;  -- left index (high index)
    constant right_index    : INTEGER                   := 0;  -- right index
    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;
    variable result   : UNRESOLVED_sfixed (left_index downto right_index);
  begin
    if arg'length < 1 or (left_index < right_index) 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;

Bound calculation functions

ufixed_high ufixed_low sfixed_high sfixed_low
  -- 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;

Saturate functions

saturate
  -- 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;

DSP-style conversion and bound functions

to_UFix to_SFix ufix_high ufix_low sfix_high sfix_low
  -- 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 UNRESOLVED_ufixed
  is
    variable result : UNRESOLVED_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 UNRESOLVED_sfixed
  is
    variable result : UNRESOLVED_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;

Conversion to scalar types

to_unsigned to_signed to_real to_integer
  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 := To_X01(cleanvec(arg));
    if (Is_X(arg_int)) then
      assert no_warning
        report fixed_generic_pkg'instance_name
        & "TO_REAL (ufixed): 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 := to_X01(cleanvec(arg));
    if (Is_X(arg_int)) then
      assert no_warning
        report fixed_generic_pkg'instance_name
        & "TO_REAL (sfixed): 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 (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 (ufixed): 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;
    variable arg_s       : UNRESOLVED_SIGNED (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 (sfixed): 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;

Metavalue translation functions

to_01 Is_X To_X01 to_X01 To_X01Z to_X01Z To_UX01 to_UX01
  function to_01 (
    s             : UNRESOLVED_ufixed;              -- ufixed point input
    constant XMAP : STD_ULOGIC := '0')              -- Map x to
    return UNRESOLVED_ufixed
  is
  begin
    if (s'length < 1) then
      assert no_warning
        report fixed_generic_pkg'instance_name
        & "TO_01(ufixed): null detected, returning NULL"
        severity warning;
      return NAUF;
    end if;
    return to_fixed (to_01(to_uns(s), XMAP), s'high, s'low);
  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
  begin
    if (s'length < 1) then
      assert no_warning
        report fixed_generic_pkg'instance_name
        & "TO_01(sfixed): null detected, returning NULL"
        severity warning;
      return NASF;
    end if;
    return to_fixed (to_01(to_s(s), XMAP), s'high, s'low);
  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_sulv(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_sulv(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_sulv(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_sulv(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_sulv(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_sulv(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_sulv(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_sulv(arg)), arg'high, arg'low);
  end function to_UX01;

Resize functions

resize
  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_sulv(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_sulv(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_sulv(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_sulv(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_sulv(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 conversion and resize functions

to_ufixed to_sfixed 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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_ufixed (size_res'left downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NAUF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_sfixed (size_res'left downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NASF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_ufixed (size_res'left downto fw);
  begin
    if (result'length < 1) then
      return NAUF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_sfixed (size_res'left downto fw);
  begin
    if (result'length < 1) then
      return NASF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_ufixed (size_res'left downto fw);
  begin
    if (result'length < 1) then
      return NAUF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_sfixed (size_res'left downto fw);
  begin
    if (result'length < 1) then
      return NASF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_ufixed (size_res'left downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NAUF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_sfixed (size_res'left downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NASF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_ufixed (size_res'high downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NAUF;
    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
    constant fw     : INTEGER := mine (size_res'low, size_res'low);  -- catch literals
    variable result : UNRESOLVED_sfixed (size_res'high downto fw);
  begin
    if (result'length < 1 or arg'length < 1) then
      return NASF;
    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;

Arithmetic operators and functions with REAL and INTEGER

"+" "-" "*" "/" "rem" "mod"
  -- 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)              -- 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)              -- 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)              -- 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 "/";

  function "rem" (
    l : UNRESOLVED_ufixed;              -- fixed point input
    r : NATURAL)
    return UNRESOLVED_ufixed is
  begin
    return (l rem to_ufixed (r, l'high, 0));
  end function "rem";

  function "rem" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return (to_ufixed (l, r'high, 0) rem r);
  end function "rem";

  function "rem" (
    l : UNRESOLVED_sfixed;              -- fixed point input
    r : INTEGER)
    return UNRESOLVED_sfixed is
  begin
    return (l rem to_sfixed (r, l'high, 0));
  end function "rem";

  function "rem" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return UNRESOLVED_sfixed is
  begin
    return (to_sfixed (l, r'high, 0) rem r);
  end function "rem";

  function "mod" (
    l : UNRESOLVED_ufixed;              -- fixed point input
    r : NATURAL)
    return UNRESOLVED_ufixed is
  begin
    return (l mod to_ufixed (r, l'high, 0));
  end function "mod";

  function "mod" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return (to_ufixed (l, r'high, 0) mod r);
  end function "mod";

  function "mod" (
    l : UNRESOLVED_sfixed;              -- fixed point input
    r : INTEGER)
    return UNRESOLVED_sfixed is
  begin
    return (l mod to_sfixed (r, l'high, 0));
  end function "mod";

  function "mod" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return UNRESOLVED_sfixed is
  begin
    return (to_sfixed (l, r'high, 0) mod r);
  end function "mod";

Comparison, matching, and min/max functions with REAL and INTEGER

"=" "/=" ">=" "<=" ">" "<" "?=" "?/=" "?>=" "?<=" "?>" "?<" maximum minimum
  -- overloaded ufixed compare functions with integer
  function "=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l = to_ufixed (r, l'high, l'low));
  end function "=";

  function "/=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l /= to_ufixed (r, l'high, l'low));
  end function "/=";

  function ">=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l >= to_ufixed (r, l'high, l'low));
  end function ">=";

  function "<=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l <= to_ufixed (r, l'high, l'low));
  end function "<=";

  function ">" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l > to_ufixed (r, l'high, l'low));
  end function ">";

  function "<" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return BOOLEAN is
  begin
    return (l < to_ufixed (r, l'high, l'low));
  end function "<";

  function "?=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?= to_ufixed (r, l'high, l'low));
  end function "?=";

  function "?/=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?/= to_ufixed (r, l'high, l'low));
  end function "?/=";

  function "?>=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?>= to_ufixed (r, l'high, l'low));
  end function "?>=";

  function "?<=" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?<= to_ufixed (r, l'high, l'low));
  end function "?<=";

  function "?>" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?> to_ufixed (r, l'high, l'low));
  end function "?>";

  function "?<" (
    l : UNRESOLVED_ufixed;
    r : NATURAL)                        -- fixed point input
    return STD_ULOGIC is
  begin
    return (l ?< to_ufixed (r, l'high, l'low));
  end function "?<";

  function maximum (
    l : UNRESOLVED_ufixed;              -- fixed point input
    r : NATURAL)
    return UNRESOLVED_ufixed is
  begin
    return maximum (l, to_ufixed (r, l'high, l'low));
  end function maximum;

  function minimum (
    l : UNRESOLVED_ufixed;              -- fixed point input
    r : NATURAL)
    return UNRESOLVED_ufixed is
  begin
    return minimum (l, to_ufixed (r, l'high, l'low));
  end function minimum;

  -- NATURAL to ufixed
  function "=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) = r);
  end function "=";

  function "/=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) /= r);
  end function "/=";

  function ">=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) >= r);
  end function ">=";

  function "<=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) <= r);
  end function "<=";

  function ">" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) > r);
  end function ">";

  function "<" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) < r);
  end function "<";

  function "?=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?= r);
  end function "?=";

  function "?/=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?/= r);
  end function "?/=";

  function "?>=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?>= r);
  end function "?>=";

  function "?<=" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?<= r);
  end function "?<=";

  function "?>" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?> r);
  end function "?>";

  function "?<" (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?< r);
  end function "?<";

  function maximum (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return maximum (to_ufixed (l, r'high, r'low), r);
  end function maximum;

  function minimum (
    l : NATURAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return minimum (to_ufixed (l, r'high, r'low), r);
  end function minimum;

  -- overloaded ufixed compare functions with real
  function "=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l = to_ufixed (r, l'high, l'low));
  end function "=";

  function "/=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l /= to_ufixed (r, l'high, l'low));
  end function "/=";

  function ">=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l >= to_ufixed (r, l'high, l'low));
  end function ">=";

  function "<=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l <= to_ufixed (r, l'high, l'low));
  end function "<=";

  function ">" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l > to_ufixed (r, l'high, l'low));
  end function ">";

  function "<" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l < to_ufixed (r, l'high, l'low));
  end function "<";

  function "?=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?= to_ufixed (r, l'high, l'low));
  end function "?=";

  function "?/=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?/= to_ufixed (r, l'high, l'low));
  end function "?/=";

  function "?>=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?>= to_ufixed (r, l'high, l'low));
  end function "?>=";

  function "?<=" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?<= to_ufixed (r, l'high, l'low));
  end function "?<=";

  function "?>" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?> to_ufixed (r, l'high, l'low));
  end function "?>";

  function "?<" (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?< to_ufixed (r, l'high, l'low));
  end function "?<";

  function maximum (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return UNRESOLVED_ufixed is
  begin
    return maximum (l, to_ufixed (r, l'high, l'low));
  end function maximum;

  function minimum (
    l : UNRESOLVED_ufixed;
    r : REAL)
    return UNRESOLVED_ufixed is
  begin
    return minimum (l, to_ufixed (r, l'high, l'low));
  end function minimum;

  -- real and ufixed
  function "=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) = r);
  end function "=";

  function "/=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) /= r);
  end function "/=";

  function ">=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) >= r);
  end function ">=";

  function "<=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) <= r);
  end function "<=";

  function ">" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) > r);
  end function ">";

  function "<" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_ufixed (l, r'high, r'low) < r);
  end function "<";

  function "?=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?= r);
  end function "?=";

  function "?/=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?/= r);
  end function "?/=";

  function "?>=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?>= r);
  end function "?>=";

  function "?<=" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?<= r);
  end function "?<=";

  function "?>" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?> r);
  end function "?>";

  function "?<" (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_ufixed (l, r'high, r'low) ?< r);
  end function "?<";

  function maximum (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return maximum (to_ufixed (l, r'high, r'low), r);
  end function maximum;

  function minimum (
    l : REAL;
    r : UNRESOLVED_ufixed)              -- fixed point input
    return UNRESOLVED_ufixed is
  begin
    return minimum (to_ufixed (l, r'high, r'low), r);
  end function minimum;

  -- overloaded sfixed compare functions with integer
  function "=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l = to_sfixed (r, l'high, l'low));
  end function "=";

  function "/=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l /= to_sfixed (r, l'high, l'low));
  end function "/=";

  function ">=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l >= to_sfixed (r, l'high, l'low));
  end function ">=";

  function "<=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l <= to_sfixed (r, l'high, l'low));
  end function "<=";

  function ">" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l > to_sfixed (r, l'high, l'low));
  end function ">";

  function "<" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return BOOLEAN is
  begin
    return (l < to_sfixed (r, l'high, l'low));
  end function "<";

  function "?=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?= to_sfixed (r, l'high, l'low));
  end function "?=";

  function "?/=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?/= to_sfixed (r, l'high, l'low));
  end function "?/=";

  function "?>=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?>= to_sfixed (r, l'high, l'low));
  end function "?>=";

  function "?<=" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?<= to_sfixed (r, l'high, l'low));
  end function "?<=";

  function "?>" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?> to_sfixed (r, l'high, l'low));
  end function "?>";

  function "?<" (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return STD_ULOGIC is
  begin
    return (l ?< to_sfixed (r, l'high, l'low));
  end function "?<";

  function maximum (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return UNRESOLVED_sfixed is
  begin
    return maximum (l, to_sfixed (r, l'high, l'low));
  end function maximum;

  function minimum (
    l : UNRESOLVED_sfixed;
    r : INTEGER)
    return UNRESOLVED_sfixed is
  begin
    return minimum (l, to_sfixed (r, l'high, l'low));
  end function minimum;

  -- integer and sfixed
  function "=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) = r);
  end function "=";

  function "/=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) /= r);
  end function "/=";

  function ">=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) >= r);
  end function ">=";

  function "<=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) <= r);
  end function "<=";

  function ">" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) > r);
  end function ">";

  function "<" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) < r);
  end function "<";

  function "?=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?= r);
  end function "?=";

  function "?/=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?/= r);
  end function "?/=";

  function "?>=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?>= r);
  end function "?>=";

  function "?<=" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?<= r);
  end function "?<=";

  function "?>" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?> r);
  end function "?>";

  function "?<" (
    l : INTEGER;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?< r);
  end function "?<";

  function maximum (
    l : INTEGER;
    r : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return maximum (to_sfixed (l, r'high, r'low), r);
  end function maximum;

  function minimum (
    l : INTEGER;
    r : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return minimum (to_sfixed (l, r'high, r'low), r);
  end function minimum;

  -- overloaded sfixed compare functions with real
  function "=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l = to_sfixed (r, l'high, l'low));
  end function "=";

  function "/=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l /= to_sfixed (r, l'high, l'low));
  end function "/=";

  function ">=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l >= to_sfixed (r, l'high, l'low));
  end function ">=";

  function "<=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l <= to_sfixed (r, l'high, l'low));
  end function "<=";

  function ">" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l > to_sfixed (r, l'high, l'low));
  end function ">";

  function "<" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return BOOLEAN is
  begin
    return (l < to_sfixed (r, l'high, l'low));
  end function "<";

  function "?=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?= to_sfixed (r, l'high, l'low));
  end function "?=";

  function "?/=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?/= to_sfixed (r, l'high, l'low));
  end function "?/=";

  function "?>=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?>= to_sfixed (r, l'high, l'low));
  end function "?>=";

  function "?<=" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?<= to_sfixed (r, l'high, l'low));
  end function "?<=";

  function "?>" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?> to_sfixed (r, l'high, l'low));
  end function "?>";

  function "?<" (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return STD_ULOGIC is
  begin
    return (l ?< to_sfixed (r, l'high, l'low));
  end function "?<";

  function maximum (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return UNRESOLVED_sfixed is
  begin
    return maximum (l, to_sfixed (r, l'high, l'low));
  end function maximum;

  function minimum (
    l : UNRESOLVED_sfixed;
    r : REAL)
    return UNRESOLVED_sfixed is
  begin
    return minimum (l, to_sfixed (r, l'high, l'low));
  end function minimum;

  -- REAL and sfixed
  function "=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) = r);
  end function "=";

  function "/=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) /= r);
  end function "/=";

  function ">=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) >= r);
  end function ">=";

  function "<=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) <= r);
  end function "<=";

  function ">" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) > r);
  end function ">";

  function "<" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return BOOLEAN is
  begin
    return (to_sfixed (l, r'high, r'low) < r);
  end function "<";

  function "?=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?= r);
  end function "?=";

  function "?/=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?/= r);
  end function "?/=";

  function "?>=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?>= r);
  end function "?>=";

  function "?<=" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?<= r);
  end function "?<=";

  function "?>" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?> r);
  end function "?>";

  function "?<" (
    l : REAL;
    r : UNRESOLVED_sfixed)              -- fixed point input
    return STD_ULOGIC is
  begin
    return (to_sfixed (l, r'high, r'low) ?< r);
  end function "?<";

  function maximum (
    l : REAL;
    r : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return maximum (to_sfixed (l, r'high, r'low), r);
  end function maximum;

  function minimum (
    l : REAL;
    r : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return minimum (to_sfixed (l, r'high, r'low), r);
  end function minimum;

String conversion and text I/O functions

MVL9plus char_indexed_by_MVL9 MVL9_indexed_by_char MVL9plus_indexed_by_char
MVL9_to_char char_to_MVL9 char_to_MVL9plus NBSP NUS
TO_STRING TO_OSTRING TO_HSTRING from_string from_ostring from_hstring
skip_whitespace write READ owrite Char2TriBits OREAD_common OREAD hwrite Char2QuadBits HREAD_common HREAD calculate_string_boundry

Helper types and parsing utilities

MVL9plus char_indexed_by_MVL9 MVL9_indexed_by_char MVL9plus_indexed_by_char
MVL9_to_char char_to_MVL9 char_to_MVL9plus NBSP NUS
skip_whitespace
  -- copied from std_logic_textio
  type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error);
  type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER;
  type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC;
  type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus;

  constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-";
  constant char_to_MVL9 : MVL9_indexed_by_char :=
    ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
     'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');
  constant char_to_MVL9plus : MVL9plus_indexed_by_char :=
    ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
     'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error);
  constant NBSP : CHARACTER      := CHARACTER'val(160);  -- space character
  constant NUS  : STRING(2 to 1) := (others => ' ');

  -- purpose: Skips white space
  procedure skip_whitespace (
    L : inout LINE) is
    variable c : CHARACTER;
    variable left : positive;
  begin
    while L /= null and L.all'length /= 0 loop
      left := L.all'left;
      c := L.all(left);
      if (c = ' ' or c = NBSP or c = HT) then
        read (L, c);
      else
        exit;
      end if;
    end loop;
  end procedure skip_whitespace;

Binary text I/O procedures

write READ
  -- purpose: writes fixed point into a line
  procedure write (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_ufixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
    variable s     : STRING(1 to VALUE'length +1) := (others => ' ');
    variable sindx : INTEGER;
  begin  -- function write   Example: 0011.1100
    sindx := 1;
    for i in VALUE'high downto VALUE'low loop
      if i = -1 then
        s(sindx) := '.';
        sindx    := sindx + 1;
      end if;
      s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
      sindx    := sindx + 1;
    end loop;
    write(L, s, JUSTIFIED, FIELD);
  end procedure write;

  -- purpose: writes fixed point into a line
  procedure write (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_sfixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
    variable s     : STRING(1 to VALUE'length +1);
    variable sindx : INTEGER;
  begin  -- function write   Example: 0011.1100
    sindx := 1;
    for i in VALUE'high downto VALUE'low loop
      if i = -1 then
        s(sindx) := '.';
        sindx    := sindx + 1;
      end if;
      s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i)));
      sindx    := sindx + 1;
    end loop;
    write(L, s, JUSTIFIED, FIELD);
  end procedure write;

  procedure READ(L     : inout LINE;
                 VALUE : out   UNRESOLVED_ufixed) is
    -- Possible data:  00000.0000000
    --                 000000000000
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
    variable i      : INTEGER;          -- index variable
    variable mv : ufixed (VALUE'range);
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
    variable founddot : BOOLEAN := false;  -- found a "."
  begin  -- READ
    VALUE := (VALUE'range => 'U');
    skip_whitespace (L);
    if VALUE'length > 0 then            -- non Null input string
      read (L, c, readOk);
      i := VALUE'high;
      while i >= VALUE'low loop
        if readOk = false then              -- Bail out if there was a bad read
          report fixed_generic_pkg'instance_name & "READ(ufixed) "
            & "End of string encountered"
            severity error;
          return;
        elsif c = '_' then
          if i = VALUE'high then
            report fixed_generic_pkg'instance_name & "READ(ufixed) "
              & "String begins with an ""_""" severity error;
            return;
          elsif lastu then
            report fixed_generic_pkg'instance_name & "READ(ufixed) "
              & "Two underscores detected in input string ""__"""
              severity error;
            return;
          else
            lastu := true;
          end if;
        elsif c = '.' then                -- binary point
          if founddot then
            report fixed_generic_pkg'instance_name & "READ(ufixed) "
              & "Two binary points found in input string" severity error;
            return;
          elsif i /= -1 then                 -- Seperator in the wrong spot
            report fixed_generic_pkg'instance_name & "READ(ufixed) "
              & "Decimal point does not match number format "
              severity error;
            return;
          end if;
          founddot := true;
          lastu := false;
        elsif c = ' ' or c = NBSP or c = HT then  -- reading done.
          report fixed_generic_pkg'instance_name & "READ(ufixed) "
            & "Short read, Space encounted in input string"
            severity error;
          return;
        elsif char_to_MVL9plus(c) = error then
          report fixed_generic_pkg'instance_name & "READ(ufixed) "
            & "Character '" &
            c & "' read, expected STD_ULOGIC literal."
            severity error;
          return;
        else
          mv(i) := char_to_MVL9(c);
          i := i - 1;
          if i < mv'low then
            VALUE := mv;
            return;
          end if;
          lastu := false;
        end if;
        read(L, c, readOk);
      end loop;
    end if;
  end procedure READ;

  procedure READ(L     : inout LINE;
                 VALUE : out   UNRESOLVED_ufixed;
                 GOOD  : out   BOOLEAN) is
    -- Possible data:  00000.0000000
    --                 000000000000
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
    variable mv : ufixed (VALUE'range);
    variable i      : INTEGER;          -- index variable
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
    variable founddot : BOOLEAN := false;  -- found a "."
  begin  -- READ
    VALUE := (VALUE'range => 'U');
    skip_whitespace (L);
    if VALUE'length > 0 then
      read (L, c, readOk);
      i := VALUE'high;
      GOOD := false;
      while i >= VALUE'low loop
        if not readOk then     -- Bail out if there was a bad read
          return;
        elsif c = '_' then
          if i = VALUE'high then          -- Begins with an "_"
            return;
          elsif lastu then               -- "__" detected
            return;
          else
            lastu := true;
          end if;
        elsif c = '.' then                -- binary point
          if founddot then
            return;
          elsif i /= -1 then                 -- Seperator in the wrong spot
            return;
          end if;
          founddot := true;
          lastu := false;
        elsif (char_to_MVL9plus(c) = error) then   -- Illegal character/short read
          return;
        else
          mv(i) := char_to_MVL9(c);
          i := i - 1;
          if i < mv'low then             -- reading done
            GOOD := true;
            VALUE := mv;
            return;
          end if;
          lastu := false;
        end if;
        read(L, c, readOk);
      end loop;
    else
      GOOD := true;                   -- read into a null array
    end if;
  end procedure READ;

  procedure READ(L     : inout LINE;
                 VALUE : out   UNRESOLVED_sfixed) is
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
    variable i      : INTEGER;          -- index variable
    variable mv : sfixed (VALUE'range);
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
    variable founddot : BOOLEAN := false;  -- found a "."
  begin  -- READ
    VALUE := (VALUE'range => 'U');
    skip_whitespace (L);
    if VALUE'length > 0 then            -- non Null input string
      read (L, c, readOk);
      i := VALUE'high;
      while i >= VALUE'low loop
        if readOk = false then              -- Bail out if there was a bad read
          report fixed_generic_pkg'instance_name & "READ(sfixed) "
            & "End of string encountered"
            severity error;
          return;
        elsif c = '_' then
          if i = VALUE'high then
            report fixed_generic_pkg'instance_name & "READ(sfixed) "
              & "String begins with an ""_""" severity error;
            return;
          elsif lastu then
            report fixed_generic_pkg'instance_name & "READ(sfixed) "
              & "Two underscores detected in input string ""__"""
              severity error;
            return;
          else
            lastu := true;
          end if;
        elsif c = '.' then                -- binary point
          if founddot then
            report fixed_generic_pkg'instance_name & "READ(sfixed) "
              & "Two binary points found in input string" severity error;
            return;
          elsif i /= -1 then                 -- Seperator in the wrong spot
            report fixed_generic_pkg'instance_name & "READ(sfixed) "
              & "Decimal point does not match number format "
              severity error;
            return;
          end if;
          founddot := true;
          lastu := false;
        elsif c = ' ' or c = NBSP or c = HT then  -- reading done.
          report fixed_generic_pkg'instance_name & "READ(sfixed) "
            & "Short read, Space encounted in input string"
            severity error;
          return;
        elsif char_to_MVL9plus(c) = error then
          report fixed_generic_pkg'instance_name & "READ(sfixed) "
            & "Character '" &
            c & "' read, expected STD_ULOGIC literal."
            severity error;
          return;
        else
          mv(i) := char_to_MVL9(c);
          i := i - 1;
          if i < mv'low then
            VALUE := mv;
            return;
          end if;
          lastu := false;
        end if;
        read(L, c, readOk);
      end loop;
    end if;
  end procedure READ;

  procedure READ(L     : inout LINE;
                 VALUE : out   UNRESOLVED_sfixed;
                 GOOD  : out   BOOLEAN) is
    variable value_ufixed : UNRESOLVED_ufixed (VALUE'range);
  begin  -- READ
    READ (L => L, VALUE => value_ufixed, GOOD => GOOD);
    VALUE := UNRESOLVED_sfixed (value_ufixed);
  end procedure READ;

Octal text I/O procedures

owrite Char2TriBits OREAD_common OREAD
  -- octal read and write
  procedure owrite (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_ufixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
  begin  -- Example 03.30
    write (L         => L,
           VALUE     => TO_OSTRING (VALUE),
           JUSTIFIED => JUSTIFIED,
           FIELD     => FIELD);
  end procedure owrite;

  procedure owrite (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_sfixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
  begin  -- Example 03.30
    write (L         => L,
           VALUE     => TO_OSTRING (VALUE),
           JUSTIFIED => JUSTIFIED,
           FIELD     => FIELD);
  end procedure owrite;

  -- Note that for Octal and Hex read, you can not start with a ".",
  -- the read is for numbers formatted "A.BC".  These routines go to
  -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3).
  procedure Char2TriBits (C           :     CHARACTER;
                          RESULT      : out STD_ULOGIC_VECTOR(2 downto 0);
                          GOOD        : out BOOLEAN;
                          ISSUE_ERROR : in  BOOLEAN) is
  begin
    case C is
      when '0' => RESULT := o"0"; GOOD := true;
      when '1' => RESULT := o"1"; GOOD := true;
      when '2' => RESULT := o"2"; GOOD := true;
      when '3' => RESULT := o"3"; GOOD := true;
      when '4' => RESULT := o"4"; GOOD := true;
      when '5' => RESULT := o"5"; GOOD := true;
      when '6' => RESULT := o"6"; GOOD := true;
      when '7' => RESULT := o"7"; GOOD := true;
      when 'Z' => RESULT := "ZZZ"; GOOD := true;
      when 'X' => RESULT := "XXX"; GOOD := true;
      when others =>
        assert not ISSUE_ERROR
          report fixed_generic_pkg'instance_name
          & "OREAD Error: Read a '" & C &
          "', expected an Octal character (0-7)."
          severity error;
        RESULT := "UUU";
        GOOD   := false;
    end case;
  end procedure Char2TriBits;

  -- purpose: Routines common to the OREAD routines
  procedure OREAD_common (
    L                : inout LINE;
    slv              : out   STD_ULOGIC_VECTOR;
    igood            : out   BOOLEAN;
    idex             : out INTEGER;
    constant bpoint : in INTEGER;       -- binary point
    constant message : in    BOOLEAN;
    constant smath   : in    BOOLEAN) is

    -- purpose: error message routine
    procedure errmes (
      constant mess : in STRING) is     -- error message
    begin
      if message then
        if smath then
          report fixed_generic_pkg'instance_name
            & "OREAD(sfixed) "
            & mess
            severity error;
        else
          report fixed_generic_pkg'instance_name
            & "OREAD(ufixed) "
            & mess
            severity error;
        end if;
      end if;
    end procedure errmes;
    variable xgood : BOOLEAN;
    variable nybble : STD_ULOGIC_VECTOR (2 downto 0);        -- 3 bits
    variable c : CHARACTER;
    variable i : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
    variable founddot : BOOLEAN := false;  -- found a dot.
  begin
    skip_whitespace (L);
    if slv'length > 0 then
      i := slv'high;
      read (L, c, xgood);
      while i > 0 loop
        if xgood = false then
          errmes ("Error: end of string encountered");
          exit;
        elsif c = '_' then
          if i = slv'length then
            errmes ("Error: String begins with an ""_""");
            xgood := false;
            exit;
          elsif lastu then
            errmes ("Error: Two underscores detected in input string ""__""");
            xgood := false;
            exit;
          else
            lastu := true;
          end if;
        elsif (c = '.') then
          if (i + 1 /= bpoint) then
            errmes ("encountered ""."" at wrong index");
            xgood := false;
            exit;
          elsif i = slv'length then
            errmes ("encounted a ""."" at the beginning of the line");
            xgood := false;
            exit;
          elsif founddot then
            errmes ("Two ""."" encounted in input string");
            xgood := false;
            exit;
          end if;
          founddot := true;
          lastu := false;
        else
          Char2TriBits(c, nybble, xgood, message);
          if not xgood then
            exit;
          end if;
          slv (i downto i-2) := nybble;
          i := i - 3;
          lastu := false;
        end if;
        if i > 0 then
          read (L, c, xgood);
        end if;
      end loop;
      idex := i;
      igood := xgood;
    else
      igood := true;                  -- read into a null array
      idex := -1;
    end if;
  end procedure OREAD_common;

  -- Note that for Octal and Hex read, you can not start with a ".",
  -- the read is for numbers formatted "A.BC".  These routines go to
  -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3).
  procedure OREAD (L     : inout LINE;
                   VALUE : out   UNRESOLVED_ufixed) is
    constant hbv    : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-2)/3)*3;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_ufixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    OREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => true,
                   smath => false);
    if igood then                       -- We did not get another error
      if not ((i = -1) and               -- We read everything, and high bits 0
              (or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
        report fixed_generic_pkg'instance_name
          & "OREAD(ufixed): Vector truncated."
          severity error;
      else
        if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
          assert no_warning
            report fixed_generic_pkg'instance_name
            & "OREAD(ufixed): Vector truncated"
            severity warning;
        end if;
        valuex := to_ufixed (slv, hbv, lbv);
        VALUE  := valuex (VALUE'range);
      end if;
    end if;
  end procedure OREAD;

  procedure OREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_ufixed;
                  GOOD  : out   BOOLEAN) is
    constant hbv    : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-2)/3)*3;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_ufixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    OREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => false,
                   smath => false);
    if (igood and                   -- We did not get another error
        (i = -1) and                -- We read everything, and high bits 0
        (or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
      valuex := to_ufixed (slv, hbv, lbv);
      VALUE  := valuex (VALUE'range);
      GOOD := true;
    else
      GOOD := false;
    end if;
  end procedure OREAD;

  procedure OREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_sfixed) is
    constant hbv    : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-2)/3)*3;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_sfixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    OREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => true,
                   smath => true);
    if igood then                       -- We did not get another error
      if not ((i = -1) and               -- We read everything
              ((slv(VALUE'high-lbv) = '0' and      -- sign bits = extra bits
                or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
               (slv(VALUE'high-lbv) = '1' and
                and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
        report fixed_generic_pkg'instance_name
          & "OREAD(sfixed): Vector truncated."
          severity error;
      else
        if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
          assert no_warning
            report fixed_generic_pkg'instance_name
            & "OREAD(sfixed): Vector truncated"
            severity warning;
        end if;
        valuex := to_sfixed (slv, hbv, lbv);
        VALUE  := valuex (VALUE'range);
      end if;
    end if;
  end procedure OREAD;

  procedure OREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_sfixed;
                  GOOD  : out   BOOLEAN) is
    constant hbv    : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-2)/3)*3;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_sfixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    OREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => false,
                   smath => true);
    if (igood                       -- We did not get another error
        and (i = -1)                -- We read everything
        and ((slv(VALUE'high-lbv) = '0' and  -- sign bits = extra bits
              or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
             (slv(VALUE'high-lbv) = '1' and
              and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
      valuex := to_sfixed (slv, hbv, lbv);
      VALUE  := valuex (VALUE'range);
      GOOD := true;
    else
      GOOD := false;
    end if;
  end procedure OREAD;

Hexadecimal text I/O procedures

hwrite Char2QuadBits HREAD_common HREAD
  -- hex read and write
  procedure hwrite (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_ufixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
  begin  -- Example 03.30
    write (L         => L,
           VALUE     => TO_HSTRING (VALUE),
           JUSTIFIED => JUSTIFIED,
           FIELD     => FIELD);
  end procedure hwrite;

  -- purpose: writes fixed point into a line
  procedure hwrite (
    L         : inout LINE;               -- input line
    VALUE     : in    UNRESOLVED_sfixed;  -- fixed point input
    JUSTIFIED : in    SIDE  := right;
    FIELD     : in    WIDTH := 0) is
  begin  -- Example 03.30
    write (L         => L,
           VALUE     => TO_HSTRING (VALUE),
           JUSTIFIED => JUSTIFIED,
           FIELD     => FIELD);
  end procedure hwrite;

  -- Hex Read and Write procedures for STD_ULOGIC_VECTOR.
  -- Modified from the original to be more forgiving.

  procedure Char2QuadBits (C           :     CHARACTER;
                           RESULT      : out STD_ULOGIC_VECTOR(3 downto 0);
                           GOOD        : out BOOLEAN;
                           ISSUE_ERROR : in  BOOLEAN) is
  begin
    case C is
      when '0'       => RESULT := x"0"; GOOD := true;
      when '1'       => RESULT := x"1"; GOOD := true;
      when '2'       => RESULT := x"2"; GOOD := true;
      when '3'       => RESULT := x"3"; GOOD := true;
      when '4'       => RESULT := x"4"; GOOD := true;
      when '5'       => RESULT := x"5"; GOOD := true;
      when '6'       => RESULT := x"6"; GOOD := true;
      when '7'       => RESULT := x"7"; GOOD := true;
      when '8'       => RESULT := x"8"; GOOD := true;
      when '9'       => RESULT := x"9"; GOOD := true;
      when 'A' | 'a' => RESULT := x"A"; GOOD := true;
      when 'B' | 'b' => RESULT := x"B"; GOOD := true;
      when 'C' | 'c' => RESULT := x"C"; GOOD := true;
      when 'D' | 'd' => RESULT := x"D"; GOOD := true;
      when 'E' | 'e' => RESULT := x"E"; GOOD := true;
      when 'F' | 'f' => RESULT := x"F"; GOOD := true;
      when 'Z'       => RESULT := "ZZZZ"; GOOD := true;
      when 'X'       => RESULT := "XXXX"; GOOD := true;
      when others =>
        assert not ISSUE_ERROR
          report fixed_generic_pkg'instance_name
          & "HREAD Error: Read a '" & C &
          "', expected a Hex character (0-F)."
          severity error;
        RESULT := "UUUU";
        GOOD   := false;
    end case;
  end procedure Char2QuadBits;

  -- purpose: Routines common to the HREAD routines
  procedure HREAD_common (
    L                : inout LINE;
    slv              : out   STD_ULOGIC_VECTOR;
    igood            : out   BOOLEAN;
    idex             : out INTEGER;
    constant bpoint : in INTEGER;       -- binary point
    constant message : in    BOOLEAN;
    constant smath   : in    BOOLEAN) is

    -- purpose: error message routine
    procedure errmes (
      constant mess : in STRING) is     -- error message
    begin
      if message then
        if smath then
          report fixed_generic_pkg'instance_name
            & "HREAD(sfixed) "
            & mess
            severity error;
        else
          report fixed_generic_pkg'instance_name
            & "HREAD(ufixed) "
            & mess
            severity error;
        end if;
      end if;
    end procedure errmes;
    variable xgood  : BOOLEAN;
    variable nybble : STD_ULOGIC_VECTOR (3 downto 0);        -- 4 bits
    variable c      : CHARACTER;
    variable i      : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
    variable founddot : BOOLEAN := false;  -- found a dot.
  begin
    skip_whitespace (L);
    if slv'length > 0 then
      i := slv'high;
      read (L, c, xgood);
      while i > 0 loop
        if xgood = false then
          errmes ("Error: end of string encountered");
          exit;
        elsif c = '_' then
          if i = slv'length then
            errmes ("Error: String begins with an ""_""");
            xgood := false;
            exit;
          elsif lastu then
            errmes ("Error: Two underscores detected in input string ""__""");
            xgood := false;
            exit;
          else
            lastu := true;
          end if;
        elsif (c = '.') then
          if (i + 1 /= bpoint) then
            errmes ("encountered ""."" at wrong index");
            xgood := false;
            exit;
          elsif i = slv'length then
            errmes ("encounted a ""."" at the beginning of the line");
            xgood := false;
            exit;
          elsif founddot then
            errmes ("Two ""."" encounted in input string");
            xgood := false;
            exit;
          end if;
          founddot := true;
          lastu := false;
        else
          Char2QuadBits(c, nybble, xgood, message);
          if not xgood then
            exit;
          end if;
          slv (i downto i-3) := nybble;
          i := i - 4;
          lastu := false;
        end if;
        if i > 0 then
          read (L, c, xgood);
        end if;
      end loop;
      idex := i;
      igood := xgood;
    else
      idex := -1;
      igood := true;                    -- read null string
    end if;
  end procedure HREAD_common;

  procedure HREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_ufixed) is
    constant hbv    : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-3)/4)*4;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_ufixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    HREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => true,
                   smath => false);
    if igood then
      if not ((i = -1) and               -- We read everything, and high bits 0
              (or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
        report fixed_generic_pkg'instance_name
          & "HREAD(ufixed): Vector truncated."
          severity error;
      else
        if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
          assert no_warning
            report fixed_generic_pkg'instance_name
            & "HREAD(ufixed): Vector truncated"
            severity warning;
        end if;
        valuex := to_ufixed (slv, hbv, lbv);
        VALUE  := valuex (VALUE'range);
      end if;
    end if;
  end procedure HREAD;

  procedure HREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_ufixed;
                  GOOD  : out   BOOLEAN) is
    constant hbv    : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-3)/4)*4;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_ufixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    HREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => false,
                   smath => false);
    if (igood and                   -- We did not get another error
        (i = -1) and                -- We read everything, and high bits 0
        (or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0')) then
      valuex := to_ufixed (slv, hbv, lbv);
      VALUE  := valuex (VALUE'range);
      GOOD := true;
    else
      GOOD := false;
    end if;
  end procedure HREAD;

  procedure HREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_sfixed) is
    constant hbv    : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-3)/4)*4;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_sfixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    HREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => true,
                   smath => true);
    if igood then                       -- We did not get another error
      if not ((i = -1)                   -- We read everything
              and ((slv(VALUE'high-lbv) = '0' and  -- sign bits = extra bits
                    or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
                   (slv(VALUE'high-lbv) = '1' and
                    and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
        report fixed_generic_pkg'instance_name
          & "HREAD(sfixed): Vector truncated."
          severity error;
      else
        if (or (slv(VALUE'low-lbv-1 downto 0)) = '1') then
          assert no_warning
            report fixed_generic_pkg'instance_name
            & "HREAD(sfixed): Vector truncated"
            severity warning;
        end if;
        valuex := to_sfixed (slv, hbv, lbv);
        VALUE  := valuex (VALUE'range);
      end if;
    end if;
  end procedure HREAD;

  procedure HREAD(L     : inout LINE;
                  VALUE : out   UNRESOLVED_sfixed;
                  GOOD  : out   BOOLEAN) is
    constant hbv    : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1;
    constant lbv    : INTEGER := ((mine(0, VALUE'low)-3)/4)*4;
    variable slv    : STD_ULOGIC_VECTOR (hbv-lbv downto 0);  -- high bits
    variable valuex : UNRESOLVED_sfixed (hbv downto lbv);
    variable igood  : BOOLEAN;
    variable i      : INTEGER;
  begin
    VALUE := (VALUE'range => 'U');
    HREAD_common ( L => L,
                   slv => slv,
                   igood => igood,
                   idex => i,
                   bpoint => -lbv,
                   message => false,
                   smath => true);
    if (igood and                   -- We did not get another error
        (i = -1) and                -- We read everything
        ((slv(VALUE'high-lbv) = '0' and  -- sign bits = extra bits
          or (slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or
         (slv(VALUE'high-lbv) = '1' and
          and (slv(hbv-lbv downto VALUE'high+1-lbv)) = '1'))) then
      valuex := to_sfixed (slv, hbv, lbv);
      VALUE  := valuex (VALUE'range);
      GOOD := true;
    else
      GOOD := false;
    end if;
  end procedure HREAD;

Conversion to string functions

TO_STRING TO_OSTRING TO_HSTRING
  -- TO_STRING functions.  Useful in "report" statements.
  -- Example:  report "result was " & TO_STRING(result);
  function TO_STRING (value : UNRESOLVED_ufixed) return STRING is
    variable s     : STRING(1 to value'length +1) := (others => ' ');
    variable subval : UNRESOLVED_ufixed (value'high downto -1);
    variable sindx : INTEGER;
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        if value(value'high) = 'Z' then
          return TO_STRING (resize (sfixed(value), 0, value'low));
        else
          return TO_STRING (resize (value, 0, value'low));
        end if;
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_STRING(subval);
        else
          return TO_STRING (resize (value, value'high, -1));
        end if;
      else
        sindx := 1;
        for i in value'high downto value'low loop
          if i = -1 then
            s(sindx) := '.';
            sindx    := sindx + 1;
          end if;
          s(sindx) := MVL9_to_char(STD_ULOGIC(value(i)));
          sindx    := sindx + 1;
        end loop;
        return s;
      end if;
    end if;
  end function TO_STRING;

  function TO_STRING (value : UNRESOLVED_sfixed) return STRING is
    variable s     : STRING(1 to value'length + 1) := (others => ' ');
    variable subval : UNRESOLVED_sfixed (value'high downto -1);
    variable sindx : INTEGER;
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        return TO_STRING (resize (value, 0, value'low));
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_STRING(subval);
        else
          return TO_STRING (resize (value, value'high, -1));
        end if;
      else
        sindx := 1;
        for i in value'high downto value'low loop
          if i = -1 then
            s(sindx) := '.';
            sindx    := sindx + 1;
          end if;
          s(sindx) := MVL9_to_char(STD_ULOGIC(value(i)));
          sindx    := sindx + 1;
        end loop;
        return s;
      end if;
    end if;
  end function TO_STRING;

  function TO_OSTRING (value : UNRESOLVED_ufixed) return STRING is
    constant lne  : INTEGER := (-value'low+2)/3;
    variable subval : UNRESOLVED_ufixed (value'high downto -3);
    variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + value'low) -1);
    variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        if value(value'high) = 'Z' then
          return TO_OSTRING (resize (sfixed(value), 2, value'low));
        else
          return TO_OSTRING (resize (value, 2, value'low));
        end if;
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_OSTRING(subval);
        else
          return TO_OSTRING (resize (value, value'high, -3));
        end if;
      else
        slv := to_sulv (value);
        if Is_X (value (value'low)) then
          lpad := (others => value (value'low));
        else
          lpad := (others => '0');
        end if;
        return TO_OSTRING(slv(slv'high downto slv'high-value'high))
          & "."
          & TO_OSTRING(slv(slv'high-value'high-1 downto 0) & lpad);
      end if;
    end if;
  end function TO_OSTRING;

  function TO_HSTRING (value : UNRESOLVED_ufixed) return STRING is
    constant lne  : INTEGER := (-value'low+3)/4;
    variable subval : UNRESOLVED_ufixed (value'high downto -4);
    variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + value'low) -1);
    variable slv : STD_ULOGIC_VECTOR (value'length-1 downto 0);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        if value(value'high) = 'Z' then
          return TO_HSTRING (resize (sfixed(value), 3, value'low));
        else
          return TO_HSTRING (resize (value, 3, value'low));
        end if;
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_HSTRING(subval);
        else
          return TO_HSTRING (resize (value, value'high, -4));
        end if;
      else
        slv := to_sulv (value);
        if Is_X (value (value'low)) then
          lpad := (others => value(value'low));
        else
          lpad := (others => '0');
        end if;
        return TO_HSTRING(slv(slv'high downto slv'high-value'high))
          & "."
          & TO_HSTRING(slv(slv'high-value'high-1 downto 0)&lpad);
      end if;
    end if;
  end function TO_HSTRING;

  function TO_OSTRING (value : UNRESOLVED_sfixed) return STRING is
    constant ne   : INTEGER := ((value'high+1)+2)/3;
    variable pad  : STD_ULOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1);
    constant lne  : INTEGER := (-value'low+2)/3;
    variable subval : UNRESOLVED_sfixed (value'high downto -3);
    variable lpad : STD_ULOGIC_VECTOR (0 to (lne*3 + value'low) -1);
    variable slv  : STD_ULOGIC_VECTOR (value'high - value'low downto 0);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        return TO_OSTRING (resize (value, 2, value'low));
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_OSTRING(subval);
        else
          return TO_OSTRING (resize (value, value'high, -3));
        end if;
      else
        pad := (others => value(value'high));
        slv := to_sulv (value);
        if Is_X (value (value'low)) then
          lpad := (others => value(value'low));
        else
          lpad := (others => '0');
        end if;
        return TO_OSTRING(pad & slv(slv'high downto slv'high-value'high))
          & "."
          & TO_OSTRING(slv(slv'high-value'high-1 downto 0) & lpad);
      end if;
    end if;
  end function TO_OSTRING;

  function TO_HSTRING (value : UNRESOLVED_sfixed) return STRING is
    constant ne   : INTEGER := ((value'high+1)+3)/4;
    variable pad  : STD_ULOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1);
    constant lne  : INTEGER := (-value'low+3)/4;
    variable subval : UNRESOLVED_sfixed (value'high downto -4);
    variable lpad : STD_ULOGIC_VECTOR (0 to (lne*4 + value'low) -1);
    variable slv  : STD_ULOGIC_VECTOR (value'length-1 downto 0);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value'high < 0 then
        return TO_HSTRING (resize (value, 3, value'low));
      elsif value'low >= 0 then
        if Is_X (value(value'low)) then
          subval := (others => value(value'low));
          subval (value'range) := value;
          return TO_HSTRING(subval);
        else
          return TO_HSTRING (resize (value, value'high, -4));
        end if;
      else
        slv := to_sulv (value);
        pad := (others => value(value'high));
        if Is_X (value (value'low)) then
          lpad := (others => value(value'low));
        else
          lpad := (others => '0');
        end if;
        return TO_HSTRING(pad & slv(slv'high downto slv'high-value'high))
          & "."
          & TO_HSTRING(slv(slv'high-value'high-1 downto 0) & lpad);
      end if;
    end if;
  end function TO_HSTRING;

Conversion from string with explicit bounds

from_string from_ostring from_hstring
  -- From string functions allow you to convert a string into a fixed
  -- point number.  Example:
  --  signal uf1 : ufixed (3 downto -3);
  --  uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5
  -- The "." is optional in this syntax, however it exist and is
  -- in the wrong location an error is produced.  Overflow will
  -- result in saturation.
  function from_string (
    bstring              : STRING;      -- binary string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_ufixed
  is
    variable result : UNRESOLVED_ufixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(bstring);
    READ (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_string: Bad string "& bstring severity error;
    return result;
  end function from_string;

  -- Octal and hex conversions work as follows:
  -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped)
  -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped)
  function from_ostring (
    ostring              : STRING;      -- Octal string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_ufixed
  is
    variable result : UNRESOLVED_ufixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(ostring);
    OREAD (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_ostring: Bad string "& ostring severity error;
    return result;
  end function from_ostring;

  function from_hstring (
    hstring              : STRING;      -- hex string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_ufixed
  is
    variable result : UNRESOLVED_ufixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(hstring);
    HREAD (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_hstring: Bad string "& hstring severity error;
    return result;
  end function from_hstring;

  function from_string (
    bstring              : STRING;      -- binary string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_sfixed
  is
    variable result : UNRESOLVED_sfixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(bstring);
    READ (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_string: Bad string "& bstring severity error;
    return result;
  end function from_string;

  function from_ostring (
    ostring              : STRING;      -- Octal string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_sfixed
  is
    variable result : UNRESOLVED_sfixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(ostring);
    OREAD (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_ostring: Bad string "& ostring severity error;
    return result;
  end function from_ostring;

  function from_hstring (
    hstring              : STRING;      -- hex string
    constant left_index  : INTEGER;
    constant right_index : INTEGER)
    return UNRESOLVED_sfixed
  is
    variable result : UNRESOLVED_sfixed (left_index downto right_index);
    variable L      : LINE;
    variable good   : BOOLEAN;
  begin
    L := new STRING'(hstring);
    HREAD (L, result, good);
    deallocate (L);
    assert (good)
      report fixed_generic_pkg'instance_name
      & "from_hstring: Bad string "& hstring severity error;
    return result;
  end function from_hstring;

Conversion from string using result size

from_string from_ostring from_hstring
  -- Same as above, "size_res" is used for it's range only.
 function from_string (
    bstring  : STRING;                  -- binary string
    size_res : UNRESOLVED_ufixed)
    return UNRESOLVED_ufixed is
  begin
    return from_string (bstring, size_res'high, size_res'low);
  end function from_string;

  function from_ostring (
    ostring  : STRING;                  -- Octal string
    size_res : UNRESOLVED_ufixed)
    return UNRESOLVED_ufixed is
  begin
    return from_ostring (ostring, size_res'high, size_res'low);
  end function from_ostring;

  function from_hstring (
    hstring  : STRING;                  -- hex string
    size_res : UNRESOLVED_ufixed)
    return UNRESOLVED_ufixed is
  begin
    return from_hstring(hstring, size_res'high, size_res'low);
  end function from_hstring;

  function from_string (
    bstring  : STRING;                  -- binary string
    size_res : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return from_string (bstring, size_res'high, size_res'low);
  end function from_string;

  function from_ostring (
    ostring  : STRING;                  -- Octal string
    size_res : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return from_ostring (ostring, size_res'high, size_res'low);
  end function from_ostring;

  function from_hstring (
    hstring  : STRING;                  -- hex string
    size_res : UNRESOLVED_sfixed)
    return UNRESOLVED_sfixed is
  begin
    return from_hstring (hstring, size_res'high, size_res'low);
  end function from_hstring;

Direct conversion from string

from_string from_ostring from_hstring
calculate_string_boundry
  -- Direct conversion functions.  Example:
  --  signal uf1 : ufixed (3 downto -3);
  --  uf1 <= from_string ("0110.100"); -- 6.5
  -- In this case the "." is not optional, and the size of
  -- the output must match exactly.
  -- purpose: Calculate the string boundaries
  procedure calculate_string_boundry (
    arg         : in  STRING;           -- input string
    left_index  : out INTEGER;          -- left
    right_index : out INTEGER) is       -- right
    -- examples "10001.111" would return +4, -3
    -- "07X.44" would return +2, -2 (then the octal routine would multiply)
    -- "A_B_._C" would return +1, -1 (then the hex routine would multiply)
    alias xarg : STRING (arg'length downto 1) is arg;  -- make it downto range
    variable l, r : INTEGER;            -- internal indexes
    variable founddot : BOOLEAN := false;
  begin
    if arg'length > 0 then
      l := xarg'high - 1;
      r := 0;
      for i in xarg'range loop
        if xarg(i) = '_' then
          if r = 0 then
            l := l - 1;
          else
            r := r + 1;
          end if;
        elsif xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT then
          report fixed_generic_pkg'instance_name
            & "Found a space in the input STRING " & xarg
            severity error;
        elsif xarg(i) = '.' then
          if founddot then
            report fixed_generic_pkg'instance_name
              & "Found two binary points in input string " & xarg
              severity error;
          else
            l := l - i;
            r := -i + 1;
            founddot := true;
          end if;
        end if;
      end loop;
      left_index := l;
      right_index := r;
    else
      left_index := 0;
      right_index := 0;
    end if;
  end procedure calculate_string_boundry;

  -- Direct conversion functions.  Example:
  --  signal uf1 : ufixed (3 downto -3);
  --  uf1 <= from_string ("0110.100"); -- 6.5
  -- In this case the "." is not optional, and the size of
  -- the output must match exactly.
  function from_string (
    bstring : STRING)                      -- binary string
    return UNRESOLVED_ufixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (bstring, left_index, right_index);
    return from_string (bstring, left_index, right_index);
  end function from_string;

  -- Direct octal and hex conversion functions.  In this case
  -- the string lengths must match.  Example:
  -- signal sf1 := sfixed (5 downto -3);
  -- sf1 <= from_ostring ("71.4") -- -6.5
  function from_ostring (
    ostring : STRING)                      -- Octal string
    return UNRESOLVED_ufixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (ostring, left_index, right_index);
    return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3);
  end function from_ostring;

  function from_hstring (
    hstring : STRING)                      -- hex string
    return UNRESOLVED_ufixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (hstring, left_index, right_index);
    return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4);
  end function from_hstring;

  function from_string (
    bstring : STRING)                      -- binary string
    return UNRESOLVED_sfixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (bstring, left_index, right_index);
    return from_string (bstring, left_index, right_index);
  end function from_string;

  function from_ostring (
    ostring : STRING)                      -- Octal string
    return UNRESOLVED_sfixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (ostring, left_index, right_index);
    return from_ostring (ostring, ((left_index+1)*3)-1, right_index*3);
  end function from_ostring;

  function from_hstring (
    hstring : STRING)                      -- hex string
    return UNRESOLVED_sfixed
  is
    variable left_index, right_index : INTEGER;
  begin
    calculate_string_boundry (hstring, left_index, right_index);
    return from_hstring (hstring, ((left_index+1)*4)-1, right_index*4);
  end function from_hstring;

end package body fixed_generic_pkg;