LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL;
PACKAGE p_time_pack IS
  TYPE t_time_mode IS (minimum, typical, maximum);
  TYPE t_rise_fall IS
    RECORD
      rise : TIME;
      fall : TIME;
    END RECORD;

  TYPE t_time_rec IS ARRAY(t_time_mode'LOW TO
                  t_time_mode'HIGH) OF t_rise_fall;

  FUNCTION calc_delay(newstate : IN std_logic; mode : IN t_time_mode;
                     delay_tab : IN t_time_rec ) return time;

END p_time_pack;

PACKAGE BODY p_time_pack IS
  FUNCTION calc_delay(newstate : IN std_logic; mode : IN t_time_mode;
                     delay_tab : IN t_time_rec ) return time IS
  BEGIN
    CASE TO_X01(newstate) IS
      WHEN '0' =>
        RETURN delay_tab(mode).fall;
      WHEN '1' =>
        RETURN delay_tab(mode).rise;
      WHEN 'X' =>
        IF (delay_tab(mode).rise <= delay_tab(mode).fall) THEN
          RETURN delay_tab(mode).rise;
        ELSE
          RETURN delay_tab(mode).fall;
        END IF;
    END CASE;
  END calc_delay;
END p_time_pack;



LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL;
USE WORK.p_time_pack.ALL;
ENTITY inv IS
  GENERIC( mode : t_time_mode;
           delay_tab : t_time_rec := 
            (( 1 ns, 2 ns),  -- min
             ( 2 ns, 3 ns),  -- typ
             ( 3 ns, 4 ns)));   -- max

  PORT( a : IN std_logic;
        b : OUT std_logic);
END inv;

ARCHITECTURE inv_gen OF inv IS
BEGIN 
  inv_proc : PROCESS(a)
    VARIABLE state : std_logic;
  BEGIN
    state := NOT(a);
    b <= state after calc_delay( state, mode, delay_tab);
  END PROCESS inv_proc;
END inv_gen;

LIBRARY IEEE; USE IEEE.std_logic_1164.ALL;
USE WORK.p_time_pack.ALL;
ENTITY and3 IS
  GENERIC( mode : t_time_mode;
    delay_tab : t_time_rec := 
       (( 2 ns, 3 ns),  -- min
        ( 3 ns, 4 ns),  -- typ
        ( 4 ns, 5 ns)));        -- max

  PORT( a1, a2, a3 : IN std_logic;
        o1 : OUT std_logic);
END and3; 

ARCHITECTURE and3_gen OF and3 IS 
BEGIN
  and3_proc : PROCESS( a1, a2, a3 )
    VARIABLE state : std_logic;
  BEGIN
    state := a1 AND a2 AND a3;
    o1 <= state after calc_delay( state, mode, delay_tab);
  END PROCESS and3_proc;
END and3_gen;


-----------------------------------------------------------------
--- added to make below compile
-----------------------------------------------------------------
use work.p_time_pack.all;
-----------------------------------------------------------------
ARCHITECTURE structural OF decode IS
  COMPONENT inv
    GENERIC( mode : t_time_mode;
             delay_tab : t_time_rec);
    PORT( a : IN std_logic;
          b : OUT std_logic);
  END COMPONENT;

  COMPONENT and3
    GENERIC( mode : t_time_mode;
             delay_tab : t_time_rec);
    PORT( a1, a2, a3 : IN std_logic;
          o1 : OUT std_logic);
  END COMPONENT;

  SIGNAL nota, notb : std_logic;
BEGIN
  I1 : inv
    GENERIC MAP( mode => maximum,
                 delay_tab => ((1.3 ns, 1.9 ns),
                               (2.1 ns, 2.9 ns),
                               (3.2 ns, 4.1 ns)))
    PORT MAP( a, nota );

  I2 : inv
    GENERIC MAP( mode => minimum,
                 delay_tab => ((1.3 ns, 1.9 ns),
                               (2.1 ns, 2.9 ns),
                               (3.2 ns, 4.1 ns)))
    PORT MAP( b, notb );

  A1 : and3
    GENERIC MAP( mode => typical,
                 delay_tab => ((1.3 ns, 1.9 ns),                                                                                      (2.1 
                               (2.1 ns, 2.9 ns),                                                                              (3.2 
                               (3.2 ns, 4.1 ns)))
    PORT MAP( nota, en, notb, q0 );

  A2 : and3
    GENERIC MAP( mode => minimum,
                 delay_tab => ((1.3 ns, 1.9 ns),
                               (2.1 ns, 2.9 ns),
                               (3.2 ns, 4.1 ns)))
    PORT MAP( a, en, notb, q1 );

  A3 : and3
    GENERIC MAP( mode => maximum,
                 delay_tab => ((1.3 ns, 1.9 ns),
                               (2.1 ns, 2.9 ns),
                               (3.2 ns, 4.1 ns)))
    PORT MAP( nota, en, b, q2 );

  A4 : and3
    GENERIC MAP( mode => maximum,
                 delay_tab => ((2.3 ns, 2.9 ns),
                               (3.1 ns, 3.9 ns),
                               (4.2 ns, 5.1 ns)))
    PORT MAP( a, en, b, q3 );
END structural;



CONFIGURATION decode_gen_con2 OF decode IS
  FOR structural
    FOR i1, i2 : inv USE ENTITY WORK.inv(inv_gen);
    END FOR;

    FOR a1, a2, a3, a4 : and3 USE ENTITY WORK.and3(and3_gen);
    END FOR;
  END FOR;
END decode_gen_con2;



LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL;
ENTITY inv IS
  GENERIC(int_rise, int_fall, ext_rise, 
          ext_fall : time);
  PORT( a: IN std_logic; b: OUT std_logic);
END inv;

ARCHITECTURE inv_gen1 OF inv IS
BEGIN
  inv_proc : PROCESS(a)
    VARIABLE state : std_logic;
  BEGIN
    state := NOT(a);
    IF state = '1' THEN
      b <= state AFTER (int_rise + ext_rise);
    ELSIF state = '0' THEN
      b <=state AFTER (int_fall + ext_fall);
    ELSE
      b <= state AFTER (int_fall + ext_fall);
    END IF;
  END PROCESS inv_proc;
END inv_gen1;
-------------------------------------------------
LIBRARY IEEE; USE IEEE.std_logic_1164.ALL;
ENTITY and3 IS
  GENERIC(int_rise, int_fall, ext_rise, ext_fall : time);
  PORT( a1, a2, a3: IN std_logic;
        o1: OUT std_logic);
END and3;

ARCHITECTURE and3_gen1 OF and3 IS
BEGIN
  and3_proc : PROCESS(a1, a2, a3)
    VARIABLE state : std_logic;
  BEGIN
    state := a1 AND a2 AND a3;

    IF state = '1' THEN
      o1 <= state AFTER (int_rise + ext_rise);
    ELSIF state = '0' THEN
      o1 <= state AFTER (int_fall + ext_fall);
    ELSE
      o1 <= state AFTER (int_fall + ext_fall);
    END IF;

  END PROCESS and3_proc;
END and3_gen1;



LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL;
ENTITY decode IS
  PORT( a, b, en : IN std_logic;
        q0, q1, q2, q3 : OUT std_logic);
END decode;

ARCHITECTURE structural OF decode IS
  COMPONENT inv
    PORT( a : IN std_logic;
          b : OUT std_logic);
  END COMPONENT;

  COMPONENT and3
    PORT( a1, a2, a3 : IN std_logic;
          o1 : OUT std_logic);
  END COMPONENT;

  SIGNAL nota, notb : std_logic;
BEGIN
  I1 : inv
    PORT MAP( a, nota);

  I2 : inv
    PORT MAP( b, notb);

  AN1 : and3
    PORT MAP( nota, en, notb, q0);

  AN2 : and3
    PORT MAP( a, en, notb, q1);

  AN3 : and3
    PORT MAP( nota, en, b, q2);

  AN4 : and3
    PORT MAP( a, en, b, q3);
END structural;




CONFIGURATION decode_gen1_con OF decode IS
  FOR structural
    FOR I1 : inv USE ENTITY WORK.inv(inv_gen1)
      GENERIC MAP( int_rise => 1.2 ns,
                   int_fall => 1.7 ns,
                   ext_rise => 2.6 ns,
                   ext_fall => 2.5 ns);
    END FOR;

    FOR I2 : inv USE ENTITY WORK.inv(inv_gen1)
      GENERIC MAP( int_rise => 1.3 ns,
                   int_fall => 1.4 ns,
                   ext_rise => 2.8 ns,
                   ext_fall => 2.9 ns);
    END FOR;

    FOR AN1 : and3 USE ENTITY WORK.and3(and3_gen1)
      GENERIC MAP( int_rise => 2.2 ns,
                   int_fall => 2.7 ns,
                   ext_rise => 3.6 ns,
                   ext_fall => 3.5 ns);
    END FOR;

    FOR AN2 : and3 USE ENTITY WORK.and3(and3_gen1)
      GENERIC MAP( int_rise => 2.2 ns,
                   int_fall => 2.7 ns,
                   ext_rise => 3.1 ns,
                   ext_fall => 3.2 ns);
    END FOR;

    FOR AN3 : and3 USE ENTITY WORK.and3(and3_gen1)
      GENERIC MAP( int_rise => 2.2 ns,
                   int_fall => 2.7 ns, 
                   ext_rise => 3.3 ns,
                   ext_fall => 3.4 ns);
    END FOR;

    FOR AN4 : and3 USE ENTITY WORK.and3(and3_gen1)
      GENERIC MAP( int_rise => 2.2 ns,
                   int_fall => 2.7 ns,
                   ext_rise => 3.0 ns,
                   ext_fall => 3.1 ns);
    END FOR;
  END FOR;
END decode_gen1_con;




