----------------------------------------------------------------------------
-- Copyright (c) 1995, Ben Cohen.   All rights reserved.
-- This model can be used in conjunction with the Kluwer Academic book
-- "VHDL Coding Styles and Methodologies", ISBN: 0-7923-9598-0
-- which discusses guidelines and testbench design issues.
--
-- This source file for the error injector model may be used and
-- distributed without restriction provided that this copyright
-- statement is not removed from the file and that any derivative work
-- contains this copyright notice.

-- File name  : errinj.vhd
-- Description: This package, entity, and architecture provide
--   the definition of a three-port component (A, B, C) capable of
--   dynamically controlling and injecting bus values on either port
--   A or B under the control of port C.  This component effectively
--   emulate a stuck at fault, thus emulating an open pin,
--   a short to Vcc, or ground.  The values asserted on ports A and B
--   are of type Std_Logic, and are resolved.
--   The component can be dynamically controlled to operate in either
--   normal mode, where A and B become a jumper wire, or zero
--   ohm resistor, passing data in either direction, or in 
--   fault injection mode. 
--
--   The applications of this component include:
--     . Normal operation of a jumper wire (data flowing in both directions)
--     . Stuck at fault where the value of the fault is defined
--       in the value of C port.  The timing of the fault injection
--       is controlled by the timing and the values asserted on port C.
--       The mode of the stuck at fault is determined by a generic.
--     . Testing of setup time by forcing of signals to
--       a forced, but resolved value, such as 'X' until setup time.
--     . Dynamic disconnect of a component pin from its connection
--       to a signal for testing or for fault isolation. 
--
--   The component consists of 3 ports:
--      . Port A: One side of the pass-through switch
--      . Port B: The other side of the pass-through switch
--      . Port C: The dynamic control port for the pass-through switch
--                This control defines operation of the switch as
--                either a straight pass-through
--                (i.e. zero ohm resistor) when the
--                value is '-', or a forced value (when other than '-').
--                The forced values to be asserted as faults can be
--                 'U' 'X' '0' '1' 'Z' 'W' 'L' 'H'
--   The model is sensitive to transactions on all ports.  Once a
--   transaction is detected, all other transactions are ignored
--   for that simulation time (i.e. further transactions in that 
--   delta time are ignored). 
--
--   The width of the pass-through switch is defined through the
--   generic "width_g".  The pass-through control and operation
--   is defined on a per bit basis (i.e. one process per bit).
--
--   The mode of error injection is defined by the generic
--   "InjMode_g" which can take one of the following values:
--
--   NoError   : Control C has no influence on the switch.
--                 Switch always operate as a pass-through.
--   StuckA    : When C(i) = '-' then
--                 Switch always operate as a pass-through
--                 between A(i) and B(i).
--               When C(i) /= '-' then
--                 C(i) is driven on "A" port of component.
--                 'Z'  is driven on "B" port of component.
--   StuckB    : When C(i) = '-' then
--                 Switch always operate as a pass-through
--                 between A(i) and B(i).
--               When C(i) /= '-' then
--                 C(i) is driven on "B" port of component.
--                 'Z'  is driven on "A" port of component.
--   StuckAB   : When C(i) = '-' then
--                 Switch always operate as a pass-through
--                 between A(i) and B(i).
--               When C(i) /= '-' then
--                 C(i) is driven on "B" port of component.
--                 C(i) is driven on "A" port of component.
--   DriverAB  : When C(i) = '-' then
--                 Switch always operate as a pass-through
--                 between A(i) and B(i).
--               When C(i) /= '-' then
--                 if one side has a strong drive, and the
--                    other side has a weak drive
--                 then
--                    C(i) is driven on the weak drive port
--                    'Z'  is driven on the strong drive port
--                 else
--                   Switch operate as a pass-through
--                   between A(i) and B(i) (i.e. no error)
--
-- Model Limitations and Restrictions:
--   Signals asserted on the ports of the error injector should not have
--   transactions occuring in multiple delta times because the model
--   is sensitive to transactions on port A, B, C ONLY ONCE during
--   a simulation time.  Thus, once fired, a process will
--   not refire if there are multiple transactions occuring in delta times.
--   This condition may occur in gate level simulations with
--   ZERO delays because transactions may occur in multiple delta times.
--
--   Another example is the control of the C port when the control
--   is a function of the data on the A or B port because the
--   error injector could force events on A or B ports at delta times.
--   Thus:
--     Control_Lbl: Process(A) -- assume error injector is on signal A
--       constant MinSimTime_c : time := 1 ns;
--     begin
--       If A = "1000" then
--         -- C <= "--01"; -- ERROR IN MODELING because error injector
--                      -- will NOT fire if A'event occured as a  result
--                      -- of signal assertion on A by the error
--                      -- injector .
--         C <= "--01" after MinSimTime_c; -- OK, error injector will
--                      -- fire after 1 ns
--       end if;
--     end process Control_Lbl;
--   One additional, but minor,  limitiation to the error
--   injector model is that data on ports A and B CANNOT 
--   be of value '-'.   This is because the model asserts the 
--   value 'Z' on those ports to determine the driving  value 
--   on ports A and B. The Std_Logic_1164 package resolves 
--   a '-' with anything but a 'U' to an 'X'. 
--
--  This modeling limitation should not affect 99% + of most models, 
--  since the value '-' is a metalogical value which is almost 
--  never used as a value assigned onto a signal.  It may be  
--  used in  systhesis for conditional testing to ignore certain bits. 
--
-- Additional Comments:  A possible variation to this model is the
--   addition of a fourth port (D) which is of type InjMode_Typ or of 
--   type InjModeAry_Typ to dynamically identify the kind of fault to
--   inject on a model basis or bit basis. This model is not shown
--   here. 
--
-- Acknowledgement: The author thanks Steve Schoessow and Johan Sandstrom
--   for their contributions and discussions in the enhancement and
--   verification of this model.
--
--=================================================================
-- Design Library: ErrInj_Lib
-------------------------------------------------
-- Revisions:
--   Date   Author       Revision  Comment
-- 07-13-95 Ben Cohen    Rev A     Creation
--          VhdlCohen@aol.com
-------------------------------------------------------------
-- Package Name : ErrInj_Pkg
-- Library      : "ErrInj_Lib"
-- Purpose      : Declaration of enumeration type for
--              : use by error injector component
-------------------------------------------------------------
library IEEE;
  use IEEE.Std_Logic_1164.all;

package ErrInj_Pkg is
  type InjMode_Typ is
    (NoError,   -- A and B is a jumper wire, data in either direction
     StuckA,    -- If C(i) /= '-' then A <= C(i); B <= 'Z'  else **
     StuckB,    -- If C(i) /= '-' then B <= C(i); A <= 'Z'  else **
     StuckAB,   -- If C(i) /= '-' then A <= C(i); B <= C(i) else **
     DriverAB); -- If C(i) /= '-' then
                --   if A is strong driver and B weak driver then
                --        A <= 'Z'; B <= C(i)
                --   elsif B is strong driver and A weak driver then
                --        B <= 'Z'; A <= C(i)
                --   else A and B is a jumper wire
                --
                -- jumper wire
                -- ** if C(i) = '-' then A <= B; B <= A

   -- The following type can be used to define the type of a fourth 
   -- port to the model to identify the error injection mode (see 
   -- the additional comments shown above).   This type is not used in 
   -- this model. 
   type InjModeAry_Typ is array(integer range <>) of InjMode_Typ;
end ErrInj_Pkg;


-------------------------------------------------------------
-- Entity        : ErrInj
-- Purpose       : Provides interface of a component
--               : intended to be placed between signals
--               : to dynamically control faults on signals.
-- Library       : User defined
-------------------------------------------------------------
library IEEE;  
use IEEE.Std_Logic_1164.all;

Library ErrInj_lib;
  use ErrInj_Lib.ErrInj_Pkg.all;
  use ErrInj_Lib.ErrInj_Pkg;

entity ErrInj is
  generic (Width_g      : Positive := 32;
           InjMode_g    : ErrInj_Pkg.InjMode_Typ := NoError);
  port
    (A : inout Std_Logic_Vector(Width_g - 1 downto 0) := (others => 'Z');
     B : inout Std_Logic_Vector(Width_g - 1 downto 0) := (others => 'Z');
     C : in    Std_Logic_Vector(Width_g - 1 downto 0) := (others => 'Z'));
end ErrInj;


--------------------------------------------------------------
-- Architecture  : ErrInj_a
-- Purpose       : Implements the error injection architecture.
--               : This model is optimized for speed by minimizing the
--               : number of transactions by generating one process
--               : for each element of the width for the
--               : mode of interest.
-- Library       : User defined
-------------------------------------------------------------
architecture ErrInj_a of ErrInj is
  type TwoDbool_Typ is array(Std_Logic, Std_Logic) of Boolean;
  constant T : Boolean := True;
  constant F : Boolean := False;

  -- True if ROW is Strong and column is weak.
  constant StrongWeak_c : TwoDbool_Typ := (
            -- accessed as (Row, Column)
            --     Side2 signal (column)
            --   U   X   0   1     Z   W   L   H   -
     ---------------------------  ---------------
               ( F , F , F , F ,   T , T , T , T , T ), --U Side 1 signal
               ( F , F , F , F ,   T , T , T , T , T ), --X (Row)
               ( F , F , F , F ,   T , T , T , T , T ), --0
               ( F , F , F , F ,   T , T , T , T , T ), --1

               ( F , F , F , F ,   F , F , F , F , F ), --Z
               ( F , F , F , F ,   F , F , F , F , F ), --W
               ( F , F , F , F ,   F , F , F , F , F ), --L
               ( F , F , F , F ,   F , F , F , F , F ), --H
               ( F , F , F , F ,   F , F , F , F , F )  ---
            );


begin
  Px_Lbl: for I in (Width_g - 1) downto 0 generate
    NoError_Lbl: if (InjMode_g = NoError) generate
      ABC0_Lbl: process
        variable ThenTime_v : time;
      begin
        wait on A(I)'transaction, B(I)'transaction until ThenTime_v /= now;
        -- Break
        ThenTime_v := now;
        A(I) <= 'Z';
        B(I) <= 'Z';
        wait for 0 ns;

        -- Make
            A(I) <= B(I);
            B(I) <= A(I);

      end process ABC0_Lbl;
    end generate NoError_Lbl;

    StuckA_Lbl: if (InjMode_g = StuckA) generate
      ABC1_Lbl: process
        variable ThenTime_v : time;
      begin
        wait on A(I)'transaction, B(I)'transaction, C(I)'transaction
          until ThenTime_v /= now;
        -- Break
        ThenTime_v := now;
        A(I) <= 'Z';
        B(I) <= 'Z';
        wait for 0 ns;

        -- Make
        if C(I) /= '-' then
            A(I) <= C(I);   -- A stuck at fault
            B(I) <= 'Z';    -- B is unaffected
                            -- (no driver from error injector)
        else
            A(I) <= B(I);
            B(I) <= A(I);
        end if;

      end process ABC1_Lbl;
    end generate StuckA_Lbl;

    StuckB_Lbl: if (InjMode_g = StuckB) generate
      ABC2_Lbl: process
        variable ThenTime_v : time;
      begin
        wait on A(I)'transaction, B(I)'transaction, C(I)'transaction
          until ThenTime_v /= now;
        -- Break
        ThenTime_v := now;
        A(I) <= 'Z';
        B(I) <= 'Z';
        wait for 0 ns;

        -- Make
        if C(I) /= '-' then
            B(I) <= C(I);   -- B stuck at fault
            A(I) <= 'Z';    -- A is unaffected
                            -- (no driver from error injector)
        else
            A(I) <= B(I);
            B(I) <= A(I);
        end if;

      end process ABC2_Lbl;
    end generate StuckB_Lbl;

    StuckAB_Lbl: if (InjMode_g = StuckAB) generate
      ABC3_Lbl: process
        variable ThenTime_v : time;
      begin
        wait on A(I)'transaction, B(I)'transaction, C(I)'transaction
          until ThenTime_v /= now;
        -- Break
        ThenTime_v := now;
        A(I) <= 'Z';
        B(I) <= 'Z';
        wait for 0 ns;

        -- Make
        if C(I) /= '-' then
            A(I) <= C(I);   -- A stuck at fault
            B(I) <= C(I);   -- B stuck at fault

        else
            A(I) <= B(I);
            B(I) <= A(I);
        end if;

      end process ABC3_Lbl;
    end generate StuckAB_Lbl;

  DriverAB_Lbl: if (InjMode_g = DriverAB) generate
      ABC4_Lbl: process
        variable ThenTime_v : time;
      begin
        wait on A(I)'transaction, B(I)'transaction, C(I)'transaction
          until ThenTime_v /= now;
        -- Break
        ThenTime_v := now;
        A(I) <= 'Z';
        B(I) <= 'Z';
        wait for 0 ns;

        -- Make
        if C(I) /= '-' then
           -- Test if A is strong,  and B is weak driver
          if StrongWeak_c(A(I), B(I)) then
             B(I) <= C(I);   -- B gets at fault
             A(I) <= 'Z';    -- A is unaffected
                             -- (no driver from error injector)

          -- Test if B is strong, and A is weak driver
          elsif StrongWeak_c(B(I), A(I)) then
             A(I) <= C(I);   -- A gets at fault
             B(I) <= 'Z';    -- B is unaffected
                             -- (no driver from error injector)

          -- Pass data with no fault injection
          -- because A and B are either both strong
          -- or both weak drivers
          else
              A(I) <= B(I);
              B(I) <= A(I);
          end if;
        else                      -- C(I) = '-'
            A(I) <= B(I);
            B(I) <= A(I);
        end if;

      end process ABC4_Lbl;
    end generate DriverAB_Lbl;
  end generate Px_Lbl;
end ErrInj_a;

<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>