------------------------------------------------------------------------------- -- Title : Standard VITAL TIMING Package -- : $Revision$ -- Library : VITAL -- : -- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 -- : -- Purpose : This packages defines standard types, attributes, constants, -- : functions and procedures for use in developing ASIC models. -- : This file contains the Package Body. -- ---------------------------------------------------------------------------- -- -- ---------------------------------------------------------------------------- -- Modification History : -- ---------------------------------------------------------------------------- -- Version No:|Auth:| Mod.Date:| Changes Made: -- v95.0 A | | 06/08/95 | Initial ballot draft 1995 -- v95.1 | | 08/31/95 | #IR203 - Timing violations at time 0 -- #IR204 - Output mapping prior to glitch detection -- v98.0 |TAG | 03/27/98 | Initial ballot draft 1998 -- | #IR225 - Negative Premptive Glitch -- **Code_effected=ReportGlitch,VitalGlitch, -- VitalPathDelay,VitalPathDelay01, -- VitalPathDelay01z. -- #IR105 - Skew timing check needed -- **Code_effected=NONE, New code added!! -- #IR245,IR246,IR251 ITC code to fix false boundry cases -- **Code_effected=InternalTimingCheck. -- #IR248 - Allows VPD to use a default timing delay -- **Code_effected=VitalPathDelay, -- VitalPathDelay01,VitalPathDelay01z, -- VitalSelectPathDelay,VitalSelectPathDelay01, -- VitalSelectPathDelay01z. -- #IR250 - Corrects fastpath condition in VPD -- **Code_effected=VitalPathDelay01, -- VitalPathDelay01z, -- #IR252 - Corrects cancelled timing check call if -- condition expires. -- **Code_effected=VitalSetupHoldCheck, -- VitalRecoveryRemovalCheck. -- v98.1 | jdc | 03/25/99 | Changed UseDefaultDelay to IgnoreDefaultDelay -- and set default to FALSE in VitalPathDelay() -- -- ---------------------------------------------------------------------------- LIBRARY STD; USE STD.TEXTIO.ALL; PACKAGE BODY VITAL_Timing IS -- -------------------------------------------------------------------- -- Package Local Declarations -- -------------------------------------------------------------------- TYPE CheckType IS ( SetupCheck, HoldCheck, RecoveryCheck, RemovalCheck, PulseWidCheck, PeriodCheck ); TYPE CheckInfoType IS RECORD Violation : BOOLEAN; CheckKind : CheckType; ObsTime : TIME; ExpTime : TIME; DetTime : TIME; State : X01; END RECORD; TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER; TYPE HiLoStrType IS ARRAY (std_ulogic RANGE 'X' TO '1') OF STRING(1 TO 4); CONSTANT LogicCvtTable : LogicCvtTableType := ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'); CONSTANT HiLoStr : HiLoStrType := (" X ", " Low", "High" ); TYPE EdgeSymbolMatchType IS ARRAY (X01,X01,VitalEdgeSymbolType) OF BOOLEAN; -- last value, present value, edge symbol CONSTANT EdgeSymbolMatch : EdgeSymbolMatchType := ( 'X'=>('X'=>( OTHERS => FALSE), '0'=>('N'|'F'|'v'|'E'|'D'|'*' => TRUE, OTHERS => FALSE ), '1'=>('P'|'R'|'^'|'E'|'A'|'*' => TRUE, OTHERS => FALSE ) ), '0'=>('X'=>( 'r'|'p'|'R'|'A'|'*' => TRUE, OTHERS => FALSE ), '0'=>( OTHERS => FALSE ), '1'=>( '/'|'P'|'p'|'R'|'*' => TRUE, OTHERS => FALSE ) ), '1'=>('X'=>( 'f'|'n'|'F'|'D'|'*' => TRUE, OTHERS => FALSE ), '0'=>( '\'|'N'|'n'|'F'|'*' => TRUE, OTHERS => FALSE ), '1'=>( OTHERS => FALSE ) ) ); --------------------------------------------------------------------------- -- Tables used to implement 'posedge' and 'negedge' in path delays -- These are new tables for Skewcheck routines. IR105 --------------------------------------------------------------------------- TYPE EdgeRable IS ARRAY(std_ulogic, std_ulogic) OF boolean; CONSTANT Posedge : EdgeRable := ( -- ------------------------------------------------------------------------ -- | U X 0 1 Z W L H - -- ------------------------------------------------------------------------ ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- U ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- X ( TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE , TRUE ), -- 0 ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- 1 ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- Z ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- W ( TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE , TRUE ), -- L ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- H ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ) -- - ); --IR105 CONSTANT Negedge : EdgeRable := ( -- ----------------------------------------------------------------------- -- | U X 0 1 Z W L H - -- ----------------------------------------------------------------------- ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- U ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- X ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- 0 ( TRUE , TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE ), -- 1 ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- Z ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- W ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- L ( TRUE , TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE ), -- H ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ) -- - ); --IR105 TYPE SkewType IS (Inphase, Outphase); --IR105 CONSTANT noTrigger : TIME := -1 ns; --IR105 --------------------------------------------------------------------------- -- End of Skew (IR105 additions) --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- -- Misc Utilities Local Utilities --------------------------------------------------------------------------- ----------------------------------------------------------------------- FUNCTION Minimum ( CONSTANT t1,t2 : IN TIME ) RETURN TIME IS BEGIN IF ( t1 < t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; END Minimum; ----------------------------------------------------------------------- FUNCTION Maximum ( CONSTANT t1,t2 : IN TIME ) RETURN TIME IS BEGIN IF ( t1 > t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; END Maximum; -------------------------------------------------------------------- -- Error Message Types and Tables -------------------------------------------------------------------- TYPE VitalErrorType IS ( ErrVctLng , ErrNoPath , ErrNegPath , ErrNegDel ); TYPE VitalErrorSeverityType IS ARRAY (VitalErrorType) OF SEVERITY_LEVEL; CONSTANT VitalErrorSeverity : VitalErrorSeverityType := ( ErrVctLng => ERROR, ErrNoPath => WARNING, ErrNegPath => WARNING, ErrNegDel => WARNING ); CONSTANT MsgNoPath : STRING := "No Delay Path Condition TRUE. 0-delay used. Output signal is: "; CONSTANT MsgNegPath : STRING := "Path Delay less than time since input. 0 delay used. Output signal is: "; CONSTANT MsgNegDel : STRING := "Negative delay. New output value not scheduled. Output signal is: "; CONSTANT MsgVctLng : STRING := "Vector (array) lengths not equal. "; CONSTANT MsgUnknown : STRING := "Unknown error message."; FUNCTION VitalMessage ( CONSTANT ErrorId : IN VitalErrorType ) RETURN STRING IS BEGIN CASE ErrorId IS WHEN ErrVctLng => RETURN MsgVctLng; WHEN ErrNoPath => RETURN MsgNoPath; WHEN ErrNegPath => RETURN MsgNegPath; WHEN ErrNegDel => RETURN MsgNegDel; WHEN OTHERS => RETURN MsgUnknown; END CASE; END; PROCEDURE VitalError ( CONSTANT Routine : IN STRING; CONSTANT ErrorId : IN VitalErrorType ) IS BEGIN ASSERT FALSE REPORT Routine & ": " & VitalMessage(ErrorId) SEVERITY VitalErrorSeverity(ErrorId); END; PROCEDURE VitalError ( CONSTANT Routine : IN STRING; CONSTANT ErrorId : IN VitalErrorType; CONSTANT Info : IN STRING ) IS BEGIN ASSERT FALSE REPORT Routine & ": " & VitalMessage(ErrorId) & Info SEVERITY VitalErrorSeverity(ErrorId); END; PROCEDURE VitalError ( CONSTANT Routine : IN STRING; CONSTANT ErrorId : IN VitalErrorType; CONSTANT Info : IN CHARACTER ) IS BEGIN ASSERT FALSE REPORT Routine & ": " & VitalMessage(ErrorId) & Info SEVERITY VitalErrorSeverity(ErrorId); END; --------------------------------------------------------------------------- -- Time Delay Assignment Subprograms --------------------------------------------------------------------------- FUNCTION VitalExtendToFillDelay ( CONSTANT Delay : IN VitalDelayType ) RETURN VitalDelayType01Z IS BEGIN RETURN (OTHERS => Delay); END VitalExtendToFillDelay; FUNCTION VitalExtendToFillDelay ( CONSTANT Delay : IN VitalDelayType01 ) RETURN VitalDelayType01Z IS VARIABLE Delay01Z : VitalDelayType01Z; BEGIN Delay01Z(tr01) := Delay(tr01); Delay01Z(tr0z) := Delay(tr01); Delay01Z(trz1) := Delay(tr01); Delay01Z(tr10) := Delay(tr10); Delay01Z(tr1z) := Delay(tr10); Delay01Z(trz0) := Delay(tr10); RETURN (Delay01Z); END VitalExtendToFillDelay; FUNCTION VitalExtendToFillDelay ( CONSTANT Delay : IN VitalDelayType01Z ) RETURN VitalDelayType01Z IS BEGIN RETURN Delay; END VitalExtendToFillDelay; --------------------------------------------------------------------------- FUNCTION VitalCalcDelay ( CONSTANT NewVal : IN std_ulogic := 'X'; CONSTANT OldVal : IN std_ulogic := 'X'; CONSTANT Delay : IN VitalDelayType ) RETURN TIME IS BEGIN RETURN delay; END VitalCalcDelay; FUNCTION VitalCalcDelay ( CONSTANT NewVal : IN std_ulogic := 'X'; CONSTANT OldVal : IN std_ulogic := 'X'; CONSTANT Delay : IN VitalDelayType01 ) RETURN TIME IS VARIABLE Result : TIME; BEGIN CASE Newval IS WHEN '0' | 'L' => Result := Delay(tr10); WHEN '1' | 'H' => Result := Delay(tr01); WHEN 'Z' => CASE Oldval IS WHEN '0' | 'L' => Result := Delay(tr01); WHEN '1' | 'H' => Result := Delay(tr10); WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); END CASE; WHEN OTHERS => CASE Oldval IS WHEN '0' | 'L' => Result := Delay(tr01); WHEN '1' | 'H' => Result := Delay(tr10); WHEN 'Z' => Result := MINIMUM(Delay(tr10), Delay(tr01)); WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); END CASE; END CASE; RETURN Result; END VitalCalcDelay; FUNCTION VitalCalcDelay ( CONSTANT NewVal : IN std_ulogic := 'X'; CONSTANT OldVal : IN std_ulogic := 'X'; CONSTANT Delay : IN VitalDelayType01Z ) RETURN TIME IS VARIABLE Result : TIME; BEGIN CASE Oldval IS WHEN '0' | 'L' => CASE Newval IS WHEN '0' | 'L' => Result := Delay(tr10); WHEN '1' | 'H' => Result := Delay(tr01); WHEN 'Z' => Result := Delay(tr0z); WHEN OTHERS => Result := MINIMUM(Delay(tr01), Delay(tr0z)); END CASE; WHEN '1' | 'H' => CASE Newval IS WHEN '0' | 'L' => Result := Delay(tr10); WHEN '1' | 'H' => Result := Delay(tr01); WHEN 'Z' => Result := Delay(tr1z); WHEN OTHERS => Result := MINIMUM(Delay(tr10), Delay(tr1z)); END CASE; WHEN 'Z' => CASE Newval IS WHEN '0' | 'L' => Result := Delay(trz0); WHEN '1' | 'H' => Result := Delay(trz1); WHEN 'Z' => Result := MAXIMUM (Delay(tr0z), Delay(tr1z)); WHEN OTHERS => Result := MINIMUM (Delay(trz1), Delay(trz0)); END CASE; WHEN 'U' | 'X' | 'W' | '-' => CASE Newval IS WHEN '0' | 'L' => Result := MAXIMUM(Delay(tr10), Delay(trz0)); WHEN '1' | 'H' => Result := MAXIMUM(Delay(tr01), Delay(trz1)); WHEN 'Z' => Result := MAXIMUM(Delay(tr1z), Delay(tr0z)); WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); END CASE; END CASE; RETURN Result; END VitalCalcDelay; --------------------------------------------------------------------------- -- -- VitalSelectPathDelay returns the path delay selected by the Paths array. -- If no paths are selected, it returns either the appropriate default -- delay or TIME'HIGH, depending upon the value of IgnoreDefaultDelay. -- FUNCTION VitalSelectPathDelay ( CONSTANT NewValue : IN std_logic; CONSTANT OldValue : IN std_logic; CONSTANT OutSignalName : IN string; CONSTANT Paths : IN VitalPathArrayType; CONSTANT DefaultDelay : IN VitalDelayType; CONSTANT IgnoreDefaultDelay : IN BOOLEAN ) RETURN TIME IS VARIABLE TmpDelay : TIME; VARIABLE InputAge : TIME := TIME'HIGH; VARIABLE PropDelay : TIME := TIME'HIGH; BEGIN -- for each delay path FOR i IN Paths'RANGE LOOP -- ignore the delay path if it is not enabled NEXT WHEN NOT Paths(i).PathCondition; -- ignore the delay path if a more recent input event has been seen NEXT WHEN Paths(i).InputChangeTime > InputAge; -- This is the most recent input change (so far) -- Get the transition dependent delay TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); -- If other inputs changed at the same time, -- then use the minimum of their propagation delays, -- else use the propagation delay from this input. IF Paths(i).InputChangeTime < InputAge THEN PropDelay := TmpDelay; ELSE -- Simultaneous inputs change IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; end if; InputAge := Paths(i).InputChangeTime; END LOOP; -- If there were no paths (with an enabled condition), -- use the default delay, if so indicated, otherwise return TIME'HIGH IF (PropDelay = TIME'HIGH) THEN IF (IgnoreDefaultDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); END IF; -- If the time since the most recent selected input event is -- greater than the propagation delay from that input, -- then use the default delay (won't happen if no paths are selected) ELSIF (InputAge > PropDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); -- Adjust the propagation delay by the time since the -- the input event occurred (Usually 0 ns). ELSE PropDelay := PropDelay - InputAge; END IF; RETURN PropDelay; END; FUNCTION VitalSelectPathDelay ( CONSTANT NewValue : IN std_logic; CONSTANT OldValue : IN std_logic; CONSTANT OutSignalName : IN string; CONSTANT Paths : IN VitalPathArray01Type; CONSTANT DefaultDelay : IN VitalDelayType01; CONSTANT IgnoreDefaultDelay : IN BOOLEAN ) RETURN TIME IS VARIABLE TmpDelay : TIME; VARIABLE InputAge : TIME := TIME'HIGH; VARIABLE PropDelay : TIME := TIME'HIGH; BEGIN -- for each delay path FOR i IN Paths'RANGE LOOP -- ignore the delay path if it is not enabled NEXT WHEN NOT Paths(i).PathCondition; -- ignore the delay path if a more recent input event has been seen NEXT WHEN Paths(i).InputChangeTime > InputAge; -- This is the most recent input change (so far) -- Get the transition dependent delay TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); -- If other inputs changed at the same time, -- then use the minimum of their propagation delays, -- else use the propagation delay from this input. IF Paths(i).InputChangeTime < InputAge THEN PropDelay := TmpDelay; ELSE -- Simultaneous inputs change IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; end if; InputAge := Paths(i).InputChangeTime; END LOOP; -- If there were no paths (with an enabled condition), -- use the default delay, if so indicated, otherwise return TIME'HIGH IF (PropDelay = TIME'HIGH) THEN IF (IgnoreDefaultDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); END IF; -- If the time since the most recent selected input event is -- greater than the propagation delay from that input, -- then use the default delay (won't happen if no paths are selected) ELSIF (InputAge > PropDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); -- Adjust the propagation delay by the time since the -- the input event occurred (Usually 0 ns). ELSE PropDelay := PropDelay - InputAge; END IF; RETURN PropDelay; END; FUNCTION VitalSelectPathDelay ( CONSTANT NewValue : IN std_logic; CONSTANT OldValue : IN std_logic; CONSTANT OutSignalName : IN string; CONSTANT Paths : IN VitalPathArray01ZType; CONSTANT DefaultDelay : IN VitalDelayType01Z; CONSTANT IgnoreDefaultDelay : IN BOOLEAN ) RETURN TIME IS VARIABLE TmpDelay : TIME; VARIABLE InputAge : TIME := TIME'HIGH; VARIABLE PropDelay : TIME := TIME'HIGH; BEGIN -- for each delay path FOR i IN Paths'RANGE LOOP -- ignore the delay path if it is not enabled NEXT WHEN NOT Paths(i).PathCondition; -- ignore the delay path if a more recent input event has been seen NEXT WHEN Paths(i).InputChangeTime > InputAge; -- This is the most recent input change (so far) -- Get the transition dependent delay TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); -- If other inputs changed at the same time, -- then use the minimum of their propagation delays, -- else use the propagation delay from this input. IF Paths(i).InputChangeTime < InputAge THEN PropDelay := TmpDelay; ELSE -- Simultaneous inputs change IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; end if; InputAge := Paths(i).InputChangeTime; END LOOP; -- If there were no paths (with an enabled condition), -- use the default delay, if so indicated, otherwise return TIME'HIGH IF (PropDelay = TIME'HIGH) THEN IF (IgnoreDefaultDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); END IF; -- If the time since the most recent selected input event is -- greater than the propagation delay from that input, -- then use the default delay (won't happen if no paths are selected) ELSIF (InputAge > PropDelay) THEN PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); -- Adjust the propagation delay by the time since the -- the input event occurred (Usually 0 ns). ELSE PropDelay := PropDelay - InputAge; END IF; RETURN PropDelay; END; --------------------------------------------------------------------------- --------------------------------------------------------------------------- -- Glitch Handlers --------------------------------------------------------------------------- --------------------------------------------------------------------------- PROCEDURE ReportGlitch ( CONSTANT GlitchRoutine : IN STRING; CONSTANT OutSignalName : IN STRING; CONSTANT PreemptedTime : IN TIME; CONSTANT PreemptedValue : IN std_ulogic; CONSTANT NewTime : IN TIME; CONSTANT NewValue : IN std_ulogic; CONSTANT Index : IN INTEGER := 0; CONSTANT IsArraySignal : IN BOOLEAN := FALSE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING ) IS VARIABLE StrPtr1, StrPtr2, StrPtr3, StrPtr4, StrPtr5 : LINE; BEGIN Write (StrPtr1, PreemptedTime ); Write (StrPtr2, NewTime); Write (StrPtr3, LogicCvtTable(PreemptedValue)); Write (StrPtr4, LogicCvtTable(NewValue)); IF IsArraySignal THEN Write (StrPtr5, STRING'( "(" ) ); Write (StrPtr5, Index); Write (StrPtr5, STRING'( ")" ) ); ELSE Write (StrPtr5, STRING'( " " ) ); END IF; -- Issue Report only if Preempted value has not been -- removed from event queue ASSERT PreemptedTime > NewTime REPORT GlitchRoutine & ": GLITCH Detected on port " & OutSignalName & StrPtr5.ALL & "; Preempted Future Value := " & StrPtr3.ALL & " @ " & StrPtr1.ALL & "; Newly Scheduled Value := " & StrPtr4.ALL & " @ " & StrPtr2.ALL & ";" SEVERITY MsgSeverity; ASSERT PreemptedTime <= NewTime REPORT GlitchRoutine & ": GLITCH Detected on port " & OutSignalName & StrPtr5.ALL & "; Negative Preempted Value := " & StrPtr3.ALL & " @ " & StrPtr1.ALL & "; Newly Scheduled Value := " & StrPtr4.ALL & " @ " & StrPtr2.ALL & ";" SEVERITY MsgSeverity; DEALLOCATE(StrPtr1); DEALLOCATE(StrPtr2); DEALLOCATE(StrPtr3); DEALLOCATE(StrPtr4); DEALLOCATE(StrPtr5); RETURN; END ReportGlitch; --------------------------------------------------------------------------- PROCEDURE VitalGlitch ( SIGNAL OutSignal : OUT std_logic; VARIABLE GlitchData : INOUT VitalGlitchDataType; CONSTANT OutSignalName : IN string; CONSTANT NewValue : IN std_logic; CONSTANT NewDelay : IN TIME := 0 ns; CONSTANT Mode : IN VitalGlitchKindType := OnEvent; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 CONSTANT MsgOn : IN BOOLEAN := FALSE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING ) IS --------------------------------------------------------------------------- VARIABLE NewGlitch : BOOLEAN := TRUE; VARIABLE dly : TIME := NewDelay; VARIABLE NOW_TIME : TIME := NOW; VARIABLE NegPreemptGlitch : BOOLEAN := FALSE; BEGIN NegPreemptGlitch:=FALSE;--reset Preempt-Glitch -- If nothing to schedule, just return IF NewDelay < 0 ns THEN IF (NewValue /= GlitchData.SchedValue) THEN VitalError ( "VitalGlitch", ErrNegDel, OutSignalName ); END IF; RETURN; END IF; -- If simple signal assignment -- perform the signal assignment IF ( Mode = VitalInertial) THEN OutSignal <= NewValue AFTER dly; ELSIF ( Mode = VitalTransport ) THEN OutSignal <= TRANSPORT NewValue AFTER dly; ELSE -- Glitch Processing --- -- If nothing currently scheduled IF GlitchData.SchedTime <= NOW THEN -- NOW >= last event -- Note: NewValue is always /= OldValue when called from VPPD IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF; NewGlitch := FALSE; GlitchData.GlitchTime := NOW+dly; -- New value earlier than the earliest previous value scheduled -- (negative preemptive) ELSIF (NOW+dly <= GlitchData.GlitchTime) AND (NOW+dly <= GlitchData.SchedTime) THEN -- Glitch is negative preemptive - check if same value and -- NegPreempt is on IR225 IF (GlitchData.SchedValue /= NewValue) AND (NegPreemptOn) AND (NOW > 0 NS) THEN NewGlitch := TRUE; NegPreemptGlitch :=TRUE; -- Set preempt Glitch condition ELSE NewGlitch := FALSE; -- No new glitch, save time for -- possible future glitch END IF; GlitchData.GlitchTime := NOW+dly; -- Transaction currently scheduled - if glitch already happened ELSIF GlitchData.GlitchTime <= NOW THEN IF (GlitchData.SchedValue = NewValue) THEN dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); END IF; NewGlitch := FALSE; -- Transaction currently scheduled (no glitch if same value) ELSIF (GlitchData.SchedValue = NewValue) AND (GlitchData.SchedTime = GlitchData.GlitchTime) THEN -- revise scheduled output time if new delay is sooner dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); -- No new glitch, save time for possable future glitch NewGlitch := FALSE; GlitchData.GlitchTime := NOW+dly; -- Transaction currently scheduled represents a glitch ELSE NewGlitch := TRUE; -- A new glitch has been detected END IF; IF NewGlitch THEN -- If messages requested, report the glitch IF MsgOn THEN IF NegPreemptGlitch THEN --IR225 ReportGlitch ("VitalGlitch-Neg", OutSignalName, GlitchData.GlitchTime, GlitchData.SchedValue, (dly + NOW), NewValue, MsgSeverity=>MsgSeverity ); ELSE ReportGlitch ("VitalGlitch", OutSignalName, GlitchData.GlitchTime, GlitchData.SchedValue, (dly + NOW), NewValue, MsgSeverity=>MsgSeverity ); END IF; END IF; -- If 'X' generation is requested, schedule the new value -- preceeded by a glitch pulse. -- Otherwise just schedule the new value (inertial mode). IF XOn THEN IF (Mode = OnDetect) THEN OutSignal <= 'X'; ELSE OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW; END IF; IF NegPreemptGlitch THEN -- IR225 OutSignal <= TRANSPORT NewValue AFTER GlitchData.SchedTime-NOW; ELSE OutSignal <= TRANSPORT NewValue AFTER dly; END IF; ELSE OutSignal <= NewValue AFTER dly; -- no glitch regular prop delay END IF; -- If there no new glitch was detected, just schedule the new value. ELSE OutSignal <= NewValue AFTER dly; END IF; END IF; -- Record the new value and time depending on glitch type just scheduled. IF NOT NegPreemptGlitch THEN -- 5/2/96 for "x-pulse" IR225 GlitchData.SchedValue := NewValue; GlitchData.SchedTime := NOW+dly; -- pulse timing. ELSE GlitchData.SchedValue := 'X'; -- leave GlitchData.SchedTime to old value since glitch is negative END IF; RETURN; END; --------------------------------------------------------------------------- PROCEDURE VitalPathDelay ( SIGNAL OutSignal : OUT std_logic; VARIABLE GlitchData : INOUT VitalGlitchDataType; CONSTANT OutSignalName : IN string; CONSTANT OutTemp : IN std_logic; CONSTANT Paths : IN VitalPathArrayType; CONSTANT DefaultDelay : IN VitalDelayType := VitalZeroDelay; CONSTANT Mode : IN VitalGlitchKindType := OnEvent; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE --IR248 3/14/98 ) IS VARIABLE PropDelay : TIME; BEGIN -- Check if the new value to be scheduled is different than the -- previously scheduled value IF (GlitchData.SchedTime <= NOW) AND (GlitchData.SchedValue = OutTemp) THEN RETURN; END IF; -- Evaluate propagation delay paths PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, OutSignalName, Paths, DefaultDelay, IgnoreDefaultDelay); GlitchData.LastValue := OutTemp; -- Schedule the output transactions - including glitch handling VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); END VitalPathDelay; --------------------------------------------------------------------------- PROCEDURE VitalPathDelay01 ( SIGNAL OutSignal : OUT std_logic; VARIABLE GlitchData : INOUT VitalGlitchDataType; CONSTANT OutSignalName : IN string; CONSTANT OutTemp : IN std_logic; CONSTANT Paths : IN VitalPathArray01Type; CONSTANT DefaultDelay : IN VitalDelayType01 := VitalZeroDelay01; CONSTANT Mode : IN VitalGlitchKindType := OnEvent; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 ) IS VARIABLE PropDelay : TIME; BEGIN -- Check if the new value to be scheduled is different than the -- previously scheduled value IF (GlitchData.SchedTime <= NOW) AND (GlitchData.SchedValue = OutTemp) THEN RETURN; -- Check if the new value to be Scheduled is the same as the -- previously scheduled output transactions. If this condition -- exists and the new scheduled time is < the current GlitchData. -- schedTime then a fast path condition exists (IR250). If the -- modeler wants this condition rejected by setting the -- RejectFastPath actual to true then exit out. ELSIF (GlitchData.SchedValue=OutTemp) AND (RejectFastPath) THEN RETURN; END IF; -- Evaluate propagation delay paths PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, OutSignalName, Paths, DefaultDelay, IgnoreDefaultDelay); GlitchData.LastValue := OutTemp; VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); END VitalPathDelay01; --------------------------------------------------------------------------- PROCEDURE VitalPathDelay01Z ( SIGNAL OutSignal : OUT std_logic; VARIABLE GlitchData : INOUT VitalGlitchDataType; CONSTANT OutSignalName : IN string; CONSTANT OutTemp : IN std_logic; CONSTANT Paths : IN VitalPathArray01ZType; CONSTANT DefaultDelay : IN VitalDelayType01Z := VitalZeroDelay01Z; CONSTANT Mode : IN VitalGlitchKindType := OnEvent; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 ) IS VARIABLE PropDelay : TIME; BEGIN -- Check if the new value to be scheduled is different than the -- previously scheduled value IF (GlitchData.SchedTime <= NOW) AND (GlitchData.SchedValue = OutTemp) THEN RETURN; -- Check if the new value to be Scheduled is the same as the -- previously scheduled output transactions. If this condition -- exists and the new scheduled time is < the current GlitchData. -- schedTime then a fast path condition exists (IR250). If the -- modeler wants this condition rejected by setting the -- RejectFastPath actual to true then exit out. ELSIF (GlitchData.SchedValue=OutTemp) AND (RejectFastPath) THEN RETURN; END IF; -- Evaluate propagation delay paths PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, OutSignalName, Paths, DefaultDelay, IgnoreDefaultDelay); GlitchData.LastValue := OutTemp; -- Schedule the output transactions - including glitch handling VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); END VitalPathDelay01Z; ---------------------------------------------------------------------------- PROCEDURE VitalWireDelay ( SIGNAL OutSig : OUT std_ulogic; SIGNAL InSig : IN std_ulogic; CONSTANT twire : IN VitalDelayType ) IS BEGIN OutSig <= TRANSPORT InSig AFTER twire; END VitalWireDelay; PROCEDURE VitalWireDelay ( SIGNAL OutSig : OUT std_ulogic; SIGNAL InSig : IN std_ulogic; CONSTANT twire : IN VitalDelayType01 ) IS VARIABLE Delay : TIME; BEGIN Delay := VitalCalcDelay( InSig, InSig'LAST_VALUE, twire ); OutSig <= TRANSPORT InSig AFTER Delay; END VitalWireDelay; PROCEDURE VitalWireDelay ( SIGNAL OutSig : OUT std_ulogic; SIGNAL InSig : IN std_ulogic; CONSTANT twire : IN VitalDelayType01Z ) IS VARIABLE Delay : TIME; BEGIN Delay := VitalCalcDelay( InSig, InSig'LAST_VALUE, twire ); OutSig <= TRANSPORT InSig AFTER Delay; END VitalWireDelay; ---------------------------------------------------------------------------- PROCEDURE VitalSignalDelay ( SIGNAL OutSig : OUT std_ulogic; SIGNAL InSig : IN std_ulogic; CONSTANT dly : IN TIME ) IS BEGIN OutSig <= TRANSPORT InSig AFTER dly; END; --------------------------------------------------------------------------- --------------------------------------------------------------------------- -- Setup and Hold Time Check Routine --------------------------------------------------------------------------- --------------------------------------------------------------------------- PROCEDURE ReportViolation ( CONSTANT TestSignalName : IN STRING := ""; CONSTANT RefSignalName : IN STRING := ""; CONSTANT HeaderMsg : IN STRING := " "; CONSTANT CheckInfo : IN CheckInfoType; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING ) IS VARIABLE Message : LINE; BEGIN IF NOT CheckInfo.Violation THEN RETURN; END IF; Write ( Message, HeaderMsg ); Case CheckInfo.CheckKind IS WHEN SetupCheck => Write ( Message, STRING'(" SETUP ") ); WHEN HoldCheck => Write ( Message, STRING'(" HOLD ") ); WHEN RecoveryCheck => Write ( Message, STRING'(" RECOVERY ") ); WHEN RemovalCheck => Write ( Message, STRING'(" REMOVAL ") ); WHEN PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH ")); WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") ); END CASE; Write ( Message, HiLoStr(CheckInfo.State) ); Write ( Message, STRING'(" VIOLATION ON ") ); Write ( Message, TestSignalName ); IF (RefSignalName'LENGTH > 0) THEN Write ( Message, STRING'(" WITH RESPECT TO ") ); Write ( Message, RefSignalName ); END IF; Write ( Message, ';' & LF ); Write ( Message, STRING'(" Expected := ") ); Write ( Message, CheckInfo.ExpTime); Write ( Message, STRING'("; Observed := ") ); Write ( Message, CheckInfo.ObsTime); Write ( Message, STRING'("; At : ") ); Write ( Message, CheckInfo.DetTime); ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity; DEALLOCATE (Message); END ReportViolation; --------------------------------------------------------------------------- -- Procedure : InternalTimingCheck --------------------------------------------------------------------------- PROCEDURE InternalTimingCheck ( CONSTANT TestSignal : IN std_ulogic; CONSTANT RefSignal : IN std_ulogic; CONSTANT TestDelay : IN TIME := 0 ns; CONSTANT RefDelay : IN TIME := 0 ns; CONSTANT SetupHigh : IN TIME := 0 ns; CONSTANT SetupLow : IN TIME := 0 ns; CONSTANT HoldHigh : IN TIME := 0 ns; CONSTANT HoldLow : IN TIME := 0 ns; VARIABLE RefTime : IN TIME; VARIABLE RefEdge : IN BOOLEAN; VARIABLE TestTime : IN TIME; VARIABLE TestEvent : IN BOOLEAN; VARIABLE SetupEn : INOUT BOOLEAN; VARIABLE HoldEn : INOUT BOOLEAN; VARIABLE CheckInfo : INOUT CheckInfoType; CONSTANT MsgOn : IN BOOLEAN ) IS VARIABLE bias : TIME; VARIABLE actualObsTime : TIME; VARIABLE BC : TIME; VARIABLE Message:LINE; BEGIN -- Check SETUP constraint IF RefEdge THEN IF SetupEn THEN CheckInfo.ObsTime := RefTime - TestTime; CheckInfo.State := To_X01(TestSignal); CASE CheckInfo.State IS WHEN '0' => CheckInfo.ExpTime := SetupLow; -- start of new code IR245-246 BC := HoldHigh; -- end of new code IR245-246 WHEN '1' => CheckInfo.ExpTime := SetupHigh; -- start of new code IR245-246 BC := HoldLow; -- end of new code IR245-246 WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); -- start of new code IR245-246 BC := Maximum(HoldHigh,HoldLow); -- end of new code IR245-246 END CASE; -- added the second condition for IR 245-246 CheckInfo.Violation := ( (CheckInfo.ObsTime < CheckInfo.ExpTime) AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))) ); -- start of new code IR245-246 IF(CheckInfo.ExpTime = 0 ns) THEN CheckInfo.CheckKind := HoldCheck; ELSE CheckInfo.CheckKind := SetupCheck; END IF; -- end of new code IR245-246 SetupEn := FALSE; ELSE CheckInfo.Violation := FALSE; END IF; -- Check HOLD constraint ELSIF TestEvent THEN IF HoldEn THEN CheckInfo.ObsTime := TestTime - RefTime; CheckInfo.State := To_X01(TestSignal); CASE CheckInfo.State IS WHEN '0' => CheckInfo.ExpTime := HoldHigh; -- new code for unnamed IR CheckInfo.State := '1'; -- start of new code IR245-246 BC := SetupLow; -- end of new code IR245-246 WHEN '1' => CheckInfo.ExpTime := HoldLow; -- new code for unnamed IR CheckInfo.State := '0'; -- start of new code IR245-246 BC := SetupHigh; -- end of new code IR245-246 WHEN 'X' => CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); -- start of new code IR245-246 BC := Maximum(SetupHigh,SetupLow); -- end of new code IR245-246 END CASE; -- added the second condition for IR 245-246 CheckInfo.Violation := ( (CheckInfo.ObsTime < CheckInfo.ExpTime) AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))) ); -- start of new code IR245-246 IF(CheckInfo.ExpTime = 0 ns) THEN CheckInfo.CheckKind := SetupCheck; ELSE CheckInfo.CheckKind := HoldCheck; END IF; -- end of new code IR245-246 HoldEn := NOT CheckInfo.Violation; ELSE CheckInfo.Violation := FALSE; END IF; ELSE CheckInfo.Violation := FALSE; END IF; -- Adjust report values to account for internal model delays -- Note: TestDelay, RefDelay, TestTime, RefTime are non-negative -- Note: bias may be negative or positive IF MsgOn AND CheckInfo.Violation THEN -- modified the code for correct reporting of violation in case of -- order of signals being reversed because of internal delays -- new variable actualObsTime := (TestTime-TestDelay)-(RefTime-RefDelay); bias := TestDelay - RefDelay; IF (actualObsTime < 0 ns) THEN -- It should be a setup check IF ( CheckInfo.CheckKind = HoldCheck) then CheckInfo.CheckKind := SetupCheck; CASE CheckInfo.State IS WHEN '0' => CheckInfo.ExpTime := SetupLow; WHEN '1' => CheckInfo.ExpTime := SetupHigh; WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); END CASE; END IF; CheckInfo.ObsTime := -actualObsTime; CheckInfo.ExpTime := CheckInfo.ExpTime + bias; CheckInfo.DetTime := RefTime - RefDelay; ELSE -- It should be a hold check IF ( CheckInfo.CheckKind = SetupCheck) then CheckInfo.CheckKind := HoldCheck; CASE CheckInfo.State IS WHEN '0' => CheckInfo.ExpTime := HoldHigh; CheckInfo.State := '1'; WHEN '1' => CheckInfo.ExpTime := HoldLow; CheckInfo.State := '0'; WHEN 'X' => CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); END CASE; END IF; CheckInfo.ObsTime := actualObsTime; CheckInfo.ExpTime := CheckInfo.ExpTime - bias; CheckInfo.DetTime := TestTime - TestDelay; END IF; END IF; END InternalTimingCheck; --------------------------------------------------------------------------- --------------------------------------------------------------------------- FUNCTION VitalTimingDataInit RETURN VitalTimingDataType IS BEGIN RETURN (FALSE,'X', 0 ns, FALSE, 'X', 0 ns, FALSE, NULL, NULL, NULL, NULL); END; --------------------------------------------------------------------------- -- Procedure : VitalSetupHoldCheck --------------------------------------------------------------------------- PROCEDURE VitalSetupHoldCheck ( VARIABLE Violation : OUT X01; VARIABLE TimingData : INOUT VitalTimingDataType; SIGNAL TestSignal : IN std_ulogic; CONSTANT TestSignalName: IN STRING := ""; CONSTANT TestDelay : IN TIME := 0 ns; SIGNAL RefSignal : IN std_ulogic; CONSTANT RefSignalName : IN STRING := ""; CONSTANT RefDelay : IN TIME := 0 ns; CONSTANT SetupHigh : IN TIME := 0 ns; CONSTANT SetupLow : IN TIME := 0 ns; CONSTANT HoldHigh : IN TIME := 0 ns; CONSTANT HoldLow : IN TIME := 0 ns; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT RefTransition : IN VitalEdgeSymbolType; CONSTANT HeaderMsg : IN STRING := " "; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 ) IS VARIABLE CheckInfo : CheckInfoType; VARIABLE RefEdge, TestEvent : BOOLEAN; VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); VARIABLE bias : TIME; BEGIN IF (TimingData.NotFirstFlag = FALSE) THEN TimingData.TestLast := To_X01(TestSignal); TimingData.RefLast := To_X01(RefSignal); TimingData.NotFirstFlag := TRUE; END IF; -- Detect reference edges and record the time of the last edge RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), RefTransition); TimingData.RefLast := To_X01(RefSignal); IF RefEdge THEN TimingData.RefTime := NOW; TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef; --IR252 3/23/98 TimingData.HoldEn := EnableHoldOnRef; --IR252 3/23/98 END IF; -- Detect test (data) changes and record the time of the last change TestEvent := TimingData.TestLast /= To_X01Z(TestSignal); TimingData.TestLast := To_X01Z(TestSignal); IF TestEvent THEN TimingData.TestTime := NOW; TimingData.SetupEn := EnableSetupOnTest; --IR252 3/23/98 TimingData.HoldEn := TimingData.HoldEn AND EnableHoldOnTest; --IR252 3/23/98 END IF; -- Perform timing checks (if enabled) Violation := '0'; IF (CheckEnabled) THEN InternalTimingCheck ( TestSignal => TestSignal, RefSignal => RefSignal, TestDelay => TestDly, RefDelay => RefDly, SetupHigh => SetupHigh, SetupLow => SetupLow, HoldHigh => HoldHigh, HoldLow => HoldLow, RefTime => TimingData.RefTime, RefEdge => RefEdge, TestTime => TimingData.TestTime, TestEvent => TestEvent, SetupEn => TimingData.SetupEn, HoldEn => TimingData.HoldEn, CheckInfo => CheckInfo, MsgOn => MsgOn ); -- Report any detected violations and set return violation flag IF CheckInfo.Violation THEN IF (MsgOn) THEN ReportViolation (TestSignalName, RefSignalName, HeaderMsg, CheckInfo, MsgSeverity ); END IF; IF (XOn) THEN Violation := 'X'; END IF; END IF; END IF; END VitalSetupHoldCheck; --------------------------------------------------------------------------- PROCEDURE VitalSetupHoldCheck ( VARIABLE Violation : OUT X01; VARIABLE TimingData : INOUT VitalTimingDataType; SIGNAL TestSignal : IN std_logic_vector; CONSTANT TestSignalName: IN STRING := ""; CONSTANT TestDelay : IN TIME := 0 ns; SIGNAL RefSignal : IN std_ulogic; CONSTANT RefSignalName : IN STRING := ""; CONSTANT RefDelay : IN TIME := 0 ns; CONSTANT SetupHigh : IN TIME := 0 ns; CONSTANT SetupLow : IN TIME := 0 ns; CONSTANT HoldHigh : IN TIME := 0 ns; CONSTANT HoldLow : IN TIME := 0 ns; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT RefTransition : IN VitalEdgeSymbolType; CONSTANT HeaderMsg : IN STRING := " "; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 ) IS VARIABLE CheckInfo : CheckInfoType; VARIABLE RefEdge : BOOLEAN; VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE); VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); VARIABLE bias : TIME; VARIABLE ChangedAllAtOnce : BOOLEAN := TRUE; VARIABLE StrPtr1 : LINE; BEGIN -- Initialization of working area. IF (TimingData.NotFirstFlag = FALSE) THEN TimingData.TestLastA := NEW std_logic_vector(TestSignal'RANGE); TimingData.TestTimeA := NEW VitalTimeArrayT(TestSignal'RANGE); TimingData.HoldEnA := NEW VitalBoolArrayT(TestSignal'RANGE); TimingData.SetupEnA := NEW VitalBoolArrayT(TestSignal'RANGE); FOR i IN TestSignal'RANGE LOOP TimingData.TestLastA(i) := To_X01(TestSignal(i)); END LOOP; TimingData.RefLast := To_X01(RefSignal); TimingData.NotFirstFlag := TRUE; END IF; -- Detect reference edges and record the time of the last edge RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), RefTransition); TimingData.RefLast := To_X01(RefSignal); IF RefEdge THEN TimingData.RefTime := NOW; TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef; --IR252 3/23/98 TimingData.HoldEnA.all := (TestSignal'RANGE => EnableHoldOnRef); --IR252 3/23/98 END IF; -- Detect test (data) changes and record the time of the last change FOR i IN TestSignal'RANGE LOOP TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignal(i)); TimingData.TestLastA(i) := To_X01Z(TestSignal(i)); IF TestEvent(i) THEN TimingData.TestTimeA(i) := NOW; TimingData.SetupEnA(i) := EnableSetupOnTest; --IR252 3/23/98 TimingData.HoldEnA(i) := TimingData.HoldEn AND EnableHoldOnTest; --IR252 3/23/98 TimingData.TestTime := NOW; --IR252 3/23/98 END IF; END LOOP; -- Check to see if the Bus subelements changed all at the same time. -- If so, then we can reduce the volume of error messages since we no -- longer have to report every subelement individually FOR i IN TestSignal'RANGE LOOP IF TimingData.TestTimeA(i) /= TimingData.TestTime THEN ChangedAllAtOnce := FALSE; EXIT; END IF; END LOOP; -- Perform timing checks (if enabled) Violation := '0'; IF (CheckEnabled) THEN FOR i IN TestSignal'RANGE LOOP InternalTimingCheck ( TestSignal => TestSignal(i), RefSignal => RefSignal, TestDelay => TestDly, RefDelay => RefDly, SetupHigh => SetupHigh, SetupLow => SetupLow, HoldHigh => HoldHigh, HoldLow => HoldLow, RefTime => TimingData.RefTime, RefEdge => RefEdge, TestTime => TimingData.TestTimeA(i), TestEvent => TestEvent(i), SetupEn => TimingData.SetupEnA(i), HoldEn => TimingData.HoldEnA(i), CheckInfo => CheckInfo, MsgOn => MsgOn ); -- Report any detected violations and set return violation flag IF CheckInfo.Violation THEN IF (MsgOn) THEN IF ( ChangedAllAtOnce AND (i = TestSignal'LEFT) ) THEN ReportViolation (TestSignalName&"(...)", RefSignalName, HeaderMsg, CheckInfo, MsgSeverity ); ELSIF (NOT ChangedAllAtOnce) THEN Write (StrPtr1, i); ReportViolation (TestSignalName & "(" & StrPtr1.ALL & ")", RefSignalName, HeaderMsg, CheckInfo, MsgSeverity ); DEALLOCATE (StrPtr1); END IF; END IF; IF (XOn) THEN Violation := 'X'; END IF; END IF; END LOOP; END IF; DEALLOCATE (StrPtr1); END VitalSetupHoldCheck; --------------------------------------------------------------------------- -- Function : VitalRecoveryRemovalCheck --------------------------------------------------------------------------- PROCEDURE VitalRecoveryRemovalCheck ( VARIABLE Violation : OUT X01; VARIABLE TimingData : INOUT VitalTimingDataType; SIGNAL TestSignal : IN std_ulogic; CONSTANT TestSignalName: IN STRING := ""; CONSTANT TestDelay : IN TIME := 0 ns; SIGNAL RefSignal : IN std_ulogic; CONSTANT RefSignalName : IN STRING := ""; CONSTANT RefDelay : IN TIME := 0 ns; CONSTANT Recovery : IN TIME := 0 ns; CONSTANT Removal : IN TIME := 0 ns; CONSTANT ActiveLow : IN BOOLEAN := TRUE; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT RefTransition : IN VitalEdgeSymbolType; CONSTANT HeaderMsg : IN STRING := " "; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT EnableRecOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableRecOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableRemOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 CONSTANT EnableRemOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 ) IS VARIABLE CheckInfo : CheckInfoType; VARIABLE RefEdge, TestEvent : BOOLEAN; VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); VARIABLE bias : TIME; BEGIN IF (TimingData.NotFirstFlag = FALSE) THEN TimingData.TestLast := To_X01(TestSignal); TimingData.RefLast := To_X01(RefSignal); TimingData.NotFirstFlag := TRUE; END IF; -- Detect reference edges and record the time of the last edge RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), RefTransition); TimingData.RefLast := To_X01(RefSignal); IF RefEdge THEN TimingData.RefTime := NOW; TimingData.SetupEn := TimingData.SetupEn AND EnableRecOnRef; --IR252 3/23/98 TimingData.HoldEn := EnableRemOnRef; --IR252 3/23/98 END IF; -- Detect test (data) changes and record the time of the last change TestEvent := TimingData.TestLast /= To_X01Z(TestSignal); TimingData.TestLast := To_X01Z(TestSignal); IF TestEvent THEN TimingData.TestTime := NOW; TimingData.SetupEn := EnableRecOnTest; --IR252 3/23/98 TimingData.HoldEn := TimingData.HoldEn AND EnableRemOnTest; --IR252 3/23/98 END IF; -- Perform timing checks (if enabled) Violation := '0'; IF (CheckEnabled) THEN IF ActiveLow THEN InternalTimingCheck ( TestSignal, RefSignal, TestDly, RefDly, Recovery, 0 ns, 0 ns, Removal, TimingData.RefTime, RefEdge, TimingData.TestTime, TestEvent, TimingData.SetupEn, TimingData.HoldEn, CheckInfo, MsgOn ); ELSE InternalTimingCheck ( TestSignal, RefSignal, TestDly, RefDly, 0 ns, Recovery, Removal, 0 ns, TimingData.RefTime, RefEdge, TimingData.TestTime, TestEvent, TimingData.SetupEn, TimingData.HoldEn, CheckInfo, MsgOn ); END IF; -- Report any detected violations and set return violation flag IF CheckInfo.Violation THEN IF CheckInfo.CheckKind = SetupCheck THEN CheckInfo.CheckKind := RecoveryCheck; ELSE CheckInfo.CheckKind := RemovalCheck; END IF; IF (MsgOn) THEN ReportViolation (TestSignalName, RefSignalName, HeaderMsg, CheckInfo, MsgSeverity ); END IF; IF (XOn) THEN Violation := 'X'; END IF; END IF; END IF; END VitalRecoveryRemovalCheck; --------------------------------------------------------------------------- PROCEDURE VitalPeriodPulseCheck ( VARIABLE Violation : OUT X01; VARIABLE PeriodData : INOUT VitalPeriodDataType; SIGNAL TestSignal : IN std_ulogic; CONSTANT TestSignalName : IN STRING := ""; CONSTANT TestDelay : IN TIME := 0 ns; CONSTANT Period : IN TIME := 0 ns; CONSTANT PulseWidthHigh : IN TIME := 0 ns; CONSTANT PulseWidthLow : IN TIME := 0 ns; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT HeaderMsg : IN STRING := " "; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING ) IS VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); VARIABLE CheckInfo : CheckInfoType; VARIABLE PeriodObs : TIME; VARIABLE PulseTest, PeriodTest : BOOLEAN; VARIABLE TestValue : X01 := To_X01(TestSignal); BEGIN IF (PeriodData.NotFirstFlag = FALSE) THEN PeriodData.Rise := -maximum(Period, maximum(PulseWidthHigh, PulseWidthLow)); PeriodData.Fall := -maximum(Period, maximum(PulseWidthHigh, PulseWidthLow)); PeriodData.Last := To_X01(TestSignal); PeriodData.NotFirstFlag := TRUE; END IF; -- Initialize for no violation -- No violation possible if no test signal change Violation := '0'; IF (PeriodData.Last = TestValue) THEN RETURN; END IF; -- record starting pulse times IF EdgeSymbolMatch(PeriodData.Last, TestValue, 'P') THEN -- Compute period times, then record the High Rise Time PeriodObs := NOW - PeriodData.Rise; PeriodData.Rise := NOW; PeriodTest := TRUE; ELSIF EdgeSymbolMatch(PeriodData.Last, TestValue, 'N') THEN -- Compute period times, then record the Low Fall Time PeriodObs := NOW - PeriodData.Fall; PeriodData.Fall := NOW; PeriodTest := TRUE; ELSE PeriodTest := FALSE; END IF; -- do checks on pulse ends IF EdgeSymbolMatch(PeriodData.Last, TestValue, 'p') THEN -- Compute pulse times CheckInfo.ObsTime := NOW - PeriodData.Fall; CheckInfo.ExpTime := PulseWidthLow; PulseTest := TRUE; ELSIF EdgeSymbolMatch(PeriodData.Last, TestValue, 'n') THEN -- Compute pulse times CheckInfo.ObsTime := NOW - PeriodData.Rise; CheckInfo.ExpTime := PulseWidthHigh; PulseTest := TRUE; ELSE PulseTest := FALSE; END IF; IF PulseTest AND CheckEnabled THEN -- Verify Pulse Width [ignore 1st edge] IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN IF (XOn) THEN Violation := 'X'; END IF; IF (MsgOn) THEN CheckInfo.Violation := TRUE; CheckInfo.CheckKind := PulseWidCheck; CheckInfo.DetTime := NOW - TestDly; CheckInfo.State := PeriodData.Last; ReportViolation (TestSignalName, "", HeaderMsg, CheckInfo, MsgSeverity ); END IF; -- MsgOn END IF; END IF; IF PeriodTest AND CheckEnabled THEN -- Verify the Period [ignore 1st edge] CheckInfo.ObsTime := PeriodObs; CheckInfo.ExpTime := Period; IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN IF (XOn) THEN Violation := 'X'; END IF; IF (MsgOn) THEN CheckInfo.Violation := TRUE; CheckInfo.CheckKind := PeriodCheck; CheckInfo.DetTime := NOW - TestDly; CheckInfo.State := TestValue; ReportViolation (TestSignalName, "", HeaderMsg, CheckInfo, MsgSeverity ); END IF; -- MsgOn END IF; END IF; PeriodData.Last := TestValue; END VitalPeriodPulseCheck; PROCEDURE ReportSkewViolation ( CONSTANT Signal1Name : IN STRING := ""; CONSTANT Signal2Name : IN STRING := ""; CONSTANT ExpectedTime : IN TIME; CONSTANT OccuranceTime : IN TIME; CONSTANT HeaderMsg : IN STRING; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT SkewPhase : IN SkewType; CONSTANT ViolationFlag : IN BOOLEAN := TRUE ) IS VARIABLE Message : LINE; BEGIN Write ( Message, HeaderMsg ); IF (ViolationFlag /= TRUE) THEN Write ( Message, STRING'(" POSSIBLE") ); END IF; IF (SkewPhase = Inphase) THEN Write ( Message, STRING'(" IN PHASE ") ); ELSE Write ( Message, STRING'(" OUT OF PHASE ") ); END IF; Write ( Message, STRING'("SKEW VIOLATION ON ") ); Write ( Message, Signal2Name ); IF (Signal1Name'LENGTH > 0) THEN Write ( Message, STRING'(" WITH RESPECT TO ") ); Write ( Message, Signal1Name ); END IF; Write ( Message, ';' & LF ); Write ( Message, STRING'(" At : ") ); Write ( Message, OccuranceTime); Write ( Message, STRING'("; Skew Limit : ") ); Write ( Message, ExpectedTime); ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity; DEALLOCATE (Message); END ReportSkewViolation; PROCEDURE VitalInPhaseSkewCheck ( VARIABLE Violation : OUT X01; VARIABLE SkewData : INOUT VitalSkewDataType; SIGNAL Signal1 : IN std_ulogic; CONSTANT Signal1Name : IN STRING := ""; CONSTANT Signal1Delay : IN TIME := 0 ns; SIGNAL Signal2 : IN std_ulogic; CONSTANT Signal2Name : IN STRING := ""; CONSTANT Signal2Delay : IN TIME := 0 ns; CONSTANT SkewS1S2RiseRise : IN TIME := TIME'HIGH; CONSTANT SkewS2S1RiseRise : IN TIME := TIME'HIGH; CONSTANT SkewS1S2FallFall : IN TIME := TIME'HIGH; CONSTANT SkewS2S1FallFall : IN TIME := TIME'HIGH; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT HeaderMsg : IN STRING := ""; SIGNAL Trigger : INOUT std_ulogic ) IS VARIABLE ReportType : VitalSkewExpectedType := none; VARIABLE ExpectedType : VitalSkewExpectedType := none; VARIABLE ReportTime : TIME; VARIABLE TriggerDelay : TIME; VARIABLE ViolationCertain : Boolean := TRUE; BEGIN Violation := '0'; ReportType := none; TriggerDelay := noTrigger; IF (CheckEnabled) THEN IF (SkewData.ExpectedType /= none) THEN IF (trigger'Event) THEN CASE SkewData.ExpectedType IS WHEN s1r => ReportType := s1r; ReportTime := NOW - Signal1Delay; WHEN s1f => ReportType := s1f; ReportTime := NOW - Signal1Delay; WHEN s2r => ReportType := s2r; ReportTime := NOW - Signal2Delay; WHEN s2f => ReportType := s2f; ReportTime := NOW - Signal2Delay; WHEN OTHERS => END CASE; SkewData.ExpectedType := none; ELSIF ( Signal1'Event OR Signal2'Event ) THEN IF ( Signal1 /= 'X' AND Signal2 /= 'X' ) THEN TriggerDelay := 0 ns; ExpectedType := none; END IF; END IF; END IF; IF (Signal1'EVENT and Signal2'EVENT) THEN IF (Signal1 = Signal2) THEN IF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - Signal2Delay) >= SkewS1S2RiseRise) THEN ReportType := s2r; ReportTime := NOW - Signal1Delay + SkewS1S2RiseRise; ELSIF ((Signal2Delay -Signal1Delay) >= SkewS2S1RiseRise) THEN ReportType := s1r; ReportTime := NOW - Signal2Delay + SkewS2S1RiseRise; END IF; ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - Signal2Delay) >= SkewS1S2FallFall) THEN ReportType := s2f; ReportTime := NOW - Signal1Delay + SkewS1S2FallFall; ELSIF ((Signal2Delay - Signal1Delay) >= SkewS2S1FallFall) THEN ReportType := s1f; ReportTime := NOW - Signal2Delay + SkewS2S1FallFall; END IF; END IF; ELSIF (Posedge(Signal1'LAST_VALUE , Signal1)) THEN IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > SkewS2S1FallFall)) THEN ReportType := s1f; ReportTime := NOW - Signal2Delay + SkewS2S1FallFall; ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > SkewS1S2RiseRise)) THEN ReportType := s2r; ReportTime := NOW - Signal1Delay + SkewS1S2RiseRise; ELSIF (Signal2Delay > Signal1Delay) THEN SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2RiseRise + Signal2Delay - Signal1Delay; ELSIF (Signal1Delay > Signal2Delay) THEN SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1RiseRise + Signal1Delay - Signal2Delay; ELSIF (SkewS1S2RiseRise < SkewS2S1RiseRise) THEN SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2RiseRise; ELSE SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1RiseRise; END IF; ELSIF (Negedge(Signal1'LAST_VALUE , Signal1)) THEN IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > SkewS2S1RiseRise)) THEN ReportType := s1r; ReportTime := NOW - Signal2Delay + SkewS2S1RiseRise; ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > SkewS1S2FallFall)) THEN ReportType := s2f; ReportTime := NOW - Signal1Delay + SkewS1S2FallFall; ELSIF (Signal2Delay > Signal1Delay) THEN SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2FallFall + Signal2Delay - Signal1Delay; ELSIF (Signal1Delay > Signal2Delay) THEN SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1FallFall + Signal1Delay - Signal2Delay; ELSIF (SkewS1S2FallFall < SkewS2S1FallFall) THEN SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2FallFall; ELSE SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1FallFall; END IF; END IF; ELSIF (Signal1'EVENT) THEN IF ( Signal1 /= Signal2) THEN IF ( Posedge( Signal1'LAST_VALUE, Signal1)) THEN IF (SkewS1S2RiseRise > (Signal1Delay - Signal2Delay)) THEN SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2RiseRise + Signal2Delay - Signal1Delay; ELSE ReportType := s2r; ReportTime := NOW + SkewS1S2RiseRise - Signal1Delay; END IF; ELSIF ( Negedge( Signal1'LAST_VALUE, Signal1)) THEN IF (SkewS1S2FallFall > (Signal1Delay - Signal2Delay)) THEN SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2FallFall + Signal2Delay - Signal1Delay; ELSE ReportType := s2f; ReportTime := NOW + SkewS1S2FallFall - Signal1Delay; END IF; END IF; ELSE IF ( Posedge( Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - SkewS1S2RiseRise) > (Signal2'LAST_EVENT + Signal2Delay)) THEN IF ((SkewData.Signal2Old2 - Signal2Delay) > (NOW - Signal1Delay + SkewS1S2RiseRise)) THEN ViolationCertain := FALSE; ReportType := s2r; ReportTime := NOW + SkewS1S2RiseRise - Signal1Delay; END IF; END IF; ELSIF ( Negedge( Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - SkewS1S2FallFall) > (Signal2'LAST_EVENT + Signal2Delay)) THEN IF (( SkewData.Signal2Old2 - Signal2Delay) > (NOW - Signal1Delay + SkewS1S2FallFall )) THEN ViolationCertain := FALSE; ReportType := s2f; ReportTime := NOW + SkewS1S2FallFall - Signal1Delay; END IF; END IF; END IF; END IF; ELSIF (Signal2'EVENT) THEN IF (Signal1 /= Signal2) THEN IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN IF ( SkewS2S1RiseRise > (Signal2Delay - Signal1Delay)) THEN SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1RiseRise + Signal1Delay - Signal2Delay; ELSE ReportType := s2r; ReportTime := NOW + SkewS2S1RiseRise - Signal2Delay; END IF; ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN IF ( SkewS2S1FallFall > (Signal2Delay - Signal1Delay)) THEN SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1FallFall + Signal1Delay - Signal2Delay; ELSE ReportType := s1f; ReportTime := NOW + SkewS2S1FallFall - Signal2Delay; END IF; END IF; ELSE IF (Posedge(Signal2'LAST_VALUE, Signal2)) THEN IF ((Signal2Delay - SkewS2S1RiseRise) > (Signal1'LAST_EVENT + Signal1Delay)) THEN IF (( SkewData.Signal1Old2 - Signal1Delay) > (NOW - Signal2Delay + SkewS2S1RiseRise )) THEN ViolationCertain := FALSE; ReportType := s1r; ReportTime := NOW + SkewS2S1RiseRise - Signal2Delay; END IF; END IF; ELSIF (Negedge(Signal2'LAST_VALUE, Signal2)) THEN IF ((Signal2Delay - SkewS2S1FallFall) > (Signal1'LAST_EVENT + Signal1Delay)) THEN IF (( SkewData.Signal1Old2 - Signal1Delay) > (NOW - Signal2Delay + SkewS2S1FallFall )) THEN ViolationCertain := FALSE; ReportType := s1f; ReportTime := NOW + SkewS2S1FallFall - Signal2Delay; END IF; END IF; END IF; END IF; END IF; IF (ReportType /= none) THEN IF (MsgOn) THEN CASE ReportType IS WHEN s1r => ReportSkewViolation( Signal2Name, Signal1Name, SkewS2S1RiseRise, ReportTime, HeaderMsg, MsgSeverity, Inphase, ViolationCertain); WHEN s1f => ReportSkewViolation( Signal2Name, Signal1Name, SkewS2S1FallFall, ReportTime, HeaderMsg, MsgSeverity, Inphase, ViolationCertain); WHEN s2r => ReportSkewViolation( Signal1Name, Signal2Name, SkewS1S2RiseRise, ReportTime, HeaderMsg, MsgSeverity, Inphase, ViolationCertain); WHEN s2f => ReportSkewViolation( Signal1Name, Signal2Name, SkewS1S2FallFall, ReportTime, HeaderMsg, MsgSeverity, Inphase, ViolationCertain); WHEN OTHERS => END CASE; END IF; IF (XOn) THEN Violation := 'X'; END IF; SkewData.ExpectedType := none; END IF; IF (TriggerDelay /= noTrigger) THEN IF (TriggerDelay = 0 ns) THEN trigger <= TRANSPORT trigger AFTER 0 ns; ELSE trigger <= TRANSPORT not (trigger) AFTER TriggerDelay; END IF; END IF; END IF; IF (Signal1'EVENT and SkewData.Signal1Old1 /= NOW) THEN SkewData.Signal1Old2 := SkewData.Signal1Old1; SkewData.Signal1Old1 := NOW; END IF; IF (Signal2'EVENT and SkewData.Signal2Old1 /= NOW) THEN SkewData.Signal2Old2 := SkewData.Signal2Old1; SkewData.Signal2Old1 := NOW; END IF; END VitalInPhaseSkewCheck; PROCEDURE VitalOutPhaseSkewCheck ( VARIABLE Violation : OUT X01; VARIABLE SkewData : INOUT VitalSkewDataType; SIGNAL Signal1 : IN std_ulogic; CONSTANT Signal1Name : IN STRING := ""; CONSTANT Signal1Delay : IN TIME := 0 ns; SIGNAL Signal2 : IN std_ulogic; CONSTANT Signal2Name : IN STRING := ""; CONSTANT Signal2Delay : IN TIME := 0 ns; CONSTANT SkewS1S2RiseFall : IN TIME := TIME'HIGH; CONSTANT SkewS2S1RiseFall : IN TIME := TIME'HIGH; CONSTANT SkewS1S2FallRise : IN TIME := TIME'HIGH; CONSTANT SkewS2S1FallRise : IN TIME := TIME'HIGH; CONSTANT CheckEnabled : IN BOOLEAN := TRUE; CONSTANT XOn : IN BOOLEAN := TRUE; CONSTANT MsgOn : IN BOOLEAN := TRUE; CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; CONSTANT HeaderMsg : IN STRING := ""; SIGNAL Trigger : INOUT std_ulogic ) IS VARIABLE ReportType : VitalSkewExpectedType := none; VARIABLE ExpectedType : VitalSkewExpectedType := none; VARIABLE ReportTime : TIME; VARIABLE TriggerDelay : TIME; VARIABLE ViolationCertain : Boolean := TRUE; BEGIN Violation := '0'; TriggerDelay := noTrigger; IF (CheckEnabled) THEN IF (SkewData.ExpectedType /= none) THEN IF (trigger'Event) THEN CASE SkewData.ExpectedType IS WHEN s1r => ReportType := s1r; ReportTime := NOW - Signal1Delay; WHEN s1f => ReportType := s1f; ReportTime := NOW - Signal1Delay; WHEN s2r => ReportType := s2r; ReportTime := NOW - Signal2Delay; WHEN s2f => ReportType := s2f; ReportTime := NOW - Signal2Delay; WHEN OTHERS => END CASE; SkewData.ExpectedType := none; ELSIF (Signal1'Event OR Signal2'Event ) THEN IF (Signal1 /= 'X' AND Signal2 /= 'X' ) THEN TriggerDelay := 0 ns; SkewData.ExpectedType := none; END IF; END IF; END IF; IF (Signal1'EVENT and Signal2'EVENT) THEN IF (Signal1 /= Signal2) THEN IF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - Signal2Delay) >= SkewS1S2RiseFall) THEN ReportType := s2f; ReportTime := NOW - Signal1Delay + SkewS1S2RiseFall; ELSIF ((Signal2Delay - Signal1Delay) >= SkewS2S1FallRise) THEN ReportType := s1r; ReportTime := NOW - Signal2Delay + SkewS2S1FallRise; END IF; ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - Signal2Delay) >= SkewS1S2FallRise) THEN ReportType := s2r; ReportTime := NOW - Signal1Delay + SkewS1S2FallRise; ELSIF ((Signal2Delay - Signal1Delay) >= SkewS2S1RiseFall) THEN ReportType := s1f; ReportTime := NOW - Signal2Delay + SkewS2S1RiseFall; END IF; END IF; ELSIF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > SkewS2S1RiseFall)) THEN ReportType := s1f; ReportTime := NOW - Signal2Delay + SkewS2S1RiseFall; ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > SkewS1S2RiseFall)) THEN ReportType := s2f; ReportTime := NOW - Signal1Delay + SkewS1S2RiseFall; ELSIF (Signal1Delay > Signal2Delay) THEN SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1RiseFall + Signal1Delay - Signal2Delay; ELSIF (Signal2Delay > Signal1Delay) THEN SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2RiseFall + Signal2Delay - Signal1Delay; ELSIF (SkewS2S1RiseFall < SkewS1S2RiseFall) THEN SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1RiseFall; ELSE SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2RiseFall; END IF; ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > SkewS2S1FallRise)) THEN ReportType := s1r; ReportTime := NOW - Signal2Delay + SkewS2S1FallRise; ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > SkewS1S2FallRise)) THEN ReportType := s2r; ReportTime := NOW - Signal1Delay + SkewS1S2FallRise; ELSIF (Signal1Delay > Signal2Delay) THEN SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1FallRise + Signal1Delay - Signal2Delay; ELSIF (Signal2Delay > Signal1Delay) THEN SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2FallRise + Signal2Delay - Signal1Delay; ELSIF (SkewS2S1FallRise < SkewS1S2FallRise) THEN SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1FallRise; ELSE SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2FallRise; END IF; END IF; ELSIF (Signal1'EVENT) THEN IF (Signal1 = Signal2) THEN IF (Posedge(Signal1'LAST_VALUE,Signal1)) THEN IF (SkewS1S2RiseFall > (Signal1Delay - Signal2Delay)) THEN SkewData.ExpectedType := s2f; TriggerDelay := SkewS1S2RiseFall + Signal2Delay - Signal1Delay; ELSE ReportType := s2f; ReportTime := NOW - Signal1Delay + SkewS1S2RiseFall; END IF; ELSIF ( Negedge(Signal1'LAST_VALUE, Signal1)) THEN IF ( SkewS1S2FallRise > (Signal1Delay - Signal2Delay)) THEN SkewData.ExpectedType := s2r; TriggerDelay := SkewS1S2FallRise + Signal2Delay - Signal1Delay; ELSE ReportType := s2r; ReportTime := NOW - Signal1Delay + SkewS1S2FallRise; END IF; END IF; ELSE IF (Posedge( Signal1'LAST_VALUE, Signal1 )) THEN IF ((Signal1Delay - SkewS1S2RiseFall) > (Signal2'LAST_EVENT + Signal2Delay)) THEN IF (( SkewData.Signal2Old2 - Signal2Delay) > (NOW - Signal1Delay + SkewS1S2RiseFall )) THEN ViolationCertain := FALSE; ReportType := s2f; ReportTime := NOW + SkewS1S2RiseFall - Signal1Delay; END IF; END IF; ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN IF ((Signal1Delay - SkewS1S2FallRise) > (Signal2'LAST_EVENT + Signal2Delay)) THEN IF (( SkewData.Signal2Old2 - Signal2Delay) > (NOW - Signal1Delay + SkewS1S2FallRise )) THEN ViolationCertain := FALSE; ReportType := s2r; ReportTime := NOW + SkewS1S2FallRise - Signal1Delay; END IF; END IF; END IF; END IF; ELSIF (Signal2'EVENT) THEN IF (Signal1 = Signal2) THEN IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN IF (SkewS2S1RiseFall > (Signal2Delay - Signal1Delay)) THEN SkewData.ExpectedType := s1f; TriggerDelay := SkewS2S1RiseFall + Signal1Delay - Signal2Delay ; ELSE ReportType := s1f; ReportTime := NOW + SkewS2S1RiseFall - Signal2Delay; END IF; ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN IF (SkewS2S1FallRise > (Signal2Delay - Signal1Delay)) THEN SkewData.ExpectedType := s1r; TriggerDelay := SkewS2S1FallRise + Signal1Delay - Signal2Delay; ELSE ReportType := s1r; ReportTime := NOW + SkewS2S1FallRise - Signal2Delay; END IF; END IF; ELSE IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN IF ((Signal2Delay - SkewS2S1RiseFall) > (Signal1'LAST_EVENT + Signal1Delay)) THEN IF (( SkewData.Signal1Old2 - Signal1Delay) > (NOW - Signal2Delay + SkewS2S1RiseFall )) THEN ViolationCertain := FALSE; ReportType := s1f; ReportTime := NOW + SkewS2S1RiseFall - Signal2Delay; END IF; END IF; ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN IF ((Signal2Delay - SkewS2S1FallRise) > (Signal1'LAST_EVENT + Signal1Delay)) THEN IF (( SkewData.Signal1Old2 - Signal1Delay) > (NOW - Signal2Delay + SkewS2S1FallRise )) THEN ViolationCertain := FALSE; ReportType := s1r; ReportTime := NOW + SkewS2S1FallRise - Signal2Delay; END IF; END IF; END IF; END IF; END IF; IF (ReportType /= none) THEN IF (MsgOn) THEN CASE ReportType IS WHEN s1r => ReportSkewViolation( Signal2Name, Signal1Name, SkewS2S1FallRise, ReportTime, HeaderMsg, MsgSeverity, Outphase, ViolationCertain); WHEN s1f => ReportSkewViolation( Signal2Name, Signal1Name, SkewS2S1RiseFall, ReportTime, HeaderMsg, MsgSeverity, Outphase, ViolationCertain); WHEN s2r => ReportSkewViolation( Signal1Name, Signal2Name, SkewS1S2FallRise, ReportTime, HeaderMsg, MsgSeverity, Outphase, ViolationCertain); WHEN s2f => ReportSkewViolation( Signal1Name, Signal2Name, SkewS1S2RiseFall, ReportTime, HeaderMsg, MsgSeverity, Outphase, ViolationCertain); WHEN OTHERS => END CASE; END IF; IF (XOn) THEN Violation := 'X'; END IF; ReportType := none; END IF; IF (TriggerDelay /= noTrigger) THEN IF (TriggerDelay = 0 ns) THEN trigger <= TRANSPORT trigger AFTER 0 ns; ELSE trigger <= TRANSPORT not (trigger) AFTER TriggerDelay; END IF; END IF; END IF; IF (Signal1'EVENT and SkewData.Signal1Old1 /= NOW) THEN SkewData.Signal1Old2 := SkewData.Signal1Old1; SkewData.Signal1Old1 := NOW; END IF; IF (Signal2'EVENT and SkewData.Signal2Old1 /= NOW) THEN SkewData.Signal2Old2 := SkewData.Signal2Old1; SkewData.Signal2Old1 := NOW; END IF; END VitalOutPhaseSkewCheck; END VITAL_Timing;