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