diff options
Diffstat (limited to 'libraries/vital2000/timing_b.vhdl')
-rw-r--r-- | libraries/vital2000/timing_b.vhdl | 2187 |
1 files changed, 2187 insertions, 0 deletions
diff --git a/libraries/vital2000/timing_b.vhdl b/libraries/vital2000/timing_b.vhdl new file mode 100644 index 0000000..28bf520 --- /dev/null +++ b/libraries/vital2000/timing_b.vhdl @@ -0,0 +1,2187 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL TIMING Package +-- : $Revision: 598 $ +-- 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; |