------------------------------------------------------------------------------
-- "std_logic_1164_additions" package contains the additions to the standard
-- "std_logic_1164" package proposed by the VHDL-200X-ft working group.
-- This package should be compiled into "ieee_proposed" and used as follows:
-- use ieee.std_logic_1164.all;
-- use ieee_proposed.std_logic_1164_additions.all;
-- Last Modified: $Date: 2007-09-11 14:52:13-04 $
-- RCS ID: $Id: std_logic_1164_additions.vhdl,v 1.12 2007-09-11 14:52:13-04 l435385 Exp $
--
--  Created for VHDL-200X par, David Bishop (dbishop@vhdl.org)
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
package std_logic_1164_additions is

  -- NOTE that in the new std_logic_1164, STD_LOGIC_VECTOR is a resolved
  -- subtype of STD_ULOGIC_VECTOR.  Thus there is no need for funcitons which
  -- take inputs in STD_LOGIC_VECTOR.
  -- For compatability with VHDL-2002, I have replicated all of these funcitons
  -- here for STD_LOGIC_VECTOR.
  -- new aliases
  alias to_bv is ieee.std_logic_1164.To_bitvector [STD_LOGIC_VECTOR, BIT return BIT_VECTOR];
  alias to_bv is ieee.std_logic_1164.To_bitvector [STD_ULOGIC_VECTOR, BIT return BIT_VECTOR];
  alias to_bit_vector is ieee.std_logic_1164.To_bitvector [STD_LOGIC_VECTOR, BIT return BIT_VECTOR];
  alias to_bit_vector is ieee.std_logic_1164.To_bitvector [STD_ULOGIC_VECTOR, BIT return BIT_VECTOR];
  alias to_slv is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return STD_LOGIC_VECTOR];
  alias to_slv is ieee.std_logic_1164.To_StdLogicVector [STD_ULOGIC_VECTOR return STD_LOGIC_VECTOR];
  alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return STD_LOGIC_VECTOR];
  alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [STD_ULOGIC_VECTOR return STD_LOGIC_VECTOR];
  alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return STD_ULOGIC_VECTOR];
  alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [STD_LOGIC_VECTOR return STD_ULOGIC_VECTOR];
  alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return STD_ULOGIC_VECTOR];
  alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [STD_LOGIC_VECTOR return STD_ULOGIC_VECTOR];

  function TO_01 (s : STD_ULOGIC_VECTOR; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC_VECTOR;
  function TO_01 (s : STD_ULOGIC; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC;
  function TO_01 (s : BIT_VECTOR; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC_VECTOR;
  function TO_01 (s : BIT; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC;

  -------------------------------------------------------------------
  -- overloaded shift operators
  -------------------------------------------------------------------

  function "sll" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR;
  function "sll" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR;

  function "srl" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR;
  function "srl" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR;

  function "rol" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR;
  function "rol" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR;

  function "ror" (l  : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR;
  function "ror" (l  : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR;
  -------------------------------------------------------------------
  -- vector/scalar overloaded logical operators
  -------------------------------------------------------------------
  function "and" (l  : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "and" (l  : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "and" (l  : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "and" (l  : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function "nand" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "nand" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "nand" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "nand" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function "or" (l   : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "or" (l   : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "or" (l   : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "or" (l   : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function "nor" (l  : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "nor" (l  : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "nor" (l  : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "nor" (l  : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function "xor" (l  : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "xor" (l  : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "xor" (l  : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "xor" (l  : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function "xnor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR;
  function "xnor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR;
  function "xnor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function "xnor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;

  -------------------------------------------------------------------
  -- vector-reduction functions.
  -- "and" functions default to "1", or defaults to "0"
  -------------------------------------------------------------------
  -----------------------------------------------------------------------------
  -- %%% Replace the "_reduce" functions with the ones commented out below.
  -----------------------------------------------------------------------------
  -- function "and" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "and" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  -- function "nand" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "nand" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  -- function "or" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "or" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  -- function "nor" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "nor" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  -- function "xor" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "xor" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  -- function "xnor" ( l  : std_logic_vector ) RETURN std_ulogic;
  -- function "xnor" ( l  : std_ulogic_vector ) RETURN std_ulogic;
  function and_reduce (l  : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function and_reduce (l  : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function nand_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function nand_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function or_reduce (l   : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function or_reduce (l   : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function nor_reduce (l  : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function nor_reduce (l  : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function xor_reduce (l  : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function xor_reduce (l  : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function xnor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function xnor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  -------------------------------------------------------------------
  -- ?= operators, same functionality as 1076.3 1994 std_match
  -------------------------------------------------------------------
--  FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic;
--  FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic;
--  FUNCTION "?=" ( l, r : std_ulogic_vector ) RETURN std_ulogic;
--  FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic;
--  FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic;
--  FUNCTION "?/=" ( l, r : std_ulogic_vector ) RETURN std_ulogic;
--  FUNCTION "?>" ( l, r : std_ulogic ) RETURN std_ulogic;
--  FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic;
--  FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic;
--  FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic;

  function \?=\ (l, r  : STD_ULOGIC) return STD_ULOGIC;
  function \?=\ (l, r  : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function \?=\ (l, r  : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC;
  function \?/=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC;
  function \?/=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC;
  function \?>\ (l, r  : STD_ULOGIC) return STD_ULOGIC;
  function \?>=\ (l, r : STD_ULOGIC) return STD_ULOGIC;
  function \?<\ (l, r  : STD_ULOGIC) return STD_ULOGIC;
  function \?<=\ (l, r : STD_ULOGIC) return STD_ULOGIC;

  -- "??" operator, converts a std_ulogic to a boolean.
  --%%% Uncomment the following operators
  -- FUNCTION "??" (S : STD_ULOGIC) RETURN BOOLEAN;
  --%%% REMOVE the following funciton (for testing only)
  function \??\ (S : STD_ULOGIC) return BOOLEAN;

  -- rtl_synthesis off
-- pragma synthesis_off
  function to_string (value : STD_ULOGIC) return STRING;
  function to_string (value : STD_ULOGIC_VECTOR) return STRING;
  function to_string (value : STD_LOGIC_VECTOR) return STRING;

  -- explicitly defined operations

  alias TO_BSTRING is TO_STRING [STD_ULOGIC_VECTOR return STRING];
  alias TO_BINARY_STRING is TO_STRING [STD_ULOGIC_VECTOR return STRING];
  function TO_OSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING;
  alias TO_OCTAL_STRING is TO_OSTRING [STD_ULOGIC_VECTOR return STRING];
  function TO_HSTRING (VALUE : STD_ULOGIC_VECTOR) return STRING;
  alias TO_HEX_STRING is TO_HSTRING [STD_ULOGIC_VECTOR return STRING];

  procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN);
  procedure READ (L : inout LINE; VALUE : out STD_ULOGIC);

  procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

  procedure WRITE (L         : inout LINE; VALUE : in STD_ULOGIC;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);

  procedure WRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);

  alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
  alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
  alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
  alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR];

  procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
  alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
  alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR];

  procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
  alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
  alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR];

  alias BWRITE is WRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH];
  alias BINARY_WRITE is WRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH];

  procedure OWRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);
  alias OCTAL_WRITE is OWRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH];

  procedure HWRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);
  alias HEX_WRITE is HWRITE [LINE, STD_ULOGIC_VECTOR, SIDE, WIDTH];

  alias TO_BSTRING is TO_STRING [STD_LOGIC_VECTOR return STRING];
  alias TO_BINARY_STRING is TO_STRING [STD_LOGIC_VECTOR return STRING];
  function TO_OSTRING (VALUE : STD_LOGIC_VECTOR) return STRING;
  alias TO_OCTAL_STRING is TO_OSTRING [STD_LOGIC_VECTOR return STRING];
  function TO_HSTRING (VALUE : STD_LOGIC_VECTOR) return STRING;
  alias TO_HEX_STRING is TO_HSTRING [STD_LOGIC_VECTOR return STRING];

  procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR);

  procedure WRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);

  alias BREAD is READ [LINE, STD_LOGIC_VECTOR, BOOLEAN];
  alias BREAD is READ [LINE, STD_LOGIC_VECTOR];
  alias BINARY_READ is READ [LINE, STD_LOGIC_VECTOR, BOOLEAN];
  alias BINARY_READ is READ [LINE, STD_LOGIC_VECTOR];

  procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR);
  alias OCTAL_READ is OREAD [LINE, STD_LOGIC_VECTOR, BOOLEAN];
  alias OCTAL_READ is OREAD [LINE, STD_LOGIC_VECTOR];

  procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN);
  procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR);
  alias HEX_READ is HREAD [LINE, STD_LOGIC_VECTOR, BOOLEAN];
  alias HEX_READ is HREAD [LINE, STD_LOGIC_VECTOR];

  alias BWRITE is WRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH];
  alias BINARY_WRITE is WRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH];

  procedure OWRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);
  alias OCTAL_WRITE is OWRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH];

  procedure HWRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0);
  alias HEX_WRITE is HWRITE [LINE, STD_LOGIC_VECTOR, SIDE, WIDTH];
  -- rtl_synthesis on
-- pragma synthesis_on
  function maximum (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function maximum (l, r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function maximum (l, r : STD_ULOGIC) return STD_ULOGIC;
  function minimum (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
  function minimum (l, r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
  function minimum (l, r : STD_ULOGIC) return STD_ULOGIC;
end package std_logic_1164_additions;

package body std_logic_1164_additions is
  type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC;
  -----------------------------------------------------------------------------
  -- New/updated funcitons for VHDL-200X fast track
  -----------------------------------------------------------------------------
  -- to_01
  -------------------------------------------------------------------
  function TO_01 (s : STD_ULOGIC_VECTOR; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC_VECTOR is
    variable RESULT      : STD_ULOGIC_VECTOR(s'length-1 downto 0);
    variable BAD_ELEMENT : BOOLEAN := false;
    alias XS             : STD_ULOGIC_VECTOR(s'length-1 downto 0) is s;
  begin
    for I in RESULT'range loop
      case XS(I) is
        when '0' | 'L' => RESULT(I)   := '0';
        when '1' | 'H' => RESULT(I)   := '1';
        when others    => BAD_ELEMENT := true;
      end case;
    end loop;
    if BAD_ELEMENT then
      for I in RESULT'range loop
        RESULT(I) := XMAP;              -- standard fixup
      end loop;
    end if;
    return RESULT;
  end function TO_01;
  -------------------------------------------------------------------
  function TO_01 (s : STD_ULOGIC; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC is
  begin
    case s is
      when '0' | 'L' => RETURN '0';
      when '1' | 'H' => RETURN '1';
      when others    => return xmap;
    end case;
  end function TO_01;
  -------------------------------------------------------------------
  function TO_01 (s : BIT_VECTOR; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC_VECTOR is
    variable RESULT : STD_ULOGIC_VECTOR(s'length-1 downto 0);
    alias XS        : BIT_VECTOR(s'length-1 downto 0) is s;
  begin
    for I in RESULT'range loop
      case XS(I) is
        when '0' => RESULT(I) := '0';
        when '1' => RESULT(I) := '1';
      end case;
    end loop;
    return RESULT;
  end function TO_01;
  -------------------------------------------------------------------
  function TO_01 (s : BIT; xmap : STD_ULOGIC := '0')
    return STD_ULOGIC is
  begin
    case s is
      when '0' => RETURN '0';
      when '1' => RETURN '1';
    end case;
  end function TO_01;
-- end Bugzilla issue #148
  -------------------------------------------------------------------

  -------------------------------------------------------------------
  -- overloaded shift operators
  -------------------------------------------------------------------

  -------------------------------------------------------------------
  -- sll
  -------------------------------------------------------------------
  function "sll" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0');
  begin
    if r >= 0 then
      result(1 to l'length - r) := lv(r + 1 to l'length);
    else
      result := l srl -r;
    end if;
    return result;
  end function "sll";
  -------------------------------------------------------------------
  function "sll" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0');
  begin
    if r >= 0 then
      result(1 to l'length - r) := lv(r + 1 to l'length);
    else
      result := l srl -r;
    end if;
    return result;
  end function "sll";

  -------------------------------------------------------------------
  -- srl
  -------------------------------------------------------------------
  function "srl" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0');
  begin
    if r >= 0 then
      result(r + 1 to l'length) := lv(1 to l'length - r);
    else
      result := l sll -r;
    end if;
    return result;
  end function "srl";
  -------------------------------------------------------------------
  function "srl" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0');
  begin
    if r >= 0 then
      result(r + 1 to l'length) := lv(1 to l'length - r);
    else
      result := l sll -r;
    end if;
    return result;
  end function "srl";

  -------------------------------------------------------------------
  -- rol
  -------------------------------------------------------------------
  function "rol" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
    constant rm     : INTEGER := r mod l'length;
  begin
    if r >= 0 then
      result(1 to l'length - rm)            := lv(rm + 1 to l'length);
      result(l'length - rm + 1 to l'length) := lv(1 to rm);
    else
      result := l ror -r;
    end if;
    return result;
  end function "rol";
  -------------------------------------------------------------------
  function "rol" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
    constant rm     : INTEGER := r mod l'length;
  begin
    if r >= 0 then
      result(1 to l'length - rm)            := lv(rm + 1 to l'length);
      result(l'length - rm + 1 to l'length) := lv(1 to rm);
    else
      result := l ror -r;
    end if;
    return result;
  end function "rol";

  -------------------------------------------------------------------
  -- ror
  -------------------------------------------------------------------
  function "ror" (l : STD_LOGIC_VECTOR; r : INTEGER) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length) := (others => '0');
    constant rm     : INTEGER := r mod l'length;
  begin
    if r >= 0 then
      result(rm + 1 to l'length) := lv(1 to l'length - rm);
      result(1 to rm)            := lv(l'length - rm + 1 to l'length);
    else
      result := l rol -r;
    end if;
    return result;
  end function "ror";
  -------------------------------------------------------------------
  function "ror" (l : STD_ULOGIC_VECTOR; r : INTEGER) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length) := (others => '0');
    constant rm     : INTEGER := r mod l'length;
  begin
    if r >= 0 then
      result(rm + 1 to l'length) := lv(1 to l'length - rm);
      result(1 to rm)            := lv(l'length - rm + 1 to l'length);
    else
      result := l rol -r;
    end if;
    return result;
  end function "ror";
  -------------------------------------------------------------------
  -- vector/scalar overloaded logical operators
  -------------------------------------------------------------------

  -------------------------------------------------------------------
  -- and
  -------------------------------------------------------------------
  function "and" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "and" (lv(i), r);
    end loop;
    return result;
  end function "and";
  -------------------------------------------------------------------
  function "and" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "and" (lv(i), r);
    end loop;
    return result;
  end function "and";
  -------------------------------------------------------------------
  function "and" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "and" (l, rv(i));
    end loop;
    return result;
  end function "and";
  -------------------------------------------------------------------
  function "and" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "and" (l, rv(i));
    end loop;
    return result;
  end function "and";

  -------------------------------------------------------------------
  -- nand
  -------------------------------------------------------------------
  function "nand" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("and" (lv(i), r));
    end loop;
    return result;
  end function "nand";
  -------------------------------------------------------------------
  function "nand" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("and" (lv(i), r));
    end loop;
    return result;
  end function "nand";
  -------------------------------------------------------------------
  function "nand" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("and" (l, rv(i)));
    end loop;
    return result;
  end function "nand";
  -------------------------------------------------------------------
  function "nand" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("and" (l, rv(i)));
    end loop;
    return result;
  end function "nand";

  -------------------------------------------------------------------
  -- or
  -------------------------------------------------------------------
  function "or" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "or" (lv(i), r);
    end loop;
    return result;
  end function "or";
  -------------------------------------------------------------------
  function "or" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "or" (lv(i), r);
    end loop;
    return result;
  end function "or";
  -------------------------------------------------------------------
  function "or" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "or" (l, rv(i));
    end loop;
    return result;
  end function "or";
  -------------------------------------------------------------------
  function "or" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "or" (l, rv(i));
    end loop;
    return result;
  end function "or";

  -------------------------------------------------------------------
  -- nor
  -------------------------------------------------------------------
  function "nor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("or" (lv(i), r));
    end loop;
    return result;
  end function "nor";
  -------------------------------------------------------------------
  function "nor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("or" (lv(i), r));
    end loop;
    return result;
  end function "nor";
  -------------------------------------------------------------------
  function "nor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("or" (l, rv(i)));
    end loop;
    return result;
  end function "nor";
  -------------------------------------------------------------------
  function "nor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("or" (l, rv(i)));
    end loop;
    return result;
  end function "nor";

  -------------------------------------------------------------------
  -- xor
  -------------------------------------------------------------------
  function "xor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "xor" (lv(i), r);
    end loop;
    return result;
  end function "xor";
  -------------------------------------------------------------------
  function "xor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "xor" (lv(i), r);
    end loop;
    return result;
  end function "xor";
  -------------------------------------------------------------------
  function "xor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "xor" (l, rv(i));
    end loop;
    return result;
  end function "xor";
  -------------------------------------------------------------------
  function "xor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "xor" (l, rv(i));
    end loop;
    return result;
  end function "xor";

  -------------------------------------------------------------------
  -- xnor
  -------------------------------------------------------------------
  function "xnor" (l : STD_LOGIC_VECTOR; r : STD_ULOGIC) return STD_LOGIC_VECTOR is
    alias lv        : STD_LOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_LOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("xor" (lv(i), r));
    end loop;
    return result;
  end function "xnor";
  -------------------------------------------------------------------
  function "xnor" (l : STD_ULOGIC_VECTOR; r : STD_ULOGIC) return STD_ULOGIC_VECTOR is
    alias lv        : STD_ULOGIC_VECTOR (1 to l'length) is l;
    variable result : STD_ULOGIC_VECTOR (1 to l'length);
  begin
    for i in result'range loop
      result(i) := "not"("xor" (lv(i), r));
    end loop;
    return result;
  end function "xnor";
  -------------------------------------------------------------------
  function "xnor" (l : STD_ULOGIC; r : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
    alias rv        : STD_LOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_LOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("xor" (l, rv(i)));
    end loop;
    return result;
  end function "xnor";
  -------------------------------------------------------------------
  function "xnor" (l : STD_ULOGIC; r : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
    alias rv        : STD_ULOGIC_VECTOR (1 to r'length) is r;
    variable result : STD_ULOGIC_VECTOR (1 to r'length);
  begin
    for i in result'range loop
      result(i) := "not"("xor" (l, rv(i)));
    end loop;
    return result;
  end function "xnor";

  -------------------------------------------------------------------
  -- vector-reduction functions
  -------------------------------------------------------------------

  -------------------------------------------------------------------
  -- and
  -------------------------------------------------------------------
  function and_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return and_reduce (to_StdULogicVector (l));
  end function and_reduce;
  -------------------------------------------------------------------
  function and_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    variable result : STD_ULOGIC := '1';
  begin
    for i in l'reverse_range loop
      result := (l(i) and result);
    end loop;
    return result;
  end function and_reduce;

  -------------------------------------------------------------------
  -- nand
  -------------------------------------------------------------------
  function nand_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return not (and_reduce(to_StdULogicVector(l)));
  end function nand_reduce;
  -------------------------------------------------------------------
  function nand_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
  begin
    return  not (and_reduce(l));
  end function nand_reduce;

  -------------------------------------------------------------------
  -- or
  -------------------------------------------------------------------
  function or_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return or_reduce (to_StdULogicVector (l));
  end function or_reduce;
  -------------------------------------------------------------------
  function or_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    variable result : STD_ULOGIC := '0';
  begin
    for i in l'reverse_range loop
      result := (l(i) or result);
    end loop;
    return result;
  end function or_reduce;

  -------------------------------------------------------------------
  -- nor
  -------------------------------------------------------------------
  function nor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return "not"(or_reduce(To_StdULogicVector(l)));
  end function nor_reduce;
  -------------------------------------------------------------------
  function nor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
  begin
    return "not"(or_reduce(l));
  end function nor_reduce;

  -------------------------------------------------------------------
  -- xor
  -------------------------------------------------------------------
  function xor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return xor_reduce (to_StdULogicVector (l));
  end function xor_reduce;
  -------------------------------------------------------------------
  function xor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    variable result : STD_ULOGIC := '0';
  begin
    for i in l'reverse_range loop
      result := (l(i) xor result);
    end loop;
    return result;
  end function xor_reduce;

  -------------------------------------------------------------------
  -- xnor
  -------------------------------------------------------------------
  function xnor_reduce (l : STD_LOGIC_VECTOR) return STD_ULOGIC is
  begin
    return "not"(xor_reduce(To_StdULogicVector(l)));
  end function xnor_reduce;
  -------------------------------------------------------------------
  function xnor_reduce (l : STD_ULOGIC_VECTOR) return STD_ULOGIC is
  begin
    return "not"(xor_reduce(l));
  end function xnor_reduce;
  -- %%% End "remove the following functions"

  -- The following functions are implicity in 1076-2006
  -- truth table for "?=" function
  constant match_logic_table : stdlogic_table := (
    -----------------------------------------------------
    -- U    X    0    1    Z    W    L    H    -         |   |
    -----------------------------------------------------
    ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'),  -- | U |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'),  -- | X |
    ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'),  -- | 0 |
    ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'),  -- | 1 |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'),  -- | Z |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'),  -- | W |
    ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'),  -- | L |
    ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'),  -- | H |
    ('1', '1', '1', '1', '1', '1', '1', '1', '1')   -- | - |
    );

  constant no_match_logic_table : stdlogic_table := (
    -----------------------------------------------------
    -- U    X    0    1    Z    W    L    H    -         |   |
    -----------------------------------------------------
    ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'),  -- | U |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'),  -- | X |
    ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'),  -- | 0 |
    ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'),  -- | 1 |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'),  -- | Z |
    ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'),  -- | W |
    ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'),  -- | L |
    ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'),  -- | H |
    ('0', '0', '0', '0', '0', '0', '0', '0', '0')   -- | - |
    );

  -------------------------------------------------------------------
  -- ?= functions, Similar to "std_match", but returns "std_ulogic".
  -------------------------------------------------------------------
  -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS
  function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
  begin
    return match_logic_table (l, r);
  end function \?=\;
  -- %%% END FUNCTION "?=";
  -------------------------------------------------------------------
  -- %%% FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic IS
  function \?=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is
    alias lv                 : STD_LOGIC_VECTOR(1 to l'length) is l;
    alias rv                 : STD_LOGIC_VECTOR(1 to r'length) is r;
    variable result, result1 : STD_ULOGIC;  -- result
  begin
    -- Logically identical to an "=" operator.
    if ((l'length < 1) or (r'length < 1)) then
      report "STD_LOGIC_1164.""?="": null detected, returning X"
        severity warning;
      return 'X';
    end if;
    if lv'length /= rv'length then
      report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X"
        severity warning;
      return 'X';
    else
      result := '1';
      for i in lv'low to lv'high loop
        result1 := match_logic_table(lv(i), rv(i));
        if result1 = 'U' then
          return 'U';
        elsif result1 = 'X' or result = 'X' then
          result := 'X';
        else
          result := result and result1;
        end if;
      end loop;
      return result;
    end if;
  end function \?=\;
  -- %%% END FUNCTION "?=";
  -------------------------------------------------------------------
  -- %%% FUNCTION "?=" ( l, r : std_ulogic_vector ) RETURN std_ulogic IS
  function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    alias lv                 : STD_ULOGIC_VECTOR(1 to l'length) is l;
    alias rv                 : STD_ULOGIC_VECTOR(1 to r'length) is r;
    variable result, result1 : STD_ULOGIC;
  begin
    if ((l'length < 1) or (r'length < 1)) then
      report "STD_LOGIC_1164.""?="": null detected, returning X"
        severity warning;
      return 'X';
    end if;
    if lv'length /= rv'length then
      report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X"
        severity warning;
      return 'X';
    else
      result := '1';
      for i in lv'low to lv'high loop
        result1 := match_logic_table(lv(i), rv(i));
        if result1 = 'U' then
          return 'U';
        elsif result1 = 'X' or result = 'X' then
          result := 'X';
        else
          result := result and result1;
        end if;
      end loop;
      return result;
    end if;
  end function \?=\;
  -- %%% END FUNCTION "?=";
  -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is
  function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
  begin
    return no_match_logic_table (l, r);
  end function \?/=\;
  -- %%% END FUNCTION "?/=";
  -- %%% FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic is
  function \?/=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is
    alias lv                 : STD_LOGIC_VECTOR(1 to l'length) is l;
    alias rv                 : STD_LOGIC_VECTOR(1 to r'length) is r;
    variable result, result1 : STD_ULOGIC;  -- result
  begin
    if ((l'length < 1) or (r'length < 1)) then
      report "STD_LOGIC_1164.""?/="": null detected, returning X"
        severity warning;
      return 'X';
    end if;
    if lv'length /= rv'length then
      report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X"
        severity warning;
      return 'X';
    else
      result := '0';
      for i in lv'low to lv'high loop
        result1 := no_match_logic_table(lv(i), rv(i));
        if result1 = 'U' then
          return 'U';
        elsif result1 = 'X' or result = 'X' then
          result := 'X';
        else
          result := result or result1;
        end if;
      end loop;
      return result;
    end if;
  end function \?/=\;
  -- %%% END FUNCTION "?/=";
  -- %%% FUNCTION "?/=" ( l, r : std_ulogic_vector ) RETURN std_ulogic is
  function \?/=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is
    alias lv                 : STD_ULOGIC_VECTOR(1 to l'length) is l;
    alias rv                 : STD_ULOGIC_VECTOR(1 to r'length) is r;
    variable result, result1 : STD_ULOGIC;
  begin
    if ((l'length < 1) or (r'length < 1)) then
      report "STD_LOGIC_1164.""?/="": null detected, returning X"
        severity warning;
      return 'X';
    end if;
    if lv'length /= rv'length then
      report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X"
        severity warning;
      return 'X';
    else
      result := '0';
      for i in lv'low to lv'high loop
        result1 := no_match_logic_table(lv(i), rv(i));
        if result1 = 'U' then
          return 'U';
        elsif result1 = 'X' or result = 'X' then
          result := 'X';
        else
          result := result or result1;
        end if;
      end loop;
      return result;
    end if;
  end function \?/=\;
  -- %%% END FUNCTION "?/=";
  -- %%% FUNCTION "?>" ( l, r : std_ulogic ) RETURN std_ulogic is
  function \?>\ (l, r : STD_ULOGIC) return STD_ULOGIC is
    variable lx, rx : STD_ULOGIC;
  begin
    if (l = '-') or (r = '-') then
      report "STD_LOGIC_1164.""?>"": '-' found in compare string"
        severity error;
      return 'X';
    else
      lx := to_x01 (l);
      rx := to_x01 (r);
      if lx = 'X' or rx = 'X' then
        return 'X';
      elsif lx > rx then
        return '1';
      else
        return '0';
      end if;
    end if;
  end function \?>\;
  -- %%% END FUNCTION "?>";

  -- %%% FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic is
  function \?>=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
    variable lx, rx : STD_ULOGIC;
  begin
    if (l = '-') or (r = '-') then
      report "STD_LOGIC_1164.""?>="": '-' found in compare string"
        severity error;
      return 'X';
    else
      lx := to_x01 (l);
      rx := to_x01 (r);
      if lx = 'X' or rx = 'X' then
        return 'X';
      elsif lx >= rx then
        return '1';
      else
        return '0';
      end if;
    end if;
  end function \?>=\;
  -- %%% END FUNCTION "?/>=";

  -- %%% FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic is
  function \?<\ (l, r : STD_ULOGIC) return STD_ULOGIC is
    variable lx, rx : STD_ULOGIC;
  begin
    if (l = '-') or (r = '-') then
      report "STD_LOGIC_1164.""?<"": '-' found in compare string"
        severity error;
      return 'X';
    else
      lx := to_x01 (l);
      rx := to_x01 (r);
      if lx = 'X' or rx = 'X' then
        return 'X';
      elsif lx < rx then
        return '1';
      else
        return '0';
      end if;
    end if;
  end function \?<\;
  -- %%% END FUNCTION "?/<";

  -- %%% FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic is
  function \?<=\ (l, r : STD_ULOGIC) return STD_ULOGIC is
    variable lx, rx : STD_ULOGIC;
  begin
    if (l = '-') or (r = '-') then
      report "STD_LOGIC_1164.""?<="": '-' found in compare string"
        severity error;
      return 'X';
    else
      lx := to_x01 (l);
      rx := to_x01 (r);
      if lx = 'X' or rx = 'X' then
        return 'X';
      elsif lx <= rx then
        return '1';
      else
        return '0';
      end if;
    end if;
  end function \?<=\;
  -- %%% END FUNCTION "?/<=";

  -- "??" operator, converts a std_ulogic to a boolean.
-- %%% FUNCTION "??"
  function \??\ (S : STD_ULOGIC) return BOOLEAN is
  begin
    return S = '1' or S = 'H';
  end function \??\;
-- %%% END FUNCTION "??";

  -- rtl_synthesis off
-- pragma synthesis_off
  -----------------------------------------------------------------------------
  -- This section copied from "std_logic_textio"
  -----------------------------------------------------------------------------
  -- Type and constant definitions used to map STD_ULOGIC values
  -- into/from character values.
  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 => ' ');     -- null STRING

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

  procedure READ (L    : inout LINE; VALUE : out STD_ULOGIC;
                  GOOD : out   BOOLEAN) is
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
  begin
    VALUE := 'U';                       -- initialize to a "U"
    Skip_whitespace (L);
    read (l, c, readOk);
    if not readOk then
      good := false;
    else
      if char_to_MVL9plus(c) = error then
        good := false;
      else
        VALUE := char_to_MVL9(c);
        good  := true;
      end if;
    end if;
  end procedure READ;

  procedure READ (L    : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                  GOOD : out   BOOLEAN) is
    variable m      : STD_ULOGIC;
    variable c      : CHARACTER;
    variable mv     : STD_ULOGIC_VECTOR(0 to VALUE'length-1);
    variable readOk : BOOLEAN;
    variable i      : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then
      read (l, c, readOk);
      i := 0;
      good := false;
      while i < VALUE'length loop
        if not readOk then     -- Bail out if there was a bad read
          return;
        elsif c = '_' then
          if i = 0 then     -- Begins with an "_"
            return;
          elsif lastu then                -- "__" detected
            return;
          else
            lastu := true;
          end if;
        elsif (char_to_MVL9plus(c) = error) then          -- Illegal character
          return;
        else
          mv(i) := char_to_MVL9(c);
          i := i + 1;
          if i > mv'high 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 STD_ULOGIC) is
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
  begin
    VALUE := 'U';                       -- initialize to a "U"
    Skip_whitespace (L);
    read (l, c, readOk);
    if not readOk then
      report "STD_LOGIC_1164.READ(STD_ULOGIC) "
        & "End of string encountered"
        severity error;
      return;
    elsif char_to_MVL9plus(c) = error then
      report
        "STD_LOGIC_1164.READ(STD_ULOGIC) Error: Character '" &
        c & "' read, expected STD_ULOGIC literal."
        severity error;
    else
      VALUE := char_to_MVL9(c);
    end if;
  end procedure READ;

  procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is
    variable m      : STD_ULOGIC;
    variable c      : CHARACTER;
    variable readOk : BOOLEAN;
    variable mv     : STD_ULOGIC_VECTOR(0 to VALUE'length-1);
    variable i      : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then            -- non Null input string
      read (l, c, readOk);
      i := 0;
      while i < VALUE'length loop
        if readOk = false then              -- Bail out if there was a bad read
          report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) "
            & "End of string encountered"
            severity error;
          return;
        elsif c = '_' then
          if i = 0 then
            report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) "
              & "String begins with an ""_""" severity error;
            return;
          elsif lastu then
            report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) "
              & "Two underscores detected in input string ""__"""
              severity error;
            return;
          else
            lastu := true;
          end if;
        elsif c = ' ' or c = NBSP or c = HT then  -- reading done.
          report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) "
            & "Short read, Space encounted in input string"
            severity error;
          return;
        elsif char_to_MVL9plus(c) = error then
          report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) "
            & "Error: Character '" &
            c & "' read, expected STD_ULOGIC literal."
            severity error;
          return;
        else
          mv(i) := char_to_MVL9(c);
          i := i + 1;
          if i > mv'high then
            VALUE := mv;
            return;
          end if;
          lastu := false;
        end if;
        read(L, c, readOk);
      end loop;
    end if;
  end procedure READ;

  procedure WRITE (L         : inout LINE; VALUE : in STD_ULOGIC;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
  begin
    write(l, MVL9_to_char(VALUE), justified, field);
  end procedure WRITE;

  procedure WRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
    variable s : STRING(1 to VALUE'length);
    variable m : STD_ULOGIC_VECTOR(1 to VALUE'length) := VALUE;
  begin
    for i in 1 to VALUE'length loop
      s(i) := MVL9_to_char(m(i));
    end loop;
    write(l, s, justified, field);
  end procedure WRITE;

  -- Read and Write procedures for STD_LOGIC_VECTOR

  procedure READ (L    : inout LINE; VALUE : out STD_LOGIC_VECTOR;
                  GOOD : out   BOOLEAN) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    READ (L => L, VALUE => ivalue, GOOD => GOOD);
    VALUE := to_stdlogicvector (ivalue);
  end procedure READ;

  procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    READ (L => L, VALUE => ivalue);
    VALUE := to_stdlogicvector (ivalue);
  end procedure READ;

  procedure WRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                   JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
    variable s : STRING(1 to VALUE'length);
    variable m : STD_LOGIC_VECTOR(1 to VALUE'length) := VALUE;
  begin
    for i in 1 to VALUE'length loop
      s(i) := MVL9_to_char(m(i));
    end loop;
    write(L, s, justified, field);
  end procedure WRITE;

  -----------------------------------------------------------------------
  -- Alias for bread and bwrite are provided with call out the read and
  -- write functions.
  -----------------------------------------------------------------------

  -- 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
          "STD_LOGIC_1164.HREAD Read a '" & c &
          "', expected a Hex character (0-F)."
          severity error;
        good := false;
    end case;
  end procedure Char2QuadBits;

  procedure HREAD (L    : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                   GOOD : out   BOOLEAN) is
    variable ok  : BOOLEAN;
    variable c   : CHARACTER;
    constant ne  : INTEGER := (VALUE'length+3)/4;
    constant pad : INTEGER := ne*4 - VALUE'length;
    variable sv  : STD_ULOGIC_VECTOR(0 to ne*4 - 1);
    variable i   : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then
      read (l, c, ok);
      i := 0;
      while i < ne loop
        -- Bail out if there was a bad read
        if not ok then
          good := false;
          return;
        elsif c = '_' then
          if i = 0 then
            good := false;                -- Begins with an "_"
            return;
          elsif lastu then
            good := false;                -- "__" detected
            return;
          else
            lastu := true;
          end if;
        else
          Char2QuadBits(c, sv(4*i to 4*i+3), ok, false);
          if not ok then
            good := false;
            return;
          end if;
          i := i + 1;
          lastu := false;
        end if;
        if i < ne then
          read(L, c, ok);
        end if;
      end loop;
      if or_reduce (sv (0 to pad-1)) = '1' then  -- %%% replace with "or"
        good := false;                           -- vector was truncated.
      else
        good  := true;
        VALUE := sv (pad to sv'high);
      end if;
    else
      good := true;                     -- Null input string, skips whitespace
    end if;
  end procedure HREAD;

  procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is
    variable ok  : BOOLEAN;
    variable c   : CHARACTER;
    constant ne  : INTEGER := (VALUE'length+3)/4;
    constant pad : INTEGER := ne*4 - VALUE'length;
    variable sv  : STD_ULOGIC_VECTOR(0 to ne*4 - 1);
    variable i   : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then           -- non Null input string
      read (l, c, ok);
      i := 0;
      while i < ne loop
        -- Bail out if there was a bad read
        if not ok then
          report "STD_LOGIC_1164.HREAD "
            & "End of string encountered"
            severity error;
          return;
        end if;
        if c = '_' then
          if i = 0 then
            report "STD_LOGIC_1164.HREAD "
              & "String begins with an ""_""" severity error;
            return;
          elsif lastu then
            report "STD_LOGIC_1164.HREAD "
              & "Two underscores detected in input string ""__"""
              severity error;
            return;
          else
            lastu := true;
          end if;
        else
          Char2QuadBits(c, sv(4*i to 4*i+3), ok, true);
          if not ok then
            return;
          end if;
          i := i + 1;
          lastu := false;
        end if;
        if i < ne then
          read(L, c, ok);
        end if;
      end loop;
      if or_reduce (sv (0 to pad-1)) = '1' then  -- %%% replace with "or"
        report "STD_LOGIC_1164.HREAD Vector truncated"
          severity error;
      else
        VALUE := sv (pad to sv'high);
      end if;
    end if;
  end procedure HREAD;

  procedure HWRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
  begin
    write (L, to_hstring (VALUE), JUSTIFIED, FIELD);
  end procedure HWRITE;

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

  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 '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
          "STD_LOGIC_1164.OREAD Error: Read a '" & c &
          "', expected an Octal character (0-7)."
          severity error;
        good := false;
    end case;
  end procedure Char2TriBits;

  procedure OREAD (L    : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                   GOOD : out   BOOLEAN) is
    variable ok  : BOOLEAN;
    variable c   : CHARACTER;
    constant ne  : INTEGER := (VALUE'length+2)/3;
    constant pad : INTEGER := ne*3 - VALUE'length;
    variable sv  : STD_ULOGIC_VECTOR(0 to ne*3 - 1);
    variable i   : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then
      read (l, c, ok);
      i := 0;
      while i < ne loop
        -- Bail out if there was a bad read
        if not ok then
          good := false;
          return;
        elsif c = '_' then
          if i = 0 then
            good := false;                -- Begins with an "_"
            return;
          elsif lastu then
            good := false;                -- "__" detected
            return;
          else
            lastu := true;
          end if;
        else
          Char2TriBits(c, sv(3*i to 3*i+2), ok, false);
          if not ok then
            good := false;
            return;
          end if;
          i := i + 1;
          lastu := false;
        end if;
        if i < ne then
          read(L, c, ok);
        end if;
      end loop;
      if or_reduce (sv (0 to pad-1)) = '1' then  -- %%% replace with "or"
        good := false;                           -- vector was truncated.
      else
        good  := true;
        VALUE := sv (pad to sv'high);
      end if;
    else
      good := true;                  -- read into a null array
    end if;
  end procedure OREAD;

  procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is
    variable c   : CHARACTER;
    variable ok  : BOOLEAN;
    constant ne  : INTEGER := (VALUE'length+2)/3;
    constant pad : INTEGER := ne*3 - VALUE'length;
    variable sv  : STD_ULOGIC_VECTOR(0 to ne*3 - 1);
    variable i   : INTEGER;
    variable lastu  : BOOLEAN := false;       -- last character was an "_"
  begin
    VALUE := (VALUE'range => 'U'); -- initialize to a "U"
    Skip_whitespace (L);
    if VALUE'length > 0 then
      read (l, c, ok);
      i := 0;
      while i < ne loop
        -- Bail out if there was a bad read
        if not ok then
          report "STD_LOGIC_1164.OREAD "
            & "End of string encountered"
            severity error;
          return;
        elsif c = '_' then
          if i = 0 then
            report "STD_LOGIC_1164.OREAD "
              & "String begins with an ""_""" severity error;
            return;
          elsif lastu then
            report "STD_LOGIC_1164.OREAD "
              & "Two underscores detected in input string ""__"""
              severity error;
            return;
          else
            lastu := true;
          end if;
        else
          Char2TriBits(c, sv(3*i to 3*i+2), ok, true);
          if not ok then
            return;
          end if;
          i := i + 1;
          lastu := false;
        end if;
        if i < ne then
          read(L, c, ok);
        end if;
      end loop;
      if or_reduce (sv (0 to pad-1)) = '1' then  -- %%% replace with "or"
        report "STD_LOGIC_1164.OREAD Vector truncated"
          severity error;
      else
        VALUE := sv (pad to sv'high);
      end if;
    end if;
  end procedure OREAD;

  procedure OWRITE (L         : inout LINE; VALUE : in STD_ULOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
  begin
    write (L, to_ostring(VALUE), JUSTIFIED, FIELD);
  end procedure OWRITE;

  -- Hex Read and Write procedures for STD_LOGIC_VECTOR

  procedure HREAD (L    : inout LINE; VALUE : out STD_LOGIC_VECTOR;
                   GOOD : out   BOOLEAN) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    HREAD (L => L, VALUE => ivalue, GOOD => GOOD);
    VALUE := to_stdlogicvector (ivalue);
  end procedure HREAD;

  procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    HREAD (L => L, VALUE => ivalue);
    VALUE := to_stdlogicvector (ivalue);
  end procedure HREAD;

  procedure HWRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
  begin
    write (L, to_hstring(VALUE), JUSTIFIED, FIELD);
  end procedure HWRITE;

  -- Octal Read and Write procedures for STD_LOGIC_VECTOR

  procedure OREAD (L    : inout LINE; VALUE : out STD_LOGIC_VECTOR;
                   GOOD : out   BOOLEAN) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    OREAD (L => L, VALUE => ivalue, GOOD => GOOD);
    VALUE := to_stdlogicvector (ivalue);
  end procedure OREAD;

  procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is
    variable ivalue : STD_ULOGIC_VECTOR (VALUE'range);
  begin
    OREAD (L => L, VALUE => ivalue);
    VALUE := to_stdlogicvector (ivalue);
  end procedure OREAD;

  procedure OWRITE (L         : inout LINE; VALUE : in STD_LOGIC_VECTOR;
                    JUSTIFIED : in    SIDE := right; FIELD : in WIDTH := 0) is
  begin
    write (L, to_ostring(VALUE), JUSTIFIED, FIELD);
  end procedure OWRITE;

  -----------------------------------------------------------------------------
  -- New string functions for vhdl-200x fast track
  -----------------------------------------------------------------------------
  function to_string (value     : STD_ULOGIC) return STRING is
    variable result : STRING (1 to 1);
  begin
    result (1) := MVL9_to_char (value);
    return result;
  end function to_string;
  -------------------------------------------------------------------
  -- TO_STRING (an alias called "to_bstring" is provide)
  -------------------------------------------------------------------
  function to_string (value     : STD_ULOGIC_VECTOR) return STRING is
    alias ivalue    : STD_ULOGIC_VECTOR(1 to value'length) is value;
    variable result : STRING(1 to value'length);
  begin
    if value'length < 1 then
      return NUS;
    else
      for i in ivalue'range loop
        result(i) := MVL9_to_char(iValue(i));
      end loop;
      return result;
    end if;
  end function to_string;

  -------------------------------------------------------------------
  -- TO_HSTRING
  -------------------------------------------------------------------
  function to_hstring (value     : STD_ULOGIC_VECTOR) return STRING is
    constant ne     : INTEGER := (value'length+3)/4;
    variable pad    : STD_ULOGIC_VECTOR(0 to (ne*4 - value'length) - 1);
    variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4 - 1);
    variable result : STRING(1 to ne);
    variable quad   : STD_ULOGIC_VECTOR(0 to 3);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value (value'left) = 'Z' then
        pad := (others => 'Z');
      else
        pad := (others => '0');
      end if;
      ivalue := pad & value;
      for i in 0 to ne-1 loop
        quad := To_X01Z(ivalue(4*i to 4*i+3));
        case quad is
          when x"0"   => result(i+1) := '0';
          when x"1"   => result(i+1) := '1';
          when x"2"   => result(i+1) := '2';
          when x"3"   => result(i+1) := '3';
          when x"4"   => result(i+1) := '4';
          when x"5"   => result(i+1) := '5';
          when x"6"   => result(i+1) := '6';
          when x"7"   => result(i+1) := '7';
          when x"8"   => result(i+1) := '8';
          when x"9"   => result(i+1) := '9';
          when x"A"   => result(i+1) := 'A';
          when x"B"   => result(i+1) := 'B';
          when x"C"   => result(i+1) := 'C';
          when x"D"   => result(i+1) := 'D';
          when x"E"   => result(i+1) := 'E';
          when x"F"   => result(i+1) := 'F';
          when "ZZZZ" => result(i+1) := 'Z';
          when others => result(i+1) := 'X';
        end case;
      end loop;
      return result;
    end if;
  end function to_hstring;

  -------------------------------------------------------------------
  -- TO_OSTRING
  -------------------------------------------------------------------
  function to_ostring (value     : STD_ULOGIC_VECTOR) return STRING is
    constant ne     : INTEGER := (value'length+2)/3;
    variable pad    : STD_ULOGIC_VECTOR(0 to (ne*3 - value'length) - 1);
    variable ivalue : STD_ULOGIC_VECTOR(0 to ne*3 - 1);
    variable result : STRING(1 to ne);
    variable tri    : STD_ULOGIC_VECTOR(0 to 2);
  begin
    if value'length < 1 then
      return NUS;
    else
      if value (value'left) = 'Z' then
        pad := (others => 'Z');
      else
        pad := (others => '0');
      end if;
      ivalue := pad & value;
      for i in 0 to ne-1 loop
        tri := To_X01Z(ivalue(3*i to 3*i+2));
        case tri is
          when o"0"   => result(i+1) := '0';
          when o"1"   => result(i+1) := '1';
          when o"2"   => result(i+1) := '2';
          when o"3"   => result(i+1) := '3';
          when o"4"   => result(i+1) := '4';
          when o"5"   => result(i+1) := '5';
          when o"6"   => result(i+1) := '6';
          when o"7"   => result(i+1) := '7';
          when "ZZZ"  => result(i+1) := 'Z';
          when others => result(i+1) := 'X';
        end case;
      end loop;
      return result;
    end if;
  end function to_ostring;

  function to_string (value     : STD_LOGIC_VECTOR) return STRING is
  begin
    return to_string (to_stdulogicvector (value));
  end function to_string;

  function to_hstring (value     : STD_LOGIC_VECTOR) return STRING is
  begin
    return to_hstring (to_stdulogicvector (value));
  end function to_hstring;

  function to_ostring (value     : STD_LOGIC_VECTOR) return STRING  is
  begin
    return to_ostring (to_stdulogicvector (value));
  end function to_ostring;

  -- rtl_synthesis on
-- pragma synthesis_on
  function maximum (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
  begin  -- function maximum
    if L > R then return L;
    else return R;
    end if;
  end function maximum;

  -- std_logic_vector output
  function minimum (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
  begin  -- function minimum
    if L > R then return R;
    else return L;
    end if;
  end function minimum;

  function maximum (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
  begin  -- function maximum
    if L > R then return L;
    else return R;
    end if;
  end function maximum;

  -- std_logic_vector output
  function minimum (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
  begin  -- function minimum
    if L > R then return R;
    else return L;
    end if;
  end function minimum;

  function maximum (L, R : STD_ULOGIC) return STD_ULOGIC is
  begin  -- function maximum
    if L > R then return L;
    else return R;
    end if;
  end function maximum;

  -- std_logic_vector output
  function minimum (L, R : STD_ULOGIC) return STD_ULOGIC is
  begin  -- function minimum
    if L > R then return R;
    else return L;
    end if;
  end function minimum;
end package body std_logic_1164_additions;

      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;


-- Test vectors for the synthesis test for the fixed point math package
-- This test is designed to test fixed_synth and exercise much of the entity.
-- Created for vhdl-200x by David Bishop (dbishop@vhdl.org)
-- --------------------------------------------------------------------
--   modification history : Last Modified $Date: 2006-06-08 10:55:54-04 $
--   Version $Id: test_fixed_synth.vhdl,v 1.1 2006-06-08 10:55:54-04 l435385 Exp $
-- --------------------------------------------------------------------

use ieee.numeric_std.all;
use ieee_proposed.fixed_pkg.all;
architecture testbench of test_fixed_synth is

  procedure report_error (
    constant errmes : in string;  -- error message
    actual : in sfixed;  -- data from algorithm
    constant expected : in sfixed) is  -- reference data
  begin  -- function report_error
    assert actual = expected
      report errmes & CR
      & "Actual: " & to_string(actual)
      & " (" & real'image(to_real(actual)) & ")" & CR
      & "     /= " & to_string(expected)
      & " (" & real'image(to_real(expected)) & ")"
      severity error;
    return;
  end procedure report_error;

  -- Device under test.  Note that all inputs and outputs are std_logic_vector.
  --  This entity can be use both pre and post synthesis.
  component fixed_synth is
    port (
      in1, in2   : in  std_logic_vector (15 downto 0);  -- inputs
      out1       : out std_logic_vector (15 downto 0);  -- output
      cmd        : in  std_logic_vector (3 downto 0);
      clk, rst_n : in  std_ulogic);                     -- clk and reset
  end component fixed_synth;
  constant clock_period : time := 500 ns;  -- clock period
  subtype sfixed7 is sfixed (3 downto -3);  -- 7 bit
  subtype sfixed16 is sfixed (7 downto -8);  -- 16 bit
  signal stop_clock : boolean := false;  -- stop the clock
  signal clk, rst_n : std_ulogic;                      -- clk and reset
  signal in1slv, in2slv, out1slv : std_logic_vector(15 downto 0);
  signal in1, in2   : sfixed16;             -- inputs
  signal out1       : sfixed16;             -- output
  signal cmd : std_logic_vector (3 downto 0);  -- command string
begin  -- architecture testbench

  -- From fixed point to Std_logic_vector
  in1slv <= to_slv(in1);
  in2slv <= to_slv(in2);
  -- Std_logic_vector to fixed point.
  out1 <= to_sfixed(out1slv, out1'high, out1'low);
  DUT: fixed_synth
    port map (
      in1   => in1slv,     -- [in  std_logic_vector (15 downto 0)] inputs
      in2   => in2slv,     -- [in  std_logic_vector (15 downto 0)] inputs
      out1  => out1slv,    -- [out std_logic_vector (15 downto 0)] output
      cmd   => cmd,                     -- [in  std_logic_vector (2 downto 0)]
      clk   => clk,                     -- [in  std_ulogic] clk and reset
      rst_n => rst_n);                  -- [in std_ulogic] clk and reset

  -- purpose: clock driver
  clkprc: process is
  begin  -- process clkprc
    if (not stop_clock) then
      clk <= '0';
      wait for clock_period/2.0;
      clk <= '1';
      wait for clock_period/2.0;
    else
      wait;
    end if;
  end process clkprc;

  -- purpose: reset driver
  reset_proc: process is
  begin  -- process reset_proc
    rst_n <= '0';
    wait for clock_period * 2.0;
    rst_n <= '1';
    wait;
  end process reset_proc;

  -- purpose: main test loop
  tester: process is
  begin  -- process tester
    cmd <= "0000";                       -- add mode
    in1 <= (others => '0');
    in2 <= (others => '0');
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0001";                        -- subtract mode
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0010";                        -- multiply mode
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0000";                       -- add mode
    in1 <= "0000000010000000";          -- 0.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    in1 <= to_sfixed (3.14, sfixed16'high, sfixed16'low);
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0011";                       -- divide
    in1 <= "0000000010000000";          -- 0.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    in1 <= to_sfixed (-0.5, sfixed16'high, sfixed16'low);          -- -0.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    cmd <= "0100";                      -- unsigned add
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0101";                        -- subtract mode
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0110";                        -- multiply mode
    in1 <= "0000011010000000";  -- 6.5
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0100";                       -- add mode
    in1 <= "0000000010000000";          -- 0.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    in1 <= to_sfixed (3.14, sfixed16'high, sfixed16'low);
    in2 <= "0000001100000000";  -- 3
    wait for clock_period;
    cmd <= "0111";                       -- divide
    in1 <= "0000000010000000";          -- 0.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    in1 <= to_sfixed (6.5, sfixed16'high, sfixed16'low);          -- 6.5
    in2 <= "0000000010000000";          -- 0.5
    wait for clock_period;
    -- resize
    cmd <= "1000";
    in1 <= to_sfixed (5.25, in1);
    in2 <= to_sfixed (-5.25, in2);
    wait for clock_period;
    in1 <= to_sfixed (21.125, in1);
    in2 <= to_sfixed (21.125, in2);
    wait for clock_period;
    in2 <= (in2'high => '0', in2'high-1 => '0', others => '0');
    cmd <= "1001";                      -- SIGNED
    in1 <= to_sfixed (6.25, in1);
    wait for clock_period;
    in2 <= (in2'high => '0', in2'high-1 => '1', others => '0');
    cmd <= "1001";                      -- UNSIGNED
    in1 <= to_sfixed (7.25, in1);
    wait for clock_period;
    in2 <= (in2'high => '1', in2'high-1 => '0', others => '0');
    cmd <= "1001";                      -- SIGNED
    in1 <= to_sfixed (6.25, in1);
    wait for clock_period;
    in2 <= (in2'high => '1', in2'high-1 => '1', others => '0');
    cmd <= "1001";                      -- UNSIGNED
    in1 <= to_sfixed (7.25, in1);
    wait for clock_period;
    cmd <= "1010";
    in2 <= (in2'high => '0', in2'high-1 => '0', others => '0');
    in1 <= to_sfixed (3, in1);
    wait for clock_period;
    cmd <= "1010";
    in2 <= (in2'high => '0', in2'high-1 => '1', others => '0');
    in1 <= to_sfixed (5, in1);
    wait for clock_period;
    cmd <= "1010";
    in2 <= (in2'high => '1', in2'high-1 => '0', others => '0');
    in1 <= to_sfixed (-5.5, in1);
    wait for clock_period;
    cmd <= "1010";
    in2 <= (in2'high => '1', in2'high-1 => '1', others => '0');
    in1 <= to_sfixed (7.25, in1);
    wait for clock_period;
    cmd <= "1010";                      -- abs (mod)
    in2 <= (in2'high => '1', in2'high-1 => '0', others => '0');
    in1 <= to_sfixed (-42, in1);
    wait for clock_period;
    cmd <= "1011";                      -- mod
    in1 <= to_sfixed (6.25, in1);
    in2 <= to_sfixed (6, in2);
    wait for clock_period;
    cmd <= "1100";                      -- REM
    in1 <= to_sfixed (6.25, in1);
    in2 <= to_sfixed (6, in2);
    wait for clock_period;
    cmd <= "1101";                      -- srl
    in1 <= to_sfixed (5.25, in1);
    in2 <= to_sfixed (-1, in2);
    wait for clock_period;
    cmd <= "1110";                      -- sra
    in1 <= to_sfixed (-7.25, in1);
    in2 <= to_sfixed (1, in2);
    wait for clock_period;
    cmd <= "1111";                      -- compare
    in1 <= to_sfixed (42, in1);
    in2 <= to_sfixed (42, in1);
    wait for clock_period;
    in1 <= to_sfixed (45, in1);
    in2 <= to_sfixed (90, in1);
    wait for clock_period;
    in1 <= to_sfixed (3.125, in1);
    in2 <= (others => '0');
    wait for clock_period;
    in1 <= "0110111110101111";
    in2 <= "1111111111111111";
    wait for clock_period;
    in1 <= (others => '0');
    in2 <= (others => '0');
    wait for clock_period;
    in1 <= "0000111000000000";
    in2 <= "0000111000000000";
    wait for clock_period;
    in1 <= (others => '1');
    in2 <= (others => '1');
    wait for clock_period;
    wait for clock_period;

    wait for clock_period;
    cmd <= "0000";                       -- add mode
    in1 <= (others => '0');
    in2 <= (others => '0');
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait;
  end process tester;

  -- purpose: check the output of the tester
  -- type   : combinational
  -- inputs :
  -- outputs:
  checktest: process is
    constant fxzero : sfixed16 := (others => '0');  -- zero
    variable chks16 : sfixed16;         -- variable
    variable sm1, sm2 : sfixed7;        -- small fixed point
  begin  -- process checktest
    wait for clock_period/2.0;
    wait for clock_period;
    wait for clock_period;
    waitloop: while (out1 = fxzero) loop
      wait for clock_period;
    end loop waitloop;
    chks16 := to_sfixed ((3.0+6.5), sfixed16'high, sfixed16'low);
    report_error ( "3.0 + 6.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed ((6.5 - 3.0), sfixed16'high, sfixed16'low);
    report_error ( "6.5 - 3.0 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed ((6.5 * 3.0), sfixed16'high, sfixed16'low);
    report_error ( "6.5 * 3.0 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (1, sfixed16'high, sfixed16'low);
    report_error ( "0.5 + 0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (6.14, sfixed16'high, sfixed16'low);
    report_error ( "3.14 + 3 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := "0000000100000000";
    report_error ( "0.5/0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (-1, sfixed16'high, sfixed16'low);
    report_error ( "-0.5/0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed ((3.0+6.5), sfixed16'high, sfixed16'low);
    report_error ( "3.0 + 6.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed ((6.5 - 3.0), sfixed16'high, sfixed16'low);
    report_error ( "6.5 - 3.0 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed ((6.5 * 3.0), sfixed16'high, sfixed16'low);
    report_error ( "6.5 * 3.0 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (1, sfixed16'high, sfixed16'low);
    report_error ( "0.5 + 0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (6.14, sfixed16'high, sfixed16'low);
    report_error ( "3.14 + 3 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := "0000000100000000";
    report_error ( "0.5/0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    chks16 := to_sfixed (13, sfixed16'high, sfixed16'low);
    report_error ( "6.5/0.5 error",
                   out1,
                   chks16);
    wait for clock_period;
    -- resize test
    sm1 := out1 (7 downto 1);
    sm2 := to_sfixed (5.25, sm2);
    report_error ( "resize 1 error", sm1, sm2);
    sm1 := out1 (-1 downto -7);
    sm2 := to_sfixed (-5.25, sm2);
    report_error ( "resize 2 error", sm1, sm2);
    wait for clock_period;
    sm1 := out1 (7 downto 1);
    sm2 := "0101001";                   -- wrapped
--    sm2 := to_sfixed (21.125, sm2, 0, false, false);  -- wrap, no round
    report_error ( "resize 1 error", sm1, sm2);
    sm1 := out1 (-1 downto -7);
    sm2 := "0111111";  -- saturate
    report_error ( "resize 2 error", sm1, sm2);
    wait for clock_period;
    -- to_signed and back
    report_error ("to_signed(6.25)", out1, to_sfixed (6, out1));
    wait for clock_period;
    -- to_unsigned and back
    report_error ("to_unsigned(7.25)", out1, to_sfixed (7, out1));
    wait for clock_period;
        -- to_integer and back
    report_error ("to_signed(6.25)", out1, to_sfixed (6, out1));
    wait for clock_period;
    -- to_integer(ufixed) and back
    report_error ("to_unsigned(7.25)", out1, to_sfixed (7, out1));
    wait for clock_period;
    report_error ("1/3", out1, to_sfixed (1.0/3.0, out1'high, -7));
    wait for clock_period;
    report_error ("unsigned 1/5", out1, to_sfixed (1.0/5.0, out1));
    wait for clock_period;
    report_error ("abs (-5.5)", out1, to_sfixed (5.5, out1));
    wait for clock_period;
    report_error ("-7.25", out1, to_sfixed (-7.25, out1));
    wait for clock_period;
    report_error ("abs(-42)", out1, to_sfixed (42, out1));
    wait for clock_period;
    report_error ("6.25 mod 6", out1, to_sfixed (0.25, out1));
    wait for clock_period;
    report_error ("6.25 rem 6", out1, to_sfixed (0.25, out1));
    wait for clock_period;
    chks16 := "0000101010000000";
    report_error ("5.25 srl -1", out1, chks16);
    wait for clock_period;
    chks16 := "1111110001100000";
    report_error ("-7.25 sra 1", out1, chks16);
    wait for clock_period;
    --         7654321012345678
    chks16 := "0111000000110001";
    assert (std_match (out1, chks16))
      report "42=42 compare " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    chks16 := "------0001010110";
    assert (std_match (out1, chks16))
      report "45=90 compare " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    chks16 := "------1010101010";
    assert (std_match (out1, chks16))
      report "3.125=0 compare " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    --         7654321012345678
    chks16 := "0--1010000101010";
    assert (std_match (out1, chks16))
      report "pattern1 compare " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    --         7654321012345678
    chks16 := "0001100000110001";
    assert (std_match (out1, chks16))
      report "zero = zero " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    --         7654321012345678
    chks16 := "1111000000110001";
    assert (std_match (out1, chks16))
      report "pattern2 compare " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    --         7654321012345678
    chks16 := "0111000000110001";
    assert (std_match (out1, chks16))
      report "-1 = -1 " & CR
      & "Actual   " & to_string(out1) & CR
      & "Expected " & to_string(chks16) severity error;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    wait for clock_period;
    assert (false) report "Testing complete" severity note;
    stop_clock <= true;
    wait;
  end process checktest;
end architecture testbench;

entity test_fixed_synth is
  generic (
    quiet : boolean := false);  -- make the simulation quiet
end entity test_fixed_synth;


-------------------------------------------------------------------------------
-- test routine for the post synthesis 32 bit multiply
-------------------------------------------------------------------------------

entity test_float_synth is
  generic (
    quiet : BOOLEAN := false);
end entity test_float_synth;

use std.textio.all;
library ieee, ieee_proposed;
use ieee.math_real.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.fixed_pkg.all;
use ieee_proposed.float_pkg.all;

--library modelsim_lib;
--use modelsim_lib.util.all;

architecture testbench of test_float_synth is
  subtype fp16 is float (6 downto -9);  -- 16 bit
  function reverse (
    inpvec : STD_LOGIC_VECTOR (0 to 31))
    return float32 is
    variable result : float32;
  begin
    for i in 0 to 31 loop
      result (i-23) := inpvec(i);
    end loop;  -- i
    return result;
  end function reverse;

  -- purpose: converts an float32 into a std_logic_vector
--  function to_slv (
--    input : float32)                        -- float32 input
--    return std_logic_vector is
--    variable result : std_logic_vector (31 downto 0);  -- result
--  begin  -- function to_slv
--    floop: for i in float32'range loop
--      result (i + fp_fraction_width) := input (i);
--    end loop floop;
--    return result;
--  end function to_slv;

  -- purpose: converts a std_logic_vector to an float32
  function to_float32x (
    signal input : STD_LOGIC_VECTOR (31 downto 0))
    return float32 is
    variable result : float32;
  begin  -- function to_float32x
    return to_float (input, float32'high, -float32'low);
  end function to_float32x;

  procedure report_error (
    constant errmes   :    STRING;       -- error message
    actual            : in float32;      -- data from algorithm
    constant expected :    float32)  is  -- reference data
  begin  -- function report_error
    assert actual = expected
      report errmes & " miscompare" & CR &
      "Actual   " & to_string (actual) & " ("
      & REAL'image(to_real(actual))& ") /= " & CR &
      "Expected " & to_string (expected) & " ("
      & REAL'image(to_real(expected))& ")"
      severity error;
    return;
  end procedure report_error;
  procedure report_error16 (
    constant errmes   :    STRING;       -- error message
    actual            : in fp16;         -- data from algorithm
    constant expected :    fp16)  is     -- reference data
  begin  -- function report_error
    assert actual = expected
      report errmes & " miscompare" & CR &
      "Actual   " & to_string (actual) & " ("
      & REAL'image(to_real(actual))& ") /= " & CR &
      "Expected " & to_string (expected) & " ("
      & REAL'image(to_real(expected))& ")"
      severity error;
    return;
  end procedure report_error16;

  component float_synth is
    port (
      in1, in2   : in  STD_LOGIC_VECTOR(31 downto 0);  -- inputs
      out1       : out STD_LOGIC_VECTOR(31 downto 0);  -- output
      cmd        : in  STD_LOGIC_VECTOR (3 downto 0);
      clk, rst_n : in  STD_ULOGIC);     -- clk and reset
  end component float_synth;
  for all : float_synth
    use entity work.float_synth(rtl);
  constant clock_period          : TIME    := 500 ns;  -- clock period
  signal stop_clock              : BOOLEAN := false;   -- stop the clock
  signal out1real                : REAL;               -- real version
  signal in1, in2                : float32;            -- inputs
  signal out1                    : float32;            -- output
  constant zero0                 : float32 := (others => '0');     -- zero
  signal cmd                     : STD_LOGIC_VECTOR (3 downto 0);  -- command
  signal clk, rst_n              : STD_ULOGIC;         -- clk and reset
  signal in1slv, in2slv, out1slv : STD_LOGIC_VECTOR(31 downto 0);
  signal indelay                 : float32;            -- spied signal
begin  -- architecture testbench
  out1real <= to_real (out1);
  in1slv   <= to_slv(in1);
  in2slv   <= to_slv(in2);
  out1     <= to_float32x(out1slv);
  DUT : float_synth
    port map (
      in1   => in1slv,                  -- [in  float32] inputs
      in2   => in2slv,                  -- [in  float32] inputs
      out1  => out1slv,                 -- [out float32] output
      cmd   => cmd,
      clk   => clk,                     -- [in  std_ulogic] clk and reset
      rst_n => rst_n);                  -- [in std_ulogic] clk and reset

--  spy_process : process
--  begin
--    signal_force ("/DUT/in2reg3", "00000000000000000000000000000000",
--                  500 ns, freeze, 5000 ns, 1);
--    wait;
--  end process spy_process;

  -- purpose: clock driver
  -- type   : combinational
  -- inputs :
  -- outputs:
  clkprc : process is

  begin  -- process clkprc


------------------------------------------------------------------------------
-- Title      : convElement
-- Project    : Haddoc2
------------------------------------------------------------------------------
-- File       : convElement.vhd
-- Author     : K. Abdelouahab
-- Company    : Institut Pascal
-- Last update: 2018-08-23
------------------------------------------------------------------------------
-- Description: A fully pipelined implementation of CNN layers that is able to process
--              one pixel/clock cycle. Each actors of a CNN graph are directly mapped
--              on the hardware following the principals of DHM and DataFlow processing
--                            ______
--                          |       |
--                          |       |-- output_streams-->
--        input_streams---->| conv  |-- output_streams-->
--        input_streams---->| Layer |-- output_streams-->
--        input_streams---->|       |-- output_streams-->
--        input_streams---->|       |-- output_streams-->
--                          |       |-- output_streams-->
--                           ______
-----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.math_real.all;
library work;
use work.cnn_types.all;

entity ConvLayer is
  generic(
    BITWIDTH   : integer;
    IMAGE_WIDTH  : integer;
    SUM_WIDTH    : integer;
    KERNEL_SIZE  : integer;
    NB_IN_FLOWS  : integer;
    NB_OUT_FLOWS : integer;
    KERNEL_VALUE : pixel_matrix;
    BIAS_VALUE   : pixel_array
    );

  port(
    clk      : in  std_logic;
    reset_n  : in  std_logic;
    enable   : in  std_logic;
    in_data  : in  pixel_array(0 to NB_IN_FLOWS - 1);
    in_dv    : in  std_logic;
    in_fv    : in  std_logic;
    out_data : out pixel_array(0 to NB_OUT_FLOWS - 1);
    out_dv   : out std_logic;
    out_fv   : out std_logic
    );
end entity;

architecture STRUCTURAL of ConvLayer is
  --------------------------------------------------------------------------------
  -- COMPONENTS
  --------------------------------------------------------------------------------
  component TensorExtractor
    generic (
      BITWIDTH  : integer;
      IMAGE_WIDTH : integer;
      KERNEL_SIZE : integer;
      NB_IN_FLOWS : integer
      );
    port (
      clk      : in  std_logic;
      reset_n  : in  std_logic;
      enable   : in  std_logic;
      in_data  : in  pixel_array (0 to NB_IN_FLOWS - 1);
      in_dv    : in  std_logic;
      in_fv    : in  std_logic;
      out_data : out pixel_array (0 to NB_IN_FLOWS * KERNEL_SIZE * KERNEL_SIZE- 1);
      out_dv   : out std_logic;
      out_fv   : out std_logic
      );
  end component TensorExtractor;

  component DotProduct
    generic (
      BITWIDTH       : integer;
      SUM_WIDTH        : integer;
      DOT_PRODUCT_SIZE : integer;
      KERNEL_VALUE     : pixel_array;
      BIAS_VALUE       : std_logic_vector
      );
    port (
      clk      : in  std_logic;
      reset_n  : in  std_logic;
      enable   : in  std_logic;
      in_data  : in  pixel_array (0 to DOT_PRODUCT_SIZE - 1);
      in_dv    : in  std_logic;
      in_fv    : in  std_logic;
      out_data : out std_logic_vector (SUM_WIDTH-1 downto 0);
      out_dv   : out std_logic;
      out_fv   : out std_logic
      );
  end component DotProduct;

  component TanhLayer
    generic (
      BITWIDTH : integer;
      SUM_WIDTH  : integer
      );
    port (
      in_data  : in  std_logic_vector (SUM_WIDTH-1 downto 0);
      out_data : out std_logic_vector (BITWIDTH-1 downto 0)
      );
  end component TanhLayer;
  ------------------------------------------------------------------------------------------
  signal neighborhood_data : pixel_array (0 to NB_IN_FLOWS * KERNEL_SIZE * KERNEL_SIZE- 1);
  signal neighborhood_dv   : std_logic;
  signal neighborhood_fv   : std_logic;
  signal dp_data           : sum_array (0 to NB_OUT_FLOWS-1);
  signal dp_dv             : std_logic;
  signal dp_fv             : std_logic;
-----------------------------------------------------------------------------------------
begin

  TensorExtractor_i : TensorExtractor

      enable   => enable,
      in_data  => in_data,
      in_dv    => in_dv,
      in_fv    => in_fv,
      out_data => neighborhood_data,
      out_dv   => neighborhood_dv,
      out_fv   => neighborhood_fv
      );

  DotProduct_loop : for n in 0 to NB_OUT_FLOWS- 1 generate
    DotProduct_i : DotProduct
      generic map (
        BITWIDTH       => BITWIDTH,
        SUM_WIDTH        => SUM_WIDTH,
        DOT_PRODUCT_SIZE => NB_IN_FLOWS * KERNEL_SIZE * KERNEL_SIZE,
        BIAS_VALUE       => BIAS_VALUE(n),
        KERNEL_VALUE     => extractRow(n,
                                   NB_OUT_FLOWS,  -- N
                                   NB_IN_FLOWS * KERNEL_SIZE * KERNEL_SIZE,  -- CJK
                                   KERNEL_VALUE)  --Theta(n)
        )
      port map (
        clk      => clk,
        reset_n  => reset_n,
        enable   => enable,
        in_data  => neighborhood_data,
        in_dv    => neighborhood_dv,
        in_fv    => neighborhood_fv,
        out_data => dp_data(n),
        out_dv   => open,
        out_fv   => open
        );

    -- Dummy Activation
    TanhLayer_i : TanhLayer
      generic map (
        BITWIDTH => BITWIDTH,
        SUM_WIDTH  => SUM_WIDTH
        )
      port map (
        in_data  => dp_data(n),
        out_data => out_data(n)
        );

    out_dv <= in_dv;
    out_fv <= in_fv;
  end generate;

end architecture;

    generic map (
      BITWIDTH  => BITWIDTH,
      IMAGE_WIDTH => IMAGE_WIDTH,
      KERNEL_SIZE => KERNEL_SIZE,
      NB_IN_FLOWS => NB_IN_FLOWS


------------------------------------------------------------------------------
-- Title      : DisplayLayer
-- Project    : Haddoc2
------------------------------------------------------------------------------
-- File       : display_mux.vhd
-- Author     : K. Abdelouahab
-- Company    : Institut Pascal
-- Last update: 2018-08-23
------------------------------------------------------------------------------
-- Description: A design of a multiplexer to be used at the end of a CNN. Can
--              be used for display puposes
------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

library work;
use work.cnn_types.all;

entity DisplayLayer is
  generic(
    BITWIDTH  : integer;
    NB_IN_FLOWS : integer
    );
  port(
    in_data  : in  pixel_array (0 to NB_IN_FLOWS-1);
    in_dv    : in  std_logic;
    in_fv    : in  std_logic;
    sel      : in  std_logic_vector(31 downto 0);
    out_data : out std_logic_vector(BITWIDTH-1 downto 0);
    out_dv   : out std_logic;
    out_fv   : out std_logic
    );
end entity;

architecture bhv of DisplayLayer is

begin
  out_data <= in_data(to_integer(unsigned(sel)));
  out_dv   <= in_dv;
  out_fv   <= in_fv;