aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/vital95/vital_timing-body.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/vital95/vital_timing-body.vhdl')
-rw-r--r--libraries/vital95/vital_timing-body.vhdl1275
1 files changed, 1275 insertions, 0 deletions
diff --git a/libraries/vital95/vital_timing-body.vhdl b/libraries/vital95/vital_timing-body.vhdl
new file mode 100644
index 000000000..49998bdb5
--- /dev/null
+++ b/libraries/vital95/vital_timing-body.vhdl
@@ -0,0 +1,1275 @@
+-------------------------------------------------------------------------------
+-- 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 | #203 - Timing violations at time 0
+-- #204 - Output mapping prior to glitch detection
+-- ----------------------------------------------------------------------------
+
+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 ) ) );
+
+ ---------------------------------------------------------------------------
+ ---------------------------------------------------------------------------
+ -- 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;
+
+ ---------------------------------------------------------------------------
+ FUNCTION VitalSelectPathDelay (
+ CONSTANT NewValue : IN std_logic;
+ CONSTANT OldValue : IN std_logic;
+ CONSTANT OutSignalName : IN string;
+ CONSTANT Paths : IN VitalPathArrayType;
+ CONSTANT DefaultDelay : IN VitalDelayType
+ ) 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 the delay
+ IF (PropDelay = TIME'HIGH ) THEN
+ PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay);
+
+ -- If the time since the most recent input event is greater than the
+ -- propagation delay from that input then
+ -- use the default the delay
+ 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
+ ) 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 the delay
+ IF (PropDelay = TIME'HIGH ) THEN
+ PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay);
+
+ -- If the time since the most recent input event is greater than the
+ -- propagation delay from that input then
+ -- use the default the delay
+ 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
+ ) 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 the delay
+ IF (PropDelay = TIME'HIGH ) THEN
+ PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay);
+
+ -- If the time since the most recent input event is greater than the
+ -- propagation delay from that input then
+ -- use the default the delay
+ 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;
+
+ 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 MsgOn : IN BOOLEAN := FALSE;
+ CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING
+ ) IS
+ ---------------------------------------------------------------------------
+ VARIABLE NewGlitch : BOOLEAN := TRUE;
+ VARIABLE dly : TIME := NewDelay;
+
+ BEGIN
+ -- 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
+ -- Note: NewValue is always /= OldValue when called from VPPD
+ IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF;
+ -- No new glitch, save time for possable future glitch
+ NewGlitch := FALSE;
+ GlitchData.GlitchTime := NOW+dly;
+
+ -- New value earlier than the earliest previous value scheduled
+ ELSIF (NOW+dly <= GlitchData.GlitchTime)
+ AND (NOW+dly <= GlitchData.SchedTime) THEN
+ -- No new glitch, save time for possible future glitch
+ NewGlitch := FALSE;
+ 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
+ -- A new glitch has been detected
+ NewGlitch := TRUE;
+ END IF;
+
+ IF NewGlitch THEN
+ -- If messages requested, report the glitch
+ IF MsgOn THEN
+ ReportGlitch ("VitalGlitch", OutSignalName,
+ GlitchData.GlitchTime, GlitchData.SchedValue,
+ (dly + NOW), NewValue,
+ MsgSeverity=>MsgSeverity );
+ END IF;
+
+ -- Force immediate glitch for "OnDetect" mode.
+ IF (Mode = OnDetect) THEN
+ GlitchData.GlitchTime := NOW;
+ 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
+ OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW;
+ OutSignal <= TRANSPORT NewValue AFTER dly;
+ ELSE
+ OutSignal <= NewValue AFTER dly;
+ 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 just scheduled.
+ GlitchData.SchedValue := NewValue;
+ GlitchData.SchedTime := NOW+dly;
+ 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
+ ) 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);
+ GlitchData.LastValue := OutTemp;
+
+ -- Schedule the output transactions - including glitch handling
+ VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp,
+ PropDelay, Mode, XOn, 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
+ ) 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);
+ GlitchData.LastValue := OutTemp;
+
+ -- Schedule the output transactions - including glitch handling
+ VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp,
+ PropDelay, Mode, XOn, 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
+ ) 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 = OutputMap(OutTemp) )
+ THEN RETURN;
+ END IF;
+
+ -- Evaluate propagation delay paths
+ PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue,
+ OutSignalName, Paths, DefaultDelay);
+ GlitchData.LastValue := OutTemp;
+
+ -- Schedule the output transactions - including glitch handling
+ VitalGlitch (OutSignal, GlitchData, OutSignalName, OutputMap(OutTemp),
+ PropDelay, Mode, XOn, 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, b2 : TIME;
+ 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;
+ WHEN '1' => CheckInfo.ExpTime := SetupHigh;
+ WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow);
+ END CASE;
+ CheckInfo.Violation := CheckInfo.ObsTime < CheckInfo.ExpTime;
+ 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;
+ WHEN '1' => CheckInfo.ExpTime := HoldLow;
+ WHEN 'X' => CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow);
+ END CASE;
+ CheckInfo.Violation := CheckInfo.ObsTime < CheckInfo.ExpTime;
+ 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 and bias are non-negative
+ IF MsgOn AND CheckInfo.Violation THEN
+ bias := TestDelay - RefDelay;
+ IF TestTime - RefTime <= bias THEN
+ CheckInfo.CheckKind := SetupCheck;
+ b2 := TIME'HIGH - bias;
+ IF (CheckInfo.ObsTime <= b2)
+ THEN CheckInfo.ObsTime := CheckInfo.ObsTime + bias;
+ ELSE CheckInfo.ObsTime := Time'HIGH;
+ END IF;
+ IF (CheckInfo.ExpTime <= b2)
+ THEN CheckInfo.ExpTime := CheckInfo.ExpTime + bias;
+ ELSE CheckInfo.ExpTime := Time'HIGH;
+ END IF;
+ CheckInfo.DetTime := RefTime - RefDelay;
+ ELSE
+ CheckInfo.CheckKind := HoldCheck;
+ CheckInfo.ObsTime := CheckInfo.ObsTime - bias;
+ IF (CheckInfo.ExpTime >= 0 ns) THEN
+ CheckInfo.ExpTime := CheckInfo.ExpTime - bias;
+ END IF;
+ 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
+ ) 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.HoldEn := TRUE;
+ 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 := TRUE;
+ 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
+ ) 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.HoldEnA.all := (TestSignal'RANGE=>TRUE);
+ 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) := TRUE;
+ TimingData.TestTime := NOW;
+ 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
+ ) 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.HoldEn := TRUE;
+ 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 := TRUE;
+ 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;
+
+END VITAL_Timing;
+