2024-12-01 22:58:28 +08:00

2188 lines
96 KiB
VHDL

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