--------------------------------------------------------------------------------
--  File name : dresistor.vhd
--------------------------------------------------------------------------------
--  Copyright (C) 1997 Free Model Foundation
--
--  This program is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License version 2 as
--  published by the Free Software Foundation.
--
--  MODIFICATION HISTORY :
--
--    version: |  author:  | mod date:  | changes made:
--      V1.0    R. Vreeland  96 AUG  9    resolution functions
--      V2.0     R. Steele   96 AUG 12    added Vital delays
--      V2.1        rev3     97 FEB 28    removed prop delays, added
--                                        property to test for 'Z' output
-- -----------------------------------------------------------------------------
--   PART DESCRIPTION :
-- 
--   Library:     DISCRETE
--   Technology:  CARBON
--   Part:        DRESISTOR
-- 
--   Desciption:  Backannotatable Resistor
-- -----------------------------------------------------------------------------
LIBRARY IEEE;   USE IEEE.std_logic_1164.ALL;
                USE IEEE.VITAL_primitives.all;
                USE IEEE.VITAL_timing.all;
LIBRARY FMF;    USE FMF.gen_utils.all;

--------------------------------------------------------------------------------
--  ENTITY DECLARATION
--------------------------------------------------------------------------------
ENTITY dresistor IS
    GENERIC (
        -- tipd delays: interconnect path delays
        tipd_A              : VitalDelayType01 := VitalZeroDelay01;
        tipd_B              : VitalDelayType01 := VitalZeroDelay01;
        -- pass in whether resistor is open-circuit in simulation
        OpenCircuit         : Boolean := FALSE;
        -- generic control parameters
        InstancePath        : STRING := DefaultInstancePath
    );
    PORT (    
        A               : INOUT STD_LOGIC := 'Z';
        B               : INOUT STD_LOGIC := 'Z'
    );

    ATTRIBUTE VITAL_level0 OF dresistor : ENTITY IS TRUE;
END dresistor;

--------------------------------------------------------------------------------
--  ARCHITECTURE DECLARATION
--------------------------------------------------------------------------------
ARCHITECTURE vhdl_behavioral OF dresistor IS
    ATTRIBUTE VITAL_level1 OF vhdl_behavioral : ARCHITECTURE IS FALSE;

    TYPE stdlogic_map IS ARRAY(std_logic) OF std_logic;
    TYPE int_stdlogic_table IS ARRAY(STD_LOGIC, STD_LOGIC)
                                 OF NATURAL RANGE 0 to 2;

    SIGNAL drive_A    : STD_ULOGIC := 'Z';
    SIGNAL drive_B    : STD_ULOGIC := 'Z';
    SIGNAL A_ipd      : STD_LOGIC := 'Z';
    SIGNAL B_ipd      : STD_LOGIC := 'Z';

    CONSTANT unres_table : int_stdlogic_table := (
    --      ---------------------------------------
    --      | U  X  0  1  Z  W  L  H  -       |   |
    --      ---------------------------------------
            ( 2, 0, 0, 0, 0, 0, 0, 0, 0 ), -- | U |
            ( 1, 2, 0, 0, 0, 0, 0, 0, 0 ), -- | X |
            ( 1, 1, 2, 0, 0, 0, 0, 0, 0 ), -- | 0 |
            ( 1, 1, 0, 2, 0, 0, 0, 0, 0 ), -- | 1 |
            ( 1, 1, 1, 1, 2, 1, 1, 1, 0 ), -- | Z |
            ( 1, 1, 1, 1, 0, 2, 0, 0, 0 ), -- | W |
            ( 1, 1, 1, 1, 0, 1, 2, 0, 0 ), -- | L |
            ( 1, 1, 1, 1, 0, 1, 0, 2, 0 ), -- | H |
            ( 1, 1, 0, 0, 0, 0, 0, 0, 2 )  -- | - |
    );

    CONSTANT res_drive_val : stdlogic_map :=

    --  -----------------------------------------------
    --  |  U    X    0    1    Z    W    L    H    -  |
    --  -----------------------------------------------
        ( 'W', 'W', 'L', 'H', 'Z', 'Z', 'L', 'H', 'W' );

BEGIN
    ----------------------------------------------------------------------------
    -- Wire delays
    ----------------------------------------------------------------------------
    WIRE_DELAY : BLOCK
    BEGIN

        w_1:  VitalWireDelay (A_ipd, A, tipd_A);
        w_2:  VitalWireDelay (B_ipd, B, tipd_B);

    END BLOCK;

    ----------------------------------------------------------------------------
    -- A Side Process
    ----------------------------------------------------------------------------
    ASide: PROCESS

        -- Functionality Result Variable
        VARIABLE state  : NATURAL RANGE 0 TO 2;
        VARIABLE A_ipd_rv : std_ulogic;
 
    BEGIN
        ------------------------------------------------------------------------
        -- Functionality Section
        ------------------------------------------------------------------------
        IF (OpenCircuit) THEN WAIT;
        END IF;

        WAIT ON A_ipd'TRANSACTION;

        state := unres_table(drive_A, A_ipd);
        A_ipd_rv := res_drive_val(A_ipd);

        CASE state IS

            WHEN 0 =>
                ASSERT FALSE REPORT "Illegal port A/drive_A combo"
                SEVERITY FAILURE;

            WHEN 1 =>
                IF (A_ipd_rv /= drive_B) THEN
                    B <= A_ipd_rv;
                    B_ipd <= A_ipd_rv;
                    drive_B <= A_ipd_rv;
                END IF;

            WHEN OTHERS =>
                IF (drive_B /= 'Z' and drive_B /= A_ipd_rv) THEN
                    B <= A_ipd_rv;
                    B_ipd <= A_ipd_rv;
                    drive_B <= A_ipd_rv;
                END IF;

        END CASE;

    END PROCESS;                                 

    ----------------------------------------------------------------------------
    -- B Side Process
    ----------------------------------------------------------------------------
    BSide: PROCESS

        -- Functionality Result Variable
        VARIABLE state  : NATURAL RANGE 0 To 2;
        VARIABLE B_ipd_rv : std_ulogic;

    BEGIN
        ------------------------------------------------------------------------
        -- Functionality Section
        ------------------------------------------------------------------------
        IF (OpenCircuit) THEN WAIT;
        END IF;

        WAIT ON B_ipd'TRANSACTION;

        state := unres_table(drive_B, B_ipd);
        B_ipd_rv := res_drive_val(B_ipd);

        CASE state IS

            WHEN 0 =>
                ASSERT FALSE REPORT "Illegal port B/drive_B combo"
                SEVERITY FAILURE;

            WHEN 1 =>
                IF (B_ipd_rv /= drive_A) THEN
                    A <= B_ipd_rv;
                    A_ipd <= B_ipd_rv;
                    drive_A <= B_ipd_rv;
                END IF;

            WHEN OTHERS =>
                IF (drive_A /= 'Z' and drive_A /= B_ipd_rv) THEN
                    A <= B_ipd_rv;
                    A_ipd <= B_ipd_rv;
                    drive_A <= B_ipd_rv;
                END IF;

        END CASE;

    END PROCESS;

END vhdl_behavioral;