From f4689c2660cb26e341f79f8104d46c808427f6c0 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 24 Apr 2019 20:45:17 +0200 Subject: libraries: rename _body files. Fix #699 --- dist/windows/compile-libraries.ps1 | 14 +- dist/windows/mcode/complib.bat | 10 +- libraries/Makefile.inc | 12 +- libraries/ieee/std_logic_1164-body.vhdl | 830 ++++ libraries/ieee/std_logic_1164_body.vhdl | 830 ---- libraries/mentor/std_logic_arith-body.vhdl | 2915 +++++++++++++ libraries/mentor/std_logic_arith_body.vhdl | 2915 ------------- libraries/std/env-body.vhdl | 65 + libraries/std/env_body.vhdl | 65 - libraries/std/textio-body.vhdl | 1558 +++++++ libraries/std/textio_body.vhdl | 1558 ------- libraries/vital95/vital_primitives-body.vhdl | 5614 ++++++++++++++++++++++++++ libraries/vital95/vital_primitives_body.vhdl | 5614 -------------------------- libraries/vital95/vital_timing-body.vhdl | 1275 ++++++ libraries/vital95/vital_timing_body.vhdl | 1275 ------ 15 files changed, 12275 insertions(+), 12275 deletions(-) create mode 100644 libraries/ieee/std_logic_1164-body.vhdl delete mode 100644 libraries/ieee/std_logic_1164_body.vhdl create mode 100644 libraries/mentor/std_logic_arith-body.vhdl delete mode 100644 libraries/mentor/std_logic_arith_body.vhdl create mode 100644 libraries/std/env-body.vhdl delete mode 100644 libraries/std/env_body.vhdl create mode 100644 libraries/std/textio-body.vhdl delete mode 100644 libraries/std/textio_body.vhdl create mode 100644 libraries/vital95/vital_primitives-body.vhdl delete mode 100644 libraries/vital95/vital_primitives_body.vhdl create mode 100644 libraries/vital95/vital_timing-body.vhdl delete mode 100644 libraries/vital95/vital_timing_body.vhdl diff --git a/dist/windows/compile-libraries.ps1 b/dist/windows/compile-libraries.ps1 index 95f793b8a..a37b78618 100644 --- a/dist/windows/compile-libraries.ps1 +++ b/dist/windows/compile-libraries.ps1 @@ -122,10 +122,10 @@ $GHDLNewExecutable = "$GHDLRootDir\$BuildDirectoryName\$Backend\bin\ghdl. # Library sources $SourceFiles = @{ "std" = @( - "textio", "textio_body" + "textio", "textio-body" ); "ieee" = @( - "std_logic_1164", "std_logic_1164_body", + "std_logic_1164", "std_logic_1164-body", "numeric_std", "numeric_std-body", "numeric_bit", "numeric_bit-body" ); @@ -134,8 +134,8 @@ $SourceFiles = @{ "math_complex", "math_complex-body" ); "std08" = @( - "textio", "textio_body", - "env", "env_body" + "textio", "textio-body", + "env", "env-body" ); "ieee2008" = @( "std_logic_1164", "std_logic_1164-body", @@ -155,8 +155,8 @@ $SourceFiles = @{ "ieee_bit_context" ); "vital95" = @( - "vital_timing", "vital_timing_body", - "vital_primitives", "vital_primitives_body" + "vital_timing", "vital_timing-body", + "vital_primitives", "vital_primitives-body" ); "vital2000" = @( "timing_p", "timing_b", @@ -173,7 +173,7 @@ $SourceFiles = @{ "std_logic_misc", "std_logic_misc-body" ); "mentor" = @( - "std_logic_arith", "std_logic_arith_body" + "std_logic_arith", "std_logic_arith-body" ) } diff --git a/dist/windows/mcode/complib.bat b/dist/windows/mcode/complib.bat index 91504a832..e7291ad03 100644 --- a/dist/windows/mcode/complib.bat +++ b/dist/windows/mcode/complib.bat @@ -10,18 +10,18 @@ set LIBSRC=%REL%\..\..\libraries :: :: library sources :: -set STD_SRCS= textio textio_body -set IEEE_SRCS= std_logic_1164 std_logic_1164_body numeric_std numeric_std-body numeric_bit numeric_bit-body +set STD_SRCS= textio textio-body +set IEEE_SRCS= std_logic_1164 std_logic_1164-body numeric_std numeric_std-body numeric_bit numeric_bit-body set MATH_SRCS= math_real math_real-body math_complex math_complex-body -set STD08_SRCS= textio textio_body env env_body +set STD08_SRCS= textio textio-body env env-body set IEEE08_SRCS= std_logic_1164 std_logic_1164-body std_logic_textio math_real math_real-body math_complex math_complex-body numeric_bit numeric_bit-body numeric_bit_unsigned numeric_bit_unsigned-body numeric_std numeric_std-body numeric_std_unsigned numeric_std_unsigned-body fixed_float_types fixed_generic_pkg fixed_generic_pkg-body fixed_pkg float_generic_pkg float_generic_pkg-body float_pkg ieee_bit_context ieee_std_context -set VITAL95_SRCS= vital_timing vital_timing_body vital_primitives vital_primitives_body +set VITAL95_SRCS= vital_timing vital_timing-body vital_primitives vital_primitives-body set VITAL2000_SRCS= timing_p timing_b prmtvs_p prmtvs_b memory_p memory_b set SYNOPSYS_SRCS= std_logic_arith std_logic_textio std_logic_unsigned std_logic_signed std_logic_misc std_logic_misc-body -set MENTOR_SRCS= std_logic_arith std_logic_arith_body +set MENTOR_SRCS= std_logic_arith std_logic_arith-body mkdir lib diff --git a/libraries/Makefile.inc b/libraries/Makefile.inc index f9f8e8c4d..c4bb87643 100644 --- a/libraries/Makefile.inc +++ b/libraries/Makefile.inc @@ -42,23 +42,23 @@ vhdl.libs.v93: std.v93 ieee.v93 synopsys.v93 vhdl.libs.v08: std.v08 ieee.v08 endif -STD_SRCS := std/textio.vhdl std/textio_body.vhdl +STD_SRCS := std/textio.vhdl std/textio-body.vhdl SYNOPSYS_BSRCS := synopsys/std_logic_arith.vhdl \ synopsys/std_logic_unsigned.vhdl \ synopsys/std_logic_signed.vhdl SYNOPSYS_V_BSRCS := synopsys/std_logic_misc.vhdl \ synopsys/std_logic_misc-body.vhdl SYNOPSYS8793_BSRCS := synopsys/std_logic_textio.vhdl -MENTOR_BSRCS := mentor/std_logic_arith.vhdl mentor/std_logic_arith_body.vhdl +MENTOR_BSRCS := mentor/std_logic_arith.vhdl mentor/std_logic_arith-body.vhdl ifeq ($(enable_openieee),false) -IEEE_SRCS := ieee/std_logic_1164.vhdl ieee/std_logic_1164_body.vhdl \ +IEEE_SRCS := ieee/std_logic_1164.vhdl ieee/std_logic_1164-body.vhdl \ ieee/numeric_bit.vhdl ieee/numeric_bit-body.vhdl \ ieee/numeric_std.vhdl ieee/numeric_std-body.vhdl MATH_SRCS := ieee/math_real.vhdl ieee/math_real-body.vhdl \ ieee/math_complex.vhdl ieee/math_complex-body.vhdl -VITAL95_BSRCS := vital95/vital_timing.vhdl vital95/vital_timing_body.vhdl \ - vital95/vital_primitives.vhdl vital95/vital_primitives_body.vhdl +VITAL95_BSRCS := vital95/vital_timing.vhdl vital95/vital_timing-body.vhdl \ + vital95/vital_primitives.vhdl vital95/vital_primitives-body.vhdl VITAL2000_BSRCS := vital2000/timing_p.vhdl vital2000/timing_b.vhdl \ vital2000/prmtvs_p.vhdl vital2000/prmtvs_b.vhdl \ vital2000/memory_p.vhdl vital2000/memory_b.vhdl @@ -93,7 +93,7 @@ ANALYZE_DEP=$(GHDL) STD87_BSRCS := $(STD_SRCS:.vhdl=.v87) STD93_BSRCS := $(STD_SRCS:.vhdl=.v93) -STD08_BSRCS := $(STD_SRCS:.vhdl=.v08) std/env.vhdl std/env_body.vhdl +STD08_BSRCS := $(STD_SRCS:.vhdl=.v08) std/env.vhdl std/env-body.vhdl IEEE87_BSRCS := $(IEEE_SRCS:.vhdl=.v87) IEEE93_BSRCS := $(IEEE_SRCS:.vhdl=.v93) $(MATH_SRCS) SYNOPSYS87_BSRCS := $(SYNOPSYS_BSRCS) $(SYNOPSYS_V_BSRCS) $(SYNOPSYS8793_BSRCS) diff --git a/libraries/ieee/std_logic_1164-body.vhdl b/libraries/ieee/std_logic_1164-body.vhdl new file mode 100644 index 000000000..88a87482c --- /dev/null +++ b/libraries/ieee/std_logic_1164-body.vhdl @@ -0,0 +1,830 @@ +-- -------------------------------------------------------------------- +-- +-- Title : std_logic_1164 multi-value logic system +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE model standards group (par 1164) +-- Purpose : This packages defines a standard for designers +-- : to use in describing the interconnection data types +-- : used in vhdl modeling. +-- : +-- Limitation: The logic system defined in this package may +-- : be insufficient for modeling switched transistors, +-- : since such a requirement is out of the scope of this +-- : effort. Furthermore, mathematics, primitives, +-- : timing standards, etc. are considered orthogonal +-- : issues as it relates to this package and are therefore +-- : beyond the scope of this effort. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : std_logic_1164. The std_logic_1164 package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- version | mod. date:| +-- v4.200 | 01/02/91 | +-- -------------------------------------------------------------------- + +PACKAGE BODY std_logic_1164 IS + ------------------------------------------------------------------- + -- local types + ------------------------------------------------------------------- + TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic; + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + CONSTANT resolution_table : stdlogic_table := ( + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- --------------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 | + ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z | + ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L | + ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | + ); + + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS + VARIABLE result : std_ulogic := 'Z'; -- weakest state default + BEGIN + -- the test for a single driver is essential otherwise the + -- loop would return 'X' for a single driver of '-' and that + -- would conflict with the value of a single driver unresolved + -- signal. + IF (s'LENGTH = 1) THEN RETURN s(s'LOW); + ELSE + FOR i IN s'RANGE LOOP + result := resolution_table(result, s(i)); + END LOOP; + END IF; + RETURN result; + END resolved; + + ------------------------------------------------------------------- + -- tables for logical operations + ------------------------------------------------------------------- + + -- truth table for "and" function + CONSTANT and_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - | + ); + + -- truth table for "or" function + CONSTANT or_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | - | + ); + + -- truth table for "xor" function + CONSTANT xor_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | + ); + + -- truth table for "not" function + CONSTANT not_table: stdlogic_1d := + -- ------------------------------------------------- + -- | U X 0 1 Z W L H - | + -- ------------------------------------------------- + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ); + + ------------------------------------------------------------------- + -- overloaded logical operators ( with optimizing hints ) + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (and_table(l, r)); + END "and"; + + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (not_table ( and_table(l, r))); + END "nand"; + + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (or_table(l, r)); + END "or"; + + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (not_table ( or_table( l, r ))); + END "nor"; + + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (xor_table(l, r)); + END "xor"; + +--START-!V87 + FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN not_table(xor_table(l, r)); + END "xnor"; +--END-!V87 + + FUNCTION "not" ( l : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (not_table(l)); + END "not"; + + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + FUNCTION "and" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'and' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := and_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "and"; + --------------------------------------------------------------------- + FUNCTION "and" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'and' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := and_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "and"; + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + FUNCTION "nand" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nand' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(and_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "nand"; + --------------------------------------------------------------------- + FUNCTION "nand" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nand' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(and_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "nand"; + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + FUNCTION "or" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'or' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := or_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "or"; + --------------------------------------------------------------------- + FUNCTION "or" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'or' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := or_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "or"; + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + FUNCTION "nor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(or_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "nor"; + --------------------------------------------------------------------- + FUNCTION "nor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(or_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "nor"; + --------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + FUNCTION "xor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := xor_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "xor"; + --------------------------------------------------------------------- + FUNCTION "xor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := xor_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + END "xor"; +-- ------------------------------------------------------------------- +-- -- xnor +-- ------------------------------------------------------------------- +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this std_logic_1164 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- +--START-!V87 + FUNCTION "xnor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xnor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(xor_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "xnor"; + --------------------------------------------------------------------- + FUNCTION "xnor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xnor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(xor_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + END "xnor"; +--END-!V87 + ------------------------------------------------------------------- + -- not + ------------------------------------------------------------------- + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := not_table( lv(i) ); + END LOOP; + RETURN result; + END; + --------------------------------------------------------------------- + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := not_table( lv(i) ); + END LOOP; + RETURN result; + END; + ------------------------------------------------------------------- + -- conversion tables + ------------------------------------------------------------------- + TYPE logic_x01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01; + TYPE logic_x01z_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01Z; + TYPE logic_ux01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF UX01; + ---------------------------------------------------------- + -- table name : cvt_to_x01 + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : x01 -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_x01 (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_x01 : logic_x01_table := ( + 'X', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'X', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + + ---------------------------------------------------------- + -- table name : cvt_to_x01z + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : x01z -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_x01z (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_x01z : logic_x01z_table := ( + 'X', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'Z', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + + ---------------------------------------------------------- + -- table name : cvt_to_ux01 + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : ux01 -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_ux01 (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_ux01 : logic_ux01_table := ( + 'U', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'X', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') RETURN BIT IS + BEGIN + CASE s IS + WHEN '0' | 'L' => RETURN ('0'); + WHEN '1' | 'H' => RETURN ('1'); + WHEN OTHERS => RETURN xmap; + END CASE; + END; + -------------------------------------------------------------------- + FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') RETURN BIT_VECTOR IS + ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + CASE sv(i) IS + WHEN '0' | 'L' => result(i) := '0'; + WHEN '1' | 'H' => result(i) := '1'; + WHEN OTHERS => result(i) := xmap; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR IS + ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + CASE sv(i) IS + WHEN '0' | 'L' => result(i) := '0'; + WHEN '1' | 'H' => result(i) := '1'; + WHEN OTHERS => result(i) := xmap; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic IS + BEGIN + CASE b IS + WHEN '0' => RETURN '0'; + WHEN '1' => RETURN '1'; + END CASE; + END; + -------------------------------------------------------------------- + FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector IS + ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; + VARIABLE result : std_logic_vector ( b'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector IS + ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := sv(i); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; + VARIABLE result : std_ulogic_vector ( b'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector IS + ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := sv(i); + END LOOP; + RETURN result; + END; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + -- to_x01 + ------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector IS + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01 (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01 (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01 IS + BEGIN + RETURN (cvt_to_x01(s)); + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT ) RETURN X01 IS + BEGIN + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + END; + -------------------------------------------------------------------- + -- to_x01z + ------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector IS + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01z (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01z (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z IS + BEGIN + RETURN (cvt_to_x01z(s)); + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z IS + BEGIN + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + END; + -------------------------------------------------------------------- + -- to_ux01 + ------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector IS + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_ux01 (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := cvt_to_ux01 (sv(i)); + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN (cvt_to_ux01(s)); + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT ) RETURN UX01 IS + BEGIN + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + END; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS + BEGIN + RETURN (s'EVENT AND (To_X01(s) = '1') AND + (To_X01(s'LAST_VALUE) = '0')); + END; + + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS + BEGIN + RETURN (s'EVENT AND (To_X01(s) = '0') AND + (To_X01(s'LAST_VALUE) = '1')); + END; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN IS + BEGIN + FOR i IN s'RANGE LOOP + CASE s(i) IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + END LOOP; + RETURN FALSE; + END; + -------------------------------------------------------------------- + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN IS + BEGIN + FOR i IN s'RANGE LOOP + CASE s(i) IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + END LOOP; + RETURN FALSE; + END; + -------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN IS + BEGIN + CASE s IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + RETURN FALSE; + END; + +END std_logic_1164; diff --git a/libraries/ieee/std_logic_1164_body.vhdl b/libraries/ieee/std_logic_1164_body.vhdl deleted file mode 100644 index 88a87482c..000000000 --- a/libraries/ieee/std_logic_1164_body.vhdl +++ /dev/null @@ -1,830 +0,0 @@ --- -------------------------------------------------------------------- --- --- Title : std_logic_1164 multi-value logic system --- Library : This package shall be compiled into a library --- : symbolically named IEEE. --- : --- Developers: IEEE model standards group (par 1164) --- Purpose : This packages defines a standard for designers --- : to use in describing the interconnection data types --- : used in vhdl modeling. --- : --- Limitation: The logic system defined in this package may --- : be insufficient for modeling switched transistors, --- : since such a requirement is out of the scope of this --- : effort. Furthermore, mathematics, primitives, --- : timing standards, etc. are considered orthogonal --- : issues as it relates to this package and are therefore --- : beyond the scope of this effort. --- : --- Note : No declarations or definitions shall be included in, --- : or excluded from this package. The "package declaration" --- : defines the types, subtypes and declarations of --- : std_logic_1164. The std_logic_1164 package body shall be --- : considered the formal definition of the semantics of --- : this package. Tool developers may choose to implement --- : the package body in the most efficient manner available --- : to them. --- : --- -------------------------------------------------------------------- --- modification history : --- -------------------------------------------------------------------- --- version | mod. date:| --- v4.200 | 01/02/91 | --- -------------------------------------------------------------------- - -PACKAGE BODY std_logic_1164 IS - ------------------------------------------------------------------- - -- local types - ------------------------------------------------------------------- - TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic; - TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; - - ------------------------------------------------------------------- - -- resolution function - ------------------------------------------------------------------- - CONSTANT resolution_table : stdlogic_table := ( - -- --------------------------------------------------------- - -- | U X 0 1 Z W L H - | | - -- --------------------------------------------------------- - ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | - ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 | - ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 | - ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z | - ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L | - ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | - ); - - FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS - VARIABLE result : std_ulogic := 'Z'; -- weakest state default - BEGIN - -- the test for a single driver is essential otherwise the - -- loop would return 'X' for a single driver of '-' and that - -- would conflict with the value of a single driver unresolved - -- signal. - IF (s'LENGTH = 1) THEN RETURN s(s'LOW); - ELSE - FOR i IN s'RANGE LOOP - result := resolution_table(result, s(i)); - END LOOP; - END IF; - RETURN result; - END resolved; - - ------------------------------------------------------------------- - -- tables for logical operations - ------------------------------------------------------------------- - - -- truth table for "and" function - CONSTANT and_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H - | | - -- ---------------------------------------------------- - ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - | - ); - - -- truth table for "or" function - CONSTANT or_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H - | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | - | - ); - - -- truth table for "xor" function - CONSTANT xor_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H - | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | - ); - - -- truth table for "not" function - CONSTANT not_table: stdlogic_1d := - -- ------------------------------------------------- - -- | U X 0 1 Z W L H - | - -- ------------------------------------------------- - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ); - - ------------------------------------------------------------------- - -- overloaded logical operators ( with optimizing hints ) - ------------------------------------------------------------------- - - FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (and_table(l, r)); - END "and"; - - FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (not_table ( and_table(l, r))); - END "nand"; - - FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (or_table(l, r)); - END "or"; - - FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (not_table ( or_table( l, r ))); - END "nor"; - - FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (xor_table(l, r)); - END "xor"; - ---START-!V87 - FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN not_table(xor_table(l, r)); - END "xnor"; ---END-!V87 - - FUNCTION "not" ( l : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (not_table(l)); - END "not"; - - ------------------------------------------------------------------- - -- and - ------------------------------------------------------------------- - FUNCTION "and" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'and' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := and_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "and"; - --------------------------------------------------------------------- - FUNCTION "and" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'and' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := and_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "and"; - ------------------------------------------------------------------- - -- nand - ------------------------------------------------------------------- - FUNCTION "nand" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'nand' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(and_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "nand"; - --------------------------------------------------------------------- - FUNCTION "nand" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'nand' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(and_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "nand"; - ------------------------------------------------------------------- - -- or - ------------------------------------------------------------------- - FUNCTION "or" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'or' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := or_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "or"; - --------------------------------------------------------------------- - FUNCTION "or" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'or' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := or_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "or"; - ------------------------------------------------------------------- - -- nor - ------------------------------------------------------------------- - FUNCTION "nor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'nor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(or_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "nor"; - --------------------------------------------------------------------- - FUNCTION "nor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'nor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(or_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "nor"; - --------------------------------------------------------------------- - -- xor - ------------------------------------------------------------------- - FUNCTION "xor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'xor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := xor_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "xor"; - --------------------------------------------------------------------- - FUNCTION "xor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'xor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := xor_table (lv(i), rv(i)); - END LOOP; - END IF; - RETURN result; - END "xor"; --- ------------------------------------------------------------------- --- -- xnor --- ------------------------------------------------------------------- --- ----------------------------------------------------------------------- --- Note : The declaration and implementation of the "xnor" function is --- specifically commented until at which time the VHDL language has been --- officially adopted as containing such a function. At such a point, --- the following comments may be removed along with this notice without --- further "official" ballotting of this std_logic_1164 package. It is --- the intent of this effort to provide such a function once it becomes --- available in the VHDL standard. --- ----------------------------------------------------------------------- ---START-!V87 - FUNCTION "xnor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'xnor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(xor_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "xnor"; - --------------------------------------------------------------------- - FUNCTION "xnor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); - BEGIN - IF ( l'LENGTH /= r'LENGTH ) THEN - ASSERT FALSE - REPORT "arguments of overloaded 'xnor' operator are not of the same length" - SEVERITY FAILURE; - ELSE - FOR i IN result'RANGE LOOP - result(i) := not_table(xor_table (lv(i), rv(i))); - END LOOP; - END IF; - RETURN result; - END "xnor"; ---END-!V87 - ------------------------------------------------------------------- - -- not - ------------------------------------------------------------------- - FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector IS - ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; - VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := not_table( lv(i) ); - END LOOP; - RETURN result; - END; - --------------------------------------------------------------------- - FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; - VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := not_table( lv(i) ); - END LOOP; - RETURN result; - END; - ------------------------------------------------------------------- - -- conversion tables - ------------------------------------------------------------------- - TYPE logic_x01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01; - TYPE logic_x01z_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01Z; - TYPE logic_ux01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF UX01; - ---------------------------------------------------------- - -- table name : cvt_to_x01 - -- - -- parameters : - -- in : std_ulogic -- some logic value - -- returns : x01 -- state value of logic value - -- purpose : to convert state-strength to state only - -- - -- example : if (cvt_to_x01 (input_signal) = '1' ) then ... - -- - ---------------------------------------------------------- - CONSTANT cvt_to_x01 : logic_x01_table := ( - 'X', -- 'U' - 'X', -- 'X' - '0', -- '0' - '1', -- '1' - 'X', -- 'Z' - 'X', -- 'W' - '0', -- 'L' - '1', -- 'H' - 'X' -- '-' - ); - - ---------------------------------------------------------- - -- table name : cvt_to_x01z - -- - -- parameters : - -- in : std_ulogic -- some logic value - -- returns : x01z -- state value of logic value - -- purpose : to convert state-strength to state only - -- - -- example : if (cvt_to_x01z (input_signal) = '1' ) then ... - -- - ---------------------------------------------------------- - CONSTANT cvt_to_x01z : logic_x01z_table := ( - 'X', -- 'U' - 'X', -- 'X' - '0', -- '0' - '1', -- '1' - 'Z', -- 'Z' - 'X', -- 'W' - '0', -- 'L' - '1', -- 'H' - 'X' -- '-' - ); - - ---------------------------------------------------------- - -- table name : cvt_to_ux01 - -- - -- parameters : - -- in : std_ulogic -- some logic value - -- returns : ux01 -- state value of logic value - -- purpose : to convert state-strength to state only - -- - -- example : if (cvt_to_ux01 (input_signal) = '1' ) then ... - -- - ---------------------------------------------------------- - CONSTANT cvt_to_ux01 : logic_ux01_table := ( - 'U', -- 'U' - 'X', -- 'X' - '0', -- '0' - '1', -- '1' - 'X', -- 'Z' - 'X', -- 'W' - '0', -- 'L' - '1', -- 'H' - 'X' -- '-' - ); - - ------------------------------------------------------------------- - -- conversion functions - ------------------------------------------------------------------- - FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') RETURN BIT IS - BEGIN - CASE s IS - WHEN '0' | 'L' => RETURN ('0'); - WHEN '1' | 'H' => RETURN ('1'); - WHEN OTHERS => RETURN xmap; - END CASE; - END; - -------------------------------------------------------------------- - FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') RETURN BIT_VECTOR IS - ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; - VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - CASE sv(i) IS - WHEN '0' | 'L' => result(i) := '0'; - WHEN '1' | 'H' => result(i) := '1'; - WHEN OTHERS => result(i) := xmap; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR IS - ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; - VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - CASE sv(i) IS - WHEN '0' | 'L' => result(i) := '0'; - WHEN '1' | 'H' => result(i) := '1'; - WHEN OTHERS => result(i) := xmap; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic IS - BEGIN - CASE b IS - WHEN '0' => RETURN '0'; - WHEN '1' => RETURN '1'; - END CASE; - END; - -------------------------------------------------------------------- - FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector IS - ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; - VARIABLE result : std_logic_vector ( b'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector IS - ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; - VARIABLE result : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := sv(i); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS - ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; - VARIABLE result : std_ulogic_vector ( b'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector IS - ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; - VARIABLE result : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := sv(i); - END LOOP; - RETURN result; - END; - - ------------------------------------------------------------------- - -- strength strippers and type convertors - ------------------------------------------------------------------- - -- to_x01 - ------------------------------------------------------------------- - FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector IS - ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_x01 (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_x01 (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01 ( s : std_ulogic ) RETURN X01 IS - BEGIN - RETURN (cvt_to_x01(s)); - END; - -------------------------------------------------------------------- - FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01 ( b : BIT ) RETURN X01 IS - BEGIN - CASE b IS - WHEN '0' => RETURN('0'); - WHEN '1' => RETURN('1'); - END CASE; - END; - -------------------------------------------------------------------- - -- to_x01z - ------------------------------------------------------------------- - FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector IS - ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_x01z (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_x01z (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z IS - BEGIN - RETURN (cvt_to_x01z(s)); - END; - -------------------------------------------------------------------- - FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_X01Z ( b : BIT ) RETURN X01Z IS - BEGIN - CASE b IS - WHEN '0' => RETURN('0'); - WHEN '1' => RETURN('1'); - END CASE; - END; - -------------------------------------------------------------------- - -- to_ux01 - ------------------------------------------------------------------- - FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector IS - ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_ux01 (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS - ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; - VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - result(i) := cvt_to_ux01 (sv(i)); - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01 IS - BEGIN - RETURN (cvt_to_ux01(s)); - END; - -------------------------------------------------------------------- - FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS - ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; - VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); - BEGIN - FOR i IN result'RANGE LOOP - CASE bv(i) IS - WHEN '0' => result(i) := '0'; - WHEN '1' => result(i) := '1'; - END CASE; - END LOOP; - RETURN result; - END; - -------------------------------------------------------------------- - FUNCTION To_UX01 ( b : BIT ) RETURN UX01 IS - BEGIN - CASE b IS - WHEN '0' => RETURN('0'); - WHEN '1' => RETURN('1'); - END CASE; - END; - - ------------------------------------------------------------------- - -- edge detection - ------------------------------------------------------------------- - FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS - BEGIN - RETURN (s'EVENT AND (To_X01(s) = '1') AND - (To_X01(s'LAST_VALUE) = '0')); - END; - - FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS - BEGIN - RETURN (s'EVENT AND (To_X01(s) = '0') AND - (To_X01(s'LAST_VALUE) = '1')); - END; - - ------------------------------------------------------------------- - -- object contains an unknown - ------------------------------------------------------------------- - FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN IS - BEGIN - FOR i IN s'RANGE LOOP - CASE s(i) IS - WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; - WHEN OTHERS => NULL; - END CASE; - END LOOP; - RETURN FALSE; - END; - -------------------------------------------------------------------- - FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN IS - BEGIN - FOR i IN s'RANGE LOOP - CASE s(i) IS - WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; - WHEN OTHERS => NULL; - END CASE; - END LOOP; - RETURN FALSE; - END; - -------------------------------------------------------------------- - FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN IS - BEGIN - CASE s IS - WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; - WHEN OTHERS => NULL; - END CASE; - RETURN FALSE; - END; - -END std_logic_1164; diff --git a/libraries/mentor/std_logic_arith-body.vhdl b/libraries/mentor/std_logic_arith-body.vhdl new file mode 100644 index 000000000..36f76cb7d --- /dev/null +++ b/libraries/mentor/std_logic_arith-body.vhdl @@ -0,0 +1,2915 @@ +LIBRARY ieee; +-- LIBRARY arithmetic; + +PACKAGE BODY std_logic_arith IS + + USE ieee.std_logic_1164.ALL; + -- USE arithmetic.utils.all; + + ------------------------------------------------------------------- + -- Local Types + ------------------------------------------------------------------- + TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic; + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + TYPE stdlogic_boolean_table IS ARRAY(std_ulogic, std_ulogic) OF BOOLEAN; + + -------------------------------------------------------------------- + -------------------------------------------------------------------- + -- FUNCTIONS DEFINED FOR SYNTHESIS + -------------------------------------------------------------------- + -------------------------------------------------------------------- + + FUNCTION std_ulogic_wired_or ( input : std_ulogic_vector ) RETURN std_ulogic IS + VARIABLE result : std_ulogic := '-'; -- weakest state default + CONSTANT resolution_table : stdlogic_table := ( + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- --------------------------------------------------------- + ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | U | + ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | + ( 'X', 'X', '0', '1', '0', 'X', '0', '1', '0' ), -- | 0 | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | + ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ), -- | Z | + ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | + ( 'X', 'X', '0', '1', '0', 'X', '0', '1', '0' ), -- | L | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | + ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ) -- | D | + ); + + BEGIN + -- Iterate through all inputs + FOR i IN input'range LOOP + result := resolution_table(result, input(i)); + END LOOP; + -- Return the resultant value + RETURN result; + END std_ulogic_wired_or; + + FUNCTION std_ulogic_wired_and ( input : std_ulogic_vector ) RETURN std_ulogic IS + VARIABLE result : std_ulogic := '-'; -- weakest state default + CONSTANT resolution_table : stdlogic_table := ( + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- --------------------------------------------------------- + ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | U | + ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'X', 'X', '0', '1', '1', 'X', '0', '1', '1' ), -- | 1 | + ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ), -- | Z | + ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'X', 'X', '0', '1', '1', 'X', '0', '1', '1' ), -- | H | + ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ) -- | D | + ); + + BEGIN + -- Iterate through all inputs + FOR i IN input'range LOOP + result := resolution_table(result, input(i)); + END LOOP; + -- Return the resultant value + RETURN result; + END std_ulogic_wired_and; + +-- +-- MGC base level functions +-- +-- +-- Convert Base Type to Integer +-- + FUNCTION to_integer (arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : INTEGER; + BEGIN + tmp := SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END to_integer; + + FUNCTION to_integer (arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : INTEGER; + BEGIN + tmp := SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END to_integer; + + FUNCTION to_integer (arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL IS + VARIABLE tmp : SIGNED( arg1'length DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : NATURAL; + BEGIN + tmp := '0' & SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END to_integer; + + FUNCTION TO_INTEGER (arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE return_int,x_tmp : INTEGER := 0; + BEGIN + ASSERT arg1'length > 0 + REPORT "NULL vector, returning 0" + SEVERITY NOTE; + assert arg1'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + ASSERT arg1'length <= 32 -- implementation dependent limit + REPORT "vector too large, conversion may cause overflow" + SEVERITY WARNING; + IF x /= 0 THEN + x_tmp := 1; + END IF; + IF arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L' OR -- positive value + ( x_tmp = 0 AND arg1(arg1'left) /= '1' AND arg1(arg1'left) /= 'H') THEN + FOR i IN arg1'range LOOP + return_int := return_int * 2; + CASE arg1(i) IS + WHEN '0'|'L' => NULL; + WHEN '1'|'H' => return_int := return_int + 1; + WHEN OTHERS => return_int := return_int + x_tmp; + END CASE; + END LOOP; + ELSE -- negative value + IF (x_tmp = 0) THEN + x_tmp := 1; + ELSE + x_tmp := 0; + END IF; + FOR i IN arg1'range LOOP + return_int := return_int * 2; + CASE arg1(i) IS + WHEN '0'|'L' => return_int := return_int + 1; + WHEN '1'|'H' => NULL; + WHEN OTHERS => return_int := return_int + x_tmp; + END CASE; + END LOOP; + return_int := (-return_int) - 1; + END IF; + RETURN return_int; + END TO_INTEGER; + + FUNCTION to_integer (arg1:STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL IS + BEGIN + IF(arg1 = '0' OR arg1 = 'L' OR (x = 0 AND arg1 /= '1' AND arg1 /= 'H')) THEN + RETURN(0); + ELSE + RETURN(1) ; + END IF ; + END ; + + FUNCTION conv_integer (arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : INTEGER; + BEGIN + tmp := SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END ; + + FUNCTION conv_integer (arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE tmp : SIGNED( arg1'length -1 DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : INTEGER; + BEGIN + tmp := SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END ; + + FUNCTION conv_integer (arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL IS + VARIABLE tmp : SIGNED( arg1'length DOWNTO 0 ) := (OTHERS => '0'); + VARIABLE result : NATURAL; + BEGIN + tmp := '0' & SIGNED(arg1); + result := TO_INTEGER( tmp, x ); + RETURN (result); + END ; + + FUNCTION conv_INTEGER (arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER IS + VARIABLE return_int,x_tmp : INTEGER := 0; + BEGIN + ASSERT arg1'length > 0 + REPORT "NULL vector, returning 0" + SEVERITY NOTE; + assert arg1'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + ASSERT arg1'length <= 32 -- implementation dependent limit + REPORT "vector too large, conversion may cause overflow" + SEVERITY WARNING; + IF x /= 0 THEN + x_tmp := 1; + END IF; + IF arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L' OR -- positive value + ( x_tmp = 0 AND arg1(arg1'left) /= '1' AND arg1(arg1'left) /= 'H') THEN + FOR i IN arg1'range LOOP + return_int := return_int * 2; + CASE arg1(i) IS + WHEN '0'|'L' => NULL; + WHEN '1'|'H' => return_int := return_int + 1; + WHEN OTHERS => return_int := return_int + x_tmp; + END CASE; + END LOOP; + ELSE -- negative value + IF (x_tmp = 0) THEN + x_tmp := 1; + ELSE + x_tmp := 0; + END IF; + FOR i IN arg1'range LOOP + return_int := return_int * 2; + CASE arg1(i) IS + WHEN '0'|'L' => return_int := return_int + 1; + WHEN '1'|'H' => NULL; + WHEN OTHERS => return_int := return_int + x_tmp; + END CASE; + END LOOP; + return_int := (-return_int) - 1; + END IF; + RETURN return_int; + END ; + + FUNCTION conv_integer (arg1:STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL IS + BEGIN + IF(arg1 = '0' OR arg1 = 'L' OR (x = 0 AND arg1 /= '1' AND arg1 /= 'H')) THEN + RETURN(0); + ELSE + RETURN(1) ; + END IF ; + END ; + +-- +-- Convert Base Type to STD_LOGIC +-- + + FUNCTION to_stdlogic (arg1:BOOLEAN) RETURN STD_LOGIC IS + BEGIN + IF(arg1) THEN + RETURN('1') ; + ELSE + RETURN('0') ; + END IF ; + END ; + +-- +-- Convert Base Type to STD_LOGIC_VECTOR +-- + FUNCTION To_StdlogicVector (arg1 : integer; size : NATURAL) RETURN std_logic_vector IS + VARIABLE vector : std_logic_vector(0 TO size-1); + VARIABLE tmp_int : integer := arg1; + VARIABLE carry : std_logic := '1'; -- setup to add 1 if needed + VARIABLE carry2 : std_logic; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + IF arg1 < 0 THEN + FOR i IN size-1 DOWNTO 0 LOOP + carry2 := (NOT vector(i)) AND carry; + vector(i) := (NOT vector(i)) XOR carry; + carry := carry2; + END LOOP; + END IF; + RETURN vector; + END To_StdlogicVector; + + FUNCTION To_StdUlogicVector (arg1 : integer; size : NATURAL) RETURN std_ulogic_vector IS + VARIABLE vector : std_ulogic_vector(0 TO size-1); + VARIABLE tmp_int : integer := arg1; + VARIABLE carry : std_ulogic := '1'; -- setup to add 1 if needed + VARIABLE carry2 : std_ulogic; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + IF arg1 < 0 THEN + FOR i IN size-1 DOWNTO 0 LOOP + carry2 := (NOT vector(i)) AND carry; + vector(i) := (NOT vector(i)) XOR carry; + carry := carry2; + END LOOP; + END IF; + RETURN vector; + END To_StdUlogicVector; + + +-- +-- Convert Base Type to UNSIGNED +-- + + FUNCTION to_unsigned (arg1:NATURAL ; size:NATURAL) RETURN UNSIGNED IS + VARIABLE vector : UNSIGNED(0 TO size-1) := (OTHERS => '0'); + VARIABLE tmp_int : INTEGER := arg1; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + RETURN vector; + END ; + + FUNCTION conv_unsigned (arg1:NATURAL ; size:NATURAL) RETURN UNSIGNED IS + VARIABLE vector : UNSIGNED(0 TO size-1) := (OTHERS => '0'); + VARIABLE tmp_int : INTEGER := arg1; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + RETURN vector; + END ; + +-- +-- Convert Base Type to SIGNED +-- + + FUNCTION to_signed (arg1:INTEGER ; size : NATURAL) RETURN SIGNED IS + VARIABLE vector : SIGNED(0 TO size-1) := (OTHERS => '0'); + VARIABLE tmp_int : INTEGER := arg1; + VARIABLE carry : STD_LOGIC := '1'; -- setup to add 1 if needed + VARIABLE carry2 : STD_LOGIC := '0'; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + IF arg1 < 0 THEN + FOR i IN size-1 DOWNTO 0 LOOP + carry2 := (NOT vector(i)) AND carry; + vector(i) := (NOT vector(i)) XOR carry; + carry := carry2; + END LOOP; + END IF; + RETURN vector; + END ; + + FUNCTION conv_signed (arg1:INTEGER ; size : NATURAL) RETURN SIGNED IS + VARIABLE vector : SIGNED(0 TO size-1) := (OTHERS => '0'); + VARIABLE tmp_int : INTEGER := arg1; + VARIABLE carry : STD_LOGIC := '1'; -- setup to add 1 if needed + VARIABLE carry2 : STD_LOGIC := '0'; + BEGIN + FOR i IN size-1 DOWNTO 0 LOOP + IF tmp_int MOD 2 = 1 THEN + vector(i) := '1'; + ELSE + vector(i) := '0'; + END IF; + tmp_int := tmp_int / 2; + END LOOP; + + IF arg1 < 0 THEN + FOR i IN size-1 DOWNTO 0 LOOP + carry2 := (NOT vector(i)) AND carry; + vector(i) := (NOT vector(i)) XOR carry; + carry := carry2; + END LOOP; + END IF; + RETURN vector; + END ; + + -- sign/zero extend functions + -- + + FUNCTION zero_extend ( arg1 : STD_ULOGIC_VECTOR; size : NATURAL ) RETURN STD_ULOGIC_VECTOR + IS + VARIABLE answer : STD_ULOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + ASSERT arg1'length <= size + REPORT "Vector is already larger then size." + SEVERITY WARNING ; + answer := (OTHERS => '0') ; + answer(arg1'length-1 DOWNTO 0) := arg1; + RETURN(answer) ; + END ; + + FUNCTION zero_extend ( arg1 : STD_LOGIC_VECTOR; size : NATURAL ) RETURN STD_LOGIC_VECTOR + IS + VARIABLE answer : STD_LOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + ASSERT arg1'length <= size + REPORT "Vector is already larger then size." + SEVERITY WARNING ; + answer := (OTHERS => '0') ; + answer(arg1'length-1 DOWNTO 0) := arg1; + RETURN(answer) ; + END ; + + FUNCTION zero_extend ( arg1 : STD_LOGIC; size : NATURAL ) RETURN STD_LOGIC_VECTOR + IS + VARIABLE answer : STD_LOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + answer := (OTHERS => '0') ; + answer(0) := arg1; + RETURN(answer) ; + END ; + + FUNCTION zero_extend ( arg1 : UNSIGNED; size : NATURAL ) RETURN UNSIGNED IS + VARIABLE answer : UNSIGNED(size-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + ASSERT arg1'length <= size + REPORT "Vector is already larger then size." + SEVERITY WARNING ; + answer := (OTHERS => '0') ; + answer(arg1'length - 1 DOWNTO 0) := arg1; + RETURN(answer) ; + END ; + + FUNCTION sign_extend ( arg1 : SIGNED; size : NATURAL ) RETURN SIGNED IS + VARIABLE answer : SIGNED(size-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + ASSERT arg1'length <= size + REPORT "Vector is already larger then size." + SEVERITY WARNING ; + answer := (OTHERS => arg1(arg1'left)) ; + answer(arg1'length - 1 DOWNTO 0) := arg1; + RETURN(answer) ; + END ; + + + + -- Some useful generic functions + + --//// Zero Extend //// + -- + -- Function zxt + -- + FUNCTION zxt( q : STD_ULOGIC_VECTOR; i : INTEGER ) RETURN STD_ULOGIC_VECTOR IS + VARIABLE qs : STD_ULOGIC_VECTOR (1 TO i); + VARIABLE qt : STD_ULOGIC_VECTOR (1 TO q'length); + BEGIN + qt := q; + IF i < q'length THEN + qs := qt( (q'length-i+1) TO qt'right); + ELSIF i > q'length THEN + qs := (OTHERS=>'0'); + qs := qs(1 TO (i-q'length)) & qt; + ELSE + qs := qt; + END IF; + RETURN qs; + END; + + --//// Zero Extend //// + -- + -- Function zxt + -- + FUNCTION zxt( q : STD_LOGIC_VECTOR; i : INTEGER ) RETURN STD_LOGIC_VECTOR IS + VARIABLE qs : STD_LOGIC_VECTOR (1 TO i); + VARIABLE qt : STD_LOGIC_VECTOR (1 TO q'length); + BEGIN + qt := q; + IF i < q'length THEN + qs := qt( (q'length-i+1) TO qt'right); + ELSIF i > q'length THEN + qs := (OTHERS=>'0'); + qs := qs(1 TO (i-q'length)) & qt; + ELSE + qs := qt; + END IF; + RETURN qs; + END; + + --//// Zero Extend //// + -- + -- Function zxt + -- + FUNCTION zxt( q : UNSIGNED; i : INTEGER ) RETURN UNSIGNED IS + VARIABLE qs : UNSIGNED (1 TO i); + VARIABLE qt : UNSIGNED (1 TO q'length); + BEGIN + qt := q; + IF i < q'length THEN + qs := qt( (q'length-i+1) TO qt'right); + ELSIF i > q'length THEN + qs := (OTHERS=>'0'); + qs := qs(1 TO (i-q'length)) & qt; + ELSE + qs := qt; + END IF; + RETURN qs; + END; + +-------------------------------------- +-- Synthesizable addition Functions -- +-------------------------------------- + + FUNCTION "+" ( arg1, arg2 : STD_LOGIC ) RETURN STD_LOGIC IS + -- truth table for "xor" function + CONSTANT xor_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | + ); + BEGIN + RETURN xor_table( arg1, arg2 ); + END "+"; + + function maximum (arg1, arg2: integer) return integer is + begin + if arg1 > arg2 then + return arg1; + else + return arg2; + end if; + end; + + FUNCTION "+" (arg1, arg2 :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE res : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE carry : STD_ULOGIC := '0'; + VARIABLE a,b,s1 : STD_ULOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := rt(i); + s1 := a + b; + res(i) := s1 + carry; + carry := (a AND b) OR (s1 AND carry); + END LOOP; + RETURN res; + END; + + FUNCTION "+" (arg1, arg2 :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE res : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE carry : STD_LOGIC := '0'; + VARIABLE a,b,s1 : STD_LOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := rt(i); + s1 := a + b; + res(i) := s1 + carry; + carry := (a AND b) OR (s1 AND carry); + END LOOP; + RETURN res; + END; + + FUNCTION "+" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : UNSIGNED(1 TO ml); + VARIABLE rt : UNSIGNED(1 TO ml); + VARIABLE res : UNSIGNED(1 TO ml); + VARIABLE carry : STD_LOGIC := '0'; + VARIABLE a,b,s1 : STD_LOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := rt(i); + s1 := a + b; + res(i) := s1 + carry; + carry := (a AND b) OR (s1 AND carry); + END LOOP; + RETURN res; + END; + + FUNCTION "+" (arg1, arg2:SIGNED) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + assert arg1'length > 1 AND arg2'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a + b); + RETURN (answer); + END ; + +----------------------------------------- +-- Synthesizable subtraction Functions -- +----------------------------------------- + + FUNCTION "-" ( arg1, arg2 : std_logic ) RETURN std_logic IS + -- truth table for "xor" function + CONSTANT xor_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | + ); + BEGIN + RETURN xor_table( arg1, arg2 ); + END "-"; + + FUNCTION "-" (arg1, arg2:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE res : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE borrow : STD_ULOGIC := '1'; + VARIABLE a,b,s1 : STD_ULOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := NOT rt(i); + s1 := a + b; + res(i) := s1 + borrow; + borrow := (a AND b) OR (s1 AND borrow); + END LOOP; + RETURN res; + END "-"; + + FUNCTION "-" (arg1, arg2:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE res : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE borrow : STD_LOGIC := '1'; + VARIABLE a,b,s1 : STD_LOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := NOT rt(i); + s1 := a + b; + res(i) := s1 + borrow; + borrow := (a AND b) OR (s1 AND borrow); + END LOOP; + RETURN res; + END "-"; + + FUNCTION "-" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS + CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); + VARIABLE lt : UNSIGNED(1 TO ml); + VARIABLE rt : UNSIGNED(1 TO ml); + VARIABLE res : UNSIGNED(1 TO ml); + VARIABLE borrow : STD_LOGIC := '1'; + VARIABLE a,b,s1 : STD_LOGIC; + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + + FOR i IN res'reverse_range LOOP + a := lt(i); + b := NOT rt(i); + s1 := a + b; + res(i) := s1 + borrow; + borrow := (a AND b) OR (s1 AND borrow); + END LOOP; + RETURN res; + END "-"; + + + FUNCTION "-" (arg1, arg2:SIGNED) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + assert arg1'length > 1 AND arg2'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED( a - b ); + RETURN (answer); + END ; + +----------------------------------------- +-- Unary subtract and add Functions -- +----------------------------------------- + FUNCTION "+" (arg1:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + BEGIN + RETURN (arg1); + END; + + FUNCTION "+" (arg1:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + BEGIN + RETURN (arg1); + END; + + FUNCTION "+" (arg1:UNSIGNED) RETURN UNSIGNED IS + BEGIN + RETURN (arg1); + END; + + FUNCTION "+" (arg1:SIGNED) RETURN SIGNED IS + BEGIN + RETURN (arg1); + END; + + FUNCTION hasx( v : SIGNED ) RETURN BOOLEAN IS + BEGIN + FOR i IN v'range LOOP + IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN + NULL; + ELSE + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END hasx; + + FUNCTION "-" (arg1:SIGNED) RETURN SIGNED IS + constant len : integer := arg1'length; + VARIABLE answer, tmp : SIGNED( len-1 downto 0 ) := (others=>'0'); + VARIABLE index : integer := len; + BEGIN + assert arg1'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + IF hasx(arg1) THEN + answer := (OTHERS => 'X'); + ELSE + tmp := arg1; + lp1 : FOR i IN answer'REVERSE_RANGE LOOP + IF (tmp(i) = '1' OR tmp(i) = 'H') THEN + index := i+1; + answer(i downto 0) := tmp(i downto 0); + exit; + END IF; + END LOOP lp1; + answer(len-1 downto index) := NOT tmp(len-1 downto index); + end if; + RETURN (answer); + END ; + +-------------------------------------------- +-- Synthesizable multiplication Functions -- +-------------------------------------------- + FUNCTION shift( v : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR IS + VARIABLE v1 : STD_ULOGIC_VECTOR( v'range ); + BEGIN + FOR i IN (v'left+1) TO v'right LOOP + v1(i-1) := v(i); + END LOOP; + v1(v1'right) := '0'; + RETURN v1; + END shift; + + PROCEDURE copy(a : IN STD_ULOGIC_VECTOR; b : OUT STD_ULOGIC_VECTOR) IS + VARIABLE bi : INTEGER := b'right; + BEGIN + FOR i IN a'reverse_range LOOP + b(bi) := a(i); + bi := bi - 1; + END LOOP; + END copy; + + FUNCTION shift( v : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR IS + VARIABLE v1 : STD_LOGIC_VECTOR( v'range ); + BEGIN + FOR i IN (v'left+1) TO v'right LOOP + v1(i-1) := v(i); + END LOOP; + v1(v1'right) := '0'; + RETURN v1; + END shift; + + PROCEDURE copy(a : IN STD_LOGIC_VECTOR; b : OUT STD_LOGIC_VECTOR) IS + VARIABLE bi : INTEGER := b'right; + BEGIN + FOR i IN a'reverse_range LOOP + b(bi) := a(i); + bi := bi - 1; + END LOOP; + END copy; + + FUNCTION shift( v : SIGNED ) RETURN SIGNED IS + VARIABLE v1 : SIGNED( v'range ); + BEGIN + FOR i IN (v'left+1) TO v'right LOOP + v1(i-1) := v(i); + END LOOP; + v1(v1'right) := '0'; + RETURN v1; + END shift; + + PROCEDURE copy(a : IN SIGNED; b : OUT SIGNED) IS + VARIABLE bi : INTEGER := b'right; + BEGIN + FOR i IN a'reverse_range LOOP + b(bi) := a(i); + bi := bi - 1; + END LOOP; + END copy; + + FUNCTION shift( v : UNSIGNED ) RETURN UNSIGNED IS + VARIABLE v1 : UNSIGNED( v'range ); + BEGIN + FOR i IN (v'left+1) TO v'right LOOP + v1(i-1) := v(i); + END LOOP; + v1(v1'right) := '0'; + RETURN v1; + END shift; + + PROCEDURE copy(a : IN UNSIGNED; b : OUT UNSIGNED) IS + VARIABLE bi : INTEGER := b'right; + BEGIN + FOR i IN a'reverse_range LOOP + b(bi) := a(i); + bi := bi - 1; + END LOOP; + END copy; + + FUNCTION "*" (arg1, arg2:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + VARIABLE ml : INTEGER := arg1'length + arg2'length; + VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE prod : STD_ULOGIC_VECTOR(1 TO ml) := (OTHERS=>'0'); + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN rt'reverse_range LOOP + IF rt(i) = '1' THEN + prod := prod + lt; + END IF; + lt := shift(lt); + END LOOP; + RETURN prod; + END "*"; + + FUNCTION "*" (arg1, arg2:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + VARIABLE ml : INTEGER := arg1'length + arg2'length; + VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE prod : STD_LOGIC_VECTOR(1 TO ml) := (OTHERS=>'0'); + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN rt'reverse_range LOOP + IF rt(i) = '1' THEN + prod := prod + lt; + END IF; + lt := shift(lt); + END LOOP; + RETURN prod; + END "*"; + + FUNCTION "*" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS + VARIABLE ml : INTEGER := arg1'length + arg2'length; + VARIABLE lt : UNSIGNED(1 TO ml); + VARIABLE rt : UNSIGNED(1 TO ml); + VARIABLE prod : UNSIGNED(1 TO ml) := (OTHERS=>'0'); + BEGIN + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN rt'reverse_range LOOP + IF rt(i) = '1' THEN + prod := prod + lt; + END IF; + lt := shift(lt); + END LOOP; + RETURN prod; + END "*"; + + --//// Sign Extend //// + -- + -- Function sxt + -- + FUNCTION sxt( q : SIGNED; i : INTEGER ) RETURN SIGNED IS + VARIABLE qs : SIGNED (1 TO i); + VARIABLE qt : SIGNED (1 TO q'length); + BEGIN + qt := q; + IF i < q'length THEN + qs := qt( (q'length-i+1) TO qt'right); + ELSIF i > q'length THEN + qs := (OTHERS=>q(q'left)); + qs := qs(1 TO (i-q'length)) & qt; + ELSE + qs := qt; + END IF; + RETURN qs; + END; + + FUNCTION "*" (arg1, arg2:SIGNED) RETURN SIGNED IS + VARIABLE ml : INTEGER := arg1'length + arg2'length; + VARIABLE lt : SIGNED(1 TO ml); + VARIABLE rt : SIGNED(1 TO ml); + VARIABLE prod : SIGNED(1 TO ml) := (OTHERS=>'0'); + BEGIN + assert arg1'length > 1 AND arg2'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := sxt( arg1, ml ); + rt := sxt( arg2, ml ); + FOR i IN rt'reverse_range LOOP + IF rt(i) = '1' THEN + prod := prod + lt; + END IF; + lt := shift(lt); + END LOOP; + RETURN prod; + END "*"; + + FUNCTION rshift( v : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR IS + VARIABLE v1 : STD_ULOGIC_VECTOR( v'range ); + BEGIN + FOR i IN v'left TO v'right-1 LOOP + v1(i+1) := v(i); + END LOOP; + v1(v1'left) := '0'; + RETURN v1; + END rshift; + + FUNCTION hasx( v : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS + BEGIN + FOR i IN v'range LOOP + IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN + NULL; + ELSE + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END hasx; + + FUNCTION rshift( v : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR IS + VARIABLE v1 : STD_LOGIC_VECTOR( v'range ); + BEGIN + FOR i IN v'left TO v'right-1 LOOP + v1(i+1) := v(i); + END LOOP; + v1(v1'left) := '0'; + RETURN v1; + END rshift; + + FUNCTION hasx( v : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS + BEGIN + FOR i IN v'range LOOP + IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN + NULL; + ELSE + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END hasx; + + FUNCTION rshift( v : UNSIGNED ) RETURN UNSIGNED IS + VARIABLE v1 : UNSIGNED( v'range ); + BEGIN + FOR i IN v'left TO v'right-1 LOOP + v1(i+1) := v(i); + END LOOP; + v1(v1'left) := '0'; + RETURN v1; + END rshift; + + FUNCTION hasx( v : UNSIGNED ) RETURN BOOLEAN IS + BEGIN + FOR i IN v'range LOOP + IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN + NULL; + ELSE + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END hasx; + + FUNCTION rshift( v : SIGNED ) RETURN SIGNED IS + VARIABLE v1 : SIGNED( v'range ); + BEGIN + FOR i IN v'left TO v'right-1 LOOP + v1(i+1) := v(i); + END LOOP; + v1(v1'left) := '0'; + RETURN v1; + END rshift; + + FUNCTION "/" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN quote'range LOOP + quote(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + n := (OTHERS=>'0'); + n(n'right) := '1'; + WHILE rt <= lt LOOP + rt := shift(rt); + n := shift(n); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + n := rshift(n); + tmp := tmp + n; + END LOOP; + END IF; + quote := tmp(2 TO ml+1); + RETURN quote; + END "/"; + + FUNCTION "/" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN quote'range LOOP + quote(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + n := (OTHERS=>'0'); + n(n'right) := '1'; + WHILE rt <= lt LOOP + rt := shift(rt); + n := shift(n); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + n := rshift(n); + tmp := tmp + n; + END LOOP; + END IF; + quote := tmp(2 TO ml+1); + RETURN quote; + END "/"; + + FUNCTION "/" (l, r :UNSIGNED) RETURN UNSIGNED IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : UNSIGNED(0 TO ml+1); + VARIABLE rt : UNSIGNED(0 TO ml+1); + VARIABLE quote : UNSIGNED(1 TO ml); + VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN quote'range LOOP + quote(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + n := (OTHERS=>'0'); + n(n'right) := '1'; + WHILE rt <= lt LOOP + rt := shift(rt); + n := shift(n); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + n := rshift(n); + tmp := tmp + n; + END LOOP; + END IF; + quote := tmp(2 TO ml+1); + RETURN quote; + END "/"; + + FUNCTION "/" (l, r :SIGNED) RETURN SIGNED IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : SIGNED(0 TO ml+1); + VARIABLE rt : SIGNED(0 TO ml+1); + VARIABLE quote : SIGNED(1 TO ml); + VARIABLE tmp : SIGNED(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : SIGNED(0 TO ml+1) := (OTHERS=>'0'); + + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN quote'range LOOP + quote(i) := 'X'; + END LOOP; + ELSE + lt := sxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := sxt( r, ml+2 ); + n := (OTHERS=>'0'); + n(n'right) := '1'; + WHILE rt <= lt LOOP + rt := shift(rt); + n := shift(n); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + n := rshift(n); + tmp := tmp + n; + END LOOP; + END IF; + quote := tmp(2 TO ml+1); + RETURN quote; + END "/"; + + FUNCTION "MOD" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "MOD"; + + FUNCTION "MOD" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_LOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "MOD"; + + FUNCTION "MOD" (l, r :UNSIGNED) RETURN UNSIGNED IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : UNSIGNED(0 TO ml+1); + VARIABLE rt : UNSIGNED(0 TO ml+1); + VARIABLE quote : UNSIGNED(1 TO ml); + VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : UNSIGNED(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "MOD"; + + FUNCTION "REM" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "REM"; + + FUNCTION "REM" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); + VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); + VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : STD_LOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "REM"; + + FUNCTION "REM" (l, r :UNSIGNED) RETURN UNSIGNED IS + + CONSTANT ml : INTEGER := maximum(l'length,r'length); + VARIABLE lt : UNSIGNED(0 TO ml+1); + VARIABLE rt : UNSIGNED(0 TO ml+1); + VARIABLE quote : UNSIGNED(1 TO ml); + VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); + VARIABLE n : UNSIGNED(0 TO ml) := (OTHERS=>'0'); + + BEGIN + ASSERT NOT (r = "0") + REPORT "Attempted divide by ZERO" + SEVERITY ERROR; + IF hasx(l) OR hasx(r) THEN + FOR i IN lt'range LOOP + lt(i) := 'X'; + END LOOP; + ELSE + lt := zxt( l, ml+2 ); + WHILE lt >= r LOOP + rt := zxt( r, ml+2 ); + WHILE rt <= lt LOOP + rt := shift(rt); + END LOOP; + rt := rshift(rt); + lt := lt - rt; + END LOOP; + END IF; + RETURN lt(2 TO ml+1); + END "REM"; + + FUNCTION "**" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS + + VARIABLE return_vector : STD_ULOGIC_VECTOR(l'range) := (OTHERS=>'0'); + VARIABLE tmp : STD_ULOGIC_VECTOR(1 TO (2 * l'length)) := (OTHERS=>'0'); + CONSTANT lsh_l : INTEGER := l'length+1; + CONSTANT lsh_r : INTEGER := 2 * l'length; + VARIABLE pow : INTEGER; + + BEGIN + IF (hasx(l) OR hasx(r)) THEN + FOR i IN return_vector'range LOOP + return_vector(i) := 'X'; + END LOOP; + ELSE + pow := to_integer( r, 0 ); + tmp( tmp'right ) := '1'; + FOR i IN 1 TO pow LOOP + tmp := tmp(lsh_l TO lsh_r) * l; + END LOOP; + return_vector := tmp(lsh_l TO lsh_r); + END IF; + RETURN return_vector; + END "**"; + + FUNCTION "**" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + + VARIABLE return_vector : STD_LOGIC_VECTOR(l'range) := (OTHERS=>'0'); + VARIABLE tmp : STD_LOGIC_VECTOR(1 TO (2 * l'length)) := (OTHERS=>'0'); + CONSTANT lsh_l : INTEGER := l'length+1; + CONSTANT lsh_r : INTEGER := 2 * l'length; + VARIABLE pow : INTEGER; + + BEGIN + IF (hasx(l) OR hasx(r)) THEN + FOR i IN return_vector'range LOOP + return_vector(i) := 'X'; + END LOOP; + ELSE + pow := to_integer( r, 0 ); + tmp( tmp'right ) := '1'; + FOR i IN 1 TO pow LOOP + tmp := tmp(lsh_l TO lsh_r) * l; + END LOOP; + return_vector := tmp(lsh_l TO lsh_r); + END IF; + RETURN return_vector; + END "**"; + + FUNCTION "**" (l, r :UNSIGNED) RETURN UNSIGNED IS + + VARIABLE return_vector : UNSIGNED(l'range) := (OTHERS=>'0'); + VARIABLE tmp : UNSIGNED(1 TO (2 * l'length)) := (OTHERS=>'0'); + CONSTANT lsh_l : INTEGER := l'length+1; + CONSTANT lsh_r : INTEGER := 2 * l'length; + VARIABLE pow : INTEGER; + + BEGIN + IF (hasx(l) OR hasx(r)) THEN + FOR i IN return_vector'range LOOP + return_vector(i) := 'X'; + END LOOP; + ELSE + pow := to_integer( r, 0 ); + tmp( tmp'right ) := '1'; + FOR i IN 1 TO pow LOOP + tmp := tmp(lsh_l TO lsh_r) * l; + END LOOP; + return_vector := tmp(lsh_l TO lsh_r); + END IF; + RETURN return_vector; + END "**"; + +-- +-- Absolute Value Functions +-- + FUNCTION "abs" (arg1:SIGNED) RETURN SIGNED IS + constant len : integer := arg1'length; + VARIABLE answer, tmp : SIGNED( len-1 downto 0 ) := (others=>'0'); + VARIABLE index : integer := len; + BEGIN + assert arg1'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + IF hasx(arg1) THEN + answer := (OTHERS => 'X'); + ELSIF (arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L') THEN + answer := arg1; + ELSE + tmp := arg1; + lp1 : FOR i IN answer'REVERSE_RANGE LOOP + IF (tmp(i) = '1' OR tmp(i) = 'H') THEN + index := i+1; + answer(i downto 0) := tmp(i downto 0); + exit; + END IF; + END LOOP lp1; + answer(len-1 downto index) := NOT tmp(len-1 downto index); + end if; + RETURN (answer); + END ; + +-- +-- Shift Left (arithmetic) Functions +-- + + FUNCTION "sla" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_ulogic_vector(1 to len) := (others => arg1(arg1'right)); + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sla" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_logic_vector(1 to len) := (others => arg1(arg1'right)); + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sla" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : UNSIGNED(1 to len) := (others => arg1(arg1'right)); + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sla" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : SIGNED(1 to len) := (others => arg1(arg1'right)); + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + +-- +-- Shift Right (arithmetics) Functions +-- + FUNCTION "sra" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_ulogic_vector(1 to len) := (others => arg1(arg1'left)); + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "sra" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_logic_vector(1 to len) := (others => arg1(arg1'left)); + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "sra" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : UNSIGNED(1 to len) := (others => arg1(arg1'left)); + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "sra" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : SIGNED(1 to len) := (others => arg1(arg1'left)); + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + +-- +-- Shift Left (logical) Functions +-- + + FUNCTION "sll" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_ulogic_vector(1 to len) := (others =>'0'); + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sll" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_logic_vector(1 to len) := (others =>'0'); + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sll" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : UNSIGNED(1 to len) := (others =>'0'); + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + + FUNCTION "sll" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : SIGNED(1 to len) := (others =>'0'); + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(arg2+1 to len) & se(1 to arg2)); + END IF; + END ; + +-- +-- Shift Right (logical) Functions +-- + FUNCTION "srl" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_ulogic_vector(1 to len) := (others => '0'); + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "srl" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : std_logic_vector(1 to len) := (others => '0'); + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "srl" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : UNSIGNED(1 to len) := (others => '0'); + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + + FUNCTION "srl" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT se : SIGNED(1 to len) := (others => '0'); + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (arg2 >= len) THEN + RETURN (se); + ELSIF (arg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (se(1 to arg2) & ans(1 to len-arg2)); + END IF; + END ; + +-- +-- Rotate Left (Logical) Functions +-- + FUNCTION "rol" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(marg2+1 to len) & ans(1 to marg2)); + END IF; + END ; + + FUNCTION "rol" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(marg2+1 to len) & ans(1 to marg2)); + END IF; + END ; + + FUNCTION "rol" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(marg2+1 to len) & ans(1 to marg2)); + END IF; + END ; + + FUNCTION "rol" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(marg2+1 to len) & ans(1 to marg2)); + END IF; + END ; + +-- +-- Rotate Right (Logical) Functions +-- + FUNCTION "ror" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); + END IF; + END ; + + FUNCTION "ror" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); + END IF; + END ; + + FUNCTION "ror" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : UNSIGNED(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); + END IF; + END ; + + FUNCTION "ror" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS + CONSTANT len : INTEGER := arg1'length ; + CONSTANT marg2 : integer := arg2 mod len; + VARIABLE ans : SIGNED(1 to len) := arg1; + BEGIN + IF (marg2 = 0) THEN + RETURN (arg1); + ELSE + RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); + END IF; + END ; + +-- +-- Equal functions. +-- + CONSTANT eq_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | + ); + + FUNCTION eq ( l, r : STD_LOGIC ) RETURN BOOLEAN IS + BEGIN + RETURN eq_table( l, r ); + END; + + FUNCTION eq ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN FALSE; + END IF; + END LOOP; + RETURN TRUE; + END; + + FUNCTION eq ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN FALSE; + END IF; + END LOOP; + RETURN TRUE; + END; + + FUNCTION eq ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN FALSE; + END IF; + END LOOP; + RETURN TRUE; + END; + + FUNCTION eq ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + RETURN (eq( lt, rt )); + END; + + FUNCTION "=" ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN FALSE; + END IF; + END LOOP; + RETURN TRUE; + END; + + FUNCTION "=" ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + RETURN (eq( lt, rt )); + END; + +-- +-- Not Equal function. +-- + CONSTANT neq_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | + ); + + + FUNCTION ne ( l, r : STD_LOGIC ) RETURN BOOLEAN IS + BEGIN + RETURN neq_table( l, r ); + END; + + FUNCTION ne ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF ne( lt(i), rt(i) ) THEN + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION ne ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF ne( lt(i), rt(i) ) THEN + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION ne ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF ne( lt(i), rt(i) ) THEN + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION ne ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + RETURN (ne( lt, rt )); + END; + + FUNCTION "/=" ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF ne( lt(i), rt(i) ) THEN + RETURN TRUE; + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION "/=" ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + RETURN (ne( lt, rt )); + END; + +-- +-- Less Than functions. +-- + CONSTANT ltb_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 1 | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | H | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | + ); + + FUNCTION lt ( l, r : STD_LOGIC ) RETURN BOOLEAN IS + BEGIN + RETURN ltb_table( l, r ); + END; + + FUNCTION lt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt : STD_ULOGIC_VECTOR ( 1 TO ml ); + VARIABLE rtt : STD_ULOGIC_VECTOR ( 1 TO ml ); + BEGIN + ltt := zxt( l, ml ); + rtt := zxt( r, ml ); + FOR i IN ltt'range LOOP + IF NOT eq( ltt(i), rtt(i) ) THEN + RETURN lt( ltt(i), rtt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION lt ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt : STD_LOGIC_VECTOR ( 1 TO ml ); + VARIABLE rtt : STD_LOGIC_VECTOR ( 1 TO ml ); + BEGIN + ltt := zxt( l, ml ); + rtt := zxt( r, ml ); + FOR i IN ltt'range LOOP + IF NOT eq( ltt(i), rtt(i) ) THEN + RETURN lt( ltt(i), rtt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION lt ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt : UNSIGNED ( 1 TO ml ); + VARIABLE rtt : UNSIGNED ( 1 TO ml ); + BEGIN + ltt := zxt( l, ml ); + rtt := zxt( r, ml ); + FOR i IN ltt'range LOOP + IF NOT eq( ltt(i), rtt(i) ) THEN + RETURN lt( ltt(i), rtt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION lt ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt, rtt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + ltt := (OTHERS => l(l'left)) ; + ltt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rtt := (OTHERS => r(r'left)) ; + rtt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(ltt(ltt'left) = '1' AND rtt(rtt'left) = '0') THEN + RETURN(TRUE) ; + ELSIF(ltt(ltt'left) = '0' AND rtt(rtt'left) = '1') THEN + RETURN(FALSE) ; + ELSE + RETURN (lt( ltt, rtt )); + END IF ; + END; + + FUNCTION "<" ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt : UNSIGNED ( 1 TO ml ); + VARIABLE rtt : UNSIGNED ( 1 TO ml ); + BEGIN + ltt := zxt( l, ml ); + rtt := zxt( r, ml ); + FOR i IN ltt'range LOOP + IF NOT eq( ltt(i), rtt(i) ) THEN + RETURN lt( ltt(i), rtt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION "<" ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE ltt, rtt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + ltt := (OTHERS => l(l'left)) ; + ltt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rtt := (OTHERS => r(r'left)) ; + rtt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(ltt(ltt'left) = '1' AND rtt(rtt'left) = '0') THEN + RETURN(TRUE) ; + ELSIF(ltt(ltt'left) = '0' AND rtt(rtt'left) = '1') THEN + RETURN(FALSE) ; + ELSE + RETURN (lt( ltt, rtt )); + END IF ; + END; + +-- +-- Greater Than functions. +-- + CONSTANT gtb_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 0 | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | L | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H | + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | + ); + + FUNCTION gt ( l, r : std_logic ) RETURN BOOLEAN IS + BEGIN + RETURN gtb_table( l, r ); + END ; + + FUNCTION gt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN gt( lt(i), rt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION gt ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); + VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN gt( lt(i), rt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION gt ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN gt( lt(i), rt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION gt ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(FALSE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(TRUE) ; + ELSE + RETURN (gt( lt, rt )); + END IF ; + END; + + FUNCTION ">" ( l,r : UNSIGNED ) RETURN BOOLEAN IS + CONSTANT ml : INTEGER := maximum( l'length, r'length ); + VARIABLE lt : UNSIGNED ( 1 TO ml ); + VARIABLE rt : UNSIGNED ( 1 TO ml ); + BEGIN + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'range LOOP + IF NOT eq( lt(i), rt(i) ) THEN + RETURN gt( lt(i), rt(i) ); + END IF; + END LOOP; + RETURN FALSE; + END; + + FUNCTION ">" ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(FALSE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(TRUE) ; + ELSE + RETURN (gt( lt, rt )); + END IF ; + END; + +-- +-- Less Than or Equal to functions. +-- + CONSTANT leb_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | U | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | X | + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | 0 | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | Z | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | W | + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | L | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H | + ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ) -- | D | + ); + + FUNCTION le ( l, r : std_logic ) RETURN BOOLEAN IS + BEGIN + RETURN leb_table( l, r ); + END ; + + TYPE std_ulogic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N'); + TYPE std_ulogic_fuzzy_state_table IS ARRAY ( std_ulogic, std_ulogic ) OF std_ulogic_fuzzy_state; + + CONSTANT le_fuzzy_table : std_ulogic_fuzzy_state_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U' ), -- | U | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | X | + ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | 0 | + ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | W | + ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | L | + ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | H | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ) -- | D | + ); + + FUNCTION le ( L,R : std_ulogic_vector ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : std_ulogic_vector ( 1 to ml ); + VARIABLE rt : std_ulogic_vector ( 1 to ml ); + VARIABLE res : std_ulogic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := le_fuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + TYPE std_logic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N'); + TYPE std_logic_fuzzy_state_table IS ARRAY ( std_logic, std_logic ) OF std_logic_fuzzy_state; + + CONSTANT le_lfuzzy_table : std_logic_fuzzy_state_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U' ), -- | U | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | X | + ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | 0 | + ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | W | + ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | L | + ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | H | + ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ) -- | D | + ); + + FUNCTION le ( L,R : std_logic_vector ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : std_logic_vector ( 1 to ml ); + VARIABLE rt : std_logic_vector ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := le_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION le ( L,R : UNSIGNED ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := le_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION le (l, r:SIGNED) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(TRUE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(FALSE) ; + ELSE + RETURN (le( lt, rt )); + END IF ; + END; + + FUNCTION "<=" ( L,R : UNSIGNED ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := le_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION "<=" (l, r:SIGNED) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(TRUE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(FALSE) ; + ELSE + RETURN (le( lt, rt )); + END IF ; + END; + +-- +-- Greater Than or Equal to functions. +-- + CONSTANT geb_table : stdlogic_boolean_table := ( + -- ---------------------------------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------------------------------- + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | U | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | X | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 | + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | 1 | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | Z | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | W | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L | + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | H | + ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ) -- | D | + ); + + FUNCTION ge ( l, r : std_logic ) RETURN BOOLEAN IS + BEGIN + RETURN geb_table( l, r ); + END ; + + CONSTANT ge_fuzzy_table : std_ulogic_fuzzy_state_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X | + ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 | + ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W | + ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L | + ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D | + ); + + FUNCTION ge ( L,R : std_ulogic_vector ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : std_ulogic_vector ( 1 to ml ); + VARIABLE rt : std_ulogic_vector ( 1 to ml ); + VARIABLE res : std_ulogic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := ge_fuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + CONSTANT ge_lfuzzy_table : std_logic_fuzzy_state_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X | + ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 | + ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W | + ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L | + ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H | + ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D | + ); + + FUNCTION ge ( L,R : std_logic_vector ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : std_logic_vector ( 1 to ml ); + VARIABLE rt : std_logic_vector ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := ge_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION ge ( L,R : UNSIGNED ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := ge_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION ge ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(FALSE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(TRUE) ; + ELSE + RETURN (ge( lt, rt )); + END IF ; + END; + + FUNCTION ">=" ( L,R : UNSIGNED ) RETURN boolean IS + CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : std_logic_fuzzy_state; + begin + lt := zxt( l, ml ); + rt := zxt( r, ml ); + FOR i IN lt'RANGE LOOP + res := ge_lfuzzy_table( lt(i), rt(i) ); + CASE res IS + WHEN 'U' => RETURN FALSE; + WHEN 'X' => RETURN FALSE; + WHEN 'T' => RETURN TRUE; + WHEN 'F' => RETURN FALSE; + WHEN OTHERS => null; + END CASE; + END LOOP; + RETURN TRUE; + end ; + + FUNCTION ">=" ( l,r : SIGNED ) RETURN BOOLEAN IS + CONSTANT len : INTEGER := maximum( l'length, r'length ); + VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); + BEGIN + assert l'length > 1 AND r'length > 1 + report "SIGNED vector must be atleast 2 bits wide" + severity ERROR; + lt := (OTHERS => l(l'left)) ; + lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); + rt := (OTHERS => r(r'left)) ; + rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); + IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN + RETURN(FALSE) ; + ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN + RETURN(TRUE) ; + ELSE + RETURN (ge( lt, rt )); + END IF ; + END; + + ------------------------------------------------------------------------------- + -- Logical Operations + ------------------------------------------------------------------------------- + + -- truth table for "and" function + CONSTANT and_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | D | + ); + + -- truth table for "or" function + CONSTANT or_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | D | + ); + + + -- truth table for "xor" function + CONSTANT xor_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H D | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | + ); + + -- truth table for "not" function + CONSTANT not_table: stdlogic_1D := + -- ------------------------------------------------- + -- | U X 0 1 Z W L H D | + -- ------------------------------------------------- + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ); + + FUNCTION "and" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := and_table( lt(i), rt(i) ); + END LOOP; + RETURN res; + end "and"; + + FUNCTION "nand" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := not_table( and_table( lt(i), rt(i) ) ); + END LOOP; + RETURN res; + end "nand"; + + FUNCTION "or" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := or_table( lt(i), rt(i) ); + END LOOP; + RETURN res; + end "or"; + + FUNCTION "nor" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := not_table( or_table( lt(i), rt(i) ) ); + END LOOP; + RETURN res; + end "nor"; + + FUNCTION "xor" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := xor_table( lt(i), rt(i) ); + END LOOP; + RETURN res; + end "xor"; + + FUNCTION "not" ( arg1 : UNSIGNED ) RETURN UNSIGNED IS + VARIABLE result : UNSIGNED ( arg1'RANGE ) := (Others => 'X'); + begin + for i in result'range loop + result(i) := not_table( arg1(i) ); + end loop; + return result; + end "not"; + + FUNCTION "and" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a and b); + RETURN (answer); + end "and"; + + FUNCTION "nand" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a nand b); + RETURN (answer); + end "nand"; + + FUNCTION "or" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a or b); + RETURN (answer); + end "or"; + + FUNCTION "nor" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a nor b); + RETURN (answer); + end "nor"; + + FUNCTION "xor" ( arg1, arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a xor b); + RETURN (answer); + end "xor"; + + FUNCTION "not" ( arg1 : SIGNED ) RETURN SIGNED IS + VARIABLE result : SIGNED ( arg1'RANGE ) := (Others => 'X'); + begin + for i in result'range loop + result(i) := not_table( arg1(i) ); + end loop; + return result; + end "not"; + + FUNCTION "xnor" ( arg1, arg2 : std_ulogic_vector ) RETURN std_ulogic_vector IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : std_ulogic_vector ( 1 to ml ); + VARIABLE rt : std_ulogic_vector ( 1 to ml ); + VARIABLE res : std_ulogic_vector ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := not_table( xor_table( lt(i), rt(i) ) ); + END LOOP; + RETURN res; + end "xnor"; + + FUNCTION "xnor" ( arg1, arg2 : std_logic_vector ) RETURN std_logic_vector IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : std_logic_vector ( 1 to ml ); + VARIABLE rt : std_logic_vector ( 1 to ml ); + VARIABLE res : std_logic_vector ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := not_table( xor_table( lt(i), rt(i) ) ); + END LOOP; + RETURN res; + end "xnor"; + + FUNCTION "xnor" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED IS + CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); + VARIABLE lt : UNSIGNED ( 1 to ml ); + VARIABLE rt : UNSIGNED ( 1 to ml ); + VARIABLE res : UNSIGNED ( 1 to ml ); + begin + lt := zxt( arg1, ml ); + rt := zxt( arg2, ml ); + FOR i IN res'RANGE LOOP + res(i) := not_table( xor_table( lt(i), rt(i) ) ); + END LOOP; + RETURN res; + end "xnor"; + + FUNCTION "xnor" ( arg1, arg2 : SIGNED ) RETURN SIGNED IS + CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; + VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; + BEGIN + a := (OTHERS => arg1(arg1'left)) ; + a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); + b := (OTHERS => arg2(arg2'left)) ; + b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); + answer := SIGNED(a xnor b); + RETURN (answer); + end "xnor"; + +END ; diff --git a/libraries/mentor/std_logic_arith_body.vhdl b/libraries/mentor/std_logic_arith_body.vhdl deleted file mode 100644 index 36f76cb7d..000000000 --- a/libraries/mentor/std_logic_arith_body.vhdl +++ /dev/null @@ -1,2915 +0,0 @@ -LIBRARY ieee; --- LIBRARY arithmetic; - -PACKAGE BODY std_logic_arith IS - - USE ieee.std_logic_1164.ALL; - -- USE arithmetic.utils.all; - - ------------------------------------------------------------------- - -- Local Types - ------------------------------------------------------------------- - TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic; - TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; - TYPE stdlogic_boolean_table IS ARRAY(std_ulogic, std_ulogic) OF BOOLEAN; - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -- FUNCTIONS DEFINED FOR SYNTHESIS - -------------------------------------------------------------------- - -------------------------------------------------------------------- - - FUNCTION std_ulogic_wired_or ( input : std_ulogic_vector ) RETURN std_ulogic IS - VARIABLE result : std_ulogic := '-'; -- weakest state default - CONSTANT resolution_table : stdlogic_table := ( - -- --------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- --------------------------------------------------------- - ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | U | - ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | - ( 'X', 'X', '0', '1', '0', 'X', '0', '1', '0' ), -- | 0 | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | - ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ), -- | Z | - ( 'X', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | - ( 'X', 'X', '0', '1', '0', 'X', '0', '1', '0' ), -- | L | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | - ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ) -- | D | - ); - - BEGIN - -- Iterate through all inputs - FOR i IN input'range LOOP - result := resolution_table(result, input(i)); - END LOOP; - -- Return the resultant value - RETURN result; - END std_ulogic_wired_or; - - FUNCTION std_ulogic_wired_and ( input : std_ulogic_vector ) RETURN std_ulogic IS - VARIABLE result : std_ulogic := '-'; -- weakest state default - CONSTANT resolution_table : stdlogic_table := ( - -- --------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- --------------------------------------------------------- - ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | U | - ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | - ( 'X', 'X', '0', '1', '1', 'X', '0', '1', '1' ), -- | 1 | - ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ), -- | Z | - ( 'X', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | - ( 'X', 'X', '0', '1', '1', 'X', '0', '1', '1' ), -- | H | - ( 'X', 'X', '0', '1', 'Z', 'X', '0', '1', 'Z' ) -- | D | - ); - - BEGIN - -- Iterate through all inputs - FOR i IN input'range LOOP - result := resolution_table(result, input(i)); - END LOOP; - -- Return the resultant value - RETURN result; - END std_ulogic_wired_and; - --- --- MGC base level functions --- --- --- Convert Base Type to Integer --- - FUNCTION to_integer (arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : INTEGER; - BEGIN - tmp := SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END to_integer; - - FUNCTION to_integer (arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : INTEGER; - BEGIN - tmp := SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END to_integer; - - FUNCTION to_integer (arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL IS - VARIABLE tmp : SIGNED( arg1'length DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : NATURAL; - BEGIN - tmp := '0' & SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END to_integer; - - FUNCTION TO_INTEGER (arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE return_int,x_tmp : INTEGER := 0; - BEGIN - ASSERT arg1'length > 0 - REPORT "NULL vector, returning 0" - SEVERITY NOTE; - assert arg1'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - ASSERT arg1'length <= 32 -- implementation dependent limit - REPORT "vector too large, conversion may cause overflow" - SEVERITY WARNING; - IF x /= 0 THEN - x_tmp := 1; - END IF; - IF arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L' OR -- positive value - ( x_tmp = 0 AND arg1(arg1'left) /= '1' AND arg1(arg1'left) /= 'H') THEN - FOR i IN arg1'range LOOP - return_int := return_int * 2; - CASE arg1(i) IS - WHEN '0'|'L' => NULL; - WHEN '1'|'H' => return_int := return_int + 1; - WHEN OTHERS => return_int := return_int + x_tmp; - END CASE; - END LOOP; - ELSE -- negative value - IF (x_tmp = 0) THEN - x_tmp := 1; - ELSE - x_tmp := 0; - END IF; - FOR i IN arg1'range LOOP - return_int := return_int * 2; - CASE arg1(i) IS - WHEN '0'|'L' => return_int := return_int + 1; - WHEN '1'|'H' => NULL; - WHEN OTHERS => return_int := return_int + x_tmp; - END CASE; - END LOOP; - return_int := (-return_int) - 1; - END IF; - RETURN return_int; - END TO_INTEGER; - - FUNCTION to_integer (arg1:STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL IS - BEGIN - IF(arg1 = '0' OR arg1 = 'L' OR (x = 0 AND arg1 /= '1' AND arg1 /= 'H')) THEN - RETURN(0); - ELSE - RETURN(1) ; - END IF ; - END ; - - FUNCTION conv_integer (arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE tmp : SIGNED( arg1'length - 1 DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : INTEGER; - BEGIN - tmp := SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END ; - - FUNCTION conv_integer (arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE tmp : SIGNED( arg1'length -1 DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : INTEGER; - BEGIN - tmp := SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END ; - - FUNCTION conv_integer (arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL IS - VARIABLE tmp : SIGNED( arg1'length DOWNTO 0 ) := (OTHERS => '0'); - VARIABLE result : NATURAL; - BEGIN - tmp := '0' & SIGNED(arg1); - result := TO_INTEGER( tmp, x ); - RETURN (result); - END ; - - FUNCTION conv_INTEGER (arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER IS - VARIABLE return_int,x_tmp : INTEGER := 0; - BEGIN - ASSERT arg1'length > 0 - REPORT "NULL vector, returning 0" - SEVERITY NOTE; - assert arg1'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - ASSERT arg1'length <= 32 -- implementation dependent limit - REPORT "vector too large, conversion may cause overflow" - SEVERITY WARNING; - IF x /= 0 THEN - x_tmp := 1; - END IF; - IF arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L' OR -- positive value - ( x_tmp = 0 AND arg1(arg1'left) /= '1' AND arg1(arg1'left) /= 'H') THEN - FOR i IN arg1'range LOOP - return_int := return_int * 2; - CASE arg1(i) IS - WHEN '0'|'L' => NULL; - WHEN '1'|'H' => return_int := return_int + 1; - WHEN OTHERS => return_int := return_int + x_tmp; - END CASE; - END LOOP; - ELSE -- negative value - IF (x_tmp = 0) THEN - x_tmp := 1; - ELSE - x_tmp := 0; - END IF; - FOR i IN arg1'range LOOP - return_int := return_int * 2; - CASE arg1(i) IS - WHEN '0'|'L' => return_int := return_int + 1; - WHEN '1'|'H' => NULL; - WHEN OTHERS => return_int := return_int + x_tmp; - END CASE; - END LOOP; - return_int := (-return_int) - 1; - END IF; - RETURN return_int; - END ; - - FUNCTION conv_integer (arg1:STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL IS - BEGIN - IF(arg1 = '0' OR arg1 = 'L' OR (x = 0 AND arg1 /= '1' AND arg1 /= 'H')) THEN - RETURN(0); - ELSE - RETURN(1) ; - END IF ; - END ; - --- --- Convert Base Type to STD_LOGIC --- - - FUNCTION to_stdlogic (arg1:BOOLEAN) RETURN STD_LOGIC IS - BEGIN - IF(arg1) THEN - RETURN('1') ; - ELSE - RETURN('0') ; - END IF ; - END ; - --- --- Convert Base Type to STD_LOGIC_VECTOR --- - FUNCTION To_StdlogicVector (arg1 : integer; size : NATURAL) RETURN std_logic_vector IS - VARIABLE vector : std_logic_vector(0 TO size-1); - VARIABLE tmp_int : integer := arg1; - VARIABLE carry : std_logic := '1'; -- setup to add 1 if needed - VARIABLE carry2 : std_logic; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - IF arg1 < 0 THEN - FOR i IN size-1 DOWNTO 0 LOOP - carry2 := (NOT vector(i)) AND carry; - vector(i) := (NOT vector(i)) XOR carry; - carry := carry2; - END LOOP; - END IF; - RETURN vector; - END To_StdlogicVector; - - FUNCTION To_StdUlogicVector (arg1 : integer; size : NATURAL) RETURN std_ulogic_vector IS - VARIABLE vector : std_ulogic_vector(0 TO size-1); - VARIABLE tmp_int : integer := arg1; - VARIABLE carry : std_ulogic := '1'; -- setup to add 1 if needed - VARIABLE carry2 : std_ulogic; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - IF arg1 < 0 THEN - FOR i IN size-1 DOWNTO 0 LOOP - carry2 := (NOT vector(i)) AND carry; - vector(i) := (NOT vector(i)) XOR carry; - carry := carry2; - END LOOP; - END IF; - RETURN vector; - END To_StdUlogicVector; - - --- --- Convert Base Type to UNSIGNED --- - - FUNCTION to_unsigned (arg1:NATURAL ; size:NATURAL) RETURN UNSIGNED IS - VARIABLE vector : UNSIGNED(0 TO size-1) := (OTHERS => '0'); - VARIABLE tmp_int : INTEGER := arg1; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - RETURN vector; - END ; - - FUNCTION conv_unsigned (arg1:NATURAL ; size:NATURAL) RETURN UNSIGNED IS - VARIABLE vector : UNSIGNED(0 TO size-1) := (OTHERS => '0'); - VARIABLE tmp_int : INTEGER := arg1; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - RETURN vector; - END ; - --- --- Convert Base Type to SIGNED --- - - FUNCTION to_signed (arg1:INTEGER ; size : NATURAL) RETURN SIGNED IS - VARIABLE vector : SIGNED(0 TO size-1) := (OTHERS => '0'); - VARIABLE tmp_int : INTEGER := arg1; - VARIABLE carry : STD_LOGIC := '1'; -- setup to add 1 if needed - VARIABLE carry2 : STD_LOGIC := '0'; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - IF arg1 < 0 THEN - FOR i IN size-1 DOWNTO 0 LOOP - carry2 := (NOT vector(i)) AND carry; - vector(i) := (NOT vector(i)) XOR carry; - carry := carry2; - END LOOP; - END IF; - RETURN vector; - END ; - - FUNCTION conv_signed (arg1:INTEGER ; size : NATURAL) RETURN SIGNED IS - VARIABLE vector : SIGNED(0 TO size-1) := (OTHERS => '0'); - VARIABLE tmp_int : INTEGER := arg1; - VARIABLE carry : STD_LOGIC := '1'; -- setup to add 1 if needed - VARIABLE carry2 : STD_LOGIC := '0'; - BEGIN - FOR i IN size-1 DOWNTO 0 LOOP - IF tmp_int MOD 2 = 1 THEN - vector(i) := '1'; - ELSE - vector(i) := '0'; - END IF; - tmp_int := tmp_int / 2; - END LOOP; - - IF arg1 < 0 THEN - FOR i IN size-1 DOWNTO 0 LOOP - carry2 := (NOT vector(i)) AND carry; - vector(i) := (NOT vector(i)) XOR carry; - carry := carry2; - END LOOP; - END IF; - RETURN vector; - END ; - - -- sign/zero extend functions - -- - - FUNCTION zero_extend ( arg1 : STD_ULOGIC_VECTOR; size : NATURAL ) RETURN STD_ULOGIC_VECTOR - IS - VARIABLE answer : STD_ULOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - ASSERT arg1'length <= size - REPORT "Vector is already larger then size." - SEVERITY WARNING ; - answer := (OTHERS => '0') ; - answer(arg1'length-1 DOWNTO 0) := arg1; - RETURN(answer) ; - END ; - - FUNCTION zero_extend ( arg1 : STD_LOGIC_VECTOR; size : NATURAL ) RETURN STD_LOGIC_VECTOR - IS - VARIABLE answer : STD_LOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - ASSERT arg1'length <= size - REPORT "Vector is already larger then size." - SEVERITY WARNING ; - answer := (OTHERS => '0') ; - answer(arg1'length-1 DOWNTO 0) := arg1; - RETURN(answer) ; - END ; - - FUNCTION zero_extend ( arg1 : STD_LOGIC; size : NATURAL ) RETURN STD_LOGIC_VECTOR - IS - VARIABLE answer : STD_LOGIC_VECTOR(size-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - answer := (OTHERS => '0') ; - answer(0) := arg1; - RETURN(answer) ; - END ; - - FUNCTION zero_extend ( arg1 : UNSIGNED; size : NATURAL ) RETURN UNSIGNED IS - VARIABLE answer : UNSIGNED(size-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - ASSERT arg1'length <= size - REPORT "Vector is already larger then size." - SEVERITY WARNING ; - answer := (OTHERS => '0') ; - answer(arg1'length - 1 DOWNTO 0) := arg1; - RETURN(answer) ; - END ; - - FUNCTION sign_extend ( arg1 : SIGNED; size : NATURAL ) RETURN SIGNED IS - VARIABLE answer : SIGNED(size-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - ASSERT arg1'length <= size - REPORT "Vector is already larger then size." - SEVERITY WARNING ; - answer := (OTHERS => arg1(arg1'left)) ; - answer(arg1'length - 1 DOWNTO 0) := arg1; - RETURN(answer) ; - END ; - - - - -- Some useful generic functions - - --//// Zero Extend //// - -- - -- Function zxt - -- - FUNCTION zxt( q : STD_ULOGIC_VECTOR; i : INTEGER ) RETURN STD_ULOGIC_VECTOR IS - VARIABLE qs : STD_ULOGIC_VECTOR (1 TO i); - VARIABLE qt : STD_ULOGIC_VECTOR (1 TO q'length); - BEGIN - qt := q; - IF i < q'length THEN - qs := qt( (q'length-i+1) TO qt'right); - ELSIF i > q'length THEN - qs := (OTHERS=>'0'); - qs := qs(1 TO (i-q'length)) & qt; - ELSE - qs := qt; - END IF; - RETURN qs; - END; - - --//// Zero Extend //// - -- - -- Function zxt - -- - FUNCTION zxt( q : STD_LOGIC_VECTOR; i : INTEGER ) RETURN STD_LOGIC_VECTOR IS - VARIABLE qs : STD_LOGIC_VECTOR (1 TO i); - VARIABLE qt : STD_LOGIC_VECTOR (1 TO q'length); - BEGIN - qt := q; - IF i < q'length THEN - qs := qt( (q'length-i+1) TO qt'right); - ELSIF i > q'length THEN - qs := (OTHERS=>'0'); - qs := qs(1 TO (i-q'length)) & qt; - ELSE - qs := qt; - END IF; - RETURN qs; - END; - - --//// Zero Extend //// - -- - -- Function zxt - -- - FUNCTION zxt( q : UNSIGNED; i : INTEGER ) RETURN UNSIGNED IS - VARIABLE qs : UNSIGNED (1 TO i); - VARIABLE qt : UNSIGNED (1 TO q'length); - BEGIN - qt := q; - IF i < q'length THEN - qs := qt( (q'length-i+1) TO qt'right); - ELSIF i > q'length THEN - qs := (OTHERS=>'0'); - qs := qs(1 TO (i-q'length)) & qt; - ELSE - qs := qt; - END IF; - RETURN qs; - END; - --------------------------------------- --- Synthesizable addition Functions -- --------------------------------------- - - FUNCTION "+" ( arg1, arg2 : STD_LOGIC ) RETURN STD_LOGIC IS - -- truth table for "xor" function - CONSTANT xor_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | - ); - BEGIN - RETURN xor_table( arg1, arg2 ); - END "+"; - - function maximum (arg1, arg2: integer) return integer is - begin - if arg1 > arg2 then - return arg1; - else - return arg2; - end if; - end; - - FUNCTION "+" (arg1, arg2 :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE res : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE carry : STD_ULOGIC := '0'; - VARIABLE a,b,s1 : STD_ULOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := rt(i); - s1 := a + b; - res(i) := s1 + carry; - carry := (a AND b) OR (s1 AND carry); - END LOOP; - RETURN res; - END; - - FUNCTION "+" (arg1, arg2 :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE res : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE carry : STD_LOGIC := '0'; - VARIABLE a,b,s1 : STD_LOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := rt(i); - s1 := a + b; - res(i) := s1 + carry; - carry := (a AND b) OR (s1 AND carry); - END LOOP; - RETURN res; - END; - - FUNCTION "+" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : UNSIGNED(1 TO ml); - VARIABLE rt : UNSIGNED(1 TO ml); - VARIABLE res : UNSIGNED(1 TO ml); - VARIABLE carry : STD_LOGIC := '0'; - VARIABLE a,b,s1 : STD_LOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := rt(i); - s1 := a + b; - res(i) := s1 + carry; - carry := (a AND b) OR (s1 AND carry); - END LOOP; - RETURN res; - END; - - FUNCTION "+" (arg1, arg2:SIGNED) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - assert arg1'length > 1 AND arg2'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a + b); - RETURN (answer); - END ; - ------------------------------------------ --- Synthesizable subtraction Functions -- ------------------------------------------ - - FUNCTION "-" ( arg1, arg2 : std_logic ) RETURN std_logic IS - -- truth table for "xor" function - CONSTANT xor_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | - ); - BEGIN - RETURN xor_table( arg1, arg2 ); - END "-"; - - FUNCTION "-" (arg1, arg2:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE res : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE borrow : STD_ULOGIC := '1'; - VARIABLE a,b,s1 : STD_ULOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := NOT rt(i); - s1 := a + b; - res(i) := s1 + borrow; - borrow := (a AND b) OR (s1 AND borrow); - END LOOP; - RETURN res; - END "-"; - - FUNCTION "-" (arg1, arg2:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE res : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE borrow : STD_LOGIC := '1'; - VARIABLE a,b,s1 : STD_LOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := NOT rt(i); - s1 := a + b; - res(i) := s1 + borrow; - borrow := (a AND b) OR (s1 AND borrow); - END LOOP; - RETURN res; - END "-"; - - FUNCTION "-" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS - CONSTANT ml : INTEGER := maximum(arg1'length,arg2'length); - VARIABLE lt : UNSIGNED(1 TO ml); - VARIABLE rt : UNSIGNED(1 TO ml); - VARIABLE res : UNSIGNED(1 TO ml); - VARIABLE borrow : STD_LOGIC := '1'; - VARIABLE a,b,s1 : STD_LOGIC; - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - - FOR i IN res'reverse_range LOOP - a := lt(i); - b := NOT rt(i); - s1 := a + b; - res(i) := s1 + borrow; - borrow := (a AND b) OR (s1 AND borrow); - END LOOP; - RETURN res; - END "-"; - - - FUNCTION "-" (arg1, arg2:SIGNED) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - assert arg1'length > 1 AND arg2'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED( a - b ); - RETURN (answer); - END ; - ------------------------------------------ --- Unary subtract and add Functions -- ------------------------------------------ - FUNCTION "+" (arg1:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - BEGIN - RETURN (arg1); - END; - - FUNCTION "+" (arg1:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - BEGIN - RETURN (arg1); - END; - - FUNCTION "+" (arg1:UNSIGNED) RETURN UNSIGNED IS - BEGIN - RETURN (arg1); - END; - - FUNCTION "+" (arg1:SIGNED) RETURN SIGNED IS - BEGIN - RETURN (arg1); - END; - - FUNCTION hasx( v : SIGNED ) RETURN BOOLEAN IS - BEGIN - FOR i IN v'range LOOP - IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN - NULL; - ELSE - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END hasx; - - FUNCTION "-" (arg1:SIGNED) RETURN SIGNED IS - constant len : integer := arg1'length; - VARIABLE answer, tmp : SIGNED( len-1 downto 0 ) := (others=>'0'); - VARIABLE index : integer := len; - BEGIN - assert arg1'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - IF hasx(arg1) THEN - answer := (OTHERS => 'X'); - ELSE - tmp := arg1; - lp1 : FOR i IN answer'REVERSE_RANGE LOOP - IF (tmp(i) = '1' OR tmp(i) = 'H') THEN - index := i+1; - answer(i downto 0) := tmp(i downto 0); - exit; - END IF; - END LOOP lp1; - answer(len-1 downto index) := NOT tmp(len-1 downto index); - end if; - RETURN (answer); - END ; - --------------------------------------------- --- Synthesizable multiplication Functions -- --------------------------------------------- - FUNCTION shift( v : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR IS - VARIABLE v1 : STD_ULOGIC_VECTOR( v'range ); - BEGIN - FOR i IN (v'left+1) TO v'right LOOP - v1(i-1) := v(i); - END LOOP; - v1(v1'right) := '0'; - RETURN v1; - END shift; - - PROCEDURE copy(a : IN STD_ULOGIC_VECTOR; b : OUT STD_ULOGIC_VECTOR) IS - VARIABLE bi : INTEGER := b'right; - BEGIN - FOR i IN a'reverse_range LOOP - b(bi) := a(i); - bi := bi - 1; - END LOOP; - END copy; - - FUNCTION shift( v : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR IS - VARIABLE v1 : STD_LOGIC_VECTOR( v'range ); - BEGIN - FOR i IN (v'left+1) TO v'right LOOP - v1(i-1) := v(i); - END LOOP; - v1(v1'right) := '0'; - RETURN v1; - END shift; - - PROCEDURE copy(a : IN STD_LOGIC_VECTOR; b : OUT STD_LOGIC_VECTOR) IS - VARIABLE bi : INTEGER := b'right; - BEGIN - FOR i IN a'reverse_range LOOP - b(bi) := a(i); - bi := bi - 1; - END LOOP; - END copy; - - FUNCTION shift( v : SIGNED ) RETURN SIGNED IS - VARIABLE v1 : SIGNED( v'range ); - BEGIN - FOR i IN (v'left+1) TO v'right LOOP - v1(i-1) := v(i); - END LOOP; - v1(v1'right) := '0'; - RETURN v1; - END shift; - - PROCEDURE copy(a : IN SIGNED; b : OUT SIGNED) IS - VARIABLE bi : INTEGER := b'right; - BEGIN - FOR i IN a'reverse_range LOOP - b(bi) := a(i); - bi := bi - 1; - END LOOP; - END copy; - - FUNCTION shift( v : UNSIGNED ) RETURN UNSIGNED IS - VARIABLE v1 : UNSIGNED( v'range ); - BEGIN - FOR i IN (v'left+1) TO v'right LOOP - v1(i-1) := v(i); - END LOOP; - v1(v1'right) := '0'; - RETURN v1; - END shift; - - PROCEDURE copy(a : IN UNSIGNED; b : OUT UNSIGNED) IS - VARIABLE bi : INTEGER := b'right; - BEGIN - FOR i IN a'reverse_range LOOP - b(bi) := a(i); - bi := bi - 1; - END LOOP; - END copy; - - FUNCTION "*" (arg1, arg2:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - VARIABLE ml : INTEGER := arg1'length + arg2'length; - VARIABLE lt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE prod : STD_ULOGIC_VECTOR(1 TO ml) := (OTHERS=>'0'); - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN rt'reverse_range LOOP - IF rt(i) = '1' THEN - prod := prod + lt; - END IF; - lt := shift(lt); - END LOOP; - RETURN prod; - END "*"; - - FUNCTION "*" (arg1, arg2:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - VARIABLE ml : INTEGER := arg1'length + arg2'length; - VARIABLE lt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE rt : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE prod : STD_LOGIC_VECTOR(1 TO ml) := (OTHERS=>'0'); - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN rt'reverse_range LOOP - IF rt(i) = '1' THEN - prod := prod + lt; - END IF; - lt := shift(lt); - END LOOP; - RETURN prod; - END "*"; - - FUNCTION "*" (arg1, arg2:UNSIGNED) RETURN UNSIGNED IS - VARIABLE ml : INTEGER := arg1'length + arg2'length; - VARIABLE lt : UNSIGNED(1 TO ml); - VARIABLE rt : UNSIGNED(1 TO ml); - VARIABLE prod : UNSIGNED(1 TO ml) := (OTHERS=>'0'); - BEGIN - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN rt'reverse_range LOOP - IF rt(i) = '1' THEN - prod := prod + lt; - END IF; - lt := shift(lt); - END LOOP; - RETURN prod; - END "*"; - - --//// Sign Extend //// - -- - -- Function sxt - -- - FUNCTION sxt( q : SIGNED; i : INTEGER ) RETURN SIGNED IS - VARIABLE qs : SIGNED (1 TO i); - VARIABLE qt : SIGNED (1 TO q'length); - BEGIN - qt := q; - IF i < q'length THEN - qs := qt( (q'length-i+1) TO qt'right); - ELSIF i > q'length THEN - qs := (OTHERS=>q(q'left)); - qs := qs(1 TO (i-q'length)) & qt; - ELSE - qs := qt; - END IF; - RETURN qs; - END; - - FUNCTION "*" (arg1, arg2:SIGNED) RETURN SIGNED IS - VARIABLE ml : INTEGER := arg1'length + arg2'length; - VARIABLE lt : SIGNED(1 TO ml); - VARIABLE rt : SIGNED(1 TO ml); - VARIABLE prod : SIGNED(1 TO ml) := (OTHERS=>'0'); - BEGIN - assert arg1'length > 1 AND arg2'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := sxt( arg1, ml ); - rt := sxt( arg2, ml ); - FOR i IN rt'reverse_range LOOP - IF rt(i) = '1' THEN - prod := prod + lt; - END IF; - lt := shift(lt); - END LOOP; - RETURN prod; - END "*"; - - FUNCTION rshift( v : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR IS - VARIABLE v1 : STD_ULOGIC_VECTOR( v'range ); - BEGIN - FOR i IN v'left TO v'right-1 LOOP - v1(i+1) := v(i); - END LOOP; - v1(v1'left) := '0'; - RETURN v1; - END rshift; - - FUNCTION hasx( v : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS - BEGIN - FOR i IN v'range LOOP - IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN - NULL; - ELSE - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END hasx; - - FUNCTION rshift( v : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR IS - VARIABLE v1 : STD_LOGIC_VECTOR( v'range ); - BEGIN - FOR i IN v'left TO v'right-1 LOOP - v1(i+1) := v(i); - END LOOP; - v1(v1'left) := '0'; - RETURN v1; - END rshift; - - FUNCTION hasx( v : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS - BEGIN - FOR i IN v'range LOOP - IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN - NULL; - ELSE - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END hasx; - - FUNCTION rshift( v : UNSIGNED ) RETURN UNSIGNED IS - VARIABLE v1 : UNSIGNED( v'range ); - BEGIN - FOR i IN v'left TO v'right-1 LOOP - v1(i+1) := v(i); - END LOOP; - v1(v1'left) := '0'; - RETURN v1; - END rshift; - - FUNCTION hasx( v : UNSIGNED ) RETURN BOOLEAN IS - BEGIN - FOR i IN v'range LOOP - IF v(i) = '0' OR v(i) = '1' OR v(i) = 'L' OR v(i) = 'H'THEN - NULL; - ELSE - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END hasx; - - FUNCTION rshift( v : SIGNED ) RETURN SIGNED IS - VARIABLE v1 : SIGNED( v'range ); - BEGIN - FOR i IN v'left TO v'right-1 LOOP - v1(i+1) := v(i); - END LOOP; - v1(v1'left) := '0'; - RETURN v1; - END rshift; - - FUNCTION "/" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN quote'range LOOP - quote(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - n := (OTHERS=>'0'); - n(n'right) := '1'; - WHILE rt <= lt LOOP - rt := shift(rt); - n := shift(n); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - n := rshift(n); - tmp := tmp + n; - END LOOP; - END IF; - quote := tmp(2 TO ml+1); - RETURN quote; - END "/"; - - FUNCTION "/" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN quote'range LOOP - quote(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - n := (OTHERS=>'0'); - n(n'right) := '1'; - WHILE rt <= lt LOOP - rt := shift(rt); - n := shift(n); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - n := rshift(n); - tmp := tmp + n; - END LOOP; - END IF; - quote := tmp(2 TO ml+1); - RETURN quote; - END "/"; - - FUNCTION "/" (l, r :UNSIGNED) RETURN UNSIGNED IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : UNSIGNED(0 TO ml+1); - VARIABLE rt : UNSIGNED(0 TO ml+1); - VARIABLE quote : UNSIGNED(1 TO ml); - VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN quote'range LOOP - quote(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - n := (OTHERS=>'0'); - n(n'right) := '1'; - WHILE rt <= lt LOOP - rt := shift(rt); - n := shift(n); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - n := rshift(n); - tmp := tmp + n; - END LOOP; - END IF; - quote := tmp(2 TO ml+1); - RETURN quote; - END "/"; - - FUNCTION "/" (l, r :SIGNED) RETURN SIGNED IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : SIGNED(0 TO ml+1); - VARIABLE rt : SIGNED(0 TO ml+1); - VARIABLE quote : SIGNED(1 TO ml); - VARIABLE tmp : SIGNED(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : SIGNED(0 TO ml+1) := (OTHERS=>'0'); - - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN quote'range LOOP - quote(i) := 'X'; - END LOOP; - ELSE - lt := sxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := sxt( r, ml+2 ); - n := (OTHERS=>'0'); - n(n'right) := '1'; - WHILE rt <= lt LOOP - rt := shift(rt); - n := shift(n); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - n := rshift(n); - tmp := tmp + n; - END LOOP; - END IF; - quote := tmp(2 TO ml+1); - RETURN quote; - END "/"; - - FUNCTION "MOD" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "MOD"; - - FUNCTION "MOD" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_LOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "MOD"; - - FUNCTION "MOD" (l, r :UNSIGNED) RETURN UNSIGNED IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : UNSIGNED(0 TO ml+1); - VARIABLE rt : UNSIGNED(0 TO ml+1); - VARIABLE quote : UNSIGNED(1 TO ml); - VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : UNSIGNED(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "MOD"; - - FUNCTION "REM" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_ULOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_ULOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_ULOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_ULOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "REM"; - - FUNCTION "REM" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE rt : STD_LOGIC_VECTOR(0 TO ml+1); - VARIABLE quote : STD_LOGIC_VECTOR(1 TO ml); - VARIABLE tmp : STD_LOGIC_VECTOR(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : STD_LOGIC_VECTOR(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "REM"; - - FUNCTION "REM" (l, r :UNSIGNED) RETURN UNSIGNED IS - - CONSTANT ml : INTEGER := maximum(l'length,r'length); - VARIABLE lt : UNSIGNED(0 TO ml+1); - VARIABLE rt : UNSIGNED(0 TO ml+1); - VARIABLE quote : UNSIGNED(1 TO ml); - VARIABLE tmp : UNSIGNED(0 TO ml+1) := (OTHERS=>'0'); - VARIABLE n : UNSIGNED(0 TO ml) := (OTHERS=>'0'); - - BEGIN - ASSERT NOT (r = "0") - REPORT "Attempted divide by ZERO" - SEVERITY ERROR; - IF hasx(l) OR hasx(r) THEN - FOR i IN lt'range LOOP - lt(i) := 'X'; - END LOOP; - ELSE - lt := zxt( l, ml+2 ); - WHILE lt >= r LOOP - rt := zxt( r, ml+2 ); - WHILE rt <= lt LOOP - rt := shift(rt); - END LOOP; - rt := rshift(rt); - lt := lt - rt; - END LOOP; - END IF; - RETURN lt(2 TO ml+1); - END "REM"; - - FUNCTION "**" (l, r :STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR IS - - VARIABLE return_vector : STD_ULOGIC_VECTOR(l'range) := (OTHERS=>'0'); - VARIABLE tmp : STD_ULOGIC_VECTOR(1 TO (2 * l'length)) := (OTHERS=>'0'); - CONSTANT lsh_l : INTEGER := l'length+1; - CONSTANT lsh_r : INTEGER := 2 * l'length; - VARIABLE pow : INTEGER; - - BEGIN - IF (hasx(l) OR hasx(r)) THEN - FOR i IN return_vector'range LOOP - return_vector(i) := 'X'; - END LOOP; - ELSE - pow := to_integer( r, 0 ); - tmp( tmp'right ) := '1'; - FOR i IN 1 TO pow LOOP - tmp := tmp(lsh_l TO lsh_r) * l; - END LOOP; - return_vector := tmp(lsh_l TO lsh_r); - END IF; - RETURN return_vector; - END "**"; - - FUNCTION "**" (l, r :STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS - - VARIABLE return_vector : STD_LOGIC_VECTOR(l'range) := (OTHERS=>'0'); - VARIABLE tmp : STD_LOGIC_VECTOR(1 TO (2 * l'length)) := (OTHERS=>'0'); - CONSTANT lsh_l : INTEGER := l'length+1; - CONSTANT lsh_r : INTEGER := 2 * l'length; - VARIABLE pow : INTEGER; - - BEGIN - IF (hasx(l) OR hasx(r)) THEN - FOR i IN return_vector'range LOOP - return_vector(i) := 'X'; - END LOOP; - ELSE - pow := to_integer( r, 0 ); - tmp( tmp'right ) := '1'; - FOR i IN 1 TO pow LOOP - tmp := tmp(lsh_l TO lsh_r) * l; - END LOOP; - return_vector := tmp(lsh_l TO lsh_r); - END IF; - RETURN return_vector; - END "**"; - - FUNCTION "**" (l, r :UNSIGNED) RETURN UNSIGNED IS - - VARIABLE return_vector : UNSIGNED(l'range) := (OTHERS=>'0'); - VARIABLE tmp : UNSIGNED(1 TO (2 * l'length)) := (OTHERS=>'0'); - CONSTANT lsh_l : INTEGER := l'length+1; - CONSTANT lsh_r : INTEGER := 2 * l'length; - VARIABLE pow : INTEGER; - - BEGIN - IF (hasx(l) OR hasx(r)) THEN - FOR i IN return_vector'range LOOP - return_vector(i) := 'X'; - END LOOP; - ELSE - pow := to_integer( r, 0 ); - tmp( tmp'right ) := '1'; - FOR i IN 1 TO pow LOOP - tmp := tmp(lsh_l TO lsh_r) * l; - END LOOP; - return_vector := tmp(lsh_l TO lsh_r); - END IF; - RETURN return_vector; - END "**"; - --- --- Absolute Value Functions --- - FUNCTION "abs" (arg1:SIGNED) RETURN SIGNED IS - constant len : integer := arg1'length; - VARIABLE answer, tmp : SIGNED( len-1 downto 0 ) := (others=>'0'); - VARIABLE index : integer := len; - BEGIN - assert arg1'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - IF hasx(arg1) THEN - answer := (OTHERS => 'X'); - ELSIF (arg1(arg1'left) = '0' OR arg1(arg1'left) = 'L') THEN - answer := arg1; - ELSE - tmp := arg1; - lp1 : FOR i IN answer'REVERSE_RANGE LOOP - IF (tmp(i) = '1' OR tmp(i) = 'H') THEN - index := i+1; - answer(i downto 0) := tmp(i downto 0); - exit; - END IF; - END LOOP lp1; - answer(len-1 downto index) := NOT tmp(len-1 downto index); - end if; - RETURN (answer); - END ; - --- --- Shift Left (arithmetic) Functions --- - - FUNCTION "sla" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_ulogic_vector(1 to len) := (others => arg1(arg1'right)); - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sla" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_logic_vector(1 to len) := (others => arg1(arg1'right)); - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sla" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : UNSIGNED(1 to len) := (others => arg1(arg1'right)); - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sla" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : SIGNED(1 to len) := (others => arg1(arg1'right)); - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - --- --- Shift Right (arithmetics) Functions --- - FUNCTION "sra" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_ulogic_vector(1 to len) := (others => arg1(arg1'left)); - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "sra" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_logic_vector(1 to len) := (others => arg1(arg1'left)); - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "sra" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : UNSIGNED(1 to len) := (others => arg1(arg1'left)); - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "sra" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : SIGNED(1 to len) := (others => arg1(arg1'left)); - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - --- --- Shift Left (logical) Functions --- - - FUNCTION "sll" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_ulogic_vector(1 to len) := (others =>'0'); - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sll" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_logic_vector(1 to len) := (others =>'0'); - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sll" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : UNSIGNED(1 to len) := (others =>'0'); - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - - FUNCTION "sll" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : SIGNED(1 to len) := (others =>'0'); - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(arg2+1 to len) & se(1 to arg2)); - END IF; - END ; - --- --- Shift Right (logical) Functions --- - FUNCTION "srl" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_ulogic_vector(1 to len) := (others => '0'); - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "srl" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : std_logic_vector(1 to len) := (others => '0'); - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "srl" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : UNSIGNED(1 to len) := (others => '0'); - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - - FUNCTION "srl" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT se : SIGNED(1 to len) := (others => '0'); - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (arg2 >= len) THEN - RETURN (se); - ELSIF (arg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (se(1 to arg2) & ans(1 to len-arg2)); - END IF; - END ; - --- --- Rotate Left (Logical) Functions --- - FUNCTION "rol" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(marg2+1 to len) & ans(1 to marg2)); - END IF; - END ; - - FUNCTION "rol" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(marg2+1 to len) & ans(1 to marg2)); - END IF; - END ; - - FUNCTION "rol" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(marg2+1 to len) & ans(1 to marg2)); - END IF; - END ; - - FUNCTION "rol" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(marg2+1 to len) & ans(1 to marg2)); - END IF; - END ; - --- --- Rotate Right (Logical) Functions --- - FUNCTION "ror" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : STD_ULOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); - END IF; - END ; - - FUNCTION "ror" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : STD_LOGIC_VECTOR(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); - END IF; - END ; - - FUNCTION "ror" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : UNSIGNED(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); - END IF; - END ; - - FUNCTION "ror" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED IS - CONSTANT len : INTEGER := arg1'length ; - CONSTANT marg2 : integer := arg2 mod len; - VARIABLE ans : SIGNED(1 to len) := arg1; - BEGIN - IF (marg2 = 0) THEN - RETURN (arg1); - ELSE - RETURN (ans(len-marg2+1 to len) & ans(1 to len-marg2)); - END IF; - END ; - --- --- Equal functions. --- - CONSTANT eq_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | - ); - - FUNCTION eq ( l, r : STD_LOGIC ) RETURN BOOLEAN IS - BEGIN - RETURN eq_table( l, r ); - END; - - FUNCTION eq ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN FALSE; - END IF; - END LOOP; - RETURN TRUE; - END; - - FUNCTION eq ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN FALSE; - END IF; - END LOOP; - RETURN TRUE; - END; - - FUNCTION eq ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN FALSE; - END IF; - END LOOP; - RETURN TRUE; - END; - - FUNCTION eq ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - RETURN (eq( lt, rt )); - END; - - FUNCTION "=" ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN FALSE; - END IF; - END LOOP; - RETURN TRUE; - END; - - FUNCTION "=" ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - RETURN (eq( lt, rt )); - END; - --- --- Not Equal function. --- - CONSTANT neq_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | - ); - - - FUNCTION ne ( l, r : STD_LOGIC ) RETURN BOOLEAN IS - BEGIN - RETURN neq_table( l, r ); - END; - - FUNCTION ne ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF ne( lt(i), rt(i) ) THEN - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION ne ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF ne( lt(i), rt(i) ) THEN - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION ne ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF ne( lt(i), rt(i) ) THEN - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION ne ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - RETURN (ne( lt, rt )); - END; - - FUNCTION "/=" ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF ne( lt(i), rt(i) ) THEN - RETURN TRUE; - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION "/=" ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - RETURN (ne( lt, rt )); - END; - --- --- Less Than functions. --- - CONSTANT ltb_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 1 | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | H | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | - ); - - FUNCTION lt ( l, r : STD_LOGIC ) RETURN BOOLEAN IS - BEGIN - RETURN ltb_table( l, r ); - END; - - FUNCTION lt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt : STD_ULOGIC_VECTOR ( 1 TO ml ); - VARIABLE rtt : STD_ULOGIC_VECTOR ( 1 TO ml ); - BEGIN - ltt := zxt( l, ml ); - rtt := zxt( r, ml ); - FOR i IN ltt'range LOOP - IF NOT eq( ltt(i), rtt(i) ) THEN - RETURN lt( ltt(i), rtt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION lt ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt : STD_LOGIC_VECTOR ( 1 TO ml ); - VARIABLE rtt : STD_LOGIC_VECTOR ( 1 TO ml ); - BEGIN - ltt := zxt( l, ml ); - rtt := zxt( r, ml ); - FOR i IN ltt'range LOOP - IF NOT eq( ltt(i), rtt(i) ) THEN - RETURN lt( ltt(i), rtt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION lt ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt : UNSIGNED ( 1 TO ml ); - VARIABLE rtt : UNSIGNED ( 1 TO ml ); - BEGIN - ltt := zxt( l, ml ); - rtt := zxt( r, ml ); - FOR i IN ltt'range LOOP - IF NOT eq( ltt(i), rtt(i) ) THEN - RETURN lt( ltt(i), rtt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION lt ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt, rtt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - ltt := (OTHERS => l(l'left)) ; - ltt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rtt := (OTHERS => r(r'left)) ; - rtt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(ltt(ltt'left) = '1' AND rtt(rtt'left) = '0') THEN - RETURN(TRUE) ; - ELSIF(ltt(ltt'left) = '0' AND rtt(rtt'left) = '1') THEN - RETURN(FALSE) ; - ELSE - RETURN (lt( ltt, rtt )); - END IF ; - END; - - FUNCTION "<" ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt : UNSIGNED ( 1 TO ml ); - VARIABLE rtt : UNSIGNED ( 1 TO ml ); - BEGIN - ltt := zxt( l, ml ); - rtt := zxt( r, ml ); - FOR i IN ltt'range LOOP - IF NOT eq( ltt(i), rtt(i) ) THEN - RETURN lt( ltt(i), rtt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION "<" ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE ltt, rtt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - ltt := (OTHERS => l(l'left)) ; - ltt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rtt := (OTHERS => r(r'left)) ; - rtt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(ltt(ltt'left) = '1' AND rtt(rtt'left) = '0') THEN - RETURN(TRUE) ; - ELSIF(ltt(ltt'left) = '0' AND rtt(rtt'left) = '1') THEN - RETURN(FALSE) ; - ELSE - RETURN (lt( ltt, rtt )); - END IF ; - END; - --- --- Greater Than functions. --- - CONSTANT gtb_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 0 | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | L | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H | - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D | - ); - - FUNCTION gt ( l, r : std_logic ) RETURN BOOLEAN IS - BEGIN - RETURN gtb_table( l, r ); - END ; - - FUNCTION gt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN gt( lt(i), rt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION gt ( l,r : STD_LOGIC_VECTOR ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : STD_LOGIC_VECTOR ( 1 TO ml ); - VARIABLE rt : STD_LOGIC_VECTOR ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN gt( lt(i), rt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION gt ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN gt( lt(i), rt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION gt ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(FALSE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(TRUE) ; - ELSE - RETURN (gt( lt, rt )); - END IF ; - END; - - FUNCTION ">" ( l,r : UNSIGNED ) RETURN BOOLEAN IS - CONSTANT ml : INTEGER := maximum( l'length, r'length ); - VARIABLE lt : UNSIGNED ( 1 TO ml ); - VARIABLE rt : UNSIGNED ( 1 TO ml ); - BEGIN - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'range LOOP - IF NOT eq( lt(i), rt(i) ) THEN - RETURN gt( lt(i), rt(i) ); - END IF; - END LOOP; - RETURN FALSE; - END; - - FUNCTION ">" ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(FALSE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(TRUE) ; - ELSE - RETURN (gt( lt, rt )); - END IF ; - END; - --- --- Less Than or Equal to functions. --- - CONSTANT leb_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | U | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | X | - ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | 0 | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | Z | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | W | - ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | L | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H | - ( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ) -- | D | - ); - - FUNCTION le ( l, r : std_logic ) RETURN BOOLEAN IS - BEGIN - RETURN leb_table( l, r ); - END ; - - TYPE std_ulogic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N'); - TYPE std_ulogic_fuzzy_state_table IS ARRAY ( std_ulogic, std_ulogic ) OF std_ulogic_fuzzy_state; - - CONSTANT le_fuzzy_table : std_ulogic_fuzzy_state_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U' ), -- | U | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | X | - ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | 0 | - ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | W | - ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | L | - ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | H | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ) -- | D | - ); - - FUNCTION le ( L,R : std_ulogic_vector ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : std_ulogic_vector ( 1 to ml ); - VARIABLE rt : std_ulogic_vector ( 1 to ml ); - VARIABLE res : std_ulogic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := le_fuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - TYPE std_logic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N'); - TYPE std_logic_fuzzy_state_table IS ARRAY ( std_logic, std_logic ) OF std_logic_fuzzy_state; - - CONSTANT le_lfuzzy_table : std_logic_fuzzy_state_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U' ), -- | U | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | X | - ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | 0 | - ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ), -- | W | - ( 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N' ), -- | L | - ( 'U', 'X', 'F', 'N', 'X', 'X', 'F', 'N', 'X' ), -- | H | - ( 'U', 'X', 'X', 'N', 'X', 'X', 'X', 'N', 'X' ) -- | D | - ); - - FUNCTION le ( L,R : std_logic_vector ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : std_logic_vector ( 1 to ml ); - VARIABLE rt : std_logic_vector ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := le_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION le ( L,R : UNSIGNED ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := le_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION le (l, r:SIGNED) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(TRUE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(FALSE) ; - ELSE - RETURN (le( lt, rt )); - END IF ; - END; - - FUNCTION "<=" ( L,R : UNSIGNED ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := le_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION "<=" (l, r:SIGNED) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(TRUE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(FALSE) ; - ELSE - RETURN (le( lt, rt )); - END IF ; - END; - --- --- Greater Than or Equal to functions. --- - CONSTANT geb_table : stdlogic_boolean_table := ( - -- ---------------------------------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------------------------------- - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | U | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | X | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 | - ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | 1 | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | Z | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | W | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L | - ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE ), -- | H | - ( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ) -- | D | - ); - - FUNCTION ge ( l, r : std_logic ) RETURN BOOLEAN IS - BEGIN - RETURN geb_table( l, r ); - END ; - - CONSTANT ge_fuzzy_table : std_ulogic_fuzzy_state_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X | - ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 | - ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W | - ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L | - ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D | - ); - - FUNCTION ge ( L,R : std_ulogic_vector ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : std_ulogic_vector ( 1 to ml ); - VARIABLE rt : std_ulogic_vector ( 1 to ml ); - VARIABLE res : std_ulogic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := ge_fuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - CONSTANT ge_lfuzzy_table : std_logic_fuzzy_state_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X | - ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 | - ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W | - ( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L | - ( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H | - ( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D | - ); - - FUNCTION ge ( L,R : std_logic_vector ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : std_logic_vector ( 1 to ml ); - VARIABLE rt : std_logic_vector ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := ge_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION ge ( L,R : UNSIGNED ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := ge_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION ge ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(FALSE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(TRUE) ; - ELSE - RETURN (ge( lt, rt )); - END IF ; - END; - - FUNCTION ">=" ( L,R : UNSIGNED ) RETURN boolean IS - CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : std_logic_fuzzy_state; - begin - lt := zxt( l, ml ); - rt := zxt( r, ml ); - FOR i IN lt'RANGE LOOP - res := ge_lfuzzy_table( lt(i), rt(i) ); - CASE res IS - WHEN 'U' => RETURN FALSE; - WHEN 'X' => RETURN FALSE; - WHEN 'T' => RETURN TRUE; - WHEN 'F' => RETURN FALSE; - WHEN OTHERS => null; - END CASE; - END LOOP; - RETURN TRUE; - end ; - - FUNCTION ">=" ( l,r : SIGNED ) RETURN BOOLEAN IS - CONSTANT len : INTEGER := maximum( l'length, r'length ); - VARIABLE lt, rt : UNSIGNED ( len-1 downto 0 ) := (OTHERS => '0'); - BEGIN - assert l'length > 1 AND r'length > 1 - report "SIGNED vector must be atleast 2 bits wide" - severity ERROR; - lt := (OTHERS => l(l'left)) ; - lt(l'length - 1 DOWNTO 0) := UNSIGNED(l); - rt := (OTHERS => r(r'left)) ; - rt(r'length - 1 DOWNTO 0) := UNSIGNED(r); - IF(lt(lt'left) = '1' AND rt(rt'left) = '0') THEN - RETURN(FALSE) ; - ELSIF(lt(lt'left) = '0' AND rt(rt'left) = '1') THEN - RETURN(TRUE) ; - ELSE - RETURN (ge( lt, rt )); - END IF ; - END; - - ------------------------------------------------------------------------------- - -- Logical Operations - ------------------------------------------------------------------------------- - - -- truth table for "and" function - CONSTANT and_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | - ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | - ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | D | - ); - - -- truth table for "or" function - CONSTANT or_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | - ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | D | - ); - - - -- truth table for "xor" function - CONSTANT xor_table : stdlogic_table := ( - -- ---------------------------------------------------- - -- | U X 0 1 Z W L H D | | - -- ---------------------------------------------------- - ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | - ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | - ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | D | - ); - - -- truth table for "not" function - CONSTANT not_table: stdlogic_1D := - -- ------------------------------------------------- - -- | U X 0 1 Z W L H D | - -- ------------------------------------------------- - ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ); - - FUNCTION "and" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := and_table( lt(i), rt(i) ); - END LOOP; - RETURN res; - end "and"; - - FUNCTION "nand" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := not_table( and_table( lt(i), rt(i) ) ); - END LOOP; - RETURN res; - end "nand"; - - FUNCTION "or" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := or_table( lt(i), rt(i) ); - END LOOP; - RETURN res; - end "or"; - - FUNCTION "nor" ( arg1,arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := not_table( or_table( lt(i), rt(i) ) ); - END LOOP; - RETURN res; - end "nor"; - - FUNCTION "xor" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := xor_table( lt(i), rt(i) ); - END LOOP; - RETURN res; - end "xor"; - - FUNCTION "not" ( arg1 : UNSIGNED ) RETURN UNSIGNED IS - VARIABLE result : UNSIGNED ( arg1'RANGE ) := (Others => 'X'); - begin - for i in result'range loop - result(i) := not_table( arg1(i) ); - end loop; - return result; - end "not"; - - FUNCTION "and" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a and b); - RETURN (answer); - end "and"; - - FUNCTION "nand" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a nand b); - RETURN (answer); - end "nand"; - - FUNCTION "or" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a or b); - RETURN (answer); - end "or"; - - FUNCTION "nor" ( arg1,arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a nor b); - RETURN (answer); - end "nor"; - - FUNCTION "xor" ( arg1, arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a xor b); - RETURN (answer); - end "xor"; - - FUNCTION "not" ( arg1 : SIGNED ) RETURN SIGNED IS - VARIABLE result : SIGNED ( arg1'RANGE ) := (Others => 'X'); - begin - for i in result'range loop - result(i) := not_table( arg1(i) ); - end loop; - return result; - end "not"; - - FUNCTION "xnor" ( arg1, arg2 : std_ulogic_vector ) RETURN std_ulogic_vector IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : std_ulogic_vector ( 1 to ml ); - VARIABLE rt : std_ulogic_vector ( 1 to ml ); - VARIABLE res : std_ulogic_vector ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := not_table( xor_table( lt(i), rt(i) ) ); - END LOOP; - RETURN res; - end "xnor"; - - FUNCTION "xnor" ( arg1, arg2 : std_logic_vector ) RETURN std_logic_vector IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : std_logic_vector ( 1 to ml ); - VARIABLE rt : std_logic_vector ( 1 to ml ); - VARIABLE res : std_logic_vector ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := not_table( xor_table( lt(i), rt(i) ) ); - END LOOP; - RETURN res; - end "xnor"; - - FUNCTION "xnor" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED IS - CONSTANT ml : integer := maximum( arg1'LENGTH, arg2'LENGTH ); - VARIABLE lt : UNSIGNED ( 1 to ml ); - VARIABLE rt : UNSIGNED ( 1 to ml ); - VARIABLE res : UNSIGNED ( 1 to ml ); - begin - lt := zxt( arg1, ml ); - rt := zxt( arg2, ml ); - FOR i IN res'RANGE LOOP - res(i) := not_table( xor_table( lt(i), rt(i) ) ); - END LOOP; - RETURN res; - end "xnor"; - - FUNCTION "xnor" ( arg1, arg2 : SIGNED ) RETURN SIGNED IS - CONSTANT len : INTEGER := maximum(arg1'length,arg2'length) ; - VARIABLE a,b : UNSIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - VARIABLE answer : SIGNED(len-1 DOWNTO 0) := (OTHERS => '0') ; - BEGIN - a := (OTHERS => arg1(arg1'left)) ; - a(arg1'length - 1 DOWNTO 0) := UNSIGNED(arg1); - b := (OTHERS => arg2(arg2'left)) ; - b(arg2'length - 1 DOWNTO 0) := UNSIGNED(arg2); - answer := SIGNED(a xnor b); - RETURN (answer); - end "xnor"; - -END ; diff --git a/libraries/std/env-body.vhdl b/libraries/std/env-body.vhdl new file mode 100644 index 000000000..d36519fc9 --- /dev/null +++ b/libraries/std/env-body.vhdl @@ -0,0 +1,65 @@ +-- Std.Env package declaration. This file is part of GHDL. +-- This file was written from the clause 14.3 of the VHDL LRM. +-- Copyright (C) 2014 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. + +package body Env is + procedure control_simulation (Is_Stop : Boolean; + Has_Status : Boolean; + Status : Integer); + attribute foreign of control_simulation : procedure is "GHDL intrinsic"; + + procedure control_simulation (Is_Stop : Boolean; + Has_Status : Boolean; + Status : Integer) is + begin + assert false report "must not be called" severity failure; + end control_simulation; + + procedure Stop (Status : Integer) is + begin + control_simulation (True, True, Status); + end Stop; + + procedure Stop is + begin + control_simulation (True, False, -1); + end Stop; + + procedure Finish (status : integer) is + begin + control_simulation (False, True, Status); + end Finish; + + procedure Finish is + begin + control_simulation (False, False, -1); + end Finish; + + function Get_Resolution_Limit return Delay_Length; + attribute foreign of Get_Resolution_Limit : function is "GHDL intrinsic"; + + function Get_Resolution_Limit return Delay_Length is + begin + assert false report "must not be called" severity failure; + end Get_Resolution_Limit; + + function Resolution_Limit return Delay_Length is + begin + return Get_Resolution_Limit; + end Resolution_Limit; +end package body Env; diff --git a/libraries/std/env_body.vhdl b/libraries/std/env_body.vhdl deleted file mode 100644 index d36519fc9..000000000 --- a/libraries/std/env_body.vhdl +++ /dev/null @@ -1,65 +0,0 @@ --- Std.Env package declaration. This file is part of GHDL. --- This file was written from the clause 14.3 of the VHDL LRM. --- Copyright (C) 2014 Tristan Gingold --- --- GHDL is free software; you can redistribute it and/or modify it under --- the terms of the GNU General Public License as published by the Free --- Software Foundation; either version 2, or (at your option) any later --- version. --- --- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY --- WARRANTY; without even the implied warranty of MERCHANTABILITY or --- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --- for more details. --- --- You should have received a copy of the GNU General Public License --- along with GCC; see the file COPYING. If not, write to the Free --- Software Foundation, 59 Temple Place - Suite 330, Boston, MA --- 02111-1307, USA. - -package body Env is - procedure control_simulation (Is_Stop : Boolean; - Has_Status : Boolean; - Status : Integer); - attribute foreign of control_simulation : procedure is "GHDL intrinsic"; - - procedure control_simulation (Is_Stop : Boolean; - Has_Status : Boolean; - Status : Integer) is - begin - assert false report "must not be called" severity failure; - end control_simulation; - - procedure Stop (Status : Integer) is - begin - control_simulation (True, True, Status); - end Stop; - - procedure Stop is - begin - control_simulation (True, False, -1); - end Stop; - - procedure Finish (status : integer) is - begin - control_simulation (False, True, Status); - end Finish; - - procedure Finish is - begin - control_simulation (False, False, -1); - end Finish; - - function Get_Resolution_Limit return Delay_Length; - attribute foreign of Get_Resolution_Limit : function is "GHDL intrinsic"; - - function Get_Resolution_Limit return Delay_Length is - begin - assert false report "must not be called" severity failure; - end Get_Resolution_Limit; - - function Resolution_Limit return Delay_Length is - begin - return Get_Resolution_Limit; - end Resolution_Limit; -end package body Env; diff --git a/libraries/std/textio-body.vhdl b/libraries/std/textio-body.vhdl new file mode 100644 index 000000000..d01cb8bad --- /dev/null +++ b/libraries/std/textio-body.vhdl @@ -0,0 +1,1558 @@ +-- Std.Textio package body. This file is part of GHDL. +-- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING3. If not see +-- . + +package body textio is + attribute foreign : string; --V87 + +--START-V08 + -- LRM08 16.4 + -- The JUSTIFY operation formats a string value within a field that is at + -- least at long as required to contain the value. Parameter FIELD + -- specifies the desired field width. Since the actual field width will + -- always be at least large enough to hold the string value, the default + -- value 0 for the FIELD parameter has the effect of causing the string + -- value to be contained in a field of exactly the right widteh (i.e., no + -- additional leading or tailing spaces). Parameter JUSTIFIED specified + -- whether the string value is to be right- or left-justified within the + -- field; the default is right-justified. If the FIELD parameter describes + -- a field width larger than the number of characters in the string value, + -- space characters are used to fill the remaining characters in the field. + -- + -- TG: Note that the bounds of the result are not specified! + function Justify (Value: String; + Justified : Side := Right; + Field: Width := 0 ) return String + is + constant len : Width := Value'Length; + begin + if Field <= Len then + return Value; + else + case Justified is + when Right => + return (1 to Field - Len => ' ') & Value; + when Left => + return Value & (1 to Field - Len => ' '); + end case; + end if; + end Justify; +--END-V08 + + -- output routines for standard types + + -- TIME_NAMES associates time units with textual names. + -- Textual names are in lower cases, since according to LRM93 14.3: + -- when written, the identifier is expressed in lowercase characters. + -- The length of the names are 3 characters, the last one may be a space + -- for 2 characters long names. + type time_unit is + record + val : time; + name : string (1 to 3); + end record; + type time_names_type is array (1 to 8) of time_unit; + constant time_names : time_names_type := + ((fs, "fs "), (ps, "ps "), (ns, "ns "), (us, "us "), + (ms, "ms "), (sec, "sec"), (min, "min"), (hr, "hr ")); + + -- Non breaking space character. --!V87 + constant nbsp : character := character'val (160); --!V87 + + function is_whitespace (c : character) return Boolean is + begin + case c is + when ' ' + | NBSP --!V87 + | HT => + return True; + when others => + return False; + end case; + end is_Whitespace; + + procedure writeline (variable f: out text; l: inout line) is --V87 + procedure writeline (file f: text; l: inout line) is --!V87 + begin + if l = null then + -- LRM93 14.3 + -- If parameter L contains a null access value at the start of the call, + -- the a null string is written to the file. + null; + else + -- LRM93 14.3 + -- Procedure WRITELINE causes the current line designated by parameter L + -- to be written to the file and returns with the value of parameter L + -- designating a null string. + write (f, l.all); + deallocate (l); + l := new string'(""); + end if; + write (f, (1 => LF)); + end writeline; + +--START-V08 + procedure Tee (file f : Text; L : inout LINE) is + begin + -- LRM08 16.4 Package TEXTIO + -- The procedure TEE additionally causes the current line to be written + -- to the file OUTPUT. + if l = null then + null; + else + write (f, l.all); + write (Output, l.all); + deallocate (l); + l := new string'(""); + end if; + write (f, (1 => LF)); + write (output, (1 => LF)); + end Tee; +--END-V08 + + procedure write + (l: inout line; value: in string; + justified: in side := right; field: in width := 0) + is + variable length: natural; + variable nl: line; + begin + -- l can be null. + if l = null then + length := 0; + else + length := l.all'length; + end if; + if value'length < field then + nl := new string (1 to length + field); + if length /= 0 then + nl (1 to length) := l.all; + end if; + if justified = right then + nl (length + 1 to length + field - value'length) := (others => ' '); + nl (nl.all'high - value'length + 1 to nl.all'high) := value; + else + nl (length + 1 to length + value'length) := value; + nl (length + value'length + 1 to nl.all'high) := (others => ' '); + end if; + else + nl := new string (1 to length + value'length); + if length /= 0 then + nl (1 to length) := l.all; + end if; + nl (length + 1 to nl.all'high) := value; + end if; + deallocate (l); + l := nl; + end write; + + procedure write + (l: inout line; value: in integer; + justified: in side := right; field: in width := 0) + is + variable str: string (11 downto 1); + variable val: integer := value; + variable digit: natural; + variable index: natural := 0; + begin + -- Note: the absolute value of VAL cannot be directly taken, since + -- it may be greather that the maximum value of an INTEGER. + loop + -- LRM93 7.2.6 + -- (A rem B) has the sign of A and an absolute value less then + -- the absoulte value of B. + digit := abs (val rem 10); + val := val / 10; + index := index + 1; + str (index) := character'val(48 + digit); + exit when val = 0; + end loop; + if value < 0 then + index := index + 1; + str(index) := '-'; + end if; + write (l, str (index downto 1), justified, field); + end write; + + procedure write + (l: inout line; value: in boolean; + justified: in side := right; field: in width := 0) + is + begin + if value then + write (l, string'("TRUE"), justified, field); + else + write (l, string'("FALSE"), justified, field); + end if; + end write; + + procedure write + (l: inout line; value: in character; + justified: in side := right; field: in width := 0) + is + variable str: string (1 to 1); + begin + str (1) := value; + write (l, str, justified, field); + end write; + + function bit_to_char (value : in bit) return character is + begin + case value is + when '0' => + return '0'; + when '1' => + return '1'; + end case; + end bit_to_char; + + procedure write + (l: inout line; value: in bit; + justified: in side := right; field: in width := 0) + is + variable str : string (1 to 1); + begin + str (1) := bit_to_char (value); + write (l, str, justified, field); + end write; + + procedure write + (l: inout line; value: in bit_vector; + justified: in side := right; field: in width := 0) + is + constant length : natural := value'length; + alias n_value : bit_vector (1 to value'length) is value; + variable str : string (1 to length); + begin + for i in str'range loop + str (i) := bit_to_char (n_value (i)); + end loop; + write (l, str, justified, field); + end write; + + procedure write + (l: inout line; value : in time; + justified: in side := right; field: in width := 0; unit : in TIME := ns) + is + -- Copy of VALUE on which we are working. + variable val : time := value; + + -- Copy of UNIT on which we are working. + variable un : time := unit; + + -- Digit extract from VAL/UN. + variable d : integer; -- natural range 0 to 9; + + -- Index for unit name. + variable n : integer; + + -- Result. + variable str : string (1 to 28); + + -- Current character in RES. + variable pos : natural := 1; + + -- Add a character to STR. + procedure add_char (c : character) is + begin + str (pos) := c; + pos := pos + 1; + end add_char; + begin + -- Note: + -- Care is taken to avoid overflow. Time may be 64 bits while integer + -- may be only 32 bits. + + -- Handle sign. + -- Note: VAL cannot be negated since its range may be not symetric + -- around 0. + if val < 0 ns then + add_char ('-'); + end if; + + -- Search for the first digit. + -- Note: we must start from unit, since all units are not a power of 10. + -- Note: UN can be multiplied only after we know it is possible. This + -- is a to avoid overflow. + if un <= 0 fs then + assert false report "UNIT argument is not positive" severity error; + un := 1 ns; + end if; + while val / 10 >= un or val / 10 <= -un loop + un := un * 10; + end loop; + + -- Extract digits one per one. + loop + d := val / un; + add_char (character'val (abs d + character'pos ('0'))); + val := val - d * un; + exit when val = 0 ns and un <= unit; + if un = unit then + add_char ('.'); + end if; + -- Stop as soon as precision will be lost. + -- This can happen only for hr and min. + -- FIXME: change the algorithm to display all the digits. + exit when (un / 10) * 10 /= un; + un := un / 10; + end loop; + + add_char (' '); + + -- Search the time unit name in the time table. + n := 0; + for i in time_names'range loop + if time_names (i).val = unit then + n := i; + exit; + end if; + end loop; + assert n /= 0 report "UNIT argument is not a unit name" severity error; + if n = 0 then + add_char ('?'); + else + add_char (time_names (n).name (1)); + add_char (time_names (n).name (2)); + if time_names (n).name (3) /= ' ' then + add_char (time_names (n).name (3)); + end if; + end if; + + -- Write the result. + write (l, str (1 to pos - 1), justified, field); + end write; + + procedure textio_write_real + (s : out string; len : out natural; value: real; ndigits : natural); + + attribute foreign of textio_write_real : procedure is "GHDL intrinsic"; + + procedure textio_write_real + (s : out string; len : out natural; value: real; ndigits : natural) is + begin + assert false report "must not be called" severity failure; + end textio_write_real; + + -- Parameter DIGITS specifies how many digits to the right of the decimal + -- point are to be output when writing a real number; the default value 0 + -- indicates that the number should be output in standard form, consisting + -- of a normalized mantissa plus exponent (e.g., 1.079236E23). If DIGITS is + -- nonzero, then the real number is output as an integer part followed by + -- '.' followed by the fractional part, using the specified number of digits + -- (e.g., 3.14159). + -- Note: Nan, +Inf, -Inf are not to be considered, since these numbers are + -- not in the bounds defined by any real range. + procedure write (L: inout line; value: in real; + justified: in side := right; field: in width := 0; + digits: in natural := 0) + is + -- STR contains the result of the conversion. + variable str : string (1 to 320); + + variable len : natural; + begin + textio_write_real (str, len, value, digits); + assert len <= str'length severity failure; + + write (l, str (1 to len), justified, field); + end write; + +--START-V08 + procedure Owrite (L : inout line; value : in Bit_Vector; + Justified : in Side := Right; Field : in Width := 0) is + begin + write (l, to_ostring (value), justified, field); + end Owrite; + + procedure Hwrite (L : inout line; value : in Bit_Vector; + Justified : in Side := Right; Field : in Width := 0) is + begin + write (l, to_hstring (value), justified, field); + end Hwrite; +--END-V08 + + procedure untruncated_text_read --V87 + (variable f : text; str : out string; len : out natural); --V87 + procedure untruncated_text_read --!V87 + (file f : text; str : out string; len : out natural); --!V87 + + attribute foreign of untruncated_text_read : procedure is "GHDL intrinsic"; + + procedure untruncated_text_read + (variable f : text; str : out string; len : out natural) is --V87 + (file f : text; str : out string; len : out natural) is --!V87 + begin + assert false report "must not be called" severity failure; + end untruncated_text_read; + + procedure readline (variable f: in text; l: inout line) --V87 + procedure readline (file f: text; l: inout line) --!V87 + is + variable len, nlen, posn : natural; + variable nl, old_l : line; + variable str : string (1 to 128); + variable is_eol : boolean; + begin + -- LRM93 14.3 + -- If parameter L contains a non-null access value at the start of the + -- call, the object designated by that value is deallocated before the + -- new object is created. + if l /= null then + deallocate (l); + end if; + + -- End of file is not expected. The user should check endfile before + -- calling readline. + assert not endfile (f) + report "eof in std.textio.readline" severity failure; + + -- We read the input in 128-byte chunks. + -- We keep reading until we reach a newline or there is no more input. + -- The loop invariant is that old_l is allocated and contains the + -- previous chunks read, and posn = old_l.all'length. + posn := 0; + loop + untruncated_text_read (f, str, len); + exit when len = 0; + if str (len) = LF or str (len) = CR then + -- LRM 14.3 + -- The representation of the line does not contain the representation + -- of the end of the line. + is_eol := true; + len := len - 1; + -- End of line is any of LF/CR/CR+LF/LF+CR. + if len > 0 and (str (len) = LF or str (len) = CR) then + len := len - 1; + end if; + elsif endfile (f) then + is_eol := true; + else + is_eol := false; + end if; + l := new string (1 to posn + len); + if old_l /= null then + l (1 to posn) := old_l (1 to posn); + deallocate (old_l); + end if; + l (posn + 1 to posn + len) := str (1 to len); + exit when is_eol; + posn := posn + len; + old_l := l; + end loop; + end readline; + + -- Replaces L with L (LEFT to/downto L'RIGHT) + procedure trim (l : inout line; left : natural) + is + variable nl : line; + begin + if l = null then + return; + end if; + if l'left < l'right then + -- Ascending. + if left > l'right then + nl := new string'(""); + else + nl := new string (left to l'right); +-- nl := new string (1 to l'right + 1 - left); + nl.all := l (left to l'right); + end if; + else + -- Descending + if left < l'right then + nl := new string'(""); + else + nl := new string (left downto l'right); +-- nl := new string (left - l'right + 1 downto 1); + nl.all := l (left downto l'right); + end if; + end if; + deallocate (l); + l := nl; + end trim; + + -- Replaces L with L (LEFT + 1 to L'RIGHT or LEFT - 1 downto L'RIGHT) + procedure trim_next (l : inout line; left : natural) + is + variable nl : line; + begin + if l = null then + return; + end if; + if l'left < l'right then + -- Ascending. + trim (l, left + 1); + else + -- Descending + trim (l, left - 1); + end if; + end trim_next; + + function to_lower (c : character) return character is + begin + if c >= 'A' and c <= 'Z' then + return character'val (character'pos (c) + 32); + else + return c; + end if; + end to_lower; + + procedure read (l: inout line; value: out character; good: out boolean) + is + variable nl : line; + begin + if l = null or l'length = 0 then + good := false; + else + value := l (l'left); + trim_next (l, l'left); + good := true; + end if; + end read; + + procedure read (l: inout line; value: out character) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "character read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out bit; good: out boolean) + is + begin + good := false; + for i in l'range loop + case l(i) is + when ' ' + | NBSP --!V87 + | HT => + null; + when '1' => + value := '1'; + good := true; + trim_next (l, i); + return; + when '0' => + value := '0'; + good := true; + trim_next (l, i); + return; + when others => + return; + end case; + end loop; + return; + end read; + + procedure read (l: inout line; value: out bit) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "bit read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out bit_vector; good: out boolean) + is + -- Number of bit to parse. + variable len : natural; + + variable pos, last : natural; + variable res : bit_vector (1 to value'length); + + -- State of the previous byte: + -- LEADING: blank before the bit vector. + -- FOUND: bit of the vector. + type state_type is (leading, found); + variable state : state_type; + begin + -- Initialization. + len := value'length; + if len = 0 then + -- If VALUE is a nul array, return now. + -- L stay unchanged. + -- FIXME: should blanks be removed ? + good := true; + return; + end if; + good := false; + state := leading; + pos := res'left; + for i in l'range loop + case l(i) is + when ' ' + | NBSP --!V87 + | HT => + case state is + when leading => + null; + when found => + return; + end case; + when '1' | '0' => + case state is + when leading => + state := found; + when found => + null; + end case; + if l(i) = '0' then + res (pos) := '0'; + else + res (pos) := '1'; + end if; + pos := pos + 1; + len := len - 1; + last := i; + exit when len = 0; + when others => + return; + end case; + end loop; + + if len /= 0 then + -- Not enough bits. + return; + end if; + + -- Note: if LEN = 0, then FIRST and LAST have been set. + good := true; + value := res; + trim_next (l, last); + return; + end read; + + procedure read (l: inout line; value: out bit_vector) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "bit_vector read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out boolean; good: out boolean) + is + -- State: + -- BLANK: space are being scaned. + -- L_TF : T(rue) or F(alse) has been scanned. + -- L_RA : (t)R(ue) or (f)A(lse) has been scanned. + -- L_UL : (tr)U(e) or (fa)L(se) has been scanned. + -- L_ES : (tru)E or (fal)S(e) has been scanned. + type state_type is (blank, l_tf, l_ra, l_ul, l_es); + variable state : state_type; + + -- Set to TRUE if T has been scanned, to FALSE if F has been scanned. + variable res : boolean; + + variable c : character; + begin + -- By default, it is a failure. + good := false; + state := blank; + for i in l'range loop + c := l (i); + case state is + when blank => + if is_whitespace (c) then + null; + elsif c = 'f' or c = 'T' then + res := true; + state := l_tf; + elsif c = 'f' or c = 'F' then + res := false; + state := l_tf; + else + return; + end if; + when l_tf => + if res = true and (c = 'r' or c = 'R') then + state := l_ra; + elsif res = false and (c = 'a' or C = 'A') then + state := l_ra; + else + return; + end if; + when l_ra => + if res = true and (c = 'u' or C = 'U') then + state := l_ul; + elsif res = false and (c = 'l' or c = 'L') then + state := l_ul; + else + return; + end if; + when l_ul => + if res = true and (c = 'e' or c = 'E') then + trim_next (l, i); + good := true; + value := true; + return; + elsif res = false and (c = 's' or c = 'S') then + state := l_es; + else + return; + end if; + when l_es => + if res = false and (c = 'e' or c = 'E') then + trim_next (l, i); + good := true; + value := false; + return; + else + return; + end if; + end case; + end loop; + return; + end read; + + procedure read (l: inout line; value: out boolean) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "boolean read failure" + severity failure; + end read; + + function char_to_nat (c : character) return natural + is + begin + return character'pos (c) - character'pos ('0'); + end char_to_nat; + + procedure read (l: inout line; value: out integer; good: out boolean) + is + variable val : integer; + variable d : natural; + + type state_t is (leading, sign, digits); + variable cur_state : state_t := leading; + begin + val := 1; + for i in l'range loop + case cur_state is + when leading => + case l(i) is + when ' ' + | NBSP --!V87 + | ht => + null; + when '+' => + cur_state := sign; + when '-' => + val := -1; + cur_state := sign; + when '0' to '9' => + val := char_to_nat (l(i)); + cur_state := digits; + when others => + good := false; + return; + end case; + when sign => + case l(i) is + when '0' to '9' => + val := val * char_to_nat (l(i)); + cur_state := digits; + when others => + good := false; + return; + end case; + when digits => + case l(i) is + when '0' to '9' => + d := char_to_nat (l(i)); + val := val * 10; + if val < 0 then + val := val - d; + else + val := val + d; + end if; + when others => + trim (l, i); + good := true; + value := val; + return; + end case; + end case; + end loop; + deallocate (l); + l := new string'(""); + if cur_state /= leading then + good := true; + value := val; + else + good := false; + end if; + end read; + + procedure read (l: inout line; value: out integer) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "integer read failure" + severity failure; + end read; + + function textio_read_real (s : string) return real; + + attribute foreign of textio_read_real : function is "GHDL intrinsic"; + + function textio_read_real (s : string) return real is + begin + assert false report "must not be called" severity failure; + return 0.0; + end textio_read_real; + + procedure read (l: inout line; value: out real; good: out boolean) + is + -- The parsing is done with a state machine. + -- LEADING: leading blank suppression. + -- SIGN: a sign has been found. + -- DIGITS: integer parts + -- DECIMALS, DECIMALS2: digits after the dot. + -- EXPONENT_SIGN: sign after "E" + -- EXPONENT_1: first digit of the exponent. + -- EXPONENT: digits of the exponent. + type state_t is (leading, sign, digits, decimals, decimals2, + exponent_sign, exponent_1, exponent); + variable state : state_t := leading; + + variable left : positive; + + procedure set_value (right : positive; off : natural) is + begin + if right > left then + value := textio_read_real (l (left to right - off)); + else + value := textio_read_real (l (left downto right + off)); + end if; + good := True; + end set_value; + begin + -- By default, parsing has failed. + good := false; + + -- Iterate over all characters of the string. + -- Return immediatly in case of parse error. + -- Trim L and call SET_VALUE and return in case of success. + for i in l'range loop + case state is + when leading => + left := i; + case l (i) is + when ' ' + | NBSP --!V87 + | ht => + null; + when '+' | '-' => + state := sign; + when '0' to '9' => + state := digits; + when others => + return; + end case; + when sign => + case l (i) is + when '0' to '9' => + state := digits; + when others => + return; + end case; + when digits => + case l (i) is + when '0' to '9' => + null; + when '.' => + state := decimals; + when others => + -- A "." (dot) is required in the string. + return; + end case; + when decimals | decimals2 => + case l (i) is + when '0' to '9' => + state := decimals2; + when 'e' | 'E' => + -- "nnn.E" is erroneous. + if state = decimals then + return; + end if; + state := exponent_sign; + when others => + -- "nnn.XX" is erroneous. + if state = decimals then + return; + end if; + set_value (i, 1); + trim (l, i); + return; + end case; + when exponent_sign => + case l (i) is + when '+' | '-' => + state := exponent_1; + when '0' to '9' => + state := exponent; + when others => + -- Error. + return; + end case; + when exponent_1 | exponent => + case l (i) is + when '0' to '9' => + state := exponent; + when others => + set_value (i, 1); + trim (l, i); + return; + end case; + end case; + end loop; + + -- End of string. + case state is + when leading | sign | digits => + -- Erroneous. + return; + when decimals => + -- "nnn.XX" is erroneous. + return; + when decimals2 => + null; + when exponent_sign => + -- Erroneous ("NNN.NNNE") + return; + when exponent_1 => + -- "NNN.NNNE-" + return; + when exponent => + null; + end case; + + set_value (l'right, 0); + + deallocate (l); + l := new string'(""); + end read; + + procedure read (l: inout line; value: out real) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "real read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out time; good: out boolean) + is + -- The result. + variable res : time; + + -- UNIT is computed from the unit name, the exponent and the number of + -- digits before the dot. UNIT is the weight of the current digit. + variable unit : time; + + -- Number of digits before the dot. + variable nbr_digits : integer; + + -- True if a unit name has been found. Used temporaly to know the status + -- at the end of the search loop. + variable unit_found : boolean; + + -- True if the number is negative. + variable is_neg : boolean; + + -- Value of the exponent. + variable exp : integer; + + -- True if the exponent is negative. + variable exp_neg : boolean; + + -- Unit name extracted from the string. + variable unit_name : string (1 to 3); + + -- state is the kind of the previous character parsed. + -- LEADING: leading blanks + -- SIGN: + or - as the first character of the number. + -- DIGITS: digit of the integer part of the number. + -- DOT: dot (.) after the integer part and before the decimal part. + -- DECIMALS: digit of the decimal part. + -- EXPONENT_MARK: e or E. + -- EXPONENT_SIGN: + or - just after the exponent mark (E). + -- EXPONENT: digit of the exponent. + -- UNIT_BLANK: blank after the exponent. + -- UNIT_1, UNIT_2, UNIT_3: first, second, third character of the unit. + type state_type is (leading, sign, digits, dot, decimals, + exponent_mark, exponent_sign, exponent, + unit_blank, unit_1, unit_2, unit_3); + variable state : state_type; + + -- Used during the second scan of the string, TRUE is digits is being + -- scaned. + variable has_digits : boolean; + + -- Position at the end of the string. + variable pos : integer; + + -- Used to compute POS. + variable length : integer; + begin + -- Initialization. + -- Fail by default; therefore, in case of error, a return statement is + -- ok. + good := false; + + nbr_digits := 0; + is_neg := false; + exp := 0; + exp_neg := false; + res := 0 fs; + + -- Look for exponent and unit name. + -- Parse the string: this loop checks the correctness of the format, and + -- must return (GOOD has been set to FALSE) in case of error. + -- Set: NBR_DIGITS, IS_NEG, EXP, EXP_NEG. + state := leading; + for i in l'range loop + case l (i) is + when ' ' + | NBSP --!V87 + | HT => + case state is + when leading | unit_blank => + null; + when sign | dot | exponent_mark | exponent_sign => + return; + when digits | decimals | exponent => + state := unit_blank; + when unit_1 | unit_2 => + exit; + when unit_3 => + -- Cannot happen, since an exit is performed at unit_3. + assert false report "internal error" severity failure; + end case; + when '+' | '-' => + case state is + when leading => + if l(i) = '-' then + is_neg := true; + end if; + state := sign; + when exponent_mark => + if l(i) = '-' then + exp_neg := true; + end if; + state := exponent_sign; + when others => + return; + end case; + when '0' to '9' => + case state is + when exponent_mark | exponent_sign | exponent => + exp := exp * 10 + char_to_nat (l (i)); + state := exponent; + when leading | sign | digits => + -- Leading "0" are not significant. + if nbr_digits > 0 or l (i) /= '0' then + nbr_digits := nbr_digits + 1; + end if; + state := digits; + when decimals => + null; + when dot => + state := decimals; + when others => + return; + end case; + when 'a' to 'z' | 'A' to 'Z' => + case state is + when digits | decimals => + -- "E" has exponent mark. + if l (i) = 'e' or l(i) = 'E' then + state := exponent_mark; + else + return; + end if; + when unit_blank => + unit_name (1) := to_lower (l(i)); + state := unit_1; + when unit_1 => + unit_name (2) := to_lower (l(i)); + state := unit_2; + pos := i; + when unit_2 => + unit_name (3) := to_lower (l(i)); + state := unit_3; + exit; + when others => + return; + end case; + when '.' => + case state is + when digits => + state := decimals; + when others => + exit; + end case; + when others => + exit; + end case; + end loop; + + -- A unit name (2 or 3 letters) must have been found. + -- The string may end anywhere. + if state /= unit_2 and state /= unit_3 then + return; + end if; + + -- Compute EXP with the sign. + if exp_neg then + exp := -exp; + end if; + + -- Search the unit name in the list of time names. + unit_found := false; + for i in time_names'range loop + -- The first two characters must match (case insensitive). + -- The third character must match if: + -- * the unit name is a three characters identifier (ie, not a blank). + -- * there is a third character in STR. + if time_names (i).name (1) = unit_name (1) + and time_names (i).name (2) = unit_name (2) + and (time_names (i).name (3) = ' ' + or time_names (i).name (3) = unit_name (3)) + then + unit := time_names (i).val; + unit_found := true; + -- POS is set to the position of the first invalid character. + if time_names (i).name (3) = ' ' then + length := 1; + else + length := 2; + end if; + if l'left < l'right then + pos := pos + length; + else + pos := pos - length; + end if; + exit; + end if; + end loop; + if not unit_found then + return; + end if; + + -- Compute UNIT, the weight of the first non-significant character. + nbr_digits := nbr_digits + exp - 1; + if nbr_digits < 0 then + unit := unit / 10 ** (-nbr_digits); + else + unit := unit * 10 ** nbr_digits; + end if; + + -- HAS_DIGITS will be set as soon as a digit is found. + -- No error is expected here (this has been checked during the first + -- pass). + has_digits := false; + for i in l'range loop + case l (i) is + when ' ' + | NBSP --!V87 + | HT => + if has_digits then + exit; + end if; + when '+' | '-' => + if not has_digits then + has_digits := true; + else + assert false report "internal error" severity failure; + return; + end if; + when '0' to '9' => + -- Leading "0" are not significant. + if l (i) /= '0' or res /= 0 fs then + res := res + char_to_nat (l (i)) * unit; + unit := unit / 10; + end if; + has_digits := true; + when 'a' to 'z' | 'A' to 'Z' => + if has_digits then + exit; + else + assert false report "internal error" severity failure; + return; + end if; + when '.' => + if not has_digits then + assert false report "internal error" severity failure; + return; + end if; + when others => + assert false report "internal error" severity failure; + return; + end case; + end loop; + + -- Set VALUE. + if is_neg then + value := -res; + else + value := res; + end if; + good := true; + trim (l, pos); + return; + end read; + + procedure read (l: inout line; value: out time) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "time read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out string; good: out boolean) + is + constant len : natural := value'length; + begin + if l'length < len then + good := false; + return; + end if; + good := true; + if len = 0 then + return; + end if; + if l'left < l'right then + -- Ascending (expected common case). + value := l (l'left to l'left + len - 1); + trim (l, l'left + len); + elsif l'left = l'right then + -- String of 1 character. We don't know the direction and therefore + -- can't use the code below which does a slice. + value := l.all; + deallocate (l); + l := new string'(""); + else + -- Descending. + value := l (l'left downto l'left - len + 1); + trim (l, l'left - len); + end if; + end read; + + procedure read (l: inout line; value: out string) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "string read failure" + severity failure; + end read; + +--START-V08 + procedure Sread (L : inout Line; Value : out String; Strlen : out Natural) + is + constant maxlen : natural := Value'Length; + alias value1 : string (1 to maxlen) is Value; + variable skipping : boolean := True; + variable f, len, nl_left : natural; + variable nl : line; + begin + -- Skip leading spaces. F designates the index of the first non-space + -- character, LEN the length of the extracted string. + len := 0; + for i in l'range loop + if skipping then + if not is_whitespace (l (i)) then + skipping := false; + f := i; + len := 1; + end if; + else + exit when is_whitespace (l (i)); + len := len + 1; + exit when len = maxlen; + end if; + end loop; + + -- Copy string. + if l'ascending then + value1 (1 to len) := l (f to f + len - 1); + else + value1 (1 to len) := l (f downto f - len + 1); + end if; + strlen := len; + + if l'ascending then + if len = 0 then + f := l'right + 1; + end if; + nl_left := f + len; + nl := new string (nl_left to l'right); + nl.all := l (nl_left to l'right); + else + if len = 0 then + f := l'right - 1; + end if; + nl_left := f - len; + nl := new string (nl_left downto l'right); + nl.all := l (nl_left downto l'right); + end if; + deallocate (l); + l := nl; + end sread; + + subtype bv4 is bit_vector (1 to 4); + + function char_to_bv4 (c : character) return bv4 is + begin + case c is + when '0' => return "0000"; + when '1' => return "0001"; + when '2' => return "0010"; + when '3' => return "0011"; + when '4' => return "0100"; + when '5' => return "0101"; + when '6' => return "0110"; + when '7' => return "0111"; + when '8' => return "1000"; + when '9' => return "1001"; + when 'a' | 'A' => return "1010"; + when 'b' | 'B' => return "1011"; + when 'c' | 'C' => return "1100"; + when 'd' | 'D' => return "1101"; + when 'e' | 'E' => return "1110"; + when 'f' | 'F' => return "1111"; + when others => + assert false report "bad hexa digit" severity failure; + end case; + end char_to_bv4; + + procedure Oread (L : inout Line; Value : out Bit_Vector; Good : out Boolean) + is + -- Length of Value + constant vlen : natural := value'length; + + -- Number of octal digits for Value + constant olen : natural := (vlen + 2) / 3; + + variable res : bit_vector (1 to olen * 3); + + -- Number of bit to parse. + variable len : natural; + + variable pos : natural; + + -- Last character from LEN to be removed + variable last : integer; + + -- State of the previous byte: + -- SKIP: blank before the bit vector. + -- DIGIT: previous character was a digit + -- UNDERSCORE: was '_' + type state_type is (skip, digit, underscore); + variable state : state_type; + begin + -- Initialization. + if vlen = 0 then + -- If VALUE is a nul array, return now. + -- L stay unchanged. + -- FIXME: should blanks be removed ? + good := true; + return; + end if; + good := false; + state := skip; + pos := res'left; + if l'ascending then + last := l'left - 1; + else + last := l'left + 1; + end if; + for i in l'range loop + case l (i) is + when ' ' + | NBSP + | HT => + exit when state /= skip; + when '_' => + exit when state /= digit; + state := underscore; + when '0' to '7' => + res (pos to pos + 2) := char_to_bv4 (l (i)) (2 to 4); + last := i; + state := digit; + pos := pos + 3; + -- LRM08 16.4 + -- Character removal and compostion also stops when the expected + -- number of digits have been removed. + exit when pos = res'right + 1; + when others => + exit; + end case; + end loop; + + -- LRM08 16.4 + -- The OREAD or HEAD procedure does not succeed if less than the expected + -- number of digits are removed. + if pos /= res'right + 1 then + return; + end if; + + -- LRM08 16.4 + -- The rightmost value'length bits of the binary number are used to form + -- the result for the VALUE parameter, [with a '0' element corresponding + -- to a 0 bit and a '1' element corresponding to a 1 bit]. The OREAD or + -- HREAD procedure does not succeed if any unused bits are 1. + for i in 1 to res'right - vlen loop + if res (i) = '1' then + return; + end if; + end loop; + + Value := res (res'right - vlen + 1 to res'right); + good := true; + trim_next (l, last); + end Oread; + + procedure Oread (L : inout Line; Value : out Bit_Vector) + is + variable res : boolean; + begin + Oread (l, value, res); + assert res = true + report "octal bit_vector read failure" + severity failure; + end Oread; + + procedure Hread (L : inout Line; Value : out Bit_Vector; Good : out Boolean) + is + -- Length of Value + constant vlen : natural := value'length; + + -- Number of hexa digits for Value + constant hlen : natural := (vlen + 3) / 4; + + variable res : bit_vector (1 to hlen * 4); + + -- Number of bit to parse. + variable len : natural; + + variable pos : natural; + + -- Last character from LEN to be removed + variable last : integer; + + -- State of the previous byte: + -- SKIP: blank before the bit vector. + -- DIGIT: previous character was a digit + -- UNDERSCORE: was '_' + type state_type is (skip, digit, underscore); + variable state : state_type; + begin + -- Initialization. + if vlen = 0 then + -- If VALUE is a nul array, return now. + -- L stay unchanged. + -- FIXME: should blanks be removed ? + good := true; + return; + end if; + good := false; + state := skip; + pos := res'left; + if l'ascending then + last := l'left - 1; + else + last := l'left + 1; + end if; + for i in l'range loop + case l (i) is + when ' ' + | NBSP + | HT => + exit when state /= skip; + when '_' => + exit when state /= digit; + state := underscore; + when '0' to '9' | 'a' to 'f' | 'A' to 'F' => + res (pos to pos + 3) := char_to_bv4 (l (i)); + last := i; + state := digit; + pos := pos + 4; + -- LRM08 16.4 + -- Character removal and compostion also stops when the expected + -- number of digits have been removed. + exit when pos = res'right + 1; + when others => + exit; + end case; + end loop; + + -- LRM08 16.4 + -- The OREAD or HEAD procedure does not succeed if less than the expected + -- number of digits are removed. + if pos /= res'right + 1 then + return; + end if; + + -- LRM08 16.4 + -- The rightmost value'length bits of the binary number are used to form + -- the result for the VALUE parameter, [with a '0' element corresponding + -- to a 0 bit and a '1' element corresponding to a 1 bit]. The OREAD or + -- HREAD procedure does not succeed if any unused bits are 1. + for i in 1 to res'right - vlen loop + if res (i) = '1' then + return; + end if; + end loop; + + Value := res (res'right - vlen + 1 to res'right); + good := true; + trim_next (l, last); + end Hread; + + procedure Hread (L : inout Line; Value : out Bit_Vector) + is + variable res : boolean; + begin + Hread (l, value, res); + assert res = true + report "hexa bit_vector read failure" + severity failure; + end Hread; +--END-V08 +end textio; diff --git a/libraries/std/textio_body.vhdl b/libraries/std/textio_body.vhdl deleted file mode 100644 index d01cb8bad..000000000 --- a/libraries/std/textio_body.vhdl +++ /dev/null @@ -1,1558 +0,0 @@ --- Std.Textio package body. This file is part of GHDL. --- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold --- --- GHDL is free software; you can redistribute it and/or modify it under --- the terms of the GNU General Public License as published by the Free --- Software Foundation; either version 2, or (at your option) any later --- version. --- --- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY --- WARRANTY; without even the implied warranty of MERCHANTABILITY or --- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --- for more details. --- --- You should have received a copy of the GNU General Public License --- along with GCC; see the file COPYING3. If not see --- . - -package body textio is - attribute foreign : string; --V87 - ---START-V08 - -- LRM08 16.4 - -- The JUSTIFY operation formats a string value within a field that is at - -- least at long as required to contain the value. Parameter FIELD - -- specifies the desired field width. Since the actual field width will - -- always be at least large enough to hold the string value, the default - -- value 0 for the FIELD parameter has the effect of causing the string - -- value to be contained in a field of exactly the right widteh (i.e., no - -- additional leading or tailing spaces). Parameter JUSTIFIED specified - -- whether the string value is to be right- or left-justified within the - -- field; the default is right-justified. If the FIELD parameter describes - -- a field width larger than the number of characters in the string value, - -- space characters are used to fill the remaining characters in the field. - -- - -- TG: Note that the bounds of the result are not specified! - function Justify (Value: String; - Justified : Side := Right; - Field: Width := 0 ) return String - is - constant len : Width := Value'Length; - begin - if Field <= Len then - return Value; - else - case Justified is - when Right => - return (1 to Field - Len => ' ') & Value; - when Left => - return Value & (1 to Field - Len => ' '); - end case; - end if; - end Justify; ---END-V08 - - -- output routines for standard types - - -- TIME_NAMES associates time units with textual names. - -- Textual names are in lower cases, since according to LRM93 14.3: - -- when written, the identifier is expressed in lowercase characters. - -- The length of the names are 3 characters, the last one may be a space - -- for 2 characters long names. - type time_unit is - record - val : time; - name : string (1 to 3); - end record; - type time_names_type is array (1 to 8) of time_unit; - constant time_names : time_names_type := - ((fs, "fs "), (ps, "ps "), (ns, "ns "), (us, "us "), - (ms, "ms "), (sec, "sec"), (min, "min"), (hr, "hr ")); - - -- Non breaking space character. --!V87 - constant nbsp : character := character'val (160); --!V87 - - function is_whitespace (c : character) return Boolean is - begin - case c is - when ' ' - | NBSP --!V87 - | HT => - return True; - when others => - return False; - end case; - end is_Whitespace; - - procedure writeline (variable f: out text; l: inout line) is --V87 - procedure writeline (file f: text; l: inout line) is --!V87 - begin - if l = null then - -- LRM93 14.3 - -- If parameter L contains a null access value at the start of the call, - -- the a null string is written to the file. - null; - else - -- LRM93 14.3 - -- Procedure WRITELINE causes the current line designated by parameter L - -- to be written to the file and returns with the value of parameter L - -- designating a null string. - write (f, l.all); - deallocate (l); - l := new string'(""); - end if; - write (f, (1 => LF)); - end writeline; - ---START-V08 - procedure Tee (file f : Text; L : inout LINE) is - begin - -- LRM08 16.4 Package TEXTIO - -- The procedure TEE additionally causes the current line to be written - -- to the file OUTPUT. - if l = null then - null; - else - write (f, l.all); - write (Output, l.all); - deallocate (l); - l := new string'(""); - end if; - write (f, (1 => LF)); - write (output, (1 => LF)); - end Tee; ---END-V08 - - procedure write - (l: inout line; value: in string; - justified: in side := right; field: in width := 0) - is - variable length: natural; - variable nl: line; - begin - -- l can be null. - if l = null then - length := 0; - else - length := l.all'length; - end if; - if value'length < field then - nl := new string (1 to length + field); - if length /= 0 then - nl (1 to length) := l.all; - end if; - if justified = right then - nl (length + 1 to length + field - value'length) := (others => ' '); - nl (nl.all'high - value'length + 1 to nl.all'high) := value; - else - nl (length + 1 to length + value'length) := value; - nl (length + value'length + 1 to nl.all'high) := (others => ' '); - end if; - else - nl := new string (1 to length + value'length); - if length /= 0 then - nl (1 to length) := l.all; - end if; - nl (length + 1 to nl.all'high) := value; - end if; - deallocate (l); - l := nl; - end write; - - procedure write - (l: inout line; value: in integer; - justified: in side := right; field: in width := 0) - is - variable str: string (11 downto 1); - variable val: integer := value; - variable digit: natural; - variable index: natural := 0; - begin - -- Note: the absolute value of VAL cannot be directly taken, since - -- it may be greather that the maximum value of an INTEGER. - loop - -- LRM93 7.2.6 - -- (A rem B) has the sign of A and an absolute value less then - -- the absoulte value of B. - digit := abs (val rem 10); - val := val / 10; - index := index + 1; - str (index) := character'val(48 + digit); - exit when val = 0; - end loop; - if value < 0 then - index := index + 1; - str(index) := '-'; - end if; - write (l, str (index downto 1), justified, field); - end write; - - procedure write - (l: inout line; value: in boolean; - justified: in side := right; field: in width := 0) - is - begin - if value then - write (l, string'("TRUE"), justified, field); - else - write (l, string'("FALSE"), justified, field); - end if; - end write; - - procedure write - (l: inout line; value: in character; - justified: in side := right; field: in width := 0) - is - variable str: string (1 to 1); - begin - str (1) := value; - write (l, str, justified, field); - end write; - - function bit_to_char (value : in bit) return character is - begin - case value is - when '0' => - return '0'; - when '1' => - return '1'; - end case; - end bit_to_char; - - procedure write - (l: inout line; value: in bit; - justified: in side := right; field: in width := 0) - is - variable str : string (1 to 1); - begin - str (1) := bit_to_char (value); - write (l, str, justified, field); - end write; - - procedure write - (l: inout line; value: in bit_vector; - justified: in side := right; field: in width := 0) - is - constant length : natural := value'length; - alias n_value : bit_vector (1 to value'length) is value; - variable str : string (1 to length); - begin - for i in str'range loop - str (i) := bit_to_char (n_value (i)); - end loop; - write (l, str, justified, field); - end write; - - procedure write - (l: inout line; value : in time; - justified: in side := right; field: in width := 0; unit : in TIME := ns) - is - -- Copy of VALUE on which we are working. - variable val : time := value; - - -- Copy of UNIT on which we are working. - variable un : time := unit; - - -- Digit extract from VAL/UN. - variable d : integer; -- natural range 0 to 9; - - -- Index for unit name. - variable n : integer; - - -- Result. - variable str : string (1 to 28); - - -- Current character in RES. - variable pos : natural := 1; - - -- Add a character to STR. - procedure add_char (c : character) is - begin - str (pos) := c; - pos := pos + 1; - end add_char; - begin - -- Note: - -- Care is taken to avoid overflow. Time may be 64 bits while integer - -- may be only 32 bits. - - -- Handle sign. - -- Note: VAL cannot be negated since its range may be not symetric - -- around 0. - if val < 0 ns then - add_char ('-'); - end if; - - -- Search for the first digit. - -- Note: we must start from unit, since all units are not a power of 10. - -- Note: UN can be multiplied only after we know it is possible. This - -- is a to avoid overflow. - if un <= 0 fs then - assert false report "UNIT argument is not positive" severity error; - un := 1 ns; - end if; - while val / 10 >= un or val / 10 <= -un loop - un := un * 10; - end loop; - - -- Extract digits one per one. - loop - d := val / un; - add_char (character'val (abs d + character'pos ('0'))); - val := val - d * un; - exit when val = 0 ns and un <= unit; - if un = unit then - add_char ('.'); - end if; - -- Stop as soon as precision will be lost. - -- This can happen only for hr and min. - -- FIXME: change the algorithm to display all the digits. - exit when (un / 10) * 10 /= un; - un := un / 10; - end loop; - - add_char (' '); - - -- Search the time unit name in the time table. - n := 0; - for i in time_names'range loop - if time_names (i).val = unit then - n := i; - exit; - end if; - end loop; - assert n /= 0 report "UNIT argument is not a unit name" severity error; - if n = 0 then - add_char ('?'); - else - add_char (time_names (n).name (1)); - add_char (time_names (n).name (2)); - if time_names (n).name (3) /= ' ' then - add_char (time_names (n).name (3)); - end if; - end if; - - -- Write the result. - write (l, str (1 to pos - 1), justified, field); - end write; - - procedure textio_write_real - (s : out string; len : out natural; value: real; ndigits : natural); - - attribute foreign of textio_write_real : procedure is "GHDL intrinsic"; - - procedure textio_write_real - (s : out string; len : out natural; value: real; ndigits : natural) is - begin - assert false report "must not be called" severity failure; - end textio_write_real; - - -- Parameter DIGITS specifies how many digits to the right of the decimal - -- point are to be output when writing a real number; the default value 0 - -- indicates that the number should be output in standard form, consisting - -- of a normalized mantissa plus exponent (e.g., 1.079236E23). If DIGITS is - -- nonzero, then the real number is output as an integer part followed by - -- '.' followed by the fractional part, using the specified number of digits - -- (e.g., 3.14159). - -- Note: Nan, +Inf, -Inf are not to be considered, since these numbers are - -- not in the bounds defined by any real range. - procedure write (L: inout line; value: in real; - justified: in side := right; field: in width := 0; - digits: in natural := 0) - is - -- STR contains the result of the conversion. - variable str : string (1 to 320); - - variable len : natural; - begin - textio_write_real (str, len, value, digits); - assert len <= str'length severity failure; - - write (l, str (1 to len), justified, field); - end write; - ---START-V08 - procedure Owrite (L : inout line; value : in Bit_Vector; - Justified : in Side := Right; Field : in Width := 0) is - begin - write (l, to_ostring (value), justified, field); - end Owrite; - - procedure Hwrite (L : inout line; value : in Bit_Vector; - Justified : in Side := Right; Field : in Width := 0) is - begin - write (l, to_hstring (value), justified, field); - end Hwrite; ---END-V08 - - procedure untruncated_text_read --V87 - (variable f : text; str : out string; len : out natural); --V87 - procedure untruncated_text_read --!V87 - (file f : text; str : out string; len : out natural); --!V87 - - attribute foreign of untruncated_text_read : procedure is "GHDL intrinsic"; - - procedure untruncated_text_read - (variable f : text; str : out string; len : out natural) is --V87 - (file f : text; str : out string; len : out natural) is --!V87 - begin - assert false report "must not be called" severity failure; - end untruncated_text_read; - - procedure readline (variable f: in text; l: inout line) --V87 - procedure readline (file f: text; l: inout line) --!V87 - is - variable len, nlen, posn : natural; - variable nl, old_l : line; - variable str : string (1 to 128); - variable is_eol : boolean; - begin - -- LRM93 14.3 - -- If parameter L contains a non-null access value at the start of the - -- call, the object designated by that value is deallocated before the - -- new object is created. - if l /= null then - deallocate (l); - end if; - - -- End of file is not expected. The user should check endfile before - -- calling readline. - assert not endfile (f) - report "eof in std.textio.readline" severity failure; - - -- We read the input in 128-byte chunks. - -- We keep reading until we reach a newline or there is no more input. - -- The loop invariant is that old_l is allocated and contains the - -- previous chunks read, and posn = old_l.all'length. - posn := 0; - loop - untruncated_text_read (f, str, len); - exit when len = 0; - if str (len) = LF or str (len) = CR then - -- LRM 14.3 - -- The representation of the line does not contain the representation - -- of the end of the line. - is_eol := true; - len := len - 1; - -- End of line is any of LF/CR/CR+LF/LF+CR. - if len > 0 and (str (len) = LF or str (len) = CR) then - len := len - 1; - end if; - elsif endfile (f) then - is_eol := true; - else - is_eol := false; - end if; - l := new string (1 to posn + len); - if old_l /= null then - l (1 to posn) := old_l (1 to posn); - deallocate (old_l); - end if; - l (posn + 1 to posn + len) := str (1 to len); - exit when is_eol; - posn := posn + len; - old_l := l; - end loop; - end readline; - - -- Replaces L with L (LEFT to/downto L'RIGHT) - procedure trim (l : inout line; left : natural) - is - variable nl : line; - begin - if l = null then - return; - end if; - if l'left < l'right then - -- Ascending. - if left > l'right then - nl := new string'(""); - else - nl := new string (left to l'right); --- nl := new string (1 to l'right + 1 - left); - nl.all := l (left to l'right); - end if; - else - -- Descending - if left < l'right then - nl := new string'(""); - else - nl := new string (left downto l'right); --- nl := new string (left - l'right + 1 downto 1); - nl.all := l (left downto l'right); - end if; - end if; - deallocate (l); - l := nl; - end trim; - - -- Replaces L with L (LEFT + 1 to L'RIGHT or LEFT - 1 downto L'RIGHT) - procedure trim_next (l : inout line; left : natural) - is - variable nl : line; - begin - if l = null then - return; - end if; - if l'left < l'right then - -- Ascending. - trim (l, left + 1); - else - -- Descending - trim (l, left - 1); - end if; - end trim_next; - - function to_lower (c : character) return character is - begin - if c >= 'A' and c <= 'Z' then - return character'val (character'pos (c) + 32); - else - return c; - end if; - end to_lower; - - procedure read (l: inout line; value: out character; good: out boolean) - is - variable nl : line; - begin - if l = null or l'length = 0 then - good := false; - else - value := l (l'left); - trim_next (l, l'left); - good := true; - end if; - end read; - - procedure read (l: inout line; value: out character) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "character read failure" - severity failure; - end read; - - procedure read (l: inout line; value: out bit; good: out boolean) - is - begin - good := false; - for i in l'range loop - case l(i) is - when ' ' - | NBSP --!V87 - | HT => - null; - when '1' => - value := '1'; - good := true; - trim_next (l, i); - return; - when '0' => - value := '0'; - good := true; - trim_next (l, i); - return; - when others => - return; - end case; - end loop; - return; - end read; - - procedure read (l: inout line; value: out bit) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "bit read failure" - severity failure; - end read; - - procedure read (l: inout line; value: out bit_vector; good: out boolean) - is - -- Number of bit to parse. - variable len : natural; - - variable pos, last : natural; - variable res : bit_vector (1 to value'length); - - -- State of the previous byte: - -- LEADING: blank before the bit vector. - -- FOUND: bit of the vector. - type state_type is (leading, found); - variable state : state_type; - begin - -- Initialization. - len := value'length; - if len = 0 then - -- If VALUE is a nul array, return now. - -- L stay unchanged. - -- FIXME: should blanks be removed ? - good := true; - return; - end if; - good := false; - state := leading; - pos := res'left; - for i in l'range loop - case l(i) is - when ' ' - | NBSP --!V87 - | HT => - case state is - when leading => - null; - when found => - return; - end case; - when '1' | '0' => - case state is - when leading => - state := found; - when found => - null; - end case; - if l(i) = '0' then - res (pos) := '0'; - else - res (pos) := '1'; - end if; - pos := pos + 1; - len := len - 1; - last := i; - exit when len = 0; - when others => - return; - end case; - end loop; - - if len /= 0 then - -- Not enough bits. - return; - end if; - - -- Note: if LEN = 0, then FIRST and LAST have been set. - good := true; - value := res; - trim_next (l, last); - return; - end read; - - procedure read (l: inout line; value: out bit_vector) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "bit_vector read failure" - severity failure; - end read; - - procedure read (l: inout line; value: out boolean; good: out boolean) - is - -- State: - -- BLANK: space are being scaned. - -- L_TF : T(rue) or F(alse) has been scanned. - -- L_RA : (t)R(ue) or (f)A(lse) has been scanned. - -- L_UL : (tr)U(e) or (fa)L(se) has been scanned. - -- L_ES : (tru)E or (fal)S(e) has been scanned. - type state_type is (blank, l_tf, l_ra, l_ul, l_es); - variable state : state_type; - - -- Set to TRUE if T has been scanned, to FALSE if F has been scanned. - variable res : boolean; - - variable c : character; - begin - -- By default, it is a failure. - good := false; - state := blank; - for i in l'range loop - c := l (i); - case state is - when blank => - if is_whitespace (c) then - null; - elsif c = 'f' or c = 'T' then - res := true; - state := l_tf; - elsif c = 'f' or c = 'F' then - res := false; - state := l_tf; - else - return; - end if; - when l_tf => - if res = true and (c = 'r' or c = 'R') then - state := l_ra; - elsif res = false and (c = 'a' or C = 'A') then - state := l_ra; - else - return; - end if; - when l_ra => - if res = true and (c = 'u' or C = 'U') then - state := l_ul; - elsif res = false and (c = 'l' or c = 'L') then - state := l_ul; - else - return; - end if; - when l_ul => - if res = true and (c = 'e' or c = 'E') then - trim_next (l, i); - good := true; - value := true; - return; - elsif res = false and (c = 's' or c = 'S') then - state := l_es; - else - return; - end if; - when l_es => - if res = false and (c = 'e' or c = 'E') then - trim_next (l, i); - good := true; - value := false; - return; - else - return; - end if; - end case; - end loop; - return; - end read; - - procedure read (l: inout line; value: out boolean) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "boolean read failure" - severity failure; - end read; - - function char_to_nat (c : character) return natural - is - begin - return character'pos (c) - character'pos ('0'); - end char_to_nat; - - procedure read (l: inout line; value: out integer; good: out boolean) - is - variable val : integer; - variable d : natural; - - type state_t is (leading, sign, digits); - variable cur_state : state_t := leading; - begin - val := 1; - for i in l'range loop - case cur_state is - when leading => - case l(i) is - when ' ' - | NBSP --!V87 - | ht => - null; - when '+' => - cur_state := sign; - when '-' => - val := -1; - cur_state := sign; - when '0' to '9' => - val := char_to_nat (l(i)); - cur_state := digits; - when others => - good := false; - return; - end case; - when sign => - case l(i) is - when '0' to '9' => - val := val * char_to_nat (l(i)); - cur_state := digits; - when others => - good := false; - return; - end case; - when digits => - case l(i) is - when '0' to '9' => - d := char_to_nat (l(i)); - val := val * 10; - if val < 0 then - val := val - d; - else - val := val + d; - end if; - when others => - trim (l, i); - good := true; - value := val; - return; - end case; - end case; - end loop; - deallocate (l); - l := new string'(""); - if cur_state /= leading then - good := true; - value := val; - else - good := false; - end if; - end read; - - procedure read (l: inout line; value: out integer) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "integer read failure" - severity failure; - end read; - - function textio_read_real (s : string) return real; - - attribute foreign of textio_read_real : function is "GHDL intrinsic"; - - function textio_read_real (s : string) return real is - begin - assert false report "must not be called" severity failure; - return 0.0; - end textio_read_real; - - procedure read (l: inout line; value: out real; good: out boolean) - is - -- The parsing is done with a state machine. - -- LEADING: leading blank suppression. - -- SIGN: a sign has been found. - -- DIGITS: integer parts - -- DECIMALS, DECIMALS2: digits after the dot. - -- EXPONENT_SIGN: sign after "E" - -- EXPONENT_1: first digit of the exponent. - -- EXPONENT: digits of the exponent. - type state_t is (leading, sign, digits, decimals, decimals2, - exponent_sign, exponent_1, exponent); - variable state : state_t := leading; - - variable left : positive; - - procedure set_value (right : positive; off : natural) is - begin - if right > left then - value := textio_read_real (l (left to right - off)); - else - value := textio_read_real (l (left downto right + off)); - end if; - good := True; - end set_value; - begin - -- By default, parsing has failed. - good := false; - - -- Iterate over all characters of the string. - -- Return immediatly in case of parse error. - -- Trim L and call SET_VALUE and return in case of success. - for i in l'range loop - case state is - when leading => - left := i; - case l (i) is - when ' ' - | NBSP --!V87 - | ht => - null; - when '+' | '-' => - state := sign; - when '0' to '9' => - state := digits; - when others => - return; - end case; - when sign => - case l (i) is - when '0' to '9' => - state := digits; - when others => - return; - end case; - when digits => - case l (i) is - when '0' to '9' => - null; - when '.' => - state := decimals; - when others => - -- A "." (dot) is required in the string. - return; - end case; - when decimals | decimals2 => - case l (i) is - when '0' to '9' => - state := decimals2; - when 'e' | 'E' => - -- "nnn.E" is erroneous. - if state = decimals then - return; - end if; - state := exponent_sign; - when others => - -- "nnn.XX" is erroneous. - if state = decimals then - return; - end if; - set_value (i, 1); - trim (l, i); - return; - end case; - when exponent_sign => - case l (i) is - when '+' | '-' => - state := exponent_1; - when '0' to '9' => - state := exponent; - when others => - -- Error. - return; - end case; - when exponent_1 | exponent => - case l (i) is - when '0' to '9' => - state := exponent; - when others => - set_value (i, 1); - trim (l, i); - return; - end case; - end case; - end loop; - - -- End of string. - case state is - when leading | sign | digits => - -- Erroneous. - return; - when decimals => - -- "nnn.XX" is erroneous. - return; - when decimals2 => - null; - when exponent_sign => - -- Erroneous ("NNN.NNNE") - return; - when exponent_1 => - -- "NNN.NNNE-" - return; - when exponent => - null; - end case; - - set_value (l'right, 0); - - deallocate (l); - l := new string'(""); - end read; - - procedure read (l: inout line; value: out real) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "real read failure" - severity failure; - end read; - - procedure read (l: inout line; value: out time; good: out boolean) - is - -- The result. - variable res : time; - - -- UNIT is computed from the unit name, the exponent and the number of - -- digits before the dot. UNIT is the weight of the current digit. - variable unit : time; - - -- Number of digits before the dot. - variable nbr_digits : integer; - - -- True if a unit name has been found. Used temporaly to know the status - -- at the end of the search loop. - variable unit_found : boolean; - - -- True if the number is negative. - variable is_neg : boolean; - - -- Value of the exponent. - variable exp : integer; - - -- True if the exponent is negative. - variable exp_neg : boolean; - - -- Unit name extracted from the string. - variable unit_name : string (1 to 3); - - -- state is the kind of the previous character parsed. - -- LEADING: leading blanks - -- SIGN: + or - as the first character of the number. - -- DIGITS: digit of the integer part of the number. - -- DOT: dot (.) after the integer part and before the decimal part. - -- DECIMALS: digit of the decimal part. - -- EXPONENT_MARK: e or E. - -- EXPONENT_SIGN: + or - just after the exponent mark (E). - -- EXPONENT: digit of the exponent. - -- UNIT_BLANK: blank after the exponent. - -- UNIT_1, UNIT_2, UNIT_3: first, second, third character of the unit. - type state_type is (leading, sign, digits, dot, decimals, - exponent_mark, exponent_sign, exponent, - unit_blank, unit_1, unit_2, unit_3); - variable state : state_type; - - -- Used during the second scan of the string, TRUE is digits is being - -- scaned. - variable has_digits : boolean; - - -- Position at the end of the string. - variable pos : integer; - - -- Used to compute POS. - variable length : integer; - begin - -- Initialization. - -- Fail by default; therefore, in case of error, a return statement is - -- ok. - good := false; - - nbr_digits := 0; - is_neg := false; - exp := 0; - exp_neg := false; - res := 0 fs; - - -- Look for exponent and unit name. - -- Parse the string: this loop checks the correctness of the format, and - -- must return (GOOD has been set to FALSE) in case of error. - -- Set: NBR_DIGITS, IS_NEG, EXP, EXP_NEG. - state := leading; - for i in l'range loop - case l (i) is - when ' ' - | NBSP --!V87 - | HT => - case state is - when leading | unit_blank => - null; - when sign | dot | exponent_mark | exponent_sign => - return; - when digits | decimals | exponent => - state := unit_blank; - when unit_1 | unit_2 => - exit; - when unit_3 => - -- Cannot happen, since an exit is performed at unit_3. - assert false report "internal error" severity failure; - end case; - when '+' | '-' => - case state is - when leading => - if l(i) = '-' then - is_neg := true; - end if; - state := sign; - when exponent_mark => - if l(i) = '-' then - exp_neg := true; - end if; - state := exponent_sign; - when others => - return; - end case; - when '0' to '9' => - case state is - when exponent_mark | exponent_sign | exponent => - exp := exp * 10 + char_to_nat (l (i)); - state := exponent; - when leading | sign | digits => - -- Leading "0" are not significant. - if nbr_digits > 0 or l (i) /= '0' then - nbr_digits := nbr_digits + 1; - end if; - state := digits; - when decimals => - null; - when dot => - state := decimals; - when others => - return; - end case; - when 'a' to 'z' | 'A' to 'Z' => - case state is - when digits | decimals => - -- "E" has exponent mark. - if l (i) = 'e' or l(i) = 'E' then - state := exponent_mark; - else - return; - end if; - when unit_blank => - unit_name (1) := to_lower (l(i)); - state := unit_1; - when unit_1 => - unit_name (2) := to_lower (l(i)); - state := unit_2; - pos := i; - when unit_2 => - unit_name (3) := to_lower (l(i)); - state := unit_3; - exit; - when others => - return; - end case; - when '.' => - case state is - when digits => - state := decimals; - when others => - exit; - end case; - when others => - exit; - end case; - end loop; - - -- A unit name (2 or 3 letters) must have been found. - -- The string may end anywhere. - if state /= unit_2 and state /= unit_3 then - return; - end if; - - -- Compute EXP with the sign. - if exp_neg then - exp := -exp; - end if; - - -- Search the unit name in the list of time names. - unit_found := false; - for i in time_names'range loop - -- The first two characters must match (case insensitive). - -- The third character must match if: - -- * the unit name is a three characters identifier (ie, not a blank). - -- * there is a third character in STR. - if time_names (i).name (1) = unit_name (1) - and time_names (i).name (2) = unit_name (2) - and (time_names (i).name (3) = ' ' - or time_names (i).name (3) = unit_name (3)) - then - unit := time_names (i).val; - unit_found := true; - -- POS is set to the position of the first invalid character. - if time_names (i).name (3) = ' ' then - length := 1; - else - length := 2; - end if; - if l'left < l'right then - pos := pos + length; - else - pos := pos - length; - end if; - exit; - end if; - end loop; - if not unit_found then - return; - end if; - - -- Compute UNIT, the weight of the first non-significant character. - nbr_digits := nbr_digits + exp - 1; - if nbr_digits < 0 then - unit := unit / 10 ** (-nbr_digits); - else - unit := unit * 10 ** nbr_digits; - end if; - - -- HAS_DIGITS will be set as soon as a digit is found. - -- No error is expected here (this has been checked during the first - -- pass). - has_digits := false; - for i in l'range loop - case l (i) is - when ' ' - | NBSP --!V87 - | HT => - if has_digits then - exit; - end if; - when '+' | '-' => - if not has_digits then - has_digits := true; - else - assert false report "internal error" severity failure; - return; - end if; - when '0' to '9' => - -- Leading "0" are not significant. - if l (i) /= '0' or res /= 0 fs then - res := res + char_to_nat (l (i)) * unit; - unit := unit / 10; - end if; - has_digits := true; - when 'a' to 'z' | 'A' to 'Z' => - if has_digits then - exit; - else - assert false report "internal error" severity failure; - return; - end if; - when '.' => - if not has_digits then - assert false report "internal error" severity failure; - return; - end if; - when others => - assert false report "internal error" severity failure; - return; - end case; - end loop; - - -- Set VALUE. - if is_neg then - value := -res; - else - value := res; - end if; - good := true; - trim (l, pos); - return; - end read; - - procedure read (l: inout line; value: out time) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "time read failure" - severity failure; - end read; - - procedure read (l: inout line; value: out string; good: out boolean) - is - constant len : natural := value'length; - begin - if l'length < len then - good := false; - return; - end if; - good := true; - if len = 0 then - return; - end if; - if l'left < l'right then - -- Ascending (expected common case). - value := l (l'left to l'left + len - 1); - trim (l, l'left + len); - elsif l'left = l'right then - -- String of 1 character. We don't know the direction and therefore - -- can't use the code below which does a slice. - value := l.all; - deallocate (l); - l := new string'(""); - else - -- Descending. - value := l (l'left downto l'left - len + 1); - trim (l, l'left - len); - end if; - end read; - - procedure read (l: inout line; value: out string) - is - variable res : boolean; - begin - read (l, value, res); - assert res = true - report "string read failure" - severity failure; - end read; - ---START-V08 - procedure Sread (L : inout Line; Value : out String; Strlen : out Natural) - is - constant maxlen : natural := Value'Length; - alias value1 : string (1 to maxlen) is Value; - variable skipping : boolean := True; - variable f, len, nl_left : natural; - variable nl : line; - begin - -- Skip leading spaces. F designates the index of the first non-space - -- character, LEN the length of the extracted string. - len := 0; - for i in l'range loop - if skipping then - if not is_whitespace (l (i)) then - skipping := false; - f := i; - len := 1; - end if; - else - exit when is_whitespace (l (i)); - len := len + 1; - exit when len = maxlen; - end if; - end loop; - - -- Copy string. - if l'ascending then - value1 (1 to len) := l (f to f + len - 1); - else - value1 (1 to len) := l (f downto f - len + 1); - end if; - strlen := len; - - if l'ascending then - if len = 0 then - f := l'right + 1; - end if; - nl_left := f + len; - nl := new string (nl_left to l'right); - nl.all := l (nl_left to l'right); - else - if len = 0 then - f := l'right - 1; - end if; - nl_left := f - len; - nl := new string (nl_left downto l'right); - nl.all := l (nl_left downto l'right); - end if; - deallocate (l); - l := nl; - end sread; - - subtype bv4 is bit_vector (1 to 4); - - function char_to_bv4 (c : character) return bv4 is - begin - case c is - when '0' => return "0000"; - when '1' => return "0001"; - when '2' => return "0010"; - when '3' => return "0011"; - when '4' => return "0100"; - when '5' => return "0101"; - when '6' => return "0110"; - when '7' => return "0111"; - when '8' => return "1000"; - when '9' => return "1001"; - when 'a' | 'A' => return "1010"; - when 'b' | 'B' => return "1011"; - when 'c' | 'C' => return "1100"; - when 'd' | 'D' => return "1101"; - when 'e' | 'E' => return "1110"; - when 'f' | 'F' => return "1111"; - when others => - assert false report "bad hexa digit" severity failure; - end case; - end char_to_bv4; - - procedure Oread (L : inout Line; Value : out Bit_Vector; Good : out Boolean) - is - -- Length of Value - constant vlen : natural := value'length; - - -- Number of octal digits for Value - constant olen : natural := (vlen + 2) / 3; - - variable res : bit_vector (1 to olen * 3); - - -- Number of bit to parse. - variable len : natural; - - variable pos : natural; - - -- Last character from LEN to be removed - variable last : integer; - - -- State of the previous byte: - -- SKIP: blank before the bit vector. - -- DIGIT: previous character was a digit - -- UNDERSCORE: was '_' - type state_type is (skip, digit, underscore); - variable state : state_type; - begin - -- Initialization. - if vlen = 0 then - -- If VALUE is a nul array, return now. - -- L stay unchanged. - -- FIXME: should blanks be removed ? - good := true; - return; - end if; - good := false; - state := skip; - pos := res'left; - if l'ascending then - last := l'left - 1; - else - last := l'left + 1; - end if; - for i in l'range loop - case l (i) is - when ' ' - | NBSP - | HT => - exit when state /= skip; - when '_' => - exit when state /= digit; - state := underscore; - when '0' to '7' => - res (pos to pos + 2) := char_to_bv4 (l (i)) (2 to 4); - last := i; - state := digit; - pos := pos + 3; - -- LRM08 16.4 - -- Character removal and compostion also stops when the expected - -- number of digits have been removed. - exit when pos = res'right + 1; - when others => - exit; - end case; - end loop; - - -- LRM08 16.4 - -- The OREAD or HEAD procedure does not succeed if less than the expected - -- number of digits are removed. - if pos /= res'right + 1 then - return; - end if; - - -- LRM08 16.4 - -- The rightmost value'length bits of the binary number are used to form - -- the result for the VALUE parameter, [with a '0' element corresponding - -- to a 0 bit and a '1' element corresponding to a 1 bit]. The OREAD or - -- HREAD procedure does not succeed if any unused bits are 1. - for i in 1 to res'right - vlen loop - if res (i) = '1' then - return; - end if; - end loop; - - Value := res (res'right - vlen + 1 to res'right); - good := true; - trim_next (l, last); - end Oread; - - procedure Oread (L : inout Line; Value : out Bit_Vector) - is - variable res : boolean; - begin - Oread (l, value, res); - assert res = true - report "octal bit_vector read failure" - severity failure; - end Oread; - - procedure Hread (L : inout Line; Value : out Bit_Vector; Good : out Boolean) - is - -- Length of Value - constant vlen : natural := value'length; - - -- Number of hexa digits for Value - constant hlen : natural := (vlen + 3) / 4; - - variable res : bit_vector (1 to hlen * 4); - - -- Number of bit to parse. - variable len : natural; - - variable pos : natural; - - -- Last character from LEN to be removed - variable last : integer; - - -- State of the previous byte: - -- SKIP: blank before the bit vector. - -- DIGIT: previous character was a digit - -- UNDERSCORE: was '_' - type state_type is (skip, digit, underscore); - variable state : state_type; - begin - -- Initialization. - if vlen = 0 then - -- If VALUE is a nul array, return now. - -- L stay unchanged. - -- FIXME: should blanks be removed ? - good := true; - return; - end if; - good := false; - state := skip; - pos := res'left; - if l'ascending then - last := l'left - 1; - else - last := l'left + 1; - end if; - for i in l'range loop - case l (i) is - when ' ' - | NBSP - | HT => - exit when state /= skip; - when '_' => - exit when state /= digit; - state := underscore; - when '0' to '9' | 'a' to 'f' | 'A' to 'F' => - res (pos to pos + 3) := char_to_bv4 (l (i)); - last := i; - state := digit; - pos := pos + 4; - -- LRM08 16.4 - -- Character removal and compostion also stops when the expected - -- number of digits have been removed. - exit when pos = res'right + 1; - when others => - exit; - end case; - end loop; - - -- LRM08 16.4 - -- The OREAD or HEAD procedure does not succeed if less than the expected - -- number of digits are removed. - if pos /= res'right + 1 then - return; - end if; - - -- LRM08 16.4 - -- The rightmost value'length bits of the binary number are used to form - -- the result for the VALUE parameter, [with a '0' element corresponding - -- to a 0 bit and a '1' element corresponding to a 1 bit]. The OREAD or - -- HREAD procedure does not succeed if any unused bits are 1. - for i in 1 to res'right - vlen loop - if res (i) = '1' then - return; - end if; - end loop; - - Value := res (res'right - vlen + 1 to res'right); - good := true; - trim_next (l, last); - end Hread; - - procedure Hread (L : inout Line; Value : out Bit_Vector) - is - variable res : boolean; - begin - Hread (l, value, res); - assert res = true - report "hexa bit_vector read failure" - severity failure; - end Hread; ---END-V08 -end textio; diff --git a/libraries/vital95/vital_primitives-body.vhdl b/libraries/vital95/vital_primitives-body.vhdl new file mode 100644 index 000000000..f8f66366c --- /dev/null +++ b/libraries/vital95/vital_primitives-body.vhdl @@ -0,0 +1,5614 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL_Primitives Package +-- : $Revision$ +-- : +-- Library : VITAL +-- : +-- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 +-- : +-- Purpose : This packages defines standard types, constants, functions +-- : and procedures for use in developing ASIC models. +-- : Specifically a set of logic primitives are defined. +-- : +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/02/95 | Initial ballot draft 1995 +-- v95.1 | | 08/31/95 | #204 - glitch detection prior to OutputMap +-- ---------------------------------------------------------------------------- + +LIBRARY STD; +USE STD.TEXTIO.ALL; + +PACKAGE BODY VITAL_Primitives IS + -- ------------------------------------------------------------------------ + -- Default values for Primitives + -- ------------------------------------------------------------------------ + -- default values for delay parameters + CONSTANT VitalDefDelay01 : VitalDelayType01 := VitalZeroDelay01; + CONSTANT VitalDefDelay01Z : VitalDelayType01Z := VitalZeroDelay01Z; + + TYPE VitalTimeArray IS ARRAY (NATURAL RANGE <>) OF TIME; + + -- default primitive model operation parameters + -- Glitch detection/reporting + TYPE VitalGlitchModeType IS ( MessagePlusX, MessageOnly, XOnly, NoGlitch); + CONSTANT PrimGlitchMode : VitalGlitchModeType := XOnly; + + -- ------------------------------------------------------------------------ + -- Local Type and Subtype Declarations + -- ------------------------------------------------------------------------ + --------------------------------------------------------------------------- + -- enumeration value representing the transition or level of the signal. + -- See function 'GetEdge' + --------------------------------------------------------------------------- + TYPE EdgeType IS ( 'U', -- Uninitialized level + 'X', -- Unknown level + '0', -- low level + '1', -- high level + '\', -- 1 to 0 falling edge + '/', -- 0 to 1 rising edge + 'F', -- * to 0 falling edge + 'R', -- * to 1 rising edge + 'f', -- rising to X edge + 'r', -- falling to X edge + 'x', -- Unknown edge (ie U->X) + 'V' -- Timing violation edge + ); + TYPE EdgeArray IS ARRAY ( NATURAL RANGE <> ) OF EdgeType; + + TYPE EdgeX1Table IS ARRAY ( EdgeType ) OF EdgeType; + TYPE EdgeX2Table IS ARRAY ( EdgeType, EdgeType ) OF EdgeType; + TYPE EdgeX3Table IS ARRAY ( EdgeType, EdgeType, EdgeType ) OF EdgeType; + TYPE EdgeX4Table IS ARRAY (EdgeType,EdgeType,EdgeType,EdgeType) OF EdgeType; + + TYPE LogicToEdgeT IS ARRAY(std_ulogic, std_ulogic) OF EdgeType; + TYPE LogicToLevelT IS ARRAY(std_ulogic ) OF EdgeType; + + TYPE GlitchDataType IS + RECORD + SchedTime : TIME; + GlitchTime : TIME; + SchedValue : std_ulogic; + CurrentValue : std_ulogic; + END RECORD; + TYPE GlitchDataArrayType IS ARRAY (NATURAL RANGE <>) + OF GlitchDataType; + + -- Enumerated type used in selection of output path delays + TYPE SchedType IS + RECORD + inp0 : TIME; -- time (abs) of output change due to input change to 0 + inp1 : TIME; -- time (abs) of output change due to input change to 1 + InpX : TIME; -- time (abs) of output change due to input change to X + Glch0 : TIME; -- time (abs) of output glitch due to input change to 0 + Glch1 : TIME; -- time (abs) of output glitch due to input change to 0 + END RECORD; + + TYPE SchedArray IS ARRAY ( NATURAL RANGE <> ) OF SchedType; + CONSTANT DefSchedType : SchedType := (TIME'HIGH, TIME'HIGH, 0 ns,0 ns,0 ns); + CONSTANT DefSchedAnd : SchedType := (TIME'HIGH, 0 ns,0 ns, TIME'HIGH,0 ns); + + -- Constrained array declarations (common sizes used by primitives) + SUBTYPE SchedArray2 IS SchedArray(1 DOWNTO 0); + SUBTYPE SchedArray3 IS SchedArray(2 DOWNTO 0); + SUBTYPE SchedArray4 IS SchedArray(3 DOWNTO 0); + SUBTYPE SchedArray8 IS SchedArray(7 DOWNTO 0); + + SUBTYPE TimeArray2 IS VitalTimeArray(1 DOWNTO 0); + SUBTYPE TimeArray3 IS VitalTimeArray(2 DOWNTO 0); + SUBTYPE TimeArray4 IS VitalTimeArray(3 DOWNTO 0); + SUBTYPE TimeArray8 IS VitalTimeArray(7 DOWNTO 0); + + SUBTYPE GlitchArray2 IS GlitchDataArrayType(1 DOWNTO 0); + SUBTYPE GlitchArray3 IS GlitchDataArrayType(2 DOWNTO 0); + SUBTYPE GlitchArray4 IS GlitchDataArrayType(3 DOWNTO 0); + SUBTYPE GlitchArray8 IS GlitchDataArrayType(7 DOWNTO 0); + + SUBTYPE EdgeArray2 IS EdgeArray(1 DOWNTO 0); + SUBTYPE EdgeArray3 IS EdgeArray(2 DOWNTO 0); + SUBTYPE EdgeArray4 IS EdgeArray(3 DOWNTO 0); + SUBTYPE EdgeArray8 IS EdgeArray(7 DOWNTO 0); + + CONSTANT DefSchedArray2 : SchedArray2 := + (OTHERS=> (0 ns, 0 ns, 0 ns, 0 ns, 0 ns)); + + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + + CONSTANT InitialEdge : LogicToLevelT := ( + '1'|'H' => 'R', + '0'|'L' => 'F', + OTHERS => 'x' + ); + + CONSTANT LogicToEdge : LogicToEdgeT := ( -- previous, current + -- old \ new: U X 0 1 Z W L H - + 'U' => ( 'U', 'x', 'F', 'R', 'x', 'x', 'F', 'R', 'x' ), + 'X' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ), + '0' => ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ), + '1' => ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ), + 'Z' => ( 'x', 'X', 'F', 'R', 'X', 'x', 'F', 'R', 'x' ), + 'W' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ), + 'L' => ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ), + 'H' => ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ), + '-' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ) + ); + CONSTANT LogicToLevel : LogicToLevelT := ( + '1'|'H' => '1', + '0'|'L' => '0', + 'U' => 'U', + OTHERS => 'X' + ); + + -- ----------------------------------- + -- 3-state logic tables + -- ----------------------------------- + CONSTANT BufIf0_Table : stdlogic_table := + -- enable data value + ( '1'|'H' => ( OTHERS => 'Z' ), + '0'|'L' => ( '1'|'H' => '1', + '0'|'L' => '0', + 'U' => 'U', + OTHERS => 'X' ), + 'U' => ( OTHERS => 'U' ), + OTHERS => ( OTHERS => 'X' ) ); + CONSTANT BufIf1_Table : stdlogic_table := + -- enable data value + ( '0'|'L' => ( OTHERS => 'Z' ), + '1'|'H' => ( '1'|'H' => '1', + '0'|'L' => '0', + 'U' => 'U', + OTHERS => 'X' ), + 'U' => ( OTHERS => 'U' ), + OTHERS => ( OTHERS => 'X' ) ); + CONSTANT InvIf0_Table : stdlogic_table := + -- enable data value + ( '1'|'H' => ( OTHERS => 'Z' ), + '0'|'L' => ( '1'|'H' => '0', + '0'|'L' => '1', + 'U' => 'U', + OTHERS => 'X' ), + 'U' => ( OTHERS => 'U' ), + OTHERS => ( OTHERS => 'X' ) ); + CONSTANT InvIf1_Table : stdlogic_table := + -- enable data value + ( '0'|'L' => ( OTHERS => 'Z' ), + '1'|'H' => ( '1'|'H' => '0', + '0'|'L' => '1', + 'U' => 'U', + OTHERS => 'X' ), + 'U' => ( OTHERS => 'U' ), + OTHERS => ( OTHERS => 'X' ) ); + + + TYPE To_StateCharType IS ARRAY (VitalStateSymbolType) OF CHARACTER; + CONSTANT To_StateChar : To_StateCharType := + ( '/', '\', 'P', 'N', 'r', 'f', 'p', 'n', 'R', 'F', '^', 'v', + 'E', 'A', 'D', '*', 'X', '0', '1', '-', 'B', 'Z', 'S' ); + TYPE To_TruthCharType IS ARRAY (VitalTruthSymbolType) OF CHARACTER; + CONSTANT To_TruthChar : To_TruthCharType := + ( 'X', '0', '1', '-', 'B', 'Z' ); + + TYPE TruthTableOutMapType IS ARRAY (VitalTruthSymbolType) OF std_ulogic; + CONSTANT TruthTableOutMap : TruthTableOutMapType := + -- 'X', '0', '1', '-', 'B', 'Z' + ( 'X', '0', '1', 'X', '-', 'Z' ); + + TYPE StateTableOutMapType IS ARRAY (VitalStateSymbolType) OF std_ulogic; + -- does conversion to X01Z or '-' if invalid + CONSTANT StateTableOutMap : StateTableOutMapType := + -- '/' '\' 'P' 'N' 'r' 'f' 'p' 'n' 'R' 'F' '^' 'v' + -- 'E' 'A' 'D' '*' 'X' '0' '1' '-' 'B' 'Z' 'S' + ( '-','-','-','-','-','-','-','-','-','-','-','-', + '-','-','-','-','X','0','1','X','-','Z','W'); + + -- ------------------------------------------------------------------------ + TYPE ValidTruthTableInputType IS ARRAY (VitalTruthSymbolType) OF BOOLEAN; + -- checks if a symbol IS valid for the stimulus portion of a truth table + CONSTANT ValidTruthTableInput : ValidTruthTableInputType := + -- 'X' '0' '1' '-' 'B' 'Z' + ( TRUE, TRUE, TRUE, TRUE, TRUE, FALSE ); + + TYPE TruthTableMatchType IS ARRAY (X01, VitalTruthSymbolType) OF BOOLEAN; + -- checks if an input matches th corresponding truth table symbol + -- use: TruthTableMatch(input_converted_to_X01, truth_table_stimulus_symbol) + CONSTANT TruthTableMatch : TruthTableMatchType := ( + -- X, 0, 1, - B Z + ( TRUE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- X + ( FALSE, TRUE, FALSE, TRUE, TRUE, FALSE ), -- 0 + ( FALSE, FALSE, TRUE, TRUE, TRUE, FALSE ) -- 1 + ); + + -- ------------------------------------------------------------------------ + TYPE ValidStateTableInputType IS ARRAY (VitalStateSymbolType) OF BOOLEAN; + CONSTANT ValidStateTableInput : ValidStateTableInputType := + -- '/', '\', 'P', 'N', 'r', 'f', + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + -- 'p', 'n', 'R', 'F', '^', 'v', + TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, + -- 'E', 'A', 'D', '*', + TRUE, TRUE, TRUE, TRUE, + -- 'X', '0', '1', '-', 'B', 'Z', + TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, + -- 'S' + TRUE ); + + CONSTANT ValidStateTableState : ValidStateTableInputType := + -- '/', '\', 'P', 'N', 'r', 'f', + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + -- 'p', 'n', 'R', 'F', '^', 'v', + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + -- 'E', 'A', 'D', '*', + FALSE, FALSE, FALSE, FALSE, + -- 'X', '0', '1', '-', 'B', 'Z', + TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, + -- 'S' + FALSE ); + + TYPE StateTableMatchType IS ARRAY (X01,X01,VitalStateSymbolType) OF BOOLEAN; + -- last value, present value, table symbol + CONSTANT StateTableMatch : StateTableMatchType := ( + ( -- X (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE, + TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), + (FALSE,FALSE,FALSE,TRUE, FALSE,FALSE, + FALSE,FALSE,FALSE,TRUE, FALSE,TRUE, + TRUE, FALSE,TRUE, TRUE, + FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE), + (FALSE,FALSE,TRUE, FALSE,FALSE,FALSE, + FALSE,FALSE,TRUE, FALSE,TRUE, FALSE, + TRUE, TRUE, FALSE,TRUE, + FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE) + ), + + (-- 0 (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + (FALSE,FALSE,FALSE,FALSE,TRUE, FALSE, + TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, + FALSE,TRUE, FALSE,TRUE, + TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), + (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,TRUE ), + (TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, + TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,TRUE, + FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE) + ), + + (-- 1 (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + (FALSE,FALSE,FALSE,FALSE,FALSE,TRUE , + FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, + FALSE,FALSE,TRUE, TRUE, + TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), + (FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, + FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, + FALSE,FALSE,FALSE,TRUE, + FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE), + (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,TRUE ) + ) + ); + + TYPE Logic_UX01Z_Table IS ARRAY (std_ulogic) OF UX01Z; + ---------------------------------------------------------- + -- table name : cvt_to_x01z + -- parameters : std_ulogic -- some logic value + -- returns : UX01Z -- state value of logic value + -- purpose : to convert state-strength to state only + ---------------------------------------------------------- + CONSTANT cvt_to_ux01z : Logic_UX01Z_Table := + ('U','X','0','1','Z','X','0','1','X' ); + + TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER; + CONSTANT LogicCvtTable : LogicCvtTableType + := ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'); + + -------------------------------------------------------------------- + -- LOCAL Utilities + -------------------------------------------------------------------- + -- ------------------------------------------------------------------------ + -- FUNCTION NAME : MINIMUM + -- + -- PARAMETERS : in1, in2 - integer, time + -- + -- DESCRIPTION : return smaller of in1 and in2 + -- ------------------------------------------------------------------------ + FUNCTION Minimum ( + CONSTANT in1, in2 : INTEGER + ) RETURN INTEGER IS + BEGIN + IF (in1 < in2) THEN + RETURN in1; + END IF; + RETURN in2; + END; + -- ------------------------------------------------------------------------ + 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 NAME : MAXIMUM + -- + -- PARAMETERS : in1, in2 - integer, time + -- + -- DESCRIPTION : return larger of in1 and in2 + -- ------------------------------------------------------------------------ + FUNCTION Maximum ( + CONSTANT in1, in2 : INTEGER + ) RETURN INTEGER IS + BEGIN + IF (in1 > in2) THEN + RETURN in1; + END IF; + RETURN in2; + END; + ----------------------------------------------------------------------- + FUNCTION Maximum ( + CONSTANT t1,t2 : IN TIME + ) RETURN TIME IS + BEGIN + IF ( t1 > t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; + END Maximum; + + ----------------------------------------------------------------------- + FUNCTION GlitchMinTime ( + CONSTANT Time1, Time2 : IN TIME + ) RETURN TIME IS + BEGIN + IF ( Time1 >= NOW ) THEN + IF ( Time2 >= NOW ) THEN + RETURN Minimum ( Time1, Time2); + ELSE + RETURN Time1; + END IF; + ELSE + IF ( Time2 >= NOW ) THEN + RETURN Time2; + ELSE + RETURN 0 ns; + END IF; + END IF; + END; + + -------------------------------------------------------------------- + -- Error Message Types and Tables + -------------------------------------------------------------------- + TYPE VitalErrorType IS ( + ErrNegDel, + ErrInpSym, + ErrOutSym, + ErrStaSym, + ErrVctLng, + ErrTabWidSml, + ErrTabWidLrg, + ErrTabResSml, + ErrTabResLrg + ); + + TYPE VitalErrorSeverityType IS ARRAY (VitalErrorType) OF SEVERITY_LEVEL; + CONSTANT VitalErrorSeverity : VitalErrorSeverityType := ( + ErrNegDel => WARNING, + ErrInpSym => ERROR, + ErrOutSym => ERROR, + ErrStaSym => ERROR, + ErrVctLng => ERROR, + ErrTabWidSml => ERROR, + ErrTabWidLrg => WARNING, + ErrTabResSml => WARNING, + ErrTabResLrg => WARNING + ); + + CONSTANT MsgNegDel : STRING := + "Negative delay. New output value not scheduled. Output signal is: "; + CONSTANT MsgInpSym : STRING := + "Illegal symbol in the input portion of a Truth/State table."; + CONSTANT MsgOutSym : STRING := + "Illegal symbol in the output portion of a Truth/State table."; + CONSTANT MsgStaSym : STRING := + "Illegal symbol in the state portion of a State table."; + CONSTANT MsgVctLng : STRING := + "Vector (array) lengths not equal. "; + CONSTANT MsgTabWidSml : STRING := + "Width of the Truth/State table is too small."; + CONSTANT MsgTabWidLrg : STRING := + "Width of Truth/State table is too large. Extra elements are ignored."; + CONSTANT MsgTabResSml : STRING := + "Result of Truth/State table has too many elements."; + CONSTANT MsgTabResLrg : STRING := + "Result of Truth/State table has too few elements."; + + CONSTANT MsgUnknown : STRING := + "Unknown error message."; + + -------------------------------------------------------------------- + -- LOCAL Utilities + -------------------------------------------------------------------- + FUNCTION VitalMessage ( + CONSTANT ErrorId : IN VitalErrorType + ) RETURN STRING IS + BEGIN + CASE ErrorId IS + WHEN ErrNegDel => RETURN MsgNegDel; + WHEN ErrInpSym => RETURN MsgInpSym; + WHEN ErrOutSym => RETURN MsgOutSym; + WHEN ErrStaSym => RETURN MsgStaSym; + WHEN ErrVctLng => RETURN MsgVctLng; + WHEN ErrTabWidSml => RETURN MsgTabWidSml; + WHEN ErrTabWidLrg => RETURN MsgTabWidLrg; + WHEN ErrTabResSml => RETURN MsgTabResSml; + WHEN ErrTabResLrg => RETURN MsgTabResLrg; + 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; + + --------------------------------------------------------------------------- + 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 Preemted 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 : VitalGlitchOnEvent + -- : + -- Parameters : OutSignal ........ signal being driven + -- : OutSignalName..... name of the driven signal + -- : GlitchData........ internal data required by the procedure + -- : NewValue.......... new value being assigned + -- : NewDelay.......... Delay accompanying the assignment + -- : (Note: for vectors, this is an array) + -- : GlitchMode........ Glitch generation mode + -- : MessagePlusX, MessageOnly, + -- : XOnly, NoGlitch ) + -- : GlitchDelay....... if <= 0 ns , then there will be no Glitch + -- : if > NewDelay, then there is no Glitch, + -- : otherwise, this is the time when a FORCED + -- : generation of a glitch will occur. + ---------------------------------------------------------------------------- + PROCEDURE VitalGlitchOnEvent ( + SIGNAL OutSignal : OUT std_logic; + CONSTANT OutSignalName : IN STRING; + VARIABLE GlitchData : INOUT GlitchDataType; + CONSTANT NewValue : IN std_logic; + CONSTANT NewDelay : IN TIME := 0 ns; + CONSTANT GlitchMode : IN VitalGlitchModeType := MessagePlusX; + CONSTANT GlitchDelay : IN TIME := 0 ns; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + -- ------------------------------------------------------------------------ + VARIABLE NoGlitchDet : BOOLEAN := FALSE; + VARIABLE OldGlitch : BOOLEAN := FALSE; + VARIABLE Dly : TIME := NewDelay; + + BEGIN + -- If nothing to schedule, just return + IF NewDelay < 0 ns THEN + IF (NewValue /= GlitchData.SchedValue) THEN + VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName ); + END IF; + + ELSE + -- If nothing currently scheduled + IF GlitchData.SchedTime <= NOW THEN + GlitchData.CurrentValue := GlitchData.SchedValue; + IF (GlitchDelay <= 0 ns) THEN + IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF; + NoGlitchDet := TRUE; + END IF; + + -- Transaction currently scheduled - if glitch already happened + ELSIF GlitchData.GlitchTime <= NOW THEN + GlitchData.CurrentValue := 'X'; + OldGlitch := TRUE; + IF (GlitchData.SchedValue = NewValue) THEN + dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); + END IF; + + -- Transaction currently scheduled (no glitch if same value) + ELSIF (GlitchData.SchedValue = NewValue) AND + (GlitchData.SchedTime = GlitchData.GlitchTime) AND + (GlitchDelay <= 0 ns) THEN + NoGlitchDet := TRUE; + Dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); + + END IF; + + GlitchData.SchedTime := NOW+Dly; + IF OldGlitch THEN + OutSignal <= NewValue AFTER Dly; + + ELSIF NoGlitchDet THEN + GlitchData.GlitchTime := NOW+Dly; + OutSignal <= NewValue AFTER Dly; + + ELSE -- new glitch + GlitchData.GlitchTime := GlitchMinTime ( GlitchData.GlitchTime, + NOW+GlitchDelay ); + + IF (GlitchMode = MessagePlusX) OR + (GlitchMode = MessageOnly) THEN + ReportGlitch ( "VitalGlitchOnEvent", OutSignalName, + GlitchData.GlitchTime, GlitchData.SchedValue, + (Dly + NOW), NewValue, + MsgSeverity=>MsgSeverity ); + END IF; + + IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN + OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW; + OutSignal <= TRANSPORT NewValue AFTER Dly; + ELSE + OutSignal <= NewValue AFTER Dly; + END IF; + END IF; + + GlitchData.SchedValue := NewValue; + END IF; + + RETURN; + END; + + ---------------------------------------------------------------------------- + PROCEDURE VitalGlitchOnEvent ( + SIGNAL OutSignal : OUT std_logic_vector; + CONSTANT OutSignalName : IN STRING; + VARIABLE GlitchData : INOUT GlitchDataArrayType; + CONSTANT NewValue : IN std_logic_vector; + CONSTANT NewDelay : IN VitalTimeArray; + CONSTANT GlitchMode : IN VitalGlitchModeType := MessagePlusX; + CONSTANT GlitchDelay : IN VitalTimeArray; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + + ALIAS GlDataAlias : GlitchDataArrayType(1 TO GlitchData'LENGTH) + IS GlitchData; + ALIAS NewValAlias : std_logic_vector(1 TO NewValue'LENGTH) IS NewValue; + ALIAS GlDelayAlias : VitalTimeArray(1 TO GlitchDelay'LENGTH) + IS GlitchDelay; + ALIAS NewDelAlias : VitalTimeArray(1 TO NewDelay'LENGTH) IS NewDelay; + + VARIABLE Index : INTEGER := OutSignal'LEFT; + VARIABLE Direction : INTEGER; + VARIABLE NoGlitchDet : BOOLEAN; + VARIABLE OldGlitch : BOOLEAN; + VARIABLE Dly, GlDly : TIME; + + BEGIN + IF (OutSignal'LEFT > OutSignal'RIGHT) THEN + Direction := -1; + ELSE + Direction := 1; + END IF; + + IF ( (OutSignal'LENGTH /= GlitchData'LENGTH) OR + (OutSignal'LENGTH /= NewValue'LENGTH) OR + (OutSignal'LENGTH /= NewDelay'LENGTH) OR + (OutSignal'LENGTH /= GlitchDelay'LENGTH) ) THEN + VitalError ( "VitalGlitchOnEvent", ErrVctLng, OutSignalName ); + RETURN; + END IF; + + -- a call to the scalar function cannot be made since the actual + -- name associated with a signal parameter must be locally static + FOR n IN 1 TO OutSignal'LENGTH LOOP + + NoGlitchDet := FALSE; + OldGlitch := FALSE; + Dly := NewDelAlias(n); + + -- If nothing to schedule, just skip to next loop iteration + IF NewDelAlias(n) < 0 ns THEN + IF (NewValAlias(n) /= GlDataAlias(n).SchedValue) THEN + VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName ); + END IF; + ELSE + -- If nothing currently scheduled (i.e. last scheduled + -- transaction already occurred) + IF GlDataAlias(n).SchedTime <= NOW THEN + GlDataAlias(n).CurrentValue := GlDataAlias(n).SchedValue; + IF (GlDelayAlias(n) <= 0 ns) THEN + -- Next iteration if no change in value + IF (NewValAlias(n) = GlDataAlias(n).SchedValue) THEN + Index := Index + Direction; + NEXT; + END IF; + -- since last transaction already occurred there is no glitch + NoGlitchDet := TRUE; + END IF; + + -- Transaction currently scheduled - if glitch already happened + ELSIF GlDataAlias(n).GlitchTime <= NOW THEN + GlDataAlias(n).CurrentValue := 'X'; + OldGlitch := TRUE; + IF (GlDataAlias(n).SchedValue = NewValAlias(n)) THEN + dly := Minimum( GlDataAlias(n).SchedTime-NOW, + NewDelAlias(n) ); + END IF; + + -- Transaction currently scheduled + ELSIF (GlDataAlias(n).SchedValue = NewValAlias(n)) AND + (GlDataAlias(n).SchedTime = GlDataAlias(n).GlitchTime) AND + (GlDelayAlias(n) <= 0 ns) THEN + NoGlitchDet := TRUE; + Dly := Minimum( GlDataAlias(n).SchedTime-NOW, + NewDelAlias(n) ); + END IF; + + -- update last scheduled transaction + GlDataAlias(n).SchedTime := NOW+Dly; + + IF OldGlitch THEN + OutSignal(Index) <= NewValAlias(n) AFTER Dly; + ELSIF NoGlitchDet THEN + -- if no glitch then update last glitch time + -- and OutSignal(actual_index) + GlDataAlias(n).GlitchTime := NOW+Dly; + OutSignal(Index) <= NewValAlias(n) AFTER Dly; + ELSE -- new glitch + GlDataAlias(n).GlitchTime := GlitchMinTime ( + GlDataAlias(n).GlitchTime, + NOW+GlDelayAlias(n) ); + + IF (GlitchMode = MessagePlusX) OR + (GlitchMode = MessageOnly) THEN + ReportGlitch ( "VitalGlitchOnEvent", OutSignalName, + GlDataAlias(n).GlitchTime, + GlDataAlias(n).SchedValue, + (Dly + NOW), NewValAlias(n), + Index, TRUE, MsgSeverity ); + END IF; + + IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN + GlDly := GlDataAlias(n).GlitchTime - NOW; + OutSignal(Index) <= 'X' AFTER GlDly; + OutSignal(Index) <= TRANSPORT NewValAlias(n) AFTER Dly; + ELSE + OutSignal(Index) <= NewValAlias(n) AFTER Dly; + END IF; + + END IF; -- glitch / no-glitch + GlDataAlias(n).SchedValue := NewValAlias(n); + + END IF; -- NewDelAlias(n) < 0 ns + Index := Index + Direction; + END LOOP; + + RETURN; + END; + + --------------------------------------------------------------------------- + -- ------------------------------------------------------------------------ + -- PROCEDURE NAME : TruthOutputX01Z + -- + -- PARAMETERS : table_out - output of table + -- X01Zout - output converted to X01Z + -- err - true if illegal character is encountered + -- + -- + -- DESCRIPTION : converts the output of a truth table to a valid + -- std_ulogic + -- ------------------------------------------------------------------------ + PROCEDURE TruthOutputX01Z ( + CONSTANT TableOut : IN VitalTruthSymbolType; + VARIABLE X01Zout : OUT std_ulogic; + VARIABLE Err : OUT BOOLEAN + ) IS + VARIABLE TempOut : std_ulogic; + BEGIN + Err := FALSE; + TempOut := TruthTableOutMap(TableOut); + IF (TempOut = '-') THEN + Err := TRUE; + TempOut := 'X'; + VitalError ( "VitalTruthTable", ErrOutSym, To_TruthChar(TableOut)); + END IF; + X01Zout := TempOut; + END; + + -- ------------------------------------------------------------------------ + -- PROCEDURE NAME : StateOutputX01Z + -- + -- PARAMETERS : table_out - output of table + -- prev_out - previous output value + -- X01Zout - output cojnverted to X01Z + -- err - true if illegal character is encountered + -- + -- DESCRIPTION : converts the output of a state table to a + -- valid std_ulogic + -- ------------------------------------------------------------------------ + PROCEDURE StateOutputX01Z ( + CONSTANT TableOut : IN VitalStateSymbolType; + CONSTANT PrevOut : IN std_ulogic; + VARIABLE X01Zout : OUT std_ulogic; + VARIABLE Err : OUT BOOLEAN + ) IS + VARIABLE TempOut : std_ulogic; + BEGIN + Err := FALSE; + TempOut := StateTableOutMap(TableOut); + IF (TempOut = '-') THEN + Err := TRUE; + TempOut := 'X'; + VitalError ( "VitalStateTable", ErrOutSym, To_StateChar(TableOut)); + ELSIF (TempOut = 'W') THEN + TempOut := To_X01Z(PrevOut); + END IF; + X01Zout := TempOut; + END; + + -- ------------------------------------------------------------------------ + -- PROCEDURE NAME: StateMatch + -- + -- PARAMETERS : symbol - symbol from state table + -- in2 - input from VitalStateTble procedure + -- to state table + -- in2LastValue - previous value of input + -- state - false if the symbol is from the input + -- portion of the table, + -- true if the symbol is from the state + -- portion of the table + -- Err - true if symbol is not a valid input symbol + -- ReturnValue - true if match occurred + -- + -- DESCRIPTION : This procedure sets ReturnValue to true if in2 matches + -- symbol (from the state table). If symbol is an edge + -- value edge is set to true and in2 and in2LastValue are + -- checked against symbol. Err is set to true if symbol + -- is an invalid value for the input portion of the state + -- table. + -- + -- ------------------------------------------------------------------------ + PROCEDURE StateMatch ( + CONSTANT Symbol : IN VitalStateSymbolType; + CONSTANT in2 : IN std_ulogic; + CONSTANT in2LastValue : IN std_ulogic; + CONSTANT State : IN BOOLEAN; + VARIABLE Err : OUT BOOLEAN; + VARIABLE ReturnValue : OUT BOOLEAN + ) IS + BEGIN + IF (State) THEN + IF (NOT ValidStateTableState(Symbol)) THEN + VitalError ( "VitalStateTable", ErrStaSym, To_StateChar(Symbol)); + Err := TRUE; + ReturnValue := FALSE; + ELSE + Err := FALSE; + ReturnValue := StateTableMatch(in2LastValue, in2, Symbol); + END IF; + ELSE + IF (NOT ValidStateTableInput(Symbol) ) THEN + VitalError ( "VitalStateTable", ErrInpSym, To_StateChar(Symbol)); + Err := TRUE; + ReturnValue := FALSE; + ELSE + ReturnValue := StateTableMatch(in2LastValue, in2, Symbol); + Err := FALSE; + END IF; + END IF; + END; + + -- ----------------------------------------------------------------------- + -- FUNCTION NAME: StateTableLookUp + -- + -- PARAMETERS : StateTable - state table + -- PresentDataIn - current inputs + -- PreviousDataIn - previous inputs and states + -- NumStates - number of state variables + -- PresentOutputs - current state and current outputs + -- + -- DESCRIPTION : This function is used to find the output of the + -- StateTable corresponding to a given set of inputs. + -- + -- ------------------------------------------------------------------------ + FUNCTION StateTableLookUp ( + CONSTANT StateTable : VitalStateTableType; + CONSTANT PresentDataIn : std_logic_vector; + CONSTANT PreviousDataIn : std_logic_vector; + CONSTANT NumStates : NATURAL; + CONSTANT PresentOutputs : std_logic_vector + ) RETURN std_logic_vector IS + + CONSTANT InputSize : INTEGER := PresentDataIn'LENGTH; + CONSTANT NumInputs : INTEGER := InputSize + NumStates - 1; + CONSTANT TableEntries : INTEGER := StateTable'LENGTH(1); + CONSTANT TableWidth : INTEGER := StateTable'LENGTH(2); + CONSTANT OutSize : INTEGER := TableWidth - InputSize - NumStates; + VARIABLE Inputs : std_logic_vector(0 TO NumInputs); + VARIABLE PrevInputs : std_logic_vector(0 TO NumInputs) + := (OTHERS => 'X'); + VARIABLE ReturnValue : std_logic_vector(0 TO (OutSize-1)) + := (OTHERS => 'X'); + VARIABLE Temp : std_ulogic; + VARIABLE Match : BOOLEAN; + VARIABLE Err : BOOLEAN := FALSE; + + -- This needs to be done since the TableLookup arrays must be + -- ascending starting with 0 + VARIABLE TableAlias : VitalStateTableType(0 TO TableEntries - 1, + 0 TO TableWidth - 1) + := StateTable; + + BEGIN + Inputs(0 TO InputSize-1) := PresentDataIn; + Inputs(InputSize TO NumInputs) := PresentOutputs(0 TO NumStates - 1); + PrevInputs(0 TO InputSize - 1) := PreviousDataIn(0 TO InputSize - 1); + + ColLoop: -- Compare each entry in the table + FOR i IN TableAlias'RANGE(1) LOOP + + RowLoop: -- Check each element of the entry + FOR j IN 0 TO InputSize + NumStates LOOP + + IF (j = InputSize + NumStates) THEN -- a match occurred + FOR k IN 0 TO Minimum(OutSize, PresentOutputs'LENGTH)-1 LOOP + StateOutputX01Z ( + TableAlias(i, TableWidth - k - 1), + PresentOutputs(PresentOutputs'LENGTH - k - 1), + Temp, Err); + ReturnValue(OutSize - k - 1) := Temp; + IF (Err) THEN + ReturnValue := (OTHERS => 'X'); + RETURN ReturnValue; + END IF; + END LOOP; + RETURN ReturnValue; + END IF; + + StateMatch ( TableAlias(i,j), + Inputs(j), PrevInputs(j), + j >= InputSize, Err, Match); + EXIT RowLoop WHEN NOT(Match); + EXIT ColLoop WHEN Err; + END LOOP RowLoop; + END LOOP ColLoop; + + ReturnValue := (OTHERS => 'X'); + RETURN ReturnValue; + END; + + -------------------------------------------------------------------- + -- to_ux01z + ------------------------------------------------------------------- + FUNCTION To_UX01Z ( s : std_ulogic + ) RETURN UX01Z IS + BEGIN + RETURN cvt_to_ux01z (s); + END; + + --------------------------------------------------------------------------- + -- Function : GetEdge + -- Purpose : Converts transitions on a given input signal into a + -- enumeration value representing the transition or level + -- of the signal. + -- + -- previous "value" current "value" := "edge" + -- --------------------------------------------------------- + -- '1' | 'H' '1' | 'H' '1' level, no edge + -- '0' | 'L' '1' | 'H' '/' rising edge + -- others '1' | 'H' 'R' rising from X + -- + -- '1' | 'H' '0' | 'L' '\' falling egde + -- '0' | 'L' '0' | 'L' '0' level, no edge + -- others '0' | 'L' 'F' falling from X + -- + -- 'X' | 'W' | '-' 'X' | 'W' | '-' 'X' unknown (X) level + -- 'Z' 'Z' 'X' unknown (X) level + -- 'U' 'U' 'U' 'U' level + -- + -- '1' | 'H' others 'f' falling to X + -- '0' | 'L' others 'r' rising to X + -- 'X' | 'W' | '-' 'U' | 'Z' 'x' unknown (X) edge + -- 'Z' 'X' | 'W' | '-' | 'U' 'x' unknown (X) edge + -- 'U' 'X' | 'W' | '-' | 'Z' 'x' unknown (X) edge + -- + --------------------------------------------------------------------------- + FUNCTION GetEdge ( + SIGNAL s : IN std_logic + ) RETURN EdgeType IS + BEGIN + IF (s'EVENT) + THEN RETURN LogicToEdge ( s'LAST_VALUE, s ); + ELSE RETURN LogicToLevel ( s ); + END IF; + END; + + --------------------------------------------------------------------------- + PROCEDURE GetEdge ( + SIGNAL s : IN std_logic_vector; + VARIABLE LastS : INOUT std_logic_vector; + VARIABLE Edge : OUT EdgeArray ) IS + + ALIAS sAlias : std_logic_vector ( 1 TO s'LENGTH ) IS s; + ALIAS LastSAlias : std_logic_vector ( 1 TO LastS'LENGTH ) IS LastS; + ALIAS EdgeAlias : EdgeArray ( 1 TO Edge'LENGTH ) IS Edge; + BEGIN + IF s'LENGTH /= LastS'LENGTH OR + s'LENGTH /= Edge'LENGTH THEN + VitalError ( "GetEdge", ErrVctLng, "s, LastS, Edge" ); + END IF; + + FOR n IN 1 TO s'LENGTH LOOP + EdgeAlias(n) := LogicToEdge( LastSAlias(n), sAlias(n) ); + LastSAlias(n) := sAlias(n); + END LOOP; + END; + + --------------------------------------------------------------------------- + FUNCTION ToEdge ( Value : IN std_logic + ) RETURN EdgeType IS + BEGIN + RETURN LogicToLevel( Value ); + END; + + -- Note: This function will likely be replaced by S'DRIVING_VALUE in VHDL'92 + ---------------------------------------------------------------------------- + FUNCTION CurValue ( + CONSTANT GlitchData : IN GlitchDataType + ) RETURN std_logic IS + BEGIN + IF NOW >= GlitchData.SchedTime THEN + RETURN GlitchData.SchedValue; + ELSIF NOW >= GlitchData.GlitchTime THEN + RETURN 'X'; + ELSE + RETURN GlitchData.CurrentValue; + END IF; + END; + --------------------------------------------------------------------------- + FUNCTION CurValue ( + CONSTANT GlitchData : IN GlitchDataArrayType + ) RETURN std_logic_vector IS + VARIABLE Result : std_logic_vector(GlitchData'RANGE); + BEGIN + FOR n IN GlitchData'RANGE LOOP + IF NOW >= GlitchData(n).SchedTime THEN + Result(n) := GlitchData(n).SchedValue; + ELSIF NOW >= GlitchData(n).GlitchTime THEN + Result(n) := 'X'; + ELSE + Result(n) := GlitchData(n).CurrentValue; + END IF; + END LOOP; + RETURN Result; + END; + + --------------------------------------------------------------------------- + -- function calculation utilities + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Function : VitalSame + -- Returns : VitalSame compares the state (UX01) of two logic value. A + -- value of 'X' is returned if the values are different. The + -- common value is returned if the values are equal. + -- Purpose : When the result of a logic model may be either of two + -- separate input values (eg. when the select on a MUX is 'X'), + -- VitalSame may be used to determine if the result needs to + -- be 'X'. + -- Arguments : See the declarations below... + --------------------------------------------------------------------------- + FUNCTION VitalSame ( + CONSTANT a, b : IN std_ulogic + ) RETURN std_ulogic IS + BEGIN + IF To_UX01(a) = To_UX01(b) + THEN RETURN To_UX01(a); + ELSE RETURN 'X'; + END IF; + END; + + --------------------------------------------------------------------------- + -- delay selection utilities + --------------------------------------------------------------------------- + + --------------------------------------------------------------------------- + -- Procedure : BufPath, InvPath + -- + -- Purpose : BufPath and InvPath compute output change times, based on + -- a change on an input port. The computed output change times + -- returned in the composite parameter 'schd'. + -- + -- BufPath and InpPath are used together with the delay path + -- selection functions (GetSchedDelay, VitalAND, VitalOR... ) + -- The 'schd' value from each of the input ports of a model are + -- combined by the delay selection functions (VitalAND, + -- VitalOR, ...). The GetSchedDelay procedure converts the + -- combined output changes times to the single delay (delta + -- time) value for scheduling the output change (passed to + -- VitalGlitchOnEvent). + -- + -- The values in 'schd' are: (absolute times) + -- inp0 : time of output change due to input change to 0 + -- inp1 : time of output change due to input change to 1 + -- inpX : time of output change due to input change to X + -- glch0 : time of output glitch due to input change to 0 + -- glch1 : time of output glitch due to input change to 1 + -- + -- The output times are computed from the model INPUT value + -- and not the final value. For this reason, 'BufPath' should + -- be used to compute the output times for a non-inverting + -- delay paths and 'InvPath' should be used to compute the + -- ouput times for inverting delay paths. Delay paths which + -- include both non-inverting and paths require usage of both + -- 'BufPath' and 'InvPath'. (IE this is needed for the + -- select->output path of a MUX -- See the VitalMUX model). + -- + -- + -- Parameters : schd....... Computed output result times. (INOUT parameter + -- modified only on input edges) + -- Iedg....... Input port edge/level value. + -- tpd....... Propagation delays from this input + -- + --------------------------------------------------------------------------- + + PROCEDURE BufPath ( + VARIABLE Schd : INOUT SchedType; + CONSTANT Iedg : IN EdgeType; + CONSTANT tpd : IN VitalDelayType01 + ) IS + BEGIN + CASE Iedg IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd.inp0 := TIME'HIGH; + Schd.inp1 := NOW + tpd(tr01); Schd.Glch1 := Schd.inp1; + Schd.InpX := Schd.inp1; + WHEN '\'|'F' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := NOW + tpd(tr10); Schd.Glch0 := Schd.inp0; + Schd.InpX := Schd.inp0; + WHEN 'r' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := TIME'HIGH; + Schd.InpX := NOW + tpd(tr01); + WHEN 'f' => Schd.inp0 := TIME'HIGH; + Schd.inp1 := TIME'HIGH; + Schd.InpX := NOW + tpd(tr10); + WHEN 'x' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := TIME'HIGH; + -- update for X->X change + Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END; + + PROCEDURE BufPath ( + VARIABLE Schd : INOUT SchedArray; + CONSTANT Iedg : IN EdgeArray; + CONSTANT tpd : IN VitalDelayArrayType01 + ) IS + BEGIN + FOR n IN Schd'RANGE LOOP + CASE Iedg(n) IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH; + Schd(n).inp1 := NOW + tpd(n)(tr01); + Schd(n).Glch1 := Schd(n).inp1; + Schd(n).InpX := Schd(n).inp1; + WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := NOW + tpd(n)(tr10); + Schd(n).Glch0 := Schd(n).inp0; + Schd(n).InpX := Schd(n).inp0; + WHEN 'r' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := TIME'HIGH; + Schd(n).InpX := NOW + tpd(n)(tr01); + WHEN 'f' => Schd(n).inp0 := TIME'HIGH; + Schd(n).inp1 := TIME'HIGH; + Schd(n).InpX := NOW + tpd(n)(tr10); + WHEN 'x' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := TIME'HIGH; + -- update for X->X change + Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10), + tpd(n)(tr01) ); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END LOOP; + END; + + PROCEDURE InvPath ( + VARIABLE Schd : INOUT SchedType; + CONSTANT Iedg : IN EdgeType; + CONSTANT tpd : IN VitalDelayType01 + ) IS + BEGIN + CASE Iedg IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd.inp0 := TIME'HIGH; + Schd.inp1 := NOW + tpd(tr10); Schd.Glch1 := Schd.inp1; + Schd.InpX := Schd.inp1; + WHEN '\'|'F' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := NOW + tpd(tr01); Schd.Glch0 := Schd.inp0; + Schd.InpX := Schd.inp0; + WHEN 'r' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := TIME'HIGH; + Schd.InpX := NOW + tpd(tr10); + WHEN 'f' => Schd.inp0 := TIME'HIGH; + Schd.inp1 := TIME'HIGH; + Schd.InpX := NOW + tpd(tr01); + WHEN 'x' => Schd.inp1 := TIME'HIGH; + Schd.inp0 := TIME'HIGH; + -- update for X->X change + Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END; + + PROCEDURE InvPath ( + VARIABLE Schd : INOUT SchedArray; + CONSTANT Iedg : IN EdgeArray; + CONSTANT tpd : IN VitalDelayArrayType01 + ) IS + BEGIN + FOR n IN Schd'RANGE LOOP + CASE Iedg(n) IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH; + Schd(n).inp1 := NOW + tpd(n)(tr10); + Schd(n).Glch1 := Schd(n).inp1; + Schd(n).InpX := Schd(n).inp1; + WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := NOW + tpd(n)(tr01); + Schd(n).Glch0 := Schd(n).inp0; + Schd(n).InpX := Schd(n).inp0; + WHEN 'r' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := TIME'HIGH; + Schd(n).InpX := NOW + tpd(n)(tr10); + WHEN 'f' => Schd(n).inp0 := TIME'HIGH; + Schd(n).inp1 := TIME'HIGH; + Schd(n).InpX := NOW + tpd(n)(tr01); + WHEN 'x' => Schd(n).inp1 := TIME'HIGH; + Schd(n).inp0 := TIME'HIGH; + -- update for X->X change + Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10), + tpd(n)(tr01) ); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END LOOP; + END; + + --------------------------------------------------------------------------- + -- Procedure : BufEnab, InvEnab + -- + -- Purpose : BufEnab and InvEnab compute output change times, from a + -- change on an input enable port for a 3-state driver. The + -- computed output change times are returned in the composite + -- parameters 'schd1', 'schd0'. + -- + -- BufEnab and InpEnab are used together with the delay path + -- selection functions (GetSchedDelay, VitalAND, VitalOR... ) + -- The 'schd' value from each of the non-enable input ports of + -- a model (See BufPath, InvPath) are combined using the delay + -- selection functions (VitalAND, VitalOR, ...). The + -- GetSchedDelay procedure combines the output times on the + -- enable path with the output times from the data path(s) and + -- computes the single delay (delta time) value for scheduling + -- the output change (passed to VitalGlitchOnEvent) + -- + -- The values in 'schd*' are: (absolute times) + -- inp0 : time of output change due to input change to 0 + -- inp1 : time of output change due to input change to 1 + -- inpX : time of output change due to input change to X + -- glch0 : time of output glitch due to input change to 0 + -- glch1 : time of output glitch due to input change to 1 + -- + -- 'schd1' contains output times for 1->Z, Z->1 transitions. + -- 'schd0' contains output times for 0->Z, Z->0 transitions. + -- + -- 'BufEnab' is used for computing the output times for an + -- high asserted enable (output 'Z' for enable='0'). + -- 'InvEnab' is used for computing the output times for an + -- low asserted enable (output 'Z' for enable='1'). + -- + -- Note: separate 'schd1', 'schd0' parameters are generated + -- so that the combination of the delay paths from + -- multiple enable signals may be combined using the + -- same functions/operators used in combining separate + -- data paths. (See exampe 2 below) + -- + -- + -- Parameters : schd1...... Computed output result times for 1->Z, Z->1 + -- transitions. This parameter is modified only on + -- input edge values (events). + -- schd0...... Computed output result times for 0->Z, 0->1 + -- transitions. This parameter is modified only on + -- input edge values (events). + -- Iedg....... Input port edge/level value. + -- tpd....... Propagation delays for the enable -> output path. + -- + --------------------------------------------------------------------------- + PROCEDURE BufEnab ( + VARIABLE Schd1 : INOUT SchedType; + VARIABLE Schd0 : INOUT SchedType; + CONSTANT Iedg : IN EdgeType; + CONSTANT tpd : IN VitalDelayType01Z + ) IS + BEGIN + CASE Iedg IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := NOW + tpd(trz1); + Schd1.Glch1 := Schd1.inp1; + Schd1.InpX := Schd1.inp1; + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := NOW + tpd(trz0); + Schd0.Glch1 := Schd0.inp1; + Schd0.InpX := Schd0.inp1; + WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH; + Schd1.inp0 := NOW + tpd(tr1z); + Schd1.Glch0 := Schd1.inp0; + Schd1.InpX := Schd1.inp0; + Schd0.inp1 := TIME'HIGH; + Schd0.inp0 := NOW + tpd(tr0z); + Schd0.Glch0 := Schd0.inp0; + Schd0.InpX := Schd0.inp0; + WHEN 'r' => Schd1.inp1 := TIME'HIGH; + Schd1.inp0 := TIME'HIGH; + Schd1.InpX := NOW + tpd(trz1); + Schd0.inp1 := TIME'HIGH; + Schd0.inp0 := TIME'HIGH; + Schd0.InpX := NOW + tpd(trz0); + WHEN 'f' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := TIME'HIGH; + Schd1.InpX := NOW + tpd(tr1z); + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := TIME'HIGH; + Schd0.InpX := NOW + tpd(tr0z); + WHEN 'x' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := TIME'HIGH; + Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := TIME'HIGH; + Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END; + + PROCEDURE InvEnab ( + VARIABLE Schd1 : INOUT SchedType; + VARIABLE Schd0 : INOUT SchedType; + CONSTANT Iedg : IN EdgeType; + CONSTANT tpd : IN VitalDelayType01Z + ) IS + BEGIN + CASE Iedg IS + WHEN '0'|'1' => NULL; -- no edge: no timing update + WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := NOW + tpd(tr1z); + Schd1.Glch1 := Schd1.inp1; + Schd1.InpX := Schd1.inp1; + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := NOW + tpd(tr0z); + Schd0.Glch1 := Schd0.inp1; + Schd0.InpX := Schd0.inp1; + WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH; + Schd1.inp0 := NOW + tpd(trz1); + Schd1.Glch0 := Schd1.inp0; + Schd1.InpX := Schd1.inp0; + Schd0.inp1 := TIME'HIGH; + Schd0.inp0 := NOW + tpd(trz0); + Schd0.Glch0 := Schd0.inp0; + Schd0.InpX := Schd0.inp0; + WHEN 'r' => Schd1.inp1 := TIME'HIGH; + Schd1.inp0 := TIME'HIGH; + Schd1.InpX := NOW + tpd(tr1z); + Schd0.inp1 := TIME'HIGH; + Schd0.inp0 := TIME'HIGH; + Schd0.InpX := NOW + tpd(tr0z); + WHEN 'f' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := TIME'HIGH; + Schd1.InpX := NOW + tpd(trz1); + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := TIME'HIGH; + Schd0.InpX := NOW + tpd(trz0); + WHEN 'x' => Schd1.inp0 := TIME'HIGH; + Schd1.inp1 := TIME'HIGH; + Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + Schd0.inp0 := TIME'HIGH; + Schd0.inp1 := TIME'HIGH; + Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); + WHEN OTHERS => NULL; -- no timing change + END CASE; + END; + + --------------------------------------------------------------------------- + -- Procedure : GetSchedDelay + -- + -- Purpose : GetSchedDelay computes the final delay (incremental) for + -- for scheduling an output signal. The delay is computed + -- from the absolute output times in the 'NewSched' parameter. + -- (See BufPath, InvPath). + -- + -- Computation of the output delay for non-3_state outputs + -- consists of selection the appropriate output time based + -- on the new output value 'NewValue' and subtracting 'NOW' + -- to convert to an incremental delay value. + -- + -- The Computation of the output delay for 3_state output + -- also includes combination of the enable path delay with + -- the date path delay. + -- + -- Parameters : NewDelay... Returned output delay value. + -- GlchDelay.. Returned output delay for the start of a glitch. + -- NewValue... New output value. + -- CurValue... Current value of the output. + -- NewSched... Composite containing the combined absolute + -- output times from the data inputs. + -- EnSched1... Composite containing the combined absolute + -- output times from the enable input(s). + -- (for a 3_state output transitions 1->Z, Z->1) + -- EnSched0... Composite containing the combined absolute + -- output times from the enable input(s). + -- (for a 3_state output transitions 0->Z, Z->0) + -- + --------------------------------------------------------------------------- + PROCEDURE GetSchedDelay ( + VARIABLE NewDelay : OUT TIME; + VARIABLE GlchDelay : OUT TIME; + CONSTANT NewValue : IN std_ulogic; + CONSTANT CurValue : IN std_ulogic; + CONSTANT NewSched : IN SchedType + ) IS + VARIABLE Tim, Glch : TIME; + BEGIN + + CASE To_UX01(NewValue) IS + WHEN '0' => Tim := NewSched.inp0; + Glch := NewSched.Glch1; + WHEN '1' => Tim := NewSched.inp1; + Glch := NewSched.Glch0; + WHEN OTHERS => Tim := NewSched.InpX; + Glch := -1 ns; + END CASE; + IF (CurValue /= NewValue) + THEN Glch := -1 ns; + END IF; + + NewDelay := Tim - NOW; + IF Glch < 0 ns + THEN GlchDelay := Glch; + ELSE GlchDelay := Glch - NOW; + END IF; -- glch < 0 ns + END; + + PROCEDURE GetSchedDelay ( + VARIABLE NewDelay : OUT VitalTimeArray; + VARIABLE GlchDelay : OUT VitalTimeArray; + CONSTANT NewValue : IN std_logic_vector; + CONSTANT CurValue : IN std_logic_vector; + CONSTANT NewSched : IN SchedArray + ) IS + VARIABLE Tim, Glch : TIME; + ALIAS NewDelayAlias : VitalTimeArray( NewDelay'LENGTH DOWNTO 1) + IS NewDelay; + ALIAS GlchDelayAlias : VitalTimeArray(GlchDelay'LENGTH DOWNTO 1) + IS GlchDelay; + ALIAS NewSchedAlias : SchedArray( NewSched'LENGTH DOWNTO 1) + IS NewSched; + ALIAS NewValueAlias : std_logic_vector ( NewValue'LENGTH DOWNTO 1 ) + IS NewValue; + ALIAS CurValueAlias : std_logic_vector ( CurValue'LENGTH DOWNTO 1 ) + IS CurValue; + BEGIN + FOR n IN NewDelay'LENGTH DOWNTO 1 LOOP + CASE To_UX01(NewValueAlias(n)) IS + WHEN '0' => Tim := NewSchedAlias(n).inp0; + Glch := NewSchedAlias(n).Glch1; + WHEN '1' => Tim := NewSchedAlias(n).inp1; + Glch := NewSchedAlias(n).Glch0; + WHEN OTHERS => Tim := NewSchedAlias(n).InpX; + Glch := -1 ns; + END CASE; + IF (CurValueAlias(n) /= NewValueAlias(n)) + THEN Glch := -1 ns; + END IF; + + NewDelayAlias(n) := Tim - NOW; + IF Glch < 0 ns + THEN GlchDelayAlias(n) := Glch; + ELSE GlchDelayAlias(n) := Glch - NOW; + END IF; -- glch < 0 ns + END LOOP; + RETURN; + END; + + PROCEDURE GetSchedDelay ( + VARIABLE NewDelay : OUT TIME; + VARIABLE GlchDelay : OUT TIME; + CONSTANT NewValue : IN std_ulogic; + CONSTANT CurValue : IN std_ulogic; + CONSTANT NewSched : IN SchedType; + CONSTANT EnSched1 : IN SchedType; + CONSTANT EnSched0 : IN SchedType + ) IS + SUBTYPE v2 IS std_logic_vector(0 TO 1); + VARIABLE Tim, Glch : TIME; + BEGIN + + CASE v2'(To_X01Z(CurValue) & To_X01Z(NewValue)) IS + WHEN "00" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); + Glch := GlitchMinTime(NewSched.Glch1,EnSched0.Glch0); + WHEN "01" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); + Glch := EnSched1.Glch0; + WHEN "0Z" => Tim := EnSched0.inp0; + Glch := NewSched.Glch1; + WHEN "0X" => Tim := Maximum (NewSched.InpX, EnSched1.InpX); + Glch := 0 ns; + WHEN "10" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); + Glch := EnSched0.Glch0; + WHEN "11" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); + Glch := GlitchMinTime(NewSched.Glch0,EnSched1.Glch0); + WHEN "1Z" => Tim := EnSched1.inp0; + Glch := NewSched.Glch0; + WHEN "1X" => Tim := Maximum (NewSched.InpX, EnSched0.InpX); + Glch := 0 ns; + WHEN "Z0" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); + IF NewSched.Glch0 > NOW + THEN Glch := Maximum(NewSched.Glch1,EnSched1.inp1); + ELSE Glch := 0 ns; + END IF; + WHEN "Z1" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); + IF NewSched.Glch1 > NOW + THEN Glch := Maximum(NewSched.Glch0,EnSched0.inp1); + ELSE Glch := 0 ns; + END IF; + WHEN "ZX" => Tim := Maximum (NewSched.InpX, EnSched1.InpX); + Glch := 0 ns; + WHEN "ZZ" => Tim := Maximum (EnSched1.InpX, EnSched0.InpX); + Glch := 0 ns; + WHEN "X0" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); + Glch := 0 ns; + WHEN "X1" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); + Glch := 0 ns; + WHEN "XZ" => Tim := Maximum (EnSched1.InpX, EnSched0.InpX); + Glch := 0 ns; + WHEN OTHERS => Tim := Maximum (NewSched.InpX, EnSched1.InpX); + Glch := 0 ns; + + END CASE; + NewDelay := Tim - NOW; + IF Glch < 0 ns + THEN GlchDelay := Glch; + ELSE GlchDelay := Glch - NOW; + END IF; -- glch < 0 ns + END; + + --------------------------------------------------------------------------- + -- Operators and Functions for combination (selection) of path delays + -- > These functions support selection of the "appripriate" path delay + -- dependent on the logic function. + -- > These functions only "select" from the possable output times. No + -- calculation (addition) of delays is performed. + -- > See description of 'BufPath', 'InvPath' and 'GetSchedDelay' + -- > See primitive PROCEDURE models for examples. + --------------------------------------------------------------------------- + + FUNCTION "not" ( + CONSTANT a : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + z.inp1 := a.inp0 ; + z.inp0 := a.inp1 ; + z.InpX := a.InpX ; + z.Glch1 := a.Glch0; + z.Glch0 := a.Glch1; + RETURN (z); + END; + + FUNCTION "and" ( + CONSTANT a, b : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + z.inp1 := Maximum ( a.inp1 , b.inp1 ); + z.inp0 := Minimum ( a.inp0 , b.inp0 ); + z.InpX := GlitchMinTime ( a.InpX , b.InpX ); + z.Glch1 := Maximum ( a.Glch1, b.Glch1 ); + z.Glch0 := GlitchMinTime ( a.Glch0, b.Glch0 ); + RETURN (z); + END; + + FUNCTION "or" ( + CONSTANT a, b : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + z.inp0 := Maximum ( a.inp0 , b.inp0 ); + z.inp1 := Minimum ( a.inp1 , b.inp1 ); + z.InpX := GlitchMinTime ( a.InpX , b.InpX ); + z.Glch0 := Maximum ( a.Glch0, b.Glch0 ); + z.Glch1 := GlitchMinTime ( a.Glch1, b.Glch1 ); + RETURN (z); + END; + + FUNCTION "nand" ( + CONSTANT a, b : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + z.inp0 := Maximum ( a.inp1 , b.inp1 ); + z.inp1 := Minimum ( a.inp0 , b.inp0 ); + z.InpX := GlitchMinTime ( a.InpX , b.InpX ); + z.Glch0 := Maximum ( a.Glch1, b.Glch1 ); + z.Glch1 := GlitchMinTime ( a.Glch0, b.Glch0 ); + RETURN (z); + END; + + FUNCTION "nor" ( + CONSTANT a, b : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + z.inp1 := Maximum ( a.inp0 , b.inp0 ); + z.inp0 := Minimum ( a.inp1 , b.inp1 ); + z.InpX := GlitchMinTime ( a.InpX , b.InpX ); + z.Glch1 := Maximum ( a.Glch0, b.Glch0 ); + z.Glch0 := GlitchMinTime ( a.Glch1, b.Glch1 ); + RETURN (z); + END; + + -- ------------------------------------------------------------------------ + -- Delay Calculation for 2-bit Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalXOR2 ( + CONSTANT ab,ai, bb,bi : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + -- z = (a AND b) NOR (a NOR b) + z.inp1 := Maximum ( Minimum (ai.inp0 , bi.inp0 ), + Minimum (ab.inp1 , bb.inp1 ) ); + z.inp0 := Minimum ( Maximum (ai.inp1 , bi.inp1 ), + Maximum (ab.inp0 , bb.inp0 ) ); + z.InpX := Maximum ( Maximum (ai.InpX , bi.InpX ), + Maximum (ab.InpX , bb.InpX ) ); + z.Glch1 := Maximum (GlitchMinTime (ai.Glch0, bi.Glch0), + GlitchMinTime (ab.Glch1, bb.Glch1) ); + z.Glch0 := GlitchMinTime ( Maximum (ai.Glch1, bi.Glch1), + Maximum (ab.Glch0, bb.Glch0) ); + RETURN (z); + END; + + FUNCTION VitalXNOR2 ( + CONSTANT ab,ai, bb,bi : IN SchedType + ) RETURN SchedType IS + VARIABLE z : SchedType; + BEGIN + -- z = (a AND b) OR (a NOR b) + z.inp0 := Maximum ( Minimum (ab.inp0 , bb.inp0 ), + Minimum (ai.inp1 , bi.inp1 ) ); + z.inp1 := Minimum ( Maximum (ab.inp1 , bb.inp1 ), + Maximum (ai.inp0 , bi.inp0 ) ); + z.InpX := Maximum ( Maximum (ab.InpX , bb.InpX ), + Maximum (ai.InpX , bi.InpX ) ); + z.Glch0 := Maximum (GlitchMinTime (ab.Glch0, bb.Glch0), + GlitchMinTime (ai.Glch1, bi.Glch1) ); + z.Glch1 := GlitchMinTime ( Maximum (ab.Glch1, bb.Glch1), + Maximum (ai.Glch0, bi.Glch0) ); + RETURN (z); + END; + + -- ------------------------------------------------------------------------ + -- Delay Calculation for 3-bit Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalXOR3 ( + CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType ) + RETURN SchedType IS + BEGIN + RETURN VitalXOR2 ( VitalXOR2 (ab,ai, bb,bi), + VitalXOR2 (ai,ab, bi,bb), + cb, ci ); + END; + + FUNCTION VitalXNOR3 ( + CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType ) + RETURN SchedType IS + BEGIN + RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ), + VitalXOR2 ( ai,ab, bi,bb ), + cb, ci ); + END; + + -- ------------------------------------------------------------------------ + -- Delay Calculation for 4-bit Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalXOR4 ( + CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType ) + RETURN SchedType IS + BEGIN + RETURN VitalXOR2 ( VitalXOR2 ( ab,ai, bb,bi ), + VitalXOR2 ( ai,ab, bi,bb ), + VitalXOR2 ( cb,ci, db,di ), + VitalXOR2 ( ci,cb, di,db ) ); + END; + + FUNCTION VitalXNOR4 ( + CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType ) + RETURN SchedType IS + BEGIN + RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ), + VitalXOR2 ( ai,ab, bi,bb ), + VitalXOR2 ( cb,ci, db,di ), + VitalXOR2 ( ci,cb, di,db ) ); + END; + + -- ------------------------------------------------------------------------ + -- Delay Calculation for N-bit Logical gates. + -- ------------------------------------------------------------------------ + -- Note: index range on datab,datai assumed to be 1 TO length. + -- This is enforced by internal only usage of this Function + FUNCTION VitalXOR ( + CONSTANT DataB, DataI : IN SchedArray + ) RETURN SchedType IS + CONSTANT Leng : INTEGER := DataB'LENGTH; + BEGIN + IF Leng = 2 THEN + RETURN VitalXOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) ); + ELSE + RETURN VitalXOR2 ( VitalXOR ( DataB(1 TO Leng-1), + DataI(1 TO Leng-1) ), + VitalXOR ( DataI(1 TO Leng-1), + DataB(1 TO Leng-1) ), + DataB(Leng),DataI(Leng) ); + END IF; + END; + + -- Note: index range on datab,datai assumed to be 1 TO length. + -- This is enforced by internal only usage of this Function + FUNCTION VitalXNOR ( + CONSTANT DataB, DataI : IN SchedArray + ) RETURN SchedType IS + CONSTANT Leng : INTEGER := DataB'LENGTH; + BEGIN + IF Leng = 2 THEN + RETURN VitalXNOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) ); + ELSE + RETURN VitalXNOR2 ( VitalXOR ( DataB(1 TO Leng-1), + DataI(1 TO Leng-1) ), + VitalXOR ( DataI(1 TO Leng-1), + DataB(1 TO Leng-1) ), + DataB(Leng),DataI(Leng) ); + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Multiplexor + -- MUX .......... result := data(dselect) + -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), + -- data1 when (dselect = '1'), + -- 'X' when (dselect = 'X') and (data0 /= data1) + -- MUX4 .......... 4-input mux; result := data(dselect) + -- MUX8 .......... 8-input mux; result := data(dselect) + -- ------------------------------------------------------------------------ + FUNCTION VitalMUX2 ( + CONSTANT d1, d0 : IN SchedType; + CONSTANT sb, SI : IN SchedType + ) RETURN SchedType IS + BEGIN + RETURN (d1 AND sb) OR (d0 AND (NOT SI) ); + END; +-- + FUNCTION VitalMUX4 ( + CONSTANT Data : IN SchedArray4; + CONSTANT sb : IN SchedArray2; + CONSTANT SI : IN SchedArray2 + ) RETURN SchedType IS + BEGIN + RETURN ( sb(1) AND VitalMUX2(Data(3),Data(2), sb(0), SI(0)) ) + OR ( (NOT SI(1)) AND VitalMUX2(Data(1),Data(0), sb(0), SI(0)) ); + END; + + FUNCTION VitalMUX8 ( + CONSTANT Data : IN SchedArray8; + CONSTANT sb : IN SchedArray3; + CONSTANT SI : IN SchedArray3 + ) RETURN SchedType IS + BEGIN + RETURN ( ( sb(2)) AND VitalMUX4 (Data(7 DOWNTO 4), + sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) ) + OR ( (NOT SI(2)) AND VitalMUX4 (Data(3 DOWNTO 0), + sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) ); + END; +-- + FUNCTION VInterMux ( + CONSTANT Data : IN SchedArray; + CONSTANT sb : IN SchedArray; + CONSTANT SI : IN SchedArray + ) RETURN SchedType IS + CONSTANT sMsb : INTEGER := sb'LENGTH; + CONSTANT dMsbHigh : INTEGER := Data'LENGTH; + CONSTANT dMsbLow : INTEGER := Data'LENGTH/2; + BEGIN + IF sb'LENGTH = 1 THEN + RETURN VitalMUX2( Data(2), Data(1), sb(1), SI(1) ); + ELSIF sb'LENGTH = 2 THEN + RETURN VitalMUX4( Data, sb, SI ); + ELSIF sb'LENGTH = 3 THEN + RETURN VitalMUX8( Data, sb, SI ); + ELSIF sb'LENGTH > 3 THEN + RETURN (( sb(sMsb)) AND VInterMux( Data(dMsbLow DOWNTO 1), + sb(sMsb-1 DOWNTO 1), + SI(sMsb-1 DOWNTO 1) )) + OR ((NOT SI(sMsb)) AND VInterMux( Data(dMsbHigh DOWNTO dMsbLow+1), + sb(sMsb-1 DOWNTO 1), + SI(sMsb-1 DOWNTO 1) )); + ELSE + RETURN (0 ns, 0 ns, 0 ns, 0 ns, 0 ns); -- dselect'LENGTH < 1 + END IF; + END; +-- + FUNCTION VitalMUX ( + CONSTANT Data : IN SchedArray; + CONSTANT sb : IN SchedArray; + CONSTANT SI : IN SchedArray + ) RETURN SchedType IS + CONSTANT msb : INTEGER := 2**sb'LENGTH; + VARIABLE lDat : SchedArray(msb DOWNTO 1); + ALIAS DataAlias : SchedArray ( Data'LENGTH DOWNTO 1 ) IS Data; + ALIAS sbAlias : SchedArray ( sb'LENGTH DOWNTO 1 ) IS sb; + ALIAS siAlias : SchedArray ( SI'LENGTH DOWNTO 1 ) IS SI; + BEGIN + IF Data'LENGTH <= msb THEN + FOR i IN Data'LENGTH DOWNTO 1 LOOP + lDat(i) := DataAlias(i); + END LOOP; + FOR i IN msb DOWNTO Data'LENGTH+1 LOOP + lDat(i) := DefSchedAnd; + END LOOP; + ELSE + FOR i IN msb DOWNTO 1 LOOP + lDat(i) := DataAlias(i); + END LOOP; + END IF; + RETURN VInterMux( lDat, sbAlias, siAlias ); + END; + + -- ------------------------------------------------------------------------ + -- Decoder + -- General Algorithm : + -- (a) Result(...) := '0' when (enable = '0') + -- (b) Result(data) := '1'; all other subelements = '0' + -- ... Result array is decending (n-1 downto 0) + -- + -- DECODERn .......... n:2**n decoder + -- ------------------------------------------------------------------------ + FUNCTION VitalDECODER2 ( + CONSTANT DataB : IN SchedType; + CONSTANT DataI : IN SchedType; + CONSTANT Enable : IN SchedType + ) RETURN SchedArray IS + VARIABLE Result : SchedArray2; + BEGIN + Result(1) := Enable AND ( DataB); + Result(0) := Enable AND (NOT DataI); + RETURN Result; + END; + + FUNCTION VitalDECODER4 ( + CONSTANT DataB : IN SchedArray2; + CONSTANT DataI : IN SchedArray2; + CONSTANT Enable : IN SchedType + ) RETURN SchedArray IS + VARIABLE Result : SchedArray4; + BEGIN + Result(3) := Enable AND ( DataB(1)) AND ( DataB(0)); + Result(2) := Enable AND ( DataB(1)) AND (NOT DataI(0)); + Result(1) := Enable AND (NOT DataI(1)) AND ( DataB(0)); + Result(0) := Enable AND (NOT DataI(1)) AND (NOT DataI(0)); + RETURN Result; + END; + + FUNCTION VitalDECODER8 ( + CONSTANT DataB : IN SchedArray3; + CONSTANT DataI : IN SchedArray3; + CONSTANT Enable : IN SchedType + ) RETURN SchedArray IS + VARIABLE Result : SchedArray8; + BEGIN + Result(7):= Enable AND ( DataB(2))AND( DataB(1))AND( DataB(0)); + Result(6):= Enable AND ( DataB(2))AND( DataB(1))AND(NOT DataI(0)); + Result(5):= Enable AND ( DataB(2))AND(NOT DataI(1))AND( DataB(0)); + Result(4):= Enable AND ( DataB(2))AND(NOT DataI(1))AND(NOT DataI(0)); + Result(3):= Enable AND (NOT DataI(2))AND( DataB(1))AND( DataB(0)); + Result(2):= Enable AND (NOT DataI(2))AND( DataB(1))AND(NOT DataI(0)); + Result(1):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND( DataB(0)); + Result(0):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND(NOT DataI(0)); + RETURN Result; + END; + + + FUNCTION VitalDECODER ( + CONSTANT DataB : IN SchedArray; + CONSTANT DataI : IN SchedArray; + CONSTANT Enable : IN SchedType + ) RETURN SchedArray IS + CONSTANT DMsb : INTEGER := DataB'LENGTH - 1; + ALIAS DataBAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataB; + ALIAS DataIAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataI; + BEGIN + IF DataB'LENGTH = 1 THEN + RETURN VitalDECODER2 ( DataBAlias( 0 ), + DataIAlias( 0 ), Enable ); + ELSIF DataB'LENGTH = 2 THEN + RETURN VitalDECODER4 ( DataBAlias(1 DOWNTO 0), + DataIAlias(1 DOWNTO 0), Enable ); + ELSIF DataB'LENGTH = 3 THEN + RETURN VitalDECODER8 ( DataBAlias(2 DOWNTO 0), + DataIAlias(2 DOWNTO 0), Enable ); + ELSIF DataB'LENGTH > 3 THEN + RETURN VitalDECODER ( DataBAlias(DMsb-1 DOWNTO 0), + DataIAlias(DMsb-1 DOWNTO 0), + Enable AND ( DataBAlias(DMsb)) ) + & VitalDECODER ( DataBAlias(DMsb-1 DOWNTO 0), + DataIAlias(DMsb-1 DOWNTO 0), + Enable AND (NOT DataIAlias(DMsb)) ); + ELSE + RETURN DefSchedArray2; + END IF; + END; + + +------------------------------------------------------------------------------- +-- PRIMITIVES +------------------------------------------------------------------------------- + -- ------------------------------------------------------------------------ + -- N-bit wide Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '1'; + FOR i IN Data'RANGE LOOP + Result := Result AND Data(i); + END LOOP; + RETURN ResultMap(Result); + END; +-- + FUNCTION VitalOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '0'; + FOR i IN Data'RANGE LOOP + Result := Result OR Data(i); + END LOOP; + RETURN ResultMap(Result); + END; +-- + FUNCTION VitalXOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '0'; + FOR i IN Data'RANGE LOOP + Result := Result XOR Data(i); + END LOOP; + RETURN ResultMap(Result); + END; +-- + FUNCTION VitalNAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '1'; + FOR i IN Data'RANGE LOOP + Result := Result AND Data(i); + END LOOP; + RETURN ResultMap(NOT Result); + END; +-- + FUNCTION VitalNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '0'; + FOR i IN Data'RANGE LOOP + Result := Result OR Data(i); + END LOOP; + RETURN ResultMap(NOT Result); + END; +-- + FUNCTION VitalXNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + Result := '0'; + FOR i IN Data'RANGE LOOP + Result := Result XOR Data(i); + END LOOP; + RETURN ResultMap(NOT Result); + END; + + -- ------------------------------------------------------------------------ + -- Commonly used 2-bit Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a AND b); + END; +-- + FUNCTION VitalOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a OR b); + END; +-- + FUNCTION VitalXOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a XOR b); + END; +-- + FUNCTION VitalNAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a NAND b); + END; +-- + FUNCTION VitalNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a NOR b); + END; +-- + FUNCTION VitalXNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a XOR b)); + END; +-- + -- ------------------------------------------------------------------------ + -- Commonly used 3-bit Logical gates. + -- ------------------------------------------------------------------------ + FUNCTION VitalAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a AND b AND c); + END; +-- + FUNCTION VitalOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a OR b OR c); + END; +-- + FUNCTION VitalXOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a XOR b XOR c); + END; +-- + FUNCTION VitalNAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a AND b AND c)); + END; +-- + FUNCTION VitalNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a OR b OR c)); + END; +-- + FUNCTION VitalXNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a XOR b XOR c)); + END; + + -- --------------------------------------------------------------------------- + -- Commonly used 4-bit Logical gates. + -- --------------------------------------------------------------------------- + FUNCTION VitalAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a AND b AND c AND d); + END; +-- + FUNCTION VitalOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a OR b OR c OR d); + END; +-- + FUNCTION VitalXOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(a XOR b XOR c XOR d); + END; +-- + FUNCTION VitalNAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a AND b AND c AND d)); + END; +-- + FUNCTION VitalNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a OR b OR c OR d)); + END; +-- + FUNCTION VitalXNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT (a XOR b XOR c XOR d)); + END; + + -- ------------------------------------------------------------------------ + -- Buffers + -- BUF ....... standard non-inverting buffer + -- BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0') + -- BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1') + -- ------------------------------------------------------------------------ + FUNCTION VitalBUF ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(To_UX01(Data)); + END; +-- + FUNCTION VitalBUFIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(BufIf0_Table(Enable,Data)); + END; +-- + FUNCTION VitalBUFIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(BufIf1_Table(Enable,Data)); + END; + FUNCTION VitalIDENT ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(To_UX01Z(Data)); + END; + + -- ------------------------------------------------------------------------ + -- Invertors + -- INV ......... standard inverting buffer + -- INVIF0 ......... inverting buffer Data passes thru if (Enable = '0') + -- INVIF1 ......... inverting buffer Data passes thru if (Enable = '1') + -- ------------------------------------------------------------------------ + FUNCTION VitalINV ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(NOT Data); + END; +-- + FUNCTION VitalINVIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(InvIf0_Table(Enable,Data)); + END; +-- + FUNCTION VitalINVIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic IS + BEGIN + RETURN ResultMap(InvIf1_Table(Enable,Data)); + END; + + -- ------------------------------------------------------------------------ + -- Multiplexor + -- MUX .......... result := data(dselect) + -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), + -- data1 when (dselect = '1'), + -- 'X' when (dselect = 'X') and (data0 /= data1) + -- MUX4 .......... 4-input mux; result := data(dselect) + -- MUX8 .......... 8-input mux; result := data(dselect) + -- ------------------------------------------------------------------------ + FUNCTION VitalMUX2 ( + CONSTANT Data1, Data0 : IN std_ulogic; + CONSTANT dSelect : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + CASE To_X01(dSelect) IS + WHEN '0' => Result := To_UX01(Data0); + WHEN '1' => Result := To_UX01(Data1); + WHEN OTHERS => Result := VitalSame( Data1, Data0 ); + END CASE; + RETURN ResultMap(Result); + END; +-- + FUNCTION VitalMUX4 ( + CONSTANT Data : IN std_logic_vector4; + CONSTANT dSelect : IN std_logic_vector2; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Slct : std_logic_vector2; + VARIABLE Result : UX01; + BEGIN + Slct := To_X01(dSelect); + CASE Slct IS + WHEN "00" => Result := To_UX01(Data(0)); + WHEN "01" => Result := To_UX01(Data(1)); + WHEN "10" => Result := To_UX01(Data(2)); + WHEN "11" => Result := To_UX01(Data(3)); + WHEN "0X" => Result := VitalSame( Data(1), Data(0) ); + WHEN "1X" => Result := VitalSame( Data(2), Data(3) ); + WHEN "X0" => Result := VitalSame( Data(2), Data(0) ); + WHEN "X1" => Result := VitalSame( Data(3), Data(1) ); + WHEN OTHERS => Result := VitalSame( VitalSame(Data(3),Data(2)), + VitalSame(Data(1),Data(0))); + END CASE; + RETURN ResultMap(Result); + END; +-- + FUNCTION VitalMUX8 ( + CONSTANT Data : IN std_logic_vector8; + CONSTANT dSelect : IN std_logic_vector3; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + VARIABLE Result : UX01; + BEGIN + CASE To_X01(dSelect(2)) IS + WHEN '0' => Result := VitalMUX4( Data(3 DOWNTO 0), + dSelect(1 DOWNTO 0)); + WHEN '1' => Result := VitalMUX4( Data(7 DOWNTO 4), + dSelect(1 DOWNTO 0)); + WHEN OTHERS => Result := VitalSame( VitalMUX4( Data(3 DOWNTO 0), + dSelect(1 DOWNTO 0)), + VitalMUX4( Data(7 DOWNTO 4), + dSelect(1 DOWNTO 0))); + END CASE; + RETURN ResultMap(Result); + END; +-- + FUNCTION VInterMux ( + CONSTANT Data : IN std_logic_vector; + CONSTANT dSelect : IN std_logic_vector + ) RETURN std_ulogic IS + + CONSTANT sMsb : INTEGER := dSelect'LENGTH; + CONSTANT dMsbHigh : INTEGER := Data'LENGTH; + CONSTANT dMsbLow : INTEGER := Data'LENGTH/2; + ALIAS DataAlias : std_logic_vector ( Data'LENGTH DOWNTO 1) IS Data; + ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect; + + VARIABLE Result : UX01; + BEGIN + IF dSelect'LENGTH = 1 THEN + Result := VitalMUX2( DataAlias(2), DataAlias(1), dSelAlias(1) ); + ELSIF dSelect'LENGTH = 2 THEN + Result := VitalMUX4( DataAlias, dSelAlias ); + ELSIF dSelect'LENGTH > 2 THEN + CASE To_X01(dSelect(sMsb)) IS + WHEN '0' => + Result := VInterMux( DataAlias(dMsbLow DOWNTO 1), + dSelAlias(sMsb-1 DOWNTO 1) ); + WHEN '1' => + Result := VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1), + dSelAlias(sMsb-1 DOWNTO 1) ); + WHEN OTHERS => + Result := VitalSame( + VInterMux( DataAlias(dMsbLow DOWNTO 1), + dSelAlias(sMsb-1 DOWNTO 1) ), + VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1), + dSelAlias(sMsb-1 DOWNTO 1) ) + ); + END CASE; + ELSE + Result := 'X'; -- dselect'LENGTH < 1 + END IF; + RETURN Result; + END; +-- + FUNCTION VitalMUX ( + CONSTANT Data : IN std_logic_vector; + CONSTANT dSelect : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic IS + CONSTANT msb : INTEGER := 2**dSelect'LENGTH; + ALIAS DataAlias : std_logic_vector ( Data'LENGTH DOWNTO 1) IS Data; + ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect; + VARIABLE lDat : std_logic_vector(msb DOWNTO 1) := (OTHERS=>'X'); + VARIABLE Result : UX01; + BEGIN + IF Data'LENGTH <= msb THEN + FOR i IN Data'LENGTH DOWNTO 1 LOOP + lDat(i) := DataAlias(i); + END LOOP; + ELSE + FOR i IN msb DOWNTO 1 LOOP + lDat(i) := DataAlias(i); + END LOOP; + END IF; + Result := VInterMux( lDat, dSelAlias ); + RETURN ResultMap(Result); + END; + + -- ------------------------------------------------------------------------ + -- Decoder + -- General Algorithm : + -- (a) Result(...) := '0' when (enable = '0') + -- (b) Result(data) := '1'; all other subelements = '0' + -- ... Result array is decending (n-1 downto 0) + -- + -- DECODERn .......... n:2**n decoder + -- ------------------------------------------------------------------------ + FUNCTION VitalDECODER2 ( + CONSTANT Data : IN std_ulogic; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector2 IS + VARIABLE Result : std_logic_vector2; + BEGIN + Result(1) := ResultMap(Enable AND ( Data)); + Result(0) := ResultMap(Enable AND (NOT Data)); + RETURN Result; + END; +-- + FUNCTION VitalDECODER4 ( + CONSTANT Data : IN std_logic_vector2; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector4 IS + VARIABLE Result : std_logic_vector4; + BEGIN + Result(3) := ResultMap(Enable AND ( Data(1)) AND ( Data(0))); + Result(2) := ResultMap(Enable AND ( Data(1)) AND (NOT Data(0))); + Result(1) := ResultMap(Enable AND (NOT Data(1)) AND ( Data(0))); + Result(0) := ResultMap(Enable AND (NOT Data(1)) AND (NOT Data(0))); + RETURN Result; + END; +-- + FUNCTION VitalDECODER8 ( + CONSTANT Data : IN std_logic_vector3; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector8 IS + VARIABLE Result : std_logic_vector8; + BEGIN + Result(7) := ( Data(2)) AND ( Data(1)) AND ( Data(0)); + Result(6) := ( Data(2)) AND ( Data(1)) AND (NOT Data(0)); + Result(5) := ( Data(2)) AND (NOT Data(1)) AND ( Data(0)); + Result(4) := ( Data(2)) AND (NOT Data(1)) AND (NOT Data(0)); + Result(3) := (NOT Data(2)) AND ( Data(1)) AND ( Data(0)); + Result(2) := (NOT Data(2)) AND ( Data(1)) AND (NOT Data(0)); + Result(1) := (NOT Data(2)) AND (NOT Data(1)) AND ( Data(0)); + Result(0) := (NOT Data(2)) AND (NOT Data(1)) AND (NOT Data(0)); + + Result(0) := ResultMap ( Enable AND Result(0) ); + Result(1) := ResultMap ( Enable AND Result(1) ); + Result(2) := ResultMap ( Enable AND Result(2) ); + Result(3) := ResultMap ( Enable AND Result(3) ); + Result(4) := ResultMap ( Enable AND Result(4) ); + Result(5) := ResultMap ( Enable AND Result(5) ); + Result(6) := ResultMap ( Enable AND Result(6) ); + Result(7) := ResultMap ( Enable AND Result(7) ); + + RETURN Result; + END; +-- + FUNCTION VitalDECODER ( + CONSTANT Data : IN std_logic_vector; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector IS + + CONSTANT DMsb : INTEGER := Data'LENGTH - 1; + ALIAS DataAlias : std_logic_vector ( DMsb DOWNTO 0 ) IS Data; + BEGIN + IF Data'LENGTH = 1 THEN + RETURN VitalDECODER2 (DataAlias( 0 ), Enable, ResultMap ); + ELSIF Data'LENGTH = 2 THEN + RETURN VitalDECODER4 (DataAlias(1 DOWNTO 0), Enable, ResultMap ); + ELSIF Data'LENGTH = 3 THEN + RETURN VitalDECODER8 (DataAlias(2 DOWNTO 0), Enable, ResultMap ); + ELSIF Data'LENGTH > 3 THEN + RETURN VitalDECODER (DataAlias(DMsb-1 DOWNTO 0), + Enable AND ( DataAlias(DMsb)), ResultMap ) + & VitalDECODER (DataAlias(DMsb-1 DOWNTO 0), + Enable AND (NOT DataAlias(DMsb)), ResultMap ); + ELSE RETURN "X"; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- N-bit wide Logical gates. + -- ------------------------------------------------------------------------ + PROCEDURE VitalAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE Data_Schd : SchedArray(Data'RANGE); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalAND(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := '1'; + new_schd := Data_Schd(Data_Schd'LEFT); + FOR i IN Data'RANGE LOOP + NewValue := NewValue AND Data(i); + new_schd := new_schd AND Data_Schd(i); + END LOOP; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; --SN + END; +-- + PROCEDURE VitalOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE Data_Schd : SchedArray(Data'RANGE); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalOR(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := '0'; + new_schd := Data_Schd(Data_Schd'LEFT); + FOR i IN Data'RANGE LOOP + NewValue := NewValue OR Data(i); + new_schd := new_schd OR Data_Schd(i); + END LOOP; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; --SN + END; +-- + PROCEDURE VitalXOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE DataB_Schd : SchedArray(1 TO Data'LENGTH); + VARIABLE DataI_Schd : SchedArray(1 TO Data'LENGTH); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd; + ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalXOR(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( DataB_Schd, Data_Edge, Atpd_data_q ); + InvPath ( DataI_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalXOR ( Data ); + new_schd := VitalXOR ( DataB_Schd, DataI_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; --SN + END; +-- + PROCEDURE VitalNAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE Data_Schd : SchedArray(Data'RANGE); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalNAND(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + InvPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := '1'; + new_schd := Data_Schd(Data_Schd'LEFT); + FOR i IN Data'RANGE LOOP + NewValue := NewValue AND Data(i); + new_schd := new_schd AND Data_Schd(i); + END LOOP; + NewValue := NOT NewValue; + new_schd := NOT new_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE Data_Schd : SchedArray(Data'RANGE); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalNOR(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + InvPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := '0'; + new_schd := Data_Schd(Data_Schd'LEFT); + FOR i IN Data'RANGE LOOP + NewValue := NewValue OR Data(i); + new_schd := new_schd OR Data_Schd(i); + END LOOP; + NewValue := NOT NewValue; + new_schd := NOT new_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; --SN + END; +-- + PROCEDURE VitalXNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE DataB_Schd : SchedArray(1 TO Data'LENGTH); + VARIABLE DataI_Schd : SchedArray(1 TO Data'LENGTH); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd; + ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN LOOP + q <= VitalXNOR(Data, ResultMap); + WAIT ON Data; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( DataB_Schd, Data_Edge, Atpd_data_q ); + InvPath ( DataI_Schd, Data_Edge, Atpd_data_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalXNOR ( Data ); + new_schd := VitalXNOR ( DataB_Schd, DataI_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data; + END LOOP; + END IF; --SN + END; +-- + + -- ------------------------------------------------------------------------ + -- Commonly used 2-bit Logical gates. + -- ------------------------------------------------------------------------ + PROCEDURE VitalAND2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalAND2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a AND b; + new_schd := a_schd AND b_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalOR2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalOR2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a OR b; + new_schd := a_schd OR b_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNAND2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNAND2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a NAND b; + new_schd := a_schd NAND b_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNOR2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNOR2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a NOR b; + new_schd := a_schd NOR b_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXOR2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd : SchedType; + VARIABLE ai_schd, bi_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXOR2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a XOR b; + new_schd := VitalXOR2 ( ab_schd,ai_schd, bb_schd,bi_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXNOR2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd : SchedType; + VARIABLE ai_schd, bi_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXNOR2 ( a, b, ResultMap ); + WAIT ON a, b; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := NOT (a XOR b); + new_schd := VitalXNOR2 ( ab_schd,ai_schd, bb_schd,bi_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Commonly used 3-bit Logical gates. + -- ------------------------------------------------------------------------ + PROCEDURE VitalAND3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN +-- + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalAND3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + BufPath ( c_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + BufPath ( c_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a AND b AND c; + new_schd := a_schd AND b_schd AND c_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalOR3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalOR3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + BufPath ( c_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + BufPath ( c_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a OR b OR c; + new_schd := a_schd OR b_schd OR c_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNAND3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNAND3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + InvPath ( c_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + InvPath ( c_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := (a AND b) NAND c; + new_schd := (a_schd AND b_schd) NAND c_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNOR3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNOR3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + InvPath ( c_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + InvPath ( c_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := (a OR b) NOR c; + new_schd := (a_schd OR b_schd) NOR c_schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXOR3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd, cb_schd : SchedType; + VARIABLE ai_schd, bi_schd, ci_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXOR3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); + InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + BufPath ( cb_schd, GetEdge(c), tpd_c_q ); + InvPath ( ci_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a XOR b XOR c; + new_schd := VitalXOR3 ( ab_schd,ai_schd, + bb_schd,bi_schd, + cb_schd,ci_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXNOR3 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd, cb_schd : SchedType; + VARIABLE ai_schd, bi_schd, ci_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXNOR3 ( a, b, c, ResultMap ); + WAIT ON a, b, c; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); + InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + BufPath ( cb_schd, GetEdge(c), tpd_c_q ); + InvPath ( ci_schd, GetEdge(c), tpd_c_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := NOT (a XOR b XOR c); + new_schd := VitalXNOR3 ( ab_schd, ai_schd, + bb_schd, bi_schd, + cb_schd, ci_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Commonly used 4-bit Logical gates. + -- ------------------------------------------------------------------------ + PROCEDURE VitalAND4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalAND4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + BufPath ( c_schd, InitialEdge(c), tpd_c_q ); + BufPath ( d_Schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + BufPath ( c_schd, GetEdge(c), tpd_c_q ); + BufPath ( d_Schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a AND b AND c AND d; + new_schd := a_schd AND b_schd AND c_schd AND d_Schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalOR4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalOR4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( a_schd, InitialEdge(a), tpd_a_q ); + BufPath ( b_schd, InitialEdge(b), tpd_b_q ); + BufPath ( c_schd, InitialEdge(c), tpd_c_q ); + BufPath ( d_Schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( a_schd, GetEdge(a), tpd_a_q ); + BufPath ( b_schd, GetEdge(b), tpd_b_q ); + BufPath ( c_schd, GetEdge(c), tpd_c_q ); + BufPath ( d_Schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a OR b OR c OR d; + new_schd := a_schd OR b_schd OR c_schd OR d_Schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNAND4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNAND4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + InvPath ( c_schd, InitialEdge(c), tpd_c_q ); + InvPath ( d_Schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + InvPath ( c_schd, GetEdge(c), tpd_c_q ); + InvPath ( d_Schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := (a AND b) NAND (c AND d); + new_schd := (a_schd AND b_schd) NAND (c_schd AND d_Schd); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalNOR4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalNOR4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( a_schd, InitialEdge(a), tpd_a_q ); + InvPath ( b_schd, InitialEdge(b), tpd_b_q ); + InvPath ( c_schd, InitialEdge(c), tpd_c_q ); + InvPath ( d_Schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( a_schd, GetEdge(a), tpd_a_q ); + InvPath ( b_schd, GetEdge(b), tpd_b_q ); + InvPath ( c_schd, GetEdge(c), tpd_c_q ); + InvPath ( d_Schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := (a OR b) NOR (c OR d); + new_schd := (a_schd OR b_schd) NOR (c_schd OR d_Schd); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXOR4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType; + VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXOR4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + + BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); + InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); + + BufPath ( DB_Schd, InitialEdge(d), tpd_d_q ); + InvPath ( di_schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + BufPath ( cb_schd, GetEdge(c), tpd_c_q ); + InvPath ( ci_schd, GetEdge(c), tpd_c_q ); + + BufPath ( DB_Schd, GetEdge(d), tpd_d_q ); + InvPath ( di_schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := a XOR b XOR c XOR d; + new_schd := VitalXOR4 ( ab_schd,ai_schd, bb_schd,bi_schd, + cb_schd,ci_schd, DB_Schd,di_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalXNOR4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL a, b, c, d : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType; + VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType; + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_a_q = VitalZeroDelay01) + AND (tpd_b_q = VitalZeroDelay01) + AND (tpd_c_q = VitalZeroDelay01) + AND (tpd_d_q = VitalZeroDelay01)) THEN + LOOP + q <= VitalXNOR4 ( a, b, c, d, ResultMap ); + WAIT ON a, b, c, d; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); + InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); + + BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); + InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); + + BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); + InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); + + BufPath ( DB_Schd, InitialEdge(d), tpd_d_q ); + InvPath ( di_schd, InitialEdge(d), tpd_d_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( ab_schd, GetEdge(a), tpd_a_q ); + InvPath ( ai_schd, GetEdge(a), tpd_a_q ); + + BufPath ( bb_schd, GetEdge(b), tpd_b_q ); + InvPath ( bi_schd, GetEdge(b), tpd_b_q ); + + BufPath ( cb_schd, GetEdge(c), tpd_c_q ); + InvPath ( ci_schd, GetEdge(c), tpd_c_q ); + + BufPath ( DB_Schd, GetEdge(d), tpd_d_q ); + InvPath ( di_schd, GetEdge(d), tpd_d_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := NOT (a XOR b XOR c XOR d); + new_schd := VitalXNOR4 ( ab_schd,ai_schd, bb_schd,bi_schd, + cb_schd,ci_schd, DB_Schd,di_schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON a, b, c, d; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Buffers + -- BUF ....... standard non-inverting buffer + -- BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0') + -- BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1') + -- ------------------------------------------------------------------------ + PROCEDURE VitalBUF ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_a_q = VitalZeroDelay01) THEN + LOOP + q <= ResultMap(To_UX01(a)); + WAIT ON a; + END LOOP; + + ELSE + LOOP + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := To_UX01(a); -- convert to forcing strengths + CASE EdgeType'(GetEdge(a)) IS + WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr01); + WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr10); + WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); + END CASE; + + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode ); + + WAIT ON a; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalBUFIF1 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_ulogic; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) IS + VARIABLE NewValue : UX01Z; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_data_q = VitalZeroDelay01 ) + AND (tpd_enable_q = VitalZeroDelay01Z)) THEN + LOOP + q <= VitalBUFIF1( Data, Enable, ResultMap ); + WAIT ON Data, Enable; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( d_Schd, InitialEdge(Data), tpd_data_q ); + BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( d_Schd, GetEdge(Data), tpd_data_q ); + BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalBUFIF1( Data, Enable ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), + d_Schd, e1_Schd, e0_Schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalBUFIF0 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_ulogic; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) IS + VARIABLE NewValue : UX01Z; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; + VARIABLE ne1_schd, ne0_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_data_q = VitalZeroDelay01 ) + AND (tpd_enable_q = VitalZeroDelay01Z)) THEN + LOOP + q <= VitalBUFIF0( Data, Enable, ResultMap ); + WAIT ON Data, Enable; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( d_Schd, InitialEdge(Data), tpd_data_q ); + InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( d_Schd, GetEdge(Data), tpd_data_q ); + InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalBUFIF0( Data, Enable ); + ne1_schd := NOT e1_Schd; + ne0_schd := NOT e0_Schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), + d_Schd, ne1_schd, ne0_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; + + PROCEDURE VitalIDENT ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) IS + SUBTYPE v2 IS std_logic_vector(0 TO 1); + VARIABLE NewValue : UX01Z; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_a_q = VitalZeroDelay01Z) THEN + LOOP + q <= ResultMap(To_UX01Z(a)); + WAIT ON a; + END LOOP; + + ELSE + LOOP + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + CASE v2'(To_X01Z(NewValue) & To_X01Z(a)) IS + WHEN "00" => Dly := tpd_a_q(tr10); + WHEN "01" => Dly := tpd_a_q(tr01); + WHEN "0Z" => Dly := tpd_a_q(tr0z); + WHEN "0X" => Dly := tpd_a_q(tr01); + WHEN "10" => Dly := tpd_a_q(tr10); + WHEN "11" => Dly := tpd_a_q(tr01); + WHEN "1Z" => Dly := tpd_a_q(tr1z); + WHEN "1X" => Dly := tpd_a_q(tr10); + WHEN "Z0" => Dly := tpd_a_q(trz0); + WHEN "Z1" => Dly := tpd_a_q(trz1); + WHEN "ZZ" => Dly := 0 ns; + WHEN "ZX" => Dly := Minimum (tpd_a_q(trz1), tpd_a_q(trz0)); + WHEN "X0" => Dly := tpd_a_q(tr10); + WHEN "X1" => Dly := tpd_a_q(tr01); + WHEN "XZ" => Dly := Minimum (tpd_a_q(tr0z), tpd_a_q(tr1z)); + WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); + END CASE; + NewValue := To_UX01Z(a); + + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode ); + + WAIT ON a; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Invertors + -- INV ......... standard inverting buffer + -- INVIF0 ......... inverting buffer Data passes thru if (Enable = '0') + -- INVIF1 ......... inverting buffer Data passes thru if (Enable = '1') + -- ------------------------------------------------------------------------ + PROCEDURE VitalINV ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic ; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + IF (tpd_a_q = VitalZeroDelay01) THEN + LOOP + q <= ResultMap(NOT a); + WAIT ON a; + END LOOP; + + ELSE + LOOP + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := NOT a; + CASE EdgeType'(GetEdge(a)) IS + WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr10); + WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr01); + WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); + END CASE; + + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode ); + + WAIT ON a; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalINVIF1 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_ulogic; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) IS + VARIABLE NewValue : UX01Z; + VARIABLE new_schd : SchedType; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_data_q = VitalZeroDelay01 ) + AND (tpd_enable_q = VitalZeroDelay01Z)) THEN + LOOP + q <= VitalINVIF1( Data, Enable, ResultMap ); + WAIT ON Data, Enable; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( d_Schd, InitialEdge(Data), tpd_data_q ); + BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( d_Schd, GetEdge(Data), tpd_data_q ); + BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalINVIF1( Data, Enable ); + new_schd := NOT d_Schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), + new_schd, e1_Schd, e0_Schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalINVIF0 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_ulogic; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) IS + VARIABLE NewValue : UX01Z; + VARIABLE new_schd : SchedType; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; + VARIABLE ne1_schd, ne0_schd : SchedType := DefSchedType; + VARIABLE Dly, Glch : TIME; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_data_q = VitalZeroDelay01 ) + AND (tpd_enable_q = VitalZeroDelay01Z)) THEN + LOOP + q <= VitalINVIF0( Data, Enable, ResultMap ); + WAIT ON Data, Enable; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + InvPath ( d_Schd, InitialEdge(Data), tpd_data_q ); + InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + InvPath ( d_Schd, GetEdge(Data), tpd_data_q ); + InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delay + -- ------------------------------------ + NewValue := VitalINVIF0( Data, Enable ); + ne1_schd := NOT e1_Schd; + ne0_schd := NOT e0_Schd; + new_schd := NOT d_Schd; + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), + new_schd, ne1_schd, ne0_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + -- Multiplexor + -- MUX .......... result := data(dselect) + -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), + -- data1 when (dselect = '1'), + -- 'X' when (dselect = 'X') and (data0 /= data1) + -- MUX4 .......... 4-input mux; result := data(dselect) + -- MUX8 .......... 8-input mux; result := data(dselect) + -- ------------------------------------------------------------------------ + PROCEDURE VitalMUX2 ( + SIGNAL q : OUT std_ulogic; + SIGNAL d1, d0 : IN std_ulogic; + SIGNAL dSel : IN std_ulogic; + CONSTANT tpd_d1_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_d0_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_dsel_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + VARIABLE d1_Schd, d0_Schd : SchedType; + VARIABLE dSel_bSchd, dSel_iSchd : SchedType; + VARIABLE d1_Edge, d0_Edge, dSel_Edge : EdgeType; + BEGIN + + -- ------------------------------------------------------------------------ + -- For ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF ( (tpd_d1_q = VitalZeroDelay01) + AND (tpd_d0_q = VitalZeroDelay01) + AND (tpd_dsel_q = VitalZeroDelay01) ) THEN + LOOP + q <= VitalMUX2 ( d1, d0, dSel, ResultMap ); + WAIT ON d1, d0, dSel; + END LOOP; + + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( d1_Schd, InitialEdge(d1), tpd_d1_q ); + BufPath ( d0_Schd, InitialEdge(d0), tpd_d0_q ); + BufPath ( dSel_bSchd, InitialEdge(dSel), tpd_dsel_q ); + InvPath ( dSel_iSchd, InitialEdge(dSel), tpd_dsel_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( d1_Schd, GetEdge(d1), tpd_d1_q ); + BufPath ( d0_Schd, GetEdge(d0), tpd_d0_q ); + BufPath ( dSel_bSchd, GetEdge(dSel), tpd_dsel_q ); + InvPath ( dSel_iSchd, GetEdge(dSel), tpd_dsel_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalMUX2 ( d1, d0, dSel ); + new_schd := VitalMUX2 ( d1_Schd, d0_Schd, dSel_bSchd, dSel_iSchd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON d1, d0, dSel; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalMUX4 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector4; + SIGNAL dSel : IN std_logic_vector2; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + VARIABLE Data_Schd : SchedArray4; + VARIABLE Data_Edge : EdgeArray4; + VARIABLE dSel_Edge : EdgeArray2; + VARIABLE dSel_bSchd : SchedArray2; + VARIABLE dSel_iSchd : SchedArray2; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN dSel'RANGE LOOP + IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + + IF (AllZeroDelay) THEN LOOP + q <= VitalMUX(Data, dSel, ResultMap); + WAIT ON Data, dSel; + END LOOP; + END IF; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + FOR n IN dSel'RANGE LOOP + BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + GetEdge ( dSel, LastdSel, dSel_Edge ); + BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); + InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalMUX4 ( Data, dSel ); + new_schd := VitalMUX4 ( Data_Schd, dSel_bSchd, dSel_iSchd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, dSel; + END LOOP; + END IF; --SN + END; + + PROCEDURE VitalMUX8 ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector8; + SIGNAL dSel : IN std_logic_vector3; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + VARIABLE Data_Schd : SchedArray8; + VARIABLE Data_Edge : EdgeArray8; + VARIABLE dSel_Edge : EdgeArray3; + VARIABLE dSel_bSchd : SchedArray3; + VARIABLE dSel_iSchd : SchedArray3; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN dSel'RANGE LOOP + IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + + IF (AllZeroDelay) THEN LOOP + q <= VitalMUX(Data, dSel, ResultMap); + WAIT ON Data, dSel; + END LOOP; + END IF; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + FOR n IN dSel'RANGE LOOP + BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + GetEdge ( dSel, LastdSel, dSel_Edge ); + BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); + InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalMUX8 ( Data, dSel ); + new_schd := VitalMUX8 ( Data_Schd, dSel_bSchd, dSel_iSchd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, dSel; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalMUX ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + SIGNAL dSel : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : UX01; + VARIABLE Glitch_Data : GlitchDataType; + VARIABLE new_schd : SchedType; + VARIABLE Dly, Glch : TIME; + VARIABLE Data_Schd : SchedArray(Data'RANGE); + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE dSel_Edge : EdgeArray(dSel'RANGE); + VARIABLE dSel_bSchd : SchedArray(dSel'RANGE); + VARIABLE dSel_iSchd : SchedArray(dSel'RANGE); + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + FOR i IN dSel'RANGE LOOP + IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + IF (AllZeroDelay) THEN + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + + IF (AllZeroDelay) THEN LOOP + q <= VitalMUX(Data, dSel, ResultMap); + WAIT ON Data, dSel; + END LOOP; + END IF; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + FOR n IN dSel'RANGE LOOP + BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); + END LOOP; + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); + + GetEdge ( dSel, LastdSel, dSel_Edge ); + BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); + InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalMUX ( Data, dSel ); + new_schd := VitalMUX ( Data_Schd, dSel_bSchd, dSel_iSchd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, dSel; + END LOOP; + END IF; --SN + END; + + -- ------------------------------------------------------------------------ + -- Decoder + -- General Algorithm : + -- (a) Result(...) := '0' when (enable = '0') + -- (b) Result(data) := '1'; all other subelements = '0' + -- ... Result array is decending (n-1 downto 0) + -- + -- DECODERn .......... n:2**n decoder + -- Caution: If 'ResultMap' defines other than strength mapping, the + -- delay selection is not defined. + -- ------------------------------------------------------------------------ + PROCEDURE VitalDECODER2 ( + SIGNAL q : OUT std_logic_vector2; + SIGNAL Data : IN std_ulogic; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE NewValue : std_logic_vector2; + VARIABLE Glitch_Data : GlitchArray2; + VARIABLE new_schd : SchedArray2; + VARIABLE Dly, Glch : TimeArray2; + VARIABLE Enable_Schd : SchedType := DefSchedType; + VARIABLE Data_BSchd, Data_ISchd : SchedType; + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_enable_q = VitalZeroDelay01) AND (tpd_data_q = VitalZeroDelay01) THEN + LOOP + q <= VitalDECODER2(Data, Enable, ResultMap); + WAIT ON Data, Enable; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + BufPath ( Data_BSchd, InitialEdge(Data), tpd_data_q ); + InvPath ( Data_ISchd, InitialEdge(Data), tpd_data_q ); + BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + BufPath ( Data_BSchd, GetEdge(Data), tpd_data_q ); + InvPath ( Data_ISchd, GetEdge(Data), tpd_data_q ); + + BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalDECODER2 ( Data, Enable, ResultMap ); + new_schd := VitalDECODER2 ( Data_BSchd, Data_ISchd, Enable_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; -- SN + END; +-- + PROCEDURE VitalDECODER4 ( + SIGNAL q : OUT std_logic_vector4; + SIGNAL Data : IN std_logic_vector2; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : std_logic_vector4; + VARIABLE Glitch_Data : GlitchArray4; + VARIABLE new_schd : SchedArray4; + VARIABLE Dly, Glch : TimeArray4; + VARIABLE Enable_Schd : SchedType; + VARIABLE Enable_Edge : EdgeType; + VARIABLE Data_Edge : EdgeArray2; + VARIABLE Data_BSchd, Data_ISchd : SchedArray2; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_enable_q /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + ELSE + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + END IF; + IF (AllZeroDelay) THEN LOOP + q <= VitalDECODER4(Data, Enable, ResultMap); + WAIT ON Data, Enable; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); + InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); + + BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalDECODER4 ( Data, Enable, ResultMap ); + new_schd := VitalDECODER4 ( Data_BSchd, Data_ISchd, Enable_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; +-- + PROCEDURE VitalDECODER8 ( + SIGNAL q : OUT std_logic_vector8; + SIGNAL Data : IN std_logic_vector3; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : std_logic_vector8; + VARIABLE Glitch_Data : GlitchArray8; + VARIABLE new_schd : SchedArray8; + VARIABLE Dly, Glch : TimeArray8; + VARIABLE Enable_Schd : SchedType; + VARIABLE Enable_Edge : EdgeType; + VARIABLE Data_Edge : EdgeArray3; + VARIABLE Data_BSchd, Data_ISchd : SchedArray3; + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_enable_q /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + ELSE + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + END IF; + IF (AllZeroDelay) THEN LOOP + q <= VitalDECODER(Data, Enable, ResultMap); + WAIT ON Data, Enable; + END LOOP; + ELSE + + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); + InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); + + BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalDECODER8 ( Data, Enable, ResultMap ); + new_schd := VitalDECODER8 ( Data_BSchd, Data_ISchd, Enable_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; --SN + END; +-- + PROCEDURE VitalDECODER ( + SIGNAL q : OUT std_logic_vector; + SIGNAL Data : IN std_logic_vector; + SIGNAL Enable : IN std_ulogic; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) IS + VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); + VARIABLE NewValue : std_logic_vector(q'RANGE); + VARIABLE Glitch_Data : GlitchDataArrayType(q'RANGE); + VARIABLE new_schd : SchedArray(q'RANGE); + VARIABLE Dly, Glch : VitalTimeArray(q'RANGE); + VARIABLE Enable_Schd : SchedType; + VARIABLE Enable_Edge : EdgeType; + VARIABLE Data_Edge : EdgeArray(Data'RANGE); + VARIABLE Data_BSchd, Data_ISchd : SchedArray(Data'RANGE); + ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; + VARIABLE AllZeroDelay : BOOLEAN := TRUE; + BEGIN + -- ------------------------------------------------------------------------ + -- Check if ALL zero delay paths, use simple model + -- ( No delay selection, glitch detection required ) + -- ------------------------------------------------------------------------ + IF (tpd_enable_q /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + ELSE + FOR i IN Data'RANGE LOOP + IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN + AllZeroDelay := FALSE; + EXIT; + END IF; + END LOOP; + END IF; + IF (AllZeroDelay) THEN LOOP + q <= VitalDECODER(Data, Enable, ResultMap); + WAIT ON Data, Enable; + END LOOP; + ELSE + -- -------------------------------------- + -- Initialize delay schedules + -- -------------------------------------- + FOR n IN Data'RANGE LOOP + BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); + END LOOP; + BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); + + LOOP + -- -------------------------------------- + -- Process input signals + -- get edge values + -- re-evaluate output schedules + -- -------------------------------------- + GetEdge ( Data, LastData, Data_Edge ); + BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); + InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); + + BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); + + -- ------------------------------------ + -- Compute function and propation delaq + -- ------------------------------------ + NewValue := VitalDECODER ( Data, Enable, ResultMap ); + new_schd := VitalDECODER ( Data_BSchd, Data_ISchd, Enable_Schd ); + + -- ------------------------------------------------------ + -- Assign Outputs + -- get delays to new value and possable glitch + -- schedule output change with On Event glitch detection + -- ------------------------------------------------------ + GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); + VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, + PrimGlitchMode, GlitchDelay=>Glch ); + + WAIT ON Data, Enable; + END LOOP; + END IF; + END; + + -- ------------------------------------------------------------------------ + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic_vector IS + + CONSTANT InputSize : INTEGER := DataIn'LENGTH; + CONSTANT OutSize : INTEGER := TruthTable'LENGTH(2) - InputSize; + VARIABLE ReturnValue : std_logic_vector(OutSize - 1 DOWNTO 0) + := (OTHERS => 'X'); + VARIABLE DataInAlias : std_logic_vector(0 TO InputSize - 1) + := To_X01(DataIn); + VARIABLE Index : INTEGER; + VARIABLE Err : BOOLEAN := FALSE; + + -- This needs to be done since the TableLookup arrays must be + -- ascending starting with 0 + VARIABLE TableAlias : VitalTruthTableType(0 TO (TruthTable'LENGTH(1)-1), + 0 TO (TruthTable'LENGTH(2)-1)) + := TruthTable; + + BEGIN + -- search through each row of the truth table + IF OutSize > 0 THEN + ColLoop: + FOR i IN TableAlias'RANGE(1) LOOP + + RowLoop: -- Check each input element of the entry + FOR j IN 0 TO InputSize LOOP + + IF (j = InputSize) THEN -- This entry matches + -- Return the Result + Index := 0; + FOR k IN TruthTable'LENGTH(2) - 1 DOWNTO InputSize LOOP + TruthOutputX01Z ( TableAlias(i,k), + ReturnValue(Index), Err); + EXIT WHEN Err; + Index := Index + 1; + END LOOP; + + IF Err THEN + ReturnValue := (OTHERS => 'X'); + END IF; + RETURN ReturnValue; + END IF; + IF NOT ValidTruthTableInput(TableAlias(i,j)) THEN + VitalError ( "VitalTruthTable", ErrInpSym, + To_TruthChar(TableAlias(i,j)) ); + EXIT ColLoop; + END IF; + EXIT RowLoop WHEN NOT ( TruthTableMatch( DataInAlias(j), + TableAlias(i, j))); + END LOOP RowLoop; + END LOOP ColLoop; + + ELSE + VitalError ( "VitalTruthTable", ErrTabWidSml ); + END IF; + RETURN ReturnValue; + END VitalTruthTable; + + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic IS + + CONSTANT InputSize : INTEGER := DataIn'LENGTH; + CONSTANT OutSize : INTEGER := TruthTable'LENGTH(2) - InputSize; + VARIABLE TempResult : std_logic_vector(OutSize - 1 DOWNTO 0) + := (OTHERS => 'X'); + BEGIN + IF (OutSize > 0) THEN + TempResult := VitalTruthTable(TruthTable, DataIn); + IF ( 1 > OutSize) THEN + VitalError ( "VitalTruthTable", ErrTabResSml ); + ELSIF ( 1 < OutSize) THEN + VitalError ( "VitalTruthTable", ErrTabResLrg ); + END IF; + RETURN (TempResult(0)); + ELSE + VitalError ( "VitalTruthTable", ErrTabWidSml ); + RETURN 'X'; + END IF; + END VitalTruthTable; + + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic_vector; + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) IS + CONSTANT ResLeng : INTEGER := Result'LENGTH; + CONSTANT ActResLen : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH; + CONSTANT FinalResLen : INTEGER := Minimum(ActResLen, ResLeng); + VARIABLE TempResult : std_logic_vector(ActResLen - 1 DOWNTO 0) + := (OTHERS => 'X'); + + BEGIN + TempResult := VitalTruthTable(TruthTable, DataIn); + + IF (ResLeng > ActResLen) THEN + VitalError ( "VitalTruthTable", ErrTabResSml ); + ELSIF (ResLeng < ActResLen) THEN + VitalError ( "VitalTruthTable", ErrTabResLrg ); + END IF; + TempResult(FinalResLen-1 DOWNTO 0) := TempResult(FinalResLen-1 DOWNTO 0); + Result <= TempResult; + + END VitalTruthTable; + + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic; + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) IS + + CONSTANT ActResLen : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH; + VARIABLE TempResult : std_logic_vector(ActResLen - 1 DOWNTO 0) + := (OTHERS => 'X'); + + BEGIN + TempResult := VitalTruthTable(TruthTable, DataIn); + + IF ( 1 > ActResLen) THEN + VitalError ( "VitalTruthTable", ErrTabResSml ); + ELSIF ( 1 < ActResLen) THEN + VitalError ( "VitalTruthTable", ErrTabResLrg ); + END IF; + IF (ActResLen > 0) THEN + Result <= TempResult(0); + END IF; + + END VitalTruthTable; + + -- ------------------------------------------------------------------------ + PROCEDURE VitalStateTable ( + VARIABLE Result : INOUT std_logic_vector; + VARIABLE PreviousDataIn : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + CONSTANT DataIn : IN std_logic_vector; + CONSTANT NumStates : IN NATURAL + ) IS + + CONSTANT InputSize : INTEGER := DataIn'LENGTH; + CONSTANT OutSize : INTEGER + := StateTable'LENGTH(2) - InputSize - NumStates; + CONSTANT ResLeng : INTEGER := Result'LENGTH; + VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1) + := To_X01(DataIn); + VARIABLE PrevDataAlias : std_logic_vector(0 TO PreviousDataIn'LENGTH-1) + := To_X01(PreviousDataIn); + VARIABLE ResultAlias : std_logic_vector(0 TO ResLeng-1) + := To_X01(Result); + VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); + + BEGIN + IF (PreviousDataIn'LENGTH < DataIn'LENGTH) THEN + VitalError ( "VitalStateTable", ErrVctLng, "PreviousDataIn 'X'); + Result := ResultAlias; + + ELSIF (OutSize <= 0) THEN + VitalError ( "VitalStateTable", ErrTabWidSml ); + + ResultAlias := (OTHERS => 'X'); + Result := ResultAlias; + + ELSE + IF (ResLeng > OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResSml ); + ELSIF (ResLeng < OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResLrg ); + END IF; + + ExpResult := StateTableLookUp ( StateTable, DataInAlias, + PrevDataAlias, NumStates, + ResultAlias); + ResultAlias := (OTHERS => 'X'); + ResultAlias ( Maximum(0, ResLeng - OutSize) TO ResLeng - 1) + := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1); + + Result := ResultAlias; + PrevDataAlias(0 TO InputSize - 1) := DataInAlias; + PreviousDataIn := PrevDataAlias; + + END IF; + END VitalStateTable; + + + PROCEDURE VitalStateTable ( + VARIABLE Result : INOUT std_logic; -- states + VARIABLE PreviousDataIn : INOUT std_logic_vector; -- previous inputs and states + CONSTANT StateTable : IN VitalStateTableType; -- User's StateTable data + CONSTANT DataIn : IN std_logic_vector -- Inputs + ) IS + + VARIABLE ResultAlias : std_logic_vector(0 TO 0); + BEGIN + ResultAlias(0) := Result; + VitalStateTable ( StateTable => StateTable, + DataIn => DataIn, + NumStates => 1, + Result => ResultAlias, + PreviousDataIn => PreviousDataIn + ); + Result := ResultAlias(0); + + END VitalStateTable; + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector; + CONSTANT NumStates : IN NATURAL + ) IS + + CONSTANT InputSize : INTEGER := DataIn'LENGTH; + CONSTANT OutSize : INTEGER + := StateTable'LENGTH(2) - InputSize - NumStates; + CONSTANT ResLeng : INTEGER := Result'LENGTH; + + VARIABLE PrevData : std_logic_vector(0 TO DataIn'LENGTH-1) + := (OTHERS => 'X'); + VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1); + VARIABLE ResultAlias : std_logic_vector(0 TO ResLeng-1); + VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); + + BEGIN + IF (OutSize <= 0) THEN + VitalError ( "VitalStateTable", ErrTabWidSml ); + + ResultAlias := (OTHERS => 'X'); + Result <= ResultAlias; + + ELSE + IF (ResLeng > OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResSml ); + ELSIF (ResLeng < OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResLrg ); + END IF; + + LOOP + DataInAlias := To_X01(DataIn); + ResultAlias := To_X01(Result); + ExpResult := StateTableLookUp ( StateTable, DataInAlias, + PrevData, NumStates, + ResultAlias); + ResultAlias := (OTHERS => 'X'); + ResultAlias(Maximum(0, ResLeng - OutSize) TO ResLeng-1) + := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1); + + Result <= ResultAlias; + PrevData := DataInAlias; + + WAIT ON DataIn; + END LOOP; + + END IF; + + END VitalStateTable; + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector + ) IS + + CONSTANT InputSize : INTEGER := DataIn'LENGTH; + CONSTANT OutSize : INTEGER := StateTable'LENGTH(2) - InputSize-1; + + VARIABLE PrevData : std_logic_vector(0 TO DataIn'LENGTH-1) + := (OTHERS => 'X'); + VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1); + VARIABLE ResultAlias : std_logic_vector(0 TO 0); + VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); + + BEGIN + IF (OutSize <= 0) THEN + VitalError ( "VitalStateTable", ErrTabWidSml ); + + Result <= 'X'; + + ELSE + IF ( 1 > OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResSml ); + ELSIF ( 1 < OutSize) THEN + VitalError ( "VitalStateTable", ErrTabResLrg ); + END IF; + + LOOP + ResultAlias(0) := To_X01(Result); + DataInAlias := To_X01(DataIn); + ExpResult := StateTableLookUp ( StateTable, DataInAlias, + PrevData, 1, ResultAlias); + + Result <= ExpResult(OutSize-1); + PrevData := DataInAlias; + + WAIT ON DataIn; + END LOOP; + END IF; + + END VitalStateTable; + + -- ------------------------------------------------------------------------ + -- std_logic resolution primitive + -- ------------------------------------------------------------------------ + PROCEDURE VitalResolve ( + SIGNAL q : OUT std_ulogic; + CONSTANT Data : IN std_logic_vector + ) IS + VARIABLE uData : std_ulogic_vector(Data'RANGE); + BEGIN + FOR i IN Data'RANGE LOOP + uData(i) := Data(i); + END LOOP; + q <= resolved(uData); + END; + +END VITAL_Primitives; diff --git a/libraries/vital95/vital_primitives_body.vhdl b/libraries/vital95/vital_primitives_body.vhdl deleted file mode 100644 index f8f66366c..000000000 --- a/libraries/vital95/vital_primitives_body.vhdl +++ /dev/null @@ -1,5614 +0,0 @@ -------------------------------------------------------------------------------- --- Title : Standard VITAL_Primitives Package --- : $Revision$ --- : --- Library : VITAL --- : --- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 --- : --- Purpose : This packages defines standard types, constants, functions --- : and procedures for use in developing ASIC models. --- : Specifically a set of logic primitives are defined. --- : --- ---------------------------------------------------------------------------- --- --- ---------------------------------------------------------------------------- --- Modification History : --- ---------------------------------------------------------------------------- --- Version No:|Auth:| Mod.Date:| Changes Made: --- v95.0 A | | 06/02/95 | Initial ballot draft 1995 --- v95.1 | | 08/31/95 | #204 - glitch detection prior to OutputMap --- ---------------------------------------------------------------------------- - -LIBRARY STD; -USE STD.TEXTIO.ALL; - -PACKAGE BODY VITAL_Primitives IS - -- ------------------------------------------------------------------------ - -- Default values for Primitives - -- ------------------------------------------------------------------------ - -- default values for delay parameters - CONSTANT VitalDefDelay01 : VitalDelayType01 := VitalZeroDelay01; - CONSTANT VitalDefDelay01Z : VitalDelayType01Z := VitalZeroDelay01Z; - - TYPE VitalTimeArray IS ARRAY (NATURAL RANGE <>) OF TIME; - - -- default primitive model operation parameters - -- Glitch detection/reporting - TYPE VitalGlitchModeType IS ( MessagePlusX, MessageOnly, XOnly, NoGlitch); - CONSTANT PrimGlitchMode : VitalGlitchModeType := XOnly; - - -- ------------------------------------------------------------------------ - -- Local Type and Subtype Declarations - -- ------------------------------------------------------------------------ - --------------------------------------------------------------------------- - -- enumeration value representing the transition or level of the signal. - -- See function 'GetEdge' - --------------------------------------------------------------------------- - TYPE EdgeType IS ( 'U', -- Uninitialized level - 'X', -- Unknown level - '0', -- low level - '1', -- high level - '\', -- 1 to 0 falling edge - '/', -- 0 to 1 rising edge - 'F', -- * to 0 falling edge - 'R', -- * to 1 rising edge - 'f', -- rising to X edge - 'r', -- falling to X edge - 'x', -- Unknown edge (ie U->X) - 'V' -- Timing violation edge - ); - TYPE EdgeArray IS ARRAY ( NATURAL RANGE <> ) OF EdgeType; - - TYPE EdgeX1Table IS ARRAY ( EdgeType ) OF EdgeType; - TYPE EdgeX2Table IS ARRAY ( EdgeType, EdgeType ) OF EdgeType; - TYPE EdgeX3Table IS ARRAY ( EdgeType, EdgeType, EdgeType ) OF EdgeType; - TYPE EdgeX4Table IS ARRAY (EdgeType,EdgeType,EdgeType,EdgeType) OF EdgeType; - - TYPE LogicToEdgeT IS ARRAY(std_ulogic, std_ulogic) OF EdgeType; - TYPE LogicToLevelT IS ARRAY(std_ulogic ) OF EdgeType; - - TYPE GlitchDataType IS - RECORD - SchedTime : TIME; - GlitchTime : TIME; - SchedValue : std_ulogic; - CurrentValue : std_ulogic; - END RECORD; - TYPE GlitchDataArrayType IS ARRAY (NATURAL RANGE <>) - OF GlitchDataType; - - -- Enumerated type used in selection of output path delays - TYPE SchedType IS - RECORD - inp0 : TIME; -- time (abs) of output change due to input change to 0 - inp1 : TIME; -- time (abs) of output change due to input change to 1 - InpX : TIME; -- time (abs) of output change due to input change to X - Glch0 : TIME; -- time (abs) of output glitch due to input change to 0 - Glch1 : TIME; -- time (abs) of output glitch due to input change to 0 - END RECORD; - - TYPE SchedArray IS ARRAY ( NATURAL RANGE <> ) OF SchedType; - CONSTANT DefSchedType : SchedType := (TIME'HIGH, TIME'HIGH, 0 ns,0 ns,0 ns); - CONSTANT DefSchedAnd : SchedType := (TIME'HIGH, 0 ns,0 ns, TIME'HIGH,0 ns); - - -- Constrained array declarations (common sizes used by primitives) - SUBTYPE SchedArray2 IS SchedArray(1 DOWNTO 0); - SUBTYPE SchedArray3 IS SchedArray(2 DOWNTO 0); - SUBTYPE SchedArray4 IS SchedArray(3 DOWNTO 0); - SUBTYPE SchedArray8 IS SchedArray(7 DOWNTO 0); - - SUBTYPE TimeArray2 IS VitalTimeArray(1 DOWNTO 0); - SUBTYPE TimeArray3 IS VitalTimeArray(2 DOWNTO 0); - SUBTYPE TimeArray4 IS VitalTimeArray(3 DOWNTO 0); - SUBTYPE TimeArray8 IS VitalTimeArray(7 DOWNTO 0); - - SUBTYPE GlitchArray2 IS GlitchDataArrayType(1 DOWNTO 0); - SUBTYPE GlitchArray3 IS GlitchDataArrayType(2 DOWNTO 0); - SUBTYPE GlitchArray4 IS GlitchDataArrayType(3 DOWNTO 0); - SUBTYPE GlitchArray8 IS GlitchDataArrayType(7 DOWNTO 0); - - SUBTYPE EdgeArray2 IS EdgeArray(1 DOWNTO 0); - SUBTYPE EdgeArray3 IS EdgeArray(2 DOWNTO 0); - SUBTYPE EdgeArray4 IS EdgeArray(3 DOWNTO 0); - SUBTYPE EdgeArray8 IS EdgeArray(7 DOWNTO 0); - - CONSTANT DefSchedArray2 : SchedArray2 := - (OTHERS=> (0 ns, 0 ns, 0 ns, 0 ns, 0 ns)); - - TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; - - CONSTANT InitialEdge : LogicToLevelT := ( - '1'|'H' => 'R', - '0'|'L' => 'F', - OTHERS => 'x' - ); - - CONSTANT LogicToEdge : LogicToEdgeT := ( -- previous, current - -- old \ new: U X 0 1 Z W L H - - 'U' => ( 'U', 'x', 'F', 'R', 'x', 'x', 'F', 'R', 'x' ), - 'X' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ), - '0' => ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ), - '1' => ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ), - 'Z' => ( 'x', 'X', 'F', 'R', 'X', 'x', 'F', 'R', 'x' ), - 'W' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ), - 'L' => ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ), - 'H' => ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ), - '-' => ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ) - ); - CONSTANT LogicToLevel : LogicToLevelT := ( - '1'|'H' => '1', - '0'|'L' => '0', - 'U' => 'U', - OTHERS => 'X' - ); - - -- ----------------------------------- - -- 3-state logic tables - -- ----------------------------------- - CONSTANT BufIf0_Table : stdlogic_table := - -- enable data value - ( '1'|'H' => ( OTHERS => 'Z' ), - '0'|'L' => ( '1'|'H' => '1', - '0'|'L' => '0', - 'U' => 'U', - OTHERS => 'X' ), - 'U' => ( OTHERS => 'U' ), - OTHERS => ( OTHERS => 'X' ) ); - CONSTANT BufIf1_Table : stdlogic_table := - -- enable data value - ( '0'|'L' => ( OTHERS => 'Z' ), - '1'|'H' => ( '1'|'H' => '1', - '0'|'L' => '0', - 'U' => 'U', - OTHERS => 'X' ), - 'U' => ( OTHERS => 'U' ), - OTHERS => ( OTHERS => 'X' ) ); - CONSTANT InvIf0_Table : stdlogic_table := - -- enable data value - ( '1'|'H' => ( OTHERS => 'Z' ), - '0'|'L' => ( '1'|'H' => '0', - '0'|'L' => '1', - 'U' => 'U', - OTHERS => 'X' ), - 'U' => ( OTHERS => 'U' ), - OTHERS => ( OTHERS => 'X' ) ); - CONSTANT InvIf1_Table : stdlogic_table := - -- enable data value - ( '0'|'L' => ( OTHERS => 'Z' ), - '1'|'H' => ( '1'|'H' => '0', - '0'|'L' => '1', - 'U' => 'U', - OTHERS => 'X' ), - 'U' => ( OTHERS => 'U' ), - OTHERS => ( OTHERS => 'X' ) ); - - - TYPE To_StateCharType IS ARRAY (VitalStateSymbolType) OF CHARACTER; - CONSTANT To_StateChar : To_StateCharType := - ( '/', '\', 'P', 'N', 'r', 'f', 'p', 'n', 'R', 'F', '^', 'v', - 'E', 'A', 'D', '*', 'X', '0', '1', '-', 'B', 'Z', 'S' ); - TYPE To_TruthCharType IS ARRAY (VitalTruthSymbolType) OF CHARACTER; - CONSTANT To_TruthChar : To_TruthCharType := - ( 'X', '0', '1', '-', 'B', 'Z' ); - - TYPE TruthTableOutMapType IS ARRAY (VitalTruthSymbolType) OF std_ulogic; - CONSTANT TruthTableOutMap : TruthTableOutMapType := - -- 'X', '0', '1', '-', 'B', 'Z' - ( 'X', '0', '1', 'X', '-', 'Z' ); - - TYPE StateTableOutMapType IS ARRAY (VitalStateSymbolType) OF std_ulogic; - -- does conversion to X01Z or '-' if invalid - CONSTANT StateTableOutMap : StateTableOutMapType := - -- '/' '\' 'P' 'N' 'r' 'f' 'p' 'n' 'R' 'F' '^' 'v' - -- 'E' 'A' 'D' '*' 'X' '0' '1' '-' 'B' 'Z' 'S' - ( '-','-','-','-','-','-','-','-','-','-','-','-', - '-','-','-','-','X','0','1','X','-','Z','W'); - - -- ------------------------------------------------------------------------ - TYPE ValidTruthTableInputType IS ARRAY (VitalTruthSymbolType) OF BOOLEAN; - -- checks if a symbol IS valid for the stimulus portion of a truth table - CONSTANT ValidTruthTableInput : ValidTruthTableInputType := - -- 'X' '0' '1' '-' 'B' 'Z' - ( TRUE, TRUE, TRUE, TRUE, TRUE, FALSE ); - - TYPE TruthTableMatchType IS ARRAY (X01, VitalTruthSymbolType) OF BOOLEAN; - -- checks if an input matches th corresponding truth table symbol - -- use: TruthTableMatch(input_converted_to_X01, truth_table_stimulus_symbol) - CONSTANT TruthTableMatch : TruthTableMatchType := ( - -- X, 0, 1, - B Z - ( TRUE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- X - ( FALSE, TRUE, FALSE, TRUE, TRUE, FALSE ), -- 0 - ( FALSE, FALSE, TRUE, TRUE, TRUE, FALSE ) -- 1 - ); - - -- ------------------------------------------------------------------------ - TYPE ValidStateTableInputType IS ARRAY (VitalStateSymbolType) OF BOOLEAN; - CONSTANT ValidStateTableInput : ValidStateTableInputType := - -- '/', '\', 'P', 'N', 'r', 'f', - ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - -- 'p', 'n', 'R', 'F', '^', 'v', - TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, - -- 'E', 'A', 'D', '*', - TRUE, TRUE, TRUE, TRUE, - -- 'X', '0', '1', '-', 'B', 'Z', - TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, - -- 'S' - TRUE ); - - CONSTANT ValidStateTableState : ValidStateTableInputType := - -- '/', '\', 'P', 'N', 'r', 'f', - ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, - -- 'p', 'n', 'R', 'F', '^', 'v', - FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, - -- 'E', 'A', 'D', '*', - FALSE, FALSE, FALSE, FALSE, - -- 'X', '0', '1', '-', 'B', 'Z', - TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, - -- 'S' - FALSE ); - - TYPE StateTableMatchType IS ARRAY (X01,X01,VitalStateSymbolType) OF BOOLEAN; - -- last value, present value, table symbol - CONSTANT StateTableMatch : StateTableMatchType := ( - ( -- X (lastvalue) - -- / \ P N r f - -- p n R F ^ v - -- E A D * - -- X 0 1 - B Z S - (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE, - TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), - (FALSE,FALSE,FALSE,TRUE, FALSE,FALSE, - FALSE,FALSE,FALSE,TRUE, FALSE,TRUE, - TRUE, FALSE,TRUE, TRUE, - FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE), - (FALSE,FALSE,TRUE, FALSE,FALSE,FALSE, - FALSE,FALSE,TRUE, FALSE,TRUE, FALSE, - TRUE, TRUE, FALSE,TRUE, - FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE) - ), - - (-- 0 (lastvalue) - -- / \ P N r f - -- p n R F ^ v - -- E A D * - -- X 0 1 - B Z S - (FALSE,FALSE,FALSE,FALSE,TRUE, FALSE, - TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, - FALSE,TRUE, FALSE,TRUE, - TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), - (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE, - FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,TRUE ), - (TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, - TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,TRUE, - FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE) - ), - - (-- 1 (lastvalue) - -- / \ P N r f - -- p n R F ^ v - -- E A D * - -- X 0 1 - B Z S - (FALSE,FALSE,FALSE,FALSE,FALSE,TRUE , - FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, - FALSE,FALSE,TRUE, TRUE, - TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE), - (FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, - FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, - FALSE,FALSE,FALSE,TRUE, - FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE), - (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,FALSE,FALSE, - FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,TRUE ) - ) - ); - - TYPE Logic_UX01Z_Table IS ARRAY (std_ulogic) OF UX01Z; - ---------------------------------------------------------- - -- table name : cvt_to_x01z - -- parameters : std_ulogic -- some logic value - -- returns : UX01Z -- state value of logic value - -- purpose : to convert state-strength to state only - ---------------------------------------------------------- - CONSTANT cvt_to_ux01z : Logic_UX01Z_Table := - ('U','X','0','1','Z','X','0','1','X' ); - - TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER; - CONSTANT LogicCvtTable : LogicCvtTableType - := ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'); - - -------------------------------------------------------------------- - -- LOCAL Utilities - -------------------------------------------------------------------- - -- ------------------------------------------------------------------------ - -- FUNCTION NAME : MINIMUM - -- - -- PARAMETERS : in1, in2 - integer, time - -- - -- DESCRIPTION : return smaller of in1 and in2 - -- ------------------------------------------------------------------------ - FUNCTION Minimum ( - CONSTANT in1, in2 : INTEGER - ) RETURN INTEGER IS - BEGIN - IF (in1 < in2) THEN - RETURN in1; - END IF; - RETURN in2; - END; - -- ------------------------------------------------------------------------ - 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 NAME : MAXIMUM - -- - -- PARAMETERS : in1, in2 - integer, time - -- - -- DESCRIPTION : return larger of in1 and in2 - -- ------------------------------------------------------------------------ - FUNCTION Maximum ( - CONSTANT in1, in2 : INTEGER - ) RETURN INTEGER IS - BEGIN - IF (in1 > in2) THEN - RETURN in1; - END IF; - RETURN in2; - END; - ----------------------------------------------------------------------- - FUNCTION Maximum ( - CONSTANT t1,t2 : IN TIME - ) RETURN TIME IS - BEGIN - IF ( t1 > t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; - END Maximum; - - ----------------------------------------------------------------------- - FUNCTION GlitchMinTime ( - CONSTANT Time1, Time2 : IN TIME - ) RETURN TIME IS - BEGIN - IF ( Time1 >= NOW ) THEN - IF ( Time2 >= NOW ) THEN - RETURN Minimum ( Time1, Time2); - ELSE - RETURN Time1; - END IF; - ELSE - IF ( Time2 >= NOW ) THEN - RETURN Time2; - ELSE - RETURN 0 ns; - END IF; - END IF; - END; - - -------------------------------------------------------------------- - -- Error Message Types and Tables - -------------------------------------------------------------------- - TYPE VitalErrorType IS ( - ErrNegDel, - ErrInpSym, - ErrOutSym, - ErrStaSym, - ErrVctLng, - ErrTabWidSml, - ErrTabWidLrg, - ErrTabResSml, - ErrTabResLrg - ); - - TYPE VitalErrorSeverityType IS ARRAY (VitalErrorType) OF SEVERITY_LEVEL; - CONSTANT VitalErrorSeverity : VitalErrorSeverityType := ( - ErrNegDel => WARNING, - ErrInpSym => ERROR, - ErrOutSym => ERROR, - ErrStaSym => ERROR, - ErrVctLng => ERROR, - ErrTabWidSml => ERROR, - ErrTabWidLrg => WARNING, - ErrTabResSml => WARNING, - ErrTabResLrg => WARNING - ); - - CONSTANT MsgNegDel : STRING := - "Negative delay. New output value not scheduled. Output signal is: "; - CONSTANT MsgInpSym : STRING := - "Illegal symbol in the input portion of a Truth/State table."; - CONSTANT MsgOutSym : STRING := - "Illegal symbol in the output portion of a Truth/State table."; - CONSTANT MsgStaSym : STRING := - "Illegal symbol in the state portion of a State table."; - CONSTANT MsgVctLng : STRING := - "Vector (array) lengths not equal. "; - CONSTANT MsgTabWidSml : STRING := - "Width of the Truth/State table is too small."; - CONSTANT MsgTabWidLrg : STRING := - "Width of Truth/State table is too large. Extra elements are ignored."; - CONSTANT MsgTabResSml : STRING := - "Result of Truth/State table has too many elements."; - CONSTANT MsgTabResLrg : STRING := - "Result of Truth/State table has too few elements."; - - CONSTANT MsgUnknown : STRING := - "Unknown error message."; - - -------------------------------------------------------------------- - -- LOCAL Utilities - -------------------------------------------------------------------- - FUNCTION VitalMessage ( - CONSTANT ErrorId : IN VitalErrorType - ) RETURN STRING IS - BEGIN - CASE ErrorId IS - WHEN ErrNegDel => RETURN MsgNegDel; - WHEN ErrInpSym => RETURN MsgInpSym; - WHEN ErrOutSym => RETURN MsgOutSym; - WHEN ErrStaSym => RETURN MsgStaSym; - WHEN ErrVctLng => RETURN MsgVctLng; - WHEN ErrTabWidSml => RETURN MsgTabWidSml; - WHEN ErrTabWidLrg => RETURN MsgTabWidLrg; - WHEN ErrTabResSml => RETURN MsgTabResSml; - WHEN ErrTabResLrg => RETURN MsgTabResLrg; - 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; - - --------------------------------------------------------------------------- - 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 Preemted 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 : VitalGlitchOnEvent - -- : - -- Parameters : OutSignal ........ signal being driven - -- : OutSignalName..... name of the driven signal - -- : GlitchData........ internal data required by the procedure - -- : NewValue.......... new value being assigned - -- : NewDelay.......... Delay accompanying the assignment - -- : (Note: for vectors, this is an array) - -- : GlitchMode........ Glitch generation mode - -- : MessagePlusX, MessageOnly, - -- : XOnly, NoGlitch ) - -- : GlitchDelay....... if <= 0 ns , then there will be no Glitch - -- : if > NewDelay, then there is no Glitch, - -- : otherwise, this is the time when a FORCED - -- : generation of a glitch will occur. - ---------------------------------------------------------------------------- - PROCEDURE VitalGlitchOnEvent ( - SIGNAL OutSignal : OUT std_logic; - CONSTANT OutSignalName : IN STRING; - VARIABLE GlitchData : INOUT GlitchDataType; - CONSTANT NewValue : IN std_logic; - CONSTANT NewDelay : IN TIME := 0 ns; - CONSTANT GlitchMode : IN VitalGlitchModeType := MessagePlusX; - CONSTANT GlitchDelay : IN TIME := 0 ns; - CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING - ) IS - -- ------------------------------------------------------------------------ - VARIABLE NoGlitchDet : BOOLEAN := FALSE; - VARIABLE OldGlitch : BOOLEAN := FALSE; - VARIABLE Dly : TIME := NewDelay; - - BEGIN - -- If nothing to schedule, just return - IF NewDelay < 0 ns THEN - IF (NewValue /= GlitchData.SchedValue) THEN - VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName ); - END IF; - - ELSE - -- If nothing currently scheduled - IF GlitchData.SchedTime <= NOW THEN - GlitchData.CurrentValue := GlitchData.SchedValue; - IF (GlitchDelay <= 0 ns) THEN - IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF; - NoGlitchDet := TRUE; - END IF; - - -- Transaction currently scheduled - if glitch already happened - ELSIF GlitchData.GlitchTime <= NOW THEN - GlitchData.CurrentValue := 'X'; - OldGlitch := TRUE; - IF (GlitchData.SchedValue = NewValue) THEN - dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); - END IF; - - -- Transaction currently scheduled (no glitch if same value) - ELSIF (GlitchData.SchedValue = NewValue) AND - (GlitchData.SchedTime = GlitchData.GlitchTime) AND - (GlitchDelay <= 0 ns) THEN - NoGlitchDet := TRUE; - Dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); - - END IF; - - GlitchData.SchedTime := NOW+Dly; - IF OldGlitch THEN - OutSignal <= NewValue AFTER Dly; - - ELSIF NoGlitchDet THEN - GlitchData.GlitchTime := NOW+Dly; - OutSignal <= NewValue AFTER Dly; - - ELSE -- new glitch - GlitchData.GlitchTime := GlitchMinTime ( GlitchData.GlitchTime, - NOW+GlitchDelay ); - - IF (GlitchMode = MessagePlusX) OR - (GlitchMode = MessageOnly) THEN - ReportGlitch ( "VitalGlitchOnEvent", OutSignalName, - GlitchData.GlitchTime, GlitchData.SchedValue, - (Dly + NOW), NewValue, - MsgSeverity=>MsgSeverity ); - END IF; - - IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN - OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW; - OutSignal <= TRANSPORT NewValue AFTER Dly; - ELSE - OutSignal <= NewValue AFTER Dly; - END IF; - END IF; - - GlitchData.SchedValue := NewValue; - END IF; - - RETURN; - END; - - ---------------------------------------------------------------------------- - PROCEDURE VitalGlitchOnEvent ( - SIGNAL OutSignal : OUT std_logic_vector; - CONSTANT OutSignalName : IN STRING; - VARIABLE GlitchData : INOUT GlitchDataArrayType; - CONSTANT NewValue : IN std_logic_vector; - CONSTANT NewDelay : IN VitalTimeArray; - CONSTANT GlitchMode : IN VitalGlitchModeType := MessagePlusX; - CONSTANT GlitchDelay : IN VitalTimeArray; - CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING - ) IS - - ALIAS GlDataAlias : GlitchDataArrayType(1 TO GlitchData'LENGTH) - IS GlitchData; - ALIAS NewValAlias : std_logic_vector(1 TO NewValue'LENGTH) IS NewValue; - ALIAS GlDelayAlias : VitalTimeArray(1 TO GlitchDelay'LENGTH) - IS GlitchDelay; - ALIAS NewDelAlias : VitalTimeArray(1 TO NewDelay'LENGTH) IS NewDelay; - - VARIABLE Index : INTEGER := OutSignal'LEFT; - VARIABLE Direction : INTEGER; - VARIABLE NoGlitchDet : BOOLEAN; - VARIABLE OldGlitch : BOOLEAN; - VARIABLE Dly, GlDly : TIME; - - BEGIN - IF (OutSignal'LEFT > OutSignal'RIGHT) THEN - Direction := -1; - ELSE - Direction := 1; - END IF; - - IF ( (OutSignal'LENGTH /= GlitchData'LENGTH) OR - (OutSignal'LENGTH /= NewValue'LENGTH) OR - (OutSignal'LENGTH /= NewDelay'LENGTH) OR - (OutSignal'LENGTH /= GlitchDelay'LENGTH) ) THEN - VitalError ( "VitalGlitchOnEvent", ErrVctLng, OutSignalName ); - RETURN; - END IF; - - -- a call to the scalar function cannot be made since the actual - -- name associated with a signal parameter must be locally static - FOR n IN 1 TO OutSignal'LENGTH LOOP - - NoGlitchDet := FALSE; - OldGlitch := FALSE; - Dly := NewDelAlias(n); - - -- If nothing to schedule, just skip to next loop iteration - IF NewDelAlias(n) < 0 ns THEN - IF (NewValAlias(n) /= GlDataAlias(n).SchedValue) THEN - VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName ); - END IF; - ELSE - -- If nothing currently scheduled (i.e. last scheduled - -- transaction already occurred) - IF GlDataAlias(n).SchedTime <= NOW THEN - GlDataAlias(n).CurrentValue := GlDataAlias(n).SchedValue; - IF (GlDelayAlias(n) <= 0 ns) THEN - -- Next iteration if no change in value - IF (NewValAlias(n) = GlDataAlias(n).SchedValue) THEN - Index := Index + Direction; - NEXT; - END IF; - -- since last transaction already occurred there is no glitch - NoGlitchDet := TRUE; - END IF; - - -- Transaction currently scheduled - if glitch already happened - ELSIF GlDataAlias(n).GlitchTime <= NOW THEN - GlDataAlias(n).CurrentValue := 'X'; - OldGlitch := TRUE; - IF (GlDataAlias(n).SchedValue = NewValAlias(n)) THEN - dly := Minimum( GlDataAlias(n).SchedTime-NOW, - NewDelAlias(n) ); - END IF; - - -- Transaction currently scheduled - ELSIF (GlDataAlias(n).SchedValue = NewValAlias(n)) AND - (GlDataAlias(n).SchedTime = GlDataAlias(n).GlitchTime) AND - (GlDelayAlias(n) <= 0 ns) THEN - NoGlitchDet := TRUE; - Dly := Minimum( GlDataAlias(n).SchedTime-NOW, - NewDelAlias(n) ); - END IF; - - -- update last scheduled transaction - GlDataAlias(n).SchedTime := NOW+Dly; - - IF OldGlitch THEN - OutSignal(Index) <= NewValAlias(n) AFTER Dly; - ELSIF NoGlitchDet THEN - -- if no glitch then update last glitch time - -- and OutSignal(actual_index) - GlDataAlias(n).GlitchTime := NOW+Dly; - OutSignal(Index) <= NewValAlias(n) AFTER Dly; - ELSE -- new glitch - GlDataAlias(n).GlitchTime := GlitchMinTime ( - GlDataAlias(n).GlitchTime, - NOW+GlDelayAlias(n) ); - - IF (GlitchMode = MessagePlusX) OR - (GlitchMode = MessageOnly) THEN - ReportGlitch ( "VitalGlitchOnEvent", OutSignalName, - GlDataAlias(n).GlitchTime, - GlDataAlias(n).SchedValue, - (Dly + NOW), NewValAlias(n), - Index, TRUE, MsgSeverity ); - END IF; - - IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN - GlDly := GlDataAlias(n).GlitchTime - NOW; - OutSignal(Index) <= 'X' AFTER GlDly; - OutSignal(Index) <= TRANSPORT NewValAlias(n) AFTER Dly; - ELSE - OutSignal(Index) <= NewValAlias(n) AFTER Dly; - END IF; - - END IF; -- glitch / no-glitch - GlDataAlias(n).SchedValue := NewValAlias(n); - - END IF; -- NewDelAlias(n) < 0 ns - Index := Index + Direction; - END LOOP; - - RETURN; - END; - - --------------------------------------------------------------------------- - -- ------------------------------------------------------------------------ - -- PROCEDURE NAME : TruthOutputX01Z - -- - -- PARAMETERS : table_out - output of table - -- X01Zout - output converted to X01Z - -- err - true if illegal character is encountered - -- - -- - -- DESCRIPTION : converts the output of a truth table to a valid - -- std_ulogic - -- ------------------------------------------------------------------------ - PROCEDURE TruthOutputX01Z ( - CONSTANT TableOut : IN VitalTruthSymbolType; - VARIABLE X01Zout : OUT std_ulogic; - VARIABLE Err : OUT BOOLEAN - ) IS - VARIABLE TempOut : std_ulogic; - BEGIN - Err := FALSE; - TempOut := TruthTableOutMap(TableOut); - IF (TempOut = '-') THEN - Err := TRUE; - TempOut := 'X'; - VitalError ( "VitalTruthTable", ErrOutSym, To_TruthChar(TableOut)); - END IF; - X01Zout := TempOut; - END; - - -- ------------------------------------------------------------------------ - -- PROCEDURE NAME : StateOutputX01Z - -- - -- PARAMETERS : table_out - output of table - -- prev_out - previous output value - -- X01Zout - output cojnverted to X01Z - -- err - true if illegal character is encountered - -- - -- DESCRIPTION : converts the output of a state table to a - -- valid std_ulogic - -- ------------------------------------------------------------------------ - PROCEDURE StateOutputX01Z ( - CONSTANT TableOut : IN VitalStateSymbolType; - CONSTANT PrevOut : IN std_ulogic; - VARIABLE X01Zout : OUT std_ulogic; - VARIABLE Err : OUT BOOLEAN - ) IS - VARIABLE TempOut : std_ulogic; - BEGIN - Err := FALSE; - TempOut := StateTableOutMap(TableOut); - IF (TempOut = '-') THEN - Err := TRUE; - TempOut := 'X'; - VitalError ( "VitalStateTable", ErrOutSym, To_StateChar(TableOut)); - ELSIF (TempOut = 'W') THEN - TempOut := To_X01Z(PrevOut); - END IF; - X01Zout := TempOut; - END; - - -- ------------------------------------------------------------------------ - -- PROCEDURE NAME: StateMatch - -- - -- PARAMETERS : symbol - symbol from state table - -- in2 - input from VitalStateTble procedure - -- to state table - -- in2LastValue - previous value of input - -- state - false if the symbol is from the input - -- portion of the table, - -- true if the symbol is from the state - -- portion of the table - -- Err - true if symbol is not a valid input symbol - -- ReturnValue - true if match occurred - -- - -- DESCRIPTION : This procedure sets ReturnValue to true if in2 matches - -- symbol (from the state table). If symbol is an edge - -- value edge is set to true and in2 and in2LastValue are - -- checked against symbol. Err is set to true if symbol - -- is an invalid value for the input portion of the state - -- table. - -- - -- ------------------------------------------------------------------------ - PROCEDURE StateMatch ( - CONSTANT Symbol : IN VitalStateSymbolType; - CONSTANT in2 : IN std_ulogic; - CONSTANT in2LastValue : IN std_ulogic; - CONSTANT State : IN BOOLEAN; - VARIABLE Err : OUT BOOLEAN; - VARIABLE ReturnValue : OUT BOOLEAN - ) IS - BEGIN - IF (State) THEN - IF (NOT ValidStateTableState(Symbol)) THEN - VitalError ( "VitalStateTable", ErrStaSym, To_StateChar(Symbol)); - Err := TRUE; - ReturnValue := FALSE; - ELSE - Err := FALSE; - ReturnValue := StateTableMatch(in2LastValue, in2, Symbol); - END IF; - ELSE - IF (NOT ValidStateTableInput(Symbol) ) THEN - VitalError ( "VitalStateTable", ErrInpSym, To_StateChar(Symbol)); - Err := TRUE; - ReturnValue := FALSE; - ELSE - ReturnValue := StateTableMatch(in2LastValue, in2, Symbol); - Err := FALSE; - END IF; - END IF; - END; - - -- ----------------------------------------------------------------------- - -- FUNCTION NAME: StateTableLookUp - -- - -- PARAMETERS : StateTable - state table - -- PresentDataIn - current inputs - -- PreviousDataIn - previous inputs and states - -- NumStates - number of state variables - -- PresentOutputs - current state and current outputs - -- - -- DESCRIPTION : This function is used to find the output of the - -- StateTable corresponding to a given set of inputs. - -- - -- ------------------------------------------------------------------------ - FUNCTION StateTableLookUp ( - CONSTANT StateTable : VitalStateTableType; - CONSTANT PresentDataIn : std_logic_vector; - CONSTANT PreviousDataIn : std_logic_vector; - CONSTANT NumStates : NATURAL; - CONSTANT PresentOutputs : std_logic_vector - ) RETURN std_logic_vector IS - - CONSTANT InputSize : INTEGER := PresentDataIn'LENGTH; - CONSTANT NumInputs : INTEGER := InputSize + NumStates - 1; - CONSTANT TableEntries : INTEGER := StateTable'LENGTH(1); - CONSTANT TableWidth : INTEGER := StateTable'LENGTH(2); - CONSTANT OutSize : INTEGER := TableWidth - InputSize - NumStates; - VARIABLE Inputs : std_logic_vector(0 TO NumInputs); - VARIABLE PrevInputs : std_logic_vector(0 TO NumInputs) - := (OTHERS => 'X'); - VARIABLE ReturnValue : std_logic_vector(0 TO (OutSize-1)) - := (OTHERS => 'X'); - VARIABLE Temp : std_ulogic; - VARIABLE Match : BOOLEAN; - VARIABLE Err : BOOLEAN := FALSE; - - -- This needs to be done since the TableLookup arrays must be - -- ascending starting with 0 - VARIABLE TableAlias : VitalStateTableType(0 TO TableEntries - 1, - 0 TO TableWidth - 1) - := StateTable; - - BEGIN - Inputs(0 TO InputSize-1) := PresentDataIn; - Inputs(InputSize TO NumInputs) := PresentOutputs(0 TO NumStates - 1); - PrevInputs(0 TO InputSize - 1) := PreviousDataIn(0 TO InputSize - 1); - - ColLoop: -- Compare each entry in the table - FOR i IN TableAlias'RANGE(1) LOOP - - RowLoop: -- Check each element of the entry - FOR j IN 0 TO InputSize + NumStates LOOP - - IF (j = InputSize + NumStates) THEN -- a match occurred - FOR k IN 0 TO Minimum(OutSize, PresentOutputs'LENGTH)-1 LOOP - StateOutputX01Z ( - TableAlias(i, TableWidth - k - 1), - PresentOutputs(PresentOutputs'LENGTH - k - 1), - Temp, Err); - ReturnValue(OutSize - k - 1) := Temp; - IF (Err) THEN - ReturnValue := (OTHERS => 'X'); - RETURN ReturnValue; - END IF; - END LOOP; - RETURN ReturnValue; - END IF; - - StateMatch ( TableAlias(i,j), - Inputs(j), PrevInputs(j), - j >= InputSize, Err, Match); - EXIT RowLoop WHEN NOT(Match); - EXIT ColLoop WHEN Err; - END LOOP RowLoop; - END LOOP ColLoop; - - ReturnValue := (OTHERS => 'X'); - RETURN ReturnValue; - END; - - -------------------------------------------------------------------- - -- to_ux01z - ------------------------------------------------------------------- - FUNCTION To_UX01Z ( s : std_ulogic - ) RETURN UX01Z IS - BEGIN - RETURN cvt_to_ux01z (s); - END; - - --------------------------------------------------------------------------- - -- Function : GetEdge - -- Purpose : Converts transitions on a given input signal into a - -- enumeration value representing the transition or level - -- of the signal. - -- - -- previous "value" current "value" := "edge" - -- --------------------------------------------------------- - -- '1' | 'H' '1' | 'H' '1' level, no edge - -- '0' | 'L' '1' | 'H' '/' rising edge - -- others '1' | 'H' 'R' rising from X - -- - -- '1' | 'H' '0' | 'L' '\' falling egde - -- '0' | 'L' '0' | 'L' '0' level, no edge - -- others '0' | 'L' 'F' falling from X - -- - -- 'X' | 'W' | '-' 'X' | 'W' | '-' 'X' unknown (X) level - -- 'Z' 'Z' 'X' unknown (X) level - -- 'U' 'U' 'U' 'U' level - -- - -- '1' | 'H' others 'f' falling to X - -- '0' | 'L' others 'r' rising to X - -- 'X' | 'W' | '-' 'U' | 'Z' 'x' unknown (X) edge - -- 'Z' 'X' | 'W' | '-' | 'U' 'x' unknown (X) edge - -- 'U' 'X' | 'W' | '-' | 'Z' 'x' unknown (X) edge - -- - --------------------------------------------------------------------------- - FUNCTION GetEdge ( - SIGNAL s : IN std_logic - ) RETURN EdgeType IS - BEGIN - IF (s'EVENT) - THEN RETURN LogicToEdge ( s'LAST_VALUE, s ); - ELSE RETURN LogicToLevel ( s ); - END IF; - END; - - --------------------------------------------------------------------------- - PROCEDURE GetEdge ( - SIGNAL s : IN std_logic_vector; - VARIABLE LastS : INOUT std_logic_vector; - VARIABLE Edge : OUT EdgeArray ) IS - - ALIAS sAlias : std_logic_vector ( 1 TO s'LENGTH ) IS s; - ALIAS LastSAlias : std_logic_vector ( 1 TO LastS'LENGTH ) IS LastS; - ALIAS EdgeAlias : EdgeArray ( 1 TO Edge'LENGTH ) IS Edge; - BEGIN - IF s'LENGTH /= LastS'LENGTH OR - s'LENGTH /= Edge'LENGTH THEN - VitalError ( "GetEdge", ErrVctLng, "s, LastS, Edge" ); - END IF; - - FOR n IN 1 TO s'LENGTH LOOP - EdgeAlias(n) := LogicToEdge( LastSAlias(n), sAlias(n) ); - LastSAlias(n) := sAlias(n); - END LOOP; - END; - - --------------------------------------------------------------------------- - FUNCTION ToEdge ( Value : IN std_logic - ) RETURN EdgeType IS - BEGIN - RETURN LogicToLevel( Value ); - END; - - -- Note: This function will likely be replaced by S'DRIVING_VALUE in VHDL'92 - ---------------------------------------------------------------------------- - FUNCTION CurValue ( - CONSTANT GlitchData : IN GlitchDataType - ) RETURN std_logic IS - BEGIN - IF NOW >= GlitchData.SchedTime THEN - RETURN GlitchData.SchedValue; - ELSIF NOW >= GlitchData.GlitchTime THEN - RETURN 'X'; - ELSE - RETURN GlitchData.CurrentValue; - END IF; - END; - --------------------------------------------------------------------------- - FUNCTION CurValue ( - CONSTANT GlitchData : IN GlitchDataArrayType - ) RETURN std_logic_vector IS - VARIABLE Result : std_logic_vector(GlitchData'RANGE); - BEGIN - FOR n IN GlitchData'RANGE LOOP - IF NOW >= GlitchData(n).SchedTime THEN - Result(n) := GlitchData(n).SchedValue; - ELSIF NOW >= GlitchData(n).GlitchTime THEN - Result(n) := 'X'; - ELSE - Result(n) := GlitchData(n).CurrentValue; - END IF; - END LOOP; - RETURN Result; - END; - - --------------------------------------------------------------------------- - -- function calculation utilities - --------------------------------------------------------------------------- - - --------------------------------------------------------------------------- - -- Function : VitalSame - -- Returns : VitalSame compares the state (UX01) of two logic value. A - -- value of 'X' is returned if the values are different. The - -- common value is returned if the values are equal. - -- Purpose : When the result of a logic model may be either of two - -- separate input values (eg. when the select on a MUX is 'X'), - -- VitalSame may be used to determine if the result needs to - -- be 'X'. - -- Arguments : See the declarations below... - --------------------------------------------------------------------------- - FUNCTION VitalSame ( - CONSTANT a, b : IN std_ulogic - ) RETURN std_ulogic IS - BEGIN - IF To_UX01(a) = To_UX01(b) - THEN RETURN To_UX01(a); - ELSE RETURN 'X'; - END IF; - END; - - --------------------------------------------------------------------------- - -- delay selection utilities - --------------------------------------------------------------------------- - - --------------------------------------------------------------------------- - -- Procedure : BufPath, InvPath - -- - -- Purpose : BufPath and InvPath compute output change times, based on - -- a change on an input port. The computed output change times - -- returned in the composite parameter 'schd'. - -- - -- BufPath and InpPath are used together with the delay path - -- selection functions (GetSchedDelay, VitalAND, VitalOR... ) - -- The 'schd' value from each of the input ports of a model are - -- combined by the delay selection functions (VitalAND, - -- VitalOR, ...). The GetSchedDelay procedure converts the - -- combined output changes times to the single delay (delta - -- time) value for scheduling the output change (passed to - -- VitalGlitchOnEvent). - -- - -- The values in 'schd' are: (absolute times) - -- inp0 : time of output change due to input change to 0 - -- inp1 : time of output change due to input change to 1 - -- inpX : time of output change due to input change to X - -- glch0 : time of output glitch due to input change to 0 - -- glch1 : time of output glitch due to input change to 1 - -- - -- The output times are computed from the model INPUT value - -- and not the final value. For this reason, 'BufPath' should - -- be used to compute the output times for a non-inverting - -- delay paths and 'InvPath' should be used to compute the - -- ouput times for inverting delay paths. Delay paths which - -- include both non-inverting and paths require usage of both - -- 'BufPath' and 'InvPath'. (IE this is needed for the - -- select->output path of a MUX -- See the VitalMUX model). - -- - -- - -- Parameters : schd....... Computed output result times. (INOUT parameter - -- modified only on input edges) - -- Iedg....... Input port edge/level value. - -- tpd....... Propagation delays from this input - -- - --------------------------------------------------------------------------- - - PROCEDURE BufPath ( - VARIABLE Schd : INOUT SchedType; - CONSTANT Iedg : IN EdgeType; - CONSTANT tpd : IN VitalDelayType01 - ) IS - BEGIN - CASE Iedg IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd.inp0 := TIME'HIGH; - Schd.inp1 := NOW + tpd(tr01); Schd.Glch1 := Schd.inp1; - Schd.InpX := Schd.inp1; - WHEN '\'|'F' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := NOW + tpd(tr10); Schd.Glch0 := Schd.inp0; - Schd.InpX := Schd.inp0; - WHEN 'r' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := TIME'HIGH; - Schd.InpX := NOW + tpd(tr01); - WHEN 'f' => Schd.inp0 := TIME'HIGH; - Schd.inp1 := TIME'HIGH; - Schd.InpX := NOW + tpd(tr10); - WHEN 'x' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := TIME'HIGH; - -- update for X->X change - Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END; - - PROCEDURE BufPath ( - VARIABLE Schd : INOUT SchedArray; - CONSTANT Iedg : IN EdgeArray; - CONSTANT tpd : IN VitalDelayArrayType01 - ) IS - BEGIN - FOR n IN Schd'RANGE LOOP - CASE Iedg(n) IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH; - Schd(n).inp1 := NOW + tpd(n)(tr01); - Schd(n).Glch1 := Schd(n).inp1; - Schd(n).InpX := Schd(n).inp1; - WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := NOW + tpd(n)(tr10); - Schd(n).Glch0 := Schd(n).inp0; - Schd(n).InpX := Schd(n).inp0; - WHEN 'r' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := TIME'HIGH; - Schd(n).InpX := NOW + tpd(n)(tr01); - WHEN 'f' => Schd(n).inp0 := TIME'HIGH; - Schd(n).inp1 := TIME'HIGH; - Schd(n).InpX := NOW + tpd(n)(tr10); - WHEN 'x' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := TIME'HIGH; - -- update for X->X change - Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10), - tpd(n)(tr01) ); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END LOOP; - END; - - PROCEDURE InvPath ( - VARIABLE Schd : INOUT SchedType; - CONSTANT Iedg : IN EdgeType; - CONSTANT tpd : IN VitalDelayType01 - ) IS - BEGIN - CASE Iedg IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd.inp0 := TIME'HIGH; - Schd.inp1 := NOW + tpd(tr10); Schd.Glch1 := Schd.inp1; - Schd.InpX := Schd.inp1; - WHEN '\'|'F' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := NOW + tpd(tr01); Schd.Glch0 := Schd.inp0; - Schd.InpX := Schd.inp0; - WHEN 'r' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := TIME'HIGH; - Schd.InpX := NOW + tpd(tr10); - WHEN 'f' => Schd.inp0 := TIME'HIGH; - Schd.inp1 := TIME'HIGH; - Schd.InpX := NOW + tpd(tr01); - WHEN 'x' => Schd.inp1 := TIME'HIGH; - Schd.inp0 := TIME'HIGH; - -- update for X->X change - Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END; - - PROCEDURE InvPath ( - VARIABLE Schd : INOUT SchedArray; - CONSTANT Iedg : IN EdgeArray; - CONSTANT tpd : IN VitalDelayArrayType01 - ) IS - BEGIN - FOR n IN Schd'RANGE LOOP - CASE Iedg(n) IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH; - Schd(n).inp1 := NOW + tpd(n)(tr10); - Schd(n).Glch1 := Schd(n).inp1; - Schd(n).InpX := Schd(n).inp1; - WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := NOW + tpd(n)(tr01); - Schd(n).Glch0 := Schd(n).inp0; - Schd(n).InpX := Schd(n).inp0; - WHEN 'r' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := TIME'HIGH; - Schd(n).InpX := NOW + tpd(n)(tr10); - WHEN 'f' => Schd(n).inp0 := TIME'HIGH; - Schd(n).inp1 := TIME'HIGH; - Schd(n).InpX := NOW + tpd(n)(tr01); - WHEN 'x' => Schd(n).inp1 := TIME'HIGH; - Schd(n).inp0 := TIME'HIGH; - -- update for X->X change - Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10), - tpd(n)(tr01) ); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END LOOP; - END; - - --------------------------------------------------------------------------- - -- Procedure : BufEnab, InvEnab - -- - -- Purpose : BufEnab and InvEnab compute output change times, from a - -- change on an input enable port for a 3-state driver. The - -- computed output change times are returned in the composite - -- parameters 'schd1', 'schd0'. - -- - -- BufEnab and InpEnab are used together with the delay path - -- selection functions (GetSchedDelay, VitalAND, VitalOR... ) - -- The 'schd' value from each of the non-enable input ports of - -- a model (See BufPath, InvPath) are combined using the delay - -- selection functions (VitalAND, VitalOR, ...). The - -- GetSchedDelay procedure combines the output times on the - -- enable path with the output times from the data path(s) and - -- computes the single delay (delta time) value for scheduling - -- the output change (passed to VitalGlitchOnEvent) - -- - -- The values in 'schd*' are: (absolute times) - -- inp0 : time of output change due to input change to 0 - -- inp1 : time of output change due to input change to 1 - -- inpX : time of output change due to input change to X - -- glch0 : time of output glitch due to input change to 0 - -- glch1 : time of output glitch due to input change to 1 - -- - -- 'schd1' contains output times for 1->Z, Z->1 transitions. - -- 'schd0' contains output times for 0->Z, Z->0 transitions. - -- - -- 'BufEnab' is used for computing the output times for an - -- high asserted enable (output 'Z' for enable='0'). - -- 'InvEnab' is used for computing the output times for an - -- low asserted enable (output 'Z' for enable='1'). - -- - -- Note: separate 'schd1', 'schd0' parameters are generated - -- so that the combination of the delay paths from - -- multiple enable signals may be combined using the - -- same functions/operators used in combining separate - -- data paths. (See exampe 2 below) - -- - -- - -- Parameters : schd1...... Computed output result times for 1->Z, Z->1 - -- transitions. This parameter is modified only on - -- input edge values (events). - -- schd0...... Computed output result times for 0->Z, 0->1 - -- transitions. This parameter is modified only on - -- input edge values (events). - -- Iedg....... Input port edge/level value. - -- tpd....... Propagation delays for the enable -> output path. - -- - --------------------------------------------------------------------------- - PROCEDURE BufEnab ( - VARIABLE Schd1 : INOUT SchedType; - VARIABLE Schd0 : INOUT SchedType; - CONSTANT Iedg : IN EdgeType; - CONSTANT tpd : IN VitalDelayType01Z - ) IS - BEGIN - CASE Iedg IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := NOW + tpd(trz1); - Schd1.Glch1 := Schd1.inp1; - Schd1.InpX := Schd1.inp1; - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := NOW + tpd(trz0); - Schd0.Glch1 := Schd0.inp1; - Schd0.InpX := Schd0.inp1; - WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH; - Schd1.inp0 := NOW + tpd(tr1z); - Schd1.Glch0 := Schd1.inp0; - Schd1.InpX := Schd1.inp0; - Schd0.inp1 := TIME'HIGH; - Schd0.inp0 := NOW + tpd(tr0z); - Schd0.Glch0 := Schd0.inp0; - Schd0.InpX := Schd0.inp0; - WHEN 'r' => Schd1.inp1 := TIME'HIGH; - Schd1.inp0 := TIME'HIGH; - Schd1.InpX := NOW + tpd(trz1); - Schd0.inp1 := TIME'HIGH; - Schd0.inp0 := TIME'HIGH; - Schd0.InpX := NOW + tpd(trz0); - WHEN 'f' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := TIME'HIGH; - Schd1.InpX := NOW + tpd(tr1z); - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := TIME'HIGH; - Schd0.InpX := NOW + tpd(tr0z); - WHEN 'x' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := TIME'HIGH; - Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := TIME'HIGH; - Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END; - - PROCEDURE InvEnab ( - VARIABLE Schd1 : INOUT SchedType; - VARIABLE Schd0 : INOUT SchedType; - CONSTANT Iedg : IN EdgeType; - CONSTANT tpd : IN VitalDelayType01Z - ) IS - BEGIN - CASE Iedg IS - WHEN '0'|'1' => NULL; -- no edge: no timing update - WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := NOW + tpd(tr1z); - Schd1.Glch1 := Schd1.inp1; - Schd1.InpX := Schd1.inp1; - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := NOW + tpd(tr0z); - Schd0.Glch1 := Schd0.inp1; - Schd0.InpX := Schd0.inp1; - WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH; - Schd1.inp0 := NOW + tpd(trz1); - Schd1.Glch0 := Schd1.inp0; - Schd1.InpX := Schd1.inp0; - Schd0.inp1 := TIME'HIGH; - Schd0.inp0 := NOW + tpd(trz0); - Schd0.Glch0 := Schd0.inp0; - Schd0.InpX := Schd0.inp0; - WHEN 'r' => Schd1.inp1 := TIME'HIGH; - Schd1.inp0 := TIME'HIGH; - Schd1.InpX := NOW + tpd(tr1z); - Schd0.inp1 := TIME'HIGH; - Schd0.inp0 := TIME'HIGH; - Schd0.InpX := NOW + tpd(tr0z); - WHEN 'f' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := TIME'HIGH; - Schd1.InpX := NOW + tpd(trz1); - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := TIME'HIGH; - Schd0.InpX := NOW + tpd(trz0); - WHEN 'x' => Schd1.inp0 := TIME'HIGH; - Schd1.inp1 := TIME'HIGH; - Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - Schd0.inp0 := TIME'HIGH; - Schd0.inp1 := TIME'HIGH; - Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01)); - WHEN OTHERS => NULL; -- no timing change - END CASE; - END; - - --------------------------------------------------------------------------- - -- Procedure : GetSchedDelay - -- - -- Purpose : GetSchedDelay computes the final delay (incremental) for - -- for scheduling an output signal. The delay is computed - -- from the absolute output times in the 'NewSched' parameter. - -- (See BufPath, InvPath). - -- - -- Computation of the output delay for non-3_state outputs - -- consists of selection the appropriate output time based - -- on the new output value 'NewValue' and subtracting 'NOW' - -- to convert to an incremental delay value. - -- - -- The Computation of the output delay for 3_state output - -- also includes combination of the enable path delay with - -- the date path delay. - -- - -- Parameters : NewDelay... Returned output delay value. - -- GlchDelay.. Returned output delay for the start of a glitch. - -- NewValue... New output value. - -- CurValue... Current value of the output. - -- NewSched... Composite containing the combined absolute - -- output times from the data inputs. - -- EnSched1... Composite containing the combined absolute - -- output times from the enable input(s). - -- (for a 3_state output transitions 1->Z, Z->1) - -- EnSched0... Composite containing the combined absolute - -- output times from the enable input(s). - -- (for a 3_state output transitions 0->Z, Z->0) - -- - --------------------------------------------------------------------------- - PROCEDURE GetSchedDelay ( - VARIABLE NewDelay : OUT TIME; - VARIABLE GlchDelay : OUT TIME; - CONSTANT NewValue : IN std_ulogic; - CONSTANT CurValue : IN std_ulogic; - CONSTANT NewSched : IN SchedType - ) IS - VARIABLE Tim, Glch : TIME; - BEGIN - - CASE To_UX01(NewValue) IS - WHEN '0' => Tim := NewSched.inp0; - Glch := NewSched.Glch1; - WHEN '1' => Tim := NewSched.inp1; - Glch := NewSched.Glch0; - WHEN OTHERS => Tim := NewSched.InpX; - Glch := -1 ns; - END CASE; - IF (CurValue /= NewValue) - THEN Glch := -1 ns; - END IF; - - NewDelay := Tim - NOW; - IF Glch < 0 ns - THEN GlchDelay := Glch; - ELSE GlchDelay := Glch - NOW; - END IF; -- glch < 0 ns - END; - - PROCEDURE GetSchedDelay ( - VARIABLE NewDelay : OUT VitalTimeArray; - VARIABLE GlchDelay : OUT VitalTimeArray; - CONSTANT NewValue : IN std_logic_vector; - CONSTANT CurValue : IN std_logic_vector; - CONSTANT NewSched : IN SchedArray - ) IS - VARIABLE Tim, Glch : TIME; - ALIAS NewDelayAlias : VitalTimeArray( NewDelay'LENGTH DOWNTO 1) - IS NewDelay; - ALIAS GlchDelayAlias : VitalTimeArray(GlchDelay'LENGTH DOWNTO 1) - IS GlchDelay; - ALIAS NewSchedAlias : SchedArray( NewSched'LENGTH DOWNTO 1) - IS NewSched; - ALIAS NewValueAlias : std_logic_vector ( NewValue'LENGTH DOWNTO 1 ) - IS NewValue; - ALIAS CurValueAlias : std_logic_vector ( CurValue'LENGTH DOWNTO 1 ) - IS CurValue; - BEGIN - FOR n IN NewDelay'LENGTH DOWNTO 1 LOOP - CASE To_UX01(NewValueAlias(n)) IS - WHEN '0' => Tim := NewSchedAlias(n).inp0; - Glch := NewSchedAlias(n).Glch1; - WHEN '1' => Tim := NewSchedAlias(n).inp1; - Glch := NewSchedAlias(n).Glch0; - WHEN OTHERS => Tim := NewSchedAlias(n).InpX; - Glch := -1 ns; - END CASE; - IF (CurValueAlias(n) /= NewValueAlias(n)) - THEN Glch := -1 ns; - END IF; - - NewDelayAlias(n) := Tim - NOW; - IF Glch < 0 ns - THEN GlchDelayAlias(n) := Glch; - ELSE GlchDelayAlias(n) := Glch - NOW; - END IF; -- glch < 0 ns - END LOOP; - RETURN; - END; - - PROCEDURE GetSchedDelay ( - VARIABLE NewDelay : OUT TIME; - VARIABLE GlchDelay : OUT TIME; - CONSTANT NewValue : IN std_ulogic; - CONSTANT CurValue : IN std_ulogic; - CONSTANT NewSched : IN SchedType; - CONSTANT EnSched1 : IN SchedType; - CONSTANT EnSched0 : IN SchedType - ) IS - SUBTYPE v2 IS std_logic_vector(0 TO 1); - VARIABLE Tim, Glch : TIME; - BEGIN - - CASE v2'(To_X01Z(CurValue) & To_X01Z(NewValue)) IS - WHEN "00" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); - Glch := GlitchMinTime(NewSched.Glch1,EnSched0.Glch0); - WHEN "01" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); - Glch := EnSched1.Glch0; - WHEN "0Z" => Tim := EnSched0.inp0; - Glch := NewSched.Glch1; - WHEN "0X" => Tim := Maximum (NewSched.InpX, EnSched1.InpX); - Glch := 0 ns; - WHEN "10" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); - Glch := EnSched0.Glch0; - WHEN "11" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); - Glch := GlitchMinTime(NewSched.Glch0,EnSched1.Glch0); - WHEN "1Z" => Tim := EnSched1.inp0; - Glch := NewSched.Glch0; - WHEN "1X" => Tim := Maximum (NewSched.InpX, EnSched0.InpX); - Glch := 0 ns; - WHEN "Z0" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); - IF NewSched.Glch0 > NOW - THEN Glch := Maximum(NewSched.Glch1,EnSched1.inp1); - ELSE Glch := 0 ns; - END IF; - WHEN "Z1" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); - IF NewSched.Glch1 > NOW - THEN Glch := Maximum(NewSched.Glch0,EnSched0.inp1); - ELSE Glch := 0 ns; - END IF; - WHEN "ZX" => Tim := Maximum (NewSched.InpX, EnSched1.InpX); - Glch := 0 ns; - WHEN "ZZ" => Tim := Maximum (EnSched1.InpX, EnSched0.InpX); - Glch := 0 ns; - WHEN "X0" => Tim := Maximum (NewSched.inp0, EnSched0.inp1); - Glch := 0 ns; - WHEN "X1" => Tim := Maximum (NewSched.inp1, EnSched1.inp1); - Glch := 0 ns; - WHEN "XZ" => Tim := Maximum (EnSched1.InpX, EnSched0.InpX); - Glch := 0 ns; - WHEN OTHERS => Tim := Maximum (NewSched.InpX, EnSched1.InpX); - Glch := 0 ns; - - END CASE; - NewDelay := Tim - NOW; - IF Glch < 0 ns - THEN GlchDelay := Glch; - ELSE GlchDelay := Glch - NOW; - END IF; -- glch < 0 ns - END; - - --------------------------------------------------------------------------- - -- Operators and Functions for combination (selection) of path delays - -- > These functions support selection of the "appripriate" path delay - -- dependent on the logic function. - -- > These functions only "select" from the possable output times. No - -- calculation (addition) of delays is performed. - -- > See description of 'BufPath', 'InvPath' and 'GetSchedDelay' - -- > See primitive PROCEDURE models for examples. - --------------------------------------------------------------------------- - - FUNCTION "not" ( - CONSTANT a : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - z.inp1 := a.inp0 ; - z.inp0 := a.inp1 ; - z.InpX := a.InpX ; - z.Glch1 := a.Glch0; - z.Glch0 := a.Glch1; - RETURN (z); - END; - - FUNCTION "and" ( - CONSTANT a, b : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - z.inp1 := Maximum ( a.inp1 , b.inp1 ); - z.inp0 := Minimum ( a.inp0 , b.inp0 ); - z.InpX := GlitchMinTime ( a.InpX , b.InpX ); - z.Glch1 := Maximum ( a.Glch1, b.Glch1 ); - z.Glch0 := GlitchMinTime ( a.Glch0, b.Glch0 ); - RETURN (z); - END; - - FUNCTION "or" ( - CONSTANT a, b : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - z.inp0 := Maximum ( a.inp0 , b.inp0 ); - z.inp1 := Minimum ( a.inp1 , b.inp1 ); - z.InpX := GlitchMinTime ( a.InpX , b.InpX ); - z.Glch0 := Maximum ( a.Glch0, b.Glch0 ); - z.Glch1 := GlitchMinTime ( a.Glch1, b.Glch1 ); - RETURN (z); - END; - - FUNCTION "nand" ( - CONSTANT a, b : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - z.inp0 := Maximum ( a.inp1 , b.inp1 ); - z.inp1 := Minimum ( a.inp0 , b.inp0 ); - z.InpX := GlitchMinTime ( a.InpX , b.InpX ); - z.Glch0 := Maximum ( a.Glch1, b.Glch1 ); - z.Glch1 := GlitchMinTime ( a.Glch0, b.Glch0 ); - RETURN (z); - END; - - FUNCTION "nor" ( - CONSTANT a, b : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - z.inp1 := Maximum ( a.inp0 , b.inp0 ); - z.inp0 := Minimum ( a.inp1 , b.inp1 ); - z.InpX := GlitchMinTime ( a.InpX , b.InpX ); - z.Glch1 := Maximum ( a.Glch0, b.Glch0 ); - z.Glch0 := GlitchMinTime ( a.Glch1, b.Glch1 ); - RETURN (z); - END; - - -- ------------------------------------------------------------------------ - -- Delay Calculation for 2-bit Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalXOR2 ( - CONSTANT ab,ai, bb,bi : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - -- z = (a AND b) NOR (a NOR b) - z.inp1 := Maximum ( Minimum (ai.inp0 , bi.inp0 ), - Minimum (ab.inp1 , bb.inp1 ) ); - z.inp0 := Minimum ( Maximum (ai.inp1 , bi.inp1 ), - Maximum (ab.inp0 , bb.inp0 ) ); - z.InpX := Maximum ( Maximum (ai.InpX , bi.InpX ), - Maximum (ab.InpX , bb.InpX ) ); - z.Glch1 := Maximum (GlitchMinTime (ai.Glch0, bi.Glch0), - GlitchMinTime (ab.Glch1, bb.Glch1) ); - z.Glch0 := GlitchMinTime ( Maximum (ai.Glch1, bi.Glch1), - Maximum (ab.Glch0, bb.Glch0) ); - RETURN (z); - END; - - FUNCTION VitalXNOR2 ( - CONSTANT ab,ai, bb,bi : IN SchedType - ) RETURN SchedType IS - VARIABLE z : SchedType; - BEGIN - -- z = (a AND b) OR (a NOR b) - z.inp0 := Maximum ( Minimum (ab.inp0 , bb.inp0 ), - Minimum (ai.inp1 , bi.inp1 ) ); - z.inp1 := Minimum ( Maximum (ab.inp1 , bb.inp1 ), - Maximum (ai.inp0 , bi.inp0 ) ); - z.InpX := Maximum ( Maximum (ab.InpX , bb.InpX ), - Maximum (ai.InpX , bi.InpX ) ); - z.Glch0 := Maximum (GlitchMinTime (ab.Glch0, bb.Glch0), - GlitchMinTime (ai.Glch1, bi.Glch1) ); - z.Glch1 := GlitchMinTime ( Maximum (ab.Glch1, bb.Glch1), - Maximum (ai.Glch0, bi.Glch0) ); - RETURN (z); - END; - - -- ------------------------------------------------------------------------ - -- Delay Calculation for 3-bit Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalXOR3 ( - CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType ) - RETURN SchedType IS - BEGIN - RETURN VitalXOR2 ( VitalXOR2 (ab,ai, bb,bi), - VitalXOR2 (ai,ab, bi,bb), - cb, ci ); - END; - - FUNCTION VitalXNOR3 ( - CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType ) - RETURN SchedType IS - BEGIN - RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ), - VitalXOR2 ( ai,ab, bi,bb ), - cb, ci ); - END; - - -- ------------------------------------------------------------------------ - -- Delay Calculation for 4-bit Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalXOR4 ( - CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType ) - RETURN SchedType IS - BEGIN - RETURN VitalXOR2 ( VitalXOR2 ( ab,ai, bb,bi ), - VitalXOR2 ( ai,ab, bi,bb ), - VitalXOR2 ( cb,ci, db,di ), - VitalXOR2 ( ci,cb, di,db ) ); - END; - - FUNCTION VitalXNOR4 ( - CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType ) - RETURN SchedType IS - BEGIN - RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ), - VitalXOR2 ( ai,ab, bi,bb ), - VitalXOR2 ( cb,ci, db,di ), - VitalXOR2 ( ci,cb, di,db ) ); - END; - - -- ------------------------------------------------------------------------ - -- Delay Calculation for N-bit Logical gates. - -- ------------------------------------------------------------------------ - -- Note: index range on datab,datai assumed to be 1 TO length. - -- This is enforced by internal only usage of this Function - FUNCTION VitalXOR ( - CONSTANT DataB, DataI : IN SchedArray - ) RETURN SchedType IS - CONSTANT Leng : INTEGER := DataB'LENGTH; - BEGIN - IF Leng = 2 THEN - RETURN VitalXOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) ); - ELSE - RETURN VitalXOR2 ( VitalXOR ( DataB(1 TO Leng-1), - DataI(1 TO Leng-1) ), - VitalXOR ( DataI(1 TO Leng-1), - DataB(1 TO Leng-1) ), - DataB(Leng),DataI(Leng) ); - END IF; - END; - - -- Note: index range on datab,datai assumed to be 1 TO length. - -- This is enforced by internal only usage of this Function - FUNCTION VitalXNOR ( - CONSTANT DataB, DataI : IN SchedArray - ) RETURN SchedType IS - CONSTANT Leng : INTEGER := DataB'LENGTH; - BEGIN - IF Leng = 2 THEN - RETURN VitalXNOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) ); - ELSE - RETURN VitalXNOR2 ( VitalXOR ( DataB(1 TO Leng-1), - DataI(1 TO Leng-1) ), - VitalXOR ( DataI(1 TO Leng-1), - DataB(1 TO Leng-1) ), - DataB(Leng),DataI(Leng) ); - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Multiplexor - -- MUX .......... result := data(dselect) - -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), - -- data1 when (dselect = '1'), - -- 'X' when (dselect = 'X') and (data0 /= data1) - -- MUX4 .......... 4-input mux; result := data(dselect) - -- MUX8 .......... 8-input mux; result := data(dselect) - -- ------------------------------------------------------------------------ - FUNCTION VitalMUX2 ( - CONSTANT d1, d0 : IN SchedType; - CONSTANT sb, SI : IN SchedType - ) RETURN SchedType IS - BEGIN - RETURN (d1 AND sb) OR (d0 AND (NOT SI) ); - END; --- - FUNCTION VitalMUX4 ( - CONSTANT Data : IN SchedArray4; - CONSTANT sb : IN SchedArray2; - CONSTANT SI : IN SchedArray2 - ) RETURN SchedType IS - BEGIN - RETURN ( sb(1) AND VitalMUX2(Data(3),Data(2), sb(0), SI(0)) ) - OR ( (NOT SI(1)) AND VitalMUX2(Data(1),Data(0), sb(0), SI(0)) ); - END; - - FUNCTION VitalMUX8 ( - CONSTANT Data : IN SchedArray8; - CONSTANT sb : IN SchedArray3; - CONSTANT SI : IN SchedArray3 - ) RETURN SchedType IS - BEGIN - RETURN ( ( sb(2)) AND VitalMUX4 (Data(7 DOWNTO 4), - sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) ) - OR ( (NOT SI(2)) AND VitalMUX4 (Data(3 DOWNTO 0), - sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) ); - END; --- - FUNCTION VInterMux ( - CONSTANT Data : IN SchedArray; - CONSTANT sb : IN SchedArray; - CONSTANT SI : IN SchedArray - ) RETURN SchedType IS - CONSTANT sMsb : INTEGER := sb'LENGTH; - CONSTANT dMsbHigh : INTEGER := Data'LENGTH; - CONSTANT dMsbLow : INTEGER := Data'LENGTH/2; - BEGIN - IF sb'LENGTH = 1 THEN - RETURN VitalMUX2( Data(2), Data(1), sb(1), SI(1) ); - ELSIF sb'LENGTH = 2 THEN - RETURN VitalMUX4( Data, sb, SI ); - ELSIF sb'LENGTH = 3 THEN - RETURN VitalMUX8( Data, sb, SI ); - ELSIF sb'LENGTH > 3 THEN - RETURN (( sb(sMsb)) AND VInterMux( Data(dMsbLow DOWNTO 1), - sb(sMsb-1 DOWNTO 1), - SI(sMsb-1 DOWNTO 1) )) - OR ((NOT SI(sMsb)) AND VInterMux( Data(dMsbHigh DOWNTO dMsbLow+1), - sb(sMsb-1 DOWNTO 1), - SI(sMsb-1 DOWNTO 1) )); - ELSE - RETURN (0 ns, 0 ns, 0 ns, 0 ns, 0 ns); -- dselect'LENGTH < 1 - END IF; - END; --- - FUNCTION VitalMUX ( - CONSTANT Data : IN SchedArray; - CONSTANT sb : IN SchedArray; - CONSTANT SI : IN SchedArray - ) RETURN SchedType IS - CONSTANT msb : INTEGER := 2**sb'LENGTH; - VARIABLE lDat : SchedArray(msb DOWNTO 1); - ALIAS DataAlias : SchedArray ( Data'LENGTH DOWNTO 1 ) IS Data; - ALIAS sbAlias : SchedArray ( sb'LENGTH DOWNTO 1 ) IS sb; - ALIAS siAlias : SchedArray ( SI'LENGTH DOWNTO 1 ) IS SI; - BEGIN - IF Data'LENGTH <= msb THEN - FOR i IN Data'LENGTH DOWNTO 1 LOOP - lDat(i) := DataAlias(i); - END LOOP; - FOR i IN msb DOWNTO Data'LENGTH+1 LOOP - lDat(i) := DefSchedAnd; - END LOOP; - ELSE - FOR i IN msb DOWNTO 1 LOOP - lDat(i) := DataAlias(i); - END LOOP; - END IF; - RETURN VInterMux( lDat, sbAlias, siAlias ); - END; - - -- ------------------------------------------------------------------------ - -- Decoder - -- General Algorithm : - -- (a) Result(...) := '0' when (enable = '0') - -- (b) Result(data) := '1'; all other subelements = '0' - -- ... Result array is decending (n-1 downto 0) - -- - -- DECODERn .......... n:2**n decoder - -- ------------------------------------------------------------------------ - FUNCTION VitalDECODER2 ( - CONSTANT DataB : IN SchedType; - CONSTANT DataI : IN SchedType; - CONSTANT Enable : IN SchedType - ) RETURN SchedArray IS - VARIABLE Result : SchedArray2; - BEGIN - Result(1) := Enable AND ( DataB); - Result(0) := Enable AND (NOT DataI); - RETURN Result; - END; - - FUNCTION VitalDECODER4 ( - CONSTANT DataB : IN SchedArray2; - CONSTANT DataI : IN SchedArray2; - CONSTANT Enable : IN SchedType - ) RETURN SchedArray IS - VARIABLE Result : SchedArray4; - BEGIN - Result(3) := Enable AND ( DataB(1)) AND ( DataB(0)); - Result(2) := Enable AND ( DataB(1)) AND (NOT DataI(0)); - Result(1) := Enable AND (NOT DataI(1)) AND ( DataB(0)); - Result(0) := Enable AND (NOT DataI(1)) AND (NOT DataI(0)); - RETURN Result; - END; - - FUNCTION VitalDECODER8 ( - CONSTANT DataB : IN SchedArray3; - CONSTANT DataI : IN SchedArray3; - CONSTANT Enable : IN SchedType - ) RETURN SchedArray IS - VARIABLE Result : SchedArray8; - BEGIN - Result(7):= Enable AND ( DataB(2))AND( DataB(1))AND( DataB(0)); - Result(6):= Enable AND ( DataB(2))AND( DataB(1))AND(NOT DataI(0)); - Result(5):= Enable AND ( DataB(2))AND(NOT DataI(1))AND( DataB(0)); - Result(4):= Enable AND ( DataB(2))AND(NOT DataI(1))AND(NOT DataI(0)); - Result(3):= Enable AND (NOT DataI(2))AND( DataB(1))AND( DataB(0)); - Result(2):= Enable AND (NOT DataI(2))AND( DataB(1))AND(NOT DataI(0)); - Result(1):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND( DataB(0)); - Result(0):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND(NOT DataI(0)); - RETURN Result; - END; - - - FUNCTION VitalDECODER ( - CONSTANT DataB : IN SchedArray; - CONSTANT DataI : IN SchedArray; - CONSTANT Enable : IN SchedType - ) RETURN SchedArray IS - CONSTANT DMsb : INTEGER := DataB'LENGTH - 1; - ALIAS DataBAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataB; - ALIAS DataIAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataI; - BEGIN - IF DataB'LENGTH = 1 THEN - RETURN VitalDECODER2 ( DataBAlias( 0 ), - DataIAlias( 0 ), Enable ); - ELSIF DataB'LENGTH = 2 THEN - RETURN VitalDECODER4 ( DataBAlias(1 DOWNTO 0), - DataIAlias(1 DOWNTO 0), Enable ); - ELSIF DataB'LENGTH = 3 THEN - RETURN VitalDECODER8 ( DataBAlias(2 DOWNTO 0), - DataIAlias(2 DOWNTO 0), Enable ); - ELSIF DataB'LENGTH > 3 THEN - RETURN VitalDECODER ( DataBAlias(DMsb-1 DOWNTO 0), - DataIAlias(DMsb-1 DOWNTO 0), - Enable AND ( DataBAlias(DMsb)) ) - & VitalDECODER ( DataBAlias(DMsb-1 DOWNTO 0), - DataIAlias(DMsb-1 DOWNTO 0), - Enable AND (NOT DataIAlias(DMsb)) ); - ELSE - RETURN DefSchedArray2; - END IF; - END; - - -------------------------------------------------------------------------------- --- PRIMITIVES -------------------------------------------------------------------------------- - -- ------------------------------------------------------------------------ - -- N-bit wide Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalAND ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '1'; - FOR i IN Data'RANGE LOOP - Result := Result AND Data(i); - END LOOP; - RETURN ResultMap(Result); - END; --- - FUNCTION VitalOR ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '0'; - FOR i IN Data'RANGE LOOP - Result := Result OR Data(i); - END LOOP; - RETURN ResultMap(Result); - END; --- - FUNCTION VitalXOR ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '0'; - FOR i IN Data'RANGE LOOP - Result := Result XOR Data(i); - END LOOP; - RETURN ResultMap(Result); - END; --- - FUNCTION VitalNAND ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '1'; - FOR i IN Data'RANGE LOOP - Result := Result AND Data(i); - END LOOP; - RETURN ResultMap(NOT Result); - END; --- - FUNCTION VitalNOR ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '0'; - FOR i IN Data'RANGE LOOP - Result := Result OR Data(i); - END LOOP; - RETURN ResultMap(NOT Result); - END; --- - FUNCTION VitalXNOR ( - CONSTANT Data : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - Result := '0'; - FOR i IN Data'RANGE LOOP - Result := Result XOR Data(i); - END LOOP; - RETURN ResultMap(NOT Result); - END; - - -- ------------------------------------------------------------------------ - -- Commonly used 2-bit Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalAND2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a AND b); - END; --- - FUNCTION VitalOR2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a OR b); - END; --- - FUNCTION VitalXOR2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a XOR b); - END; --- - FUNCTION VitalNAND2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a NAND b); - END; --- - FUNCTION VitalNOR2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a NOR b); - END; --- - FUNCTION VitalXNOR2 ( - CONSTANT a, b : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a XOR b)); - END; --- - -- ------------------------------------------------------------------------ - -- Commonly used 3-bit Logical gates. - -- ------------------------------------------------------------------------ - FUNCTION VitalAND3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a AND b AND c); - END; --- - FUNCTION VitalOR3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a OR b OR c); - END; --- - FUNCTION VitalXOR3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a XOR b XOR c); - END; --- - FUNCTION VitalNAND3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a AND b AND c)); - END; --- - FUNCTION VitalNOR3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a OR b OR c)); - END; --- - FUNCTION VitalXNOR3 ( - CONSTANT a, b, c : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a XOR b XOR c)); - END; - - -- --------------------------------------------------------------------------- - -- Commonly used 4-bit Logical gates. - -- --------------------------------------------------------------------------- - FUNCTION VitalAND4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a AND b AND c AND d); - END; --- - FUNCTION VitalOR4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a OR b OR c OR d); - END; --- - FUNCTION VitalXOR4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(a XOR b XOR c XOR d); - END; --- - FUNCTION VitalNAND4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a AND b AND c AND d)); - END; --- - FUNCTION VitalNOR4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a OR b OR c OR d)); - END; --- - FUNCTION VitalXNOR4 ( - CONSTANT a, b, c, d : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT (a XOR b XOR c XOR d)); - END; - - -- ------------------------------------------------------------------------ - -- Buffers - -- BUF ....... standard non-inverting buffer - -- BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0') - -- BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1') - -- ------------------------------------------------------------------------ - FUNCTION VitalBUF ( - CONSTANT Data : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(To_UX01(Data)); - END; --- - FUNCTION VitalBUFIF0 ( - CONSTANT Data, Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(BufIf0_Table(Enable,Data)); - END; --- - FUNCTION VitalBUFIF1 ( - CONSTANT Data, Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(BufIf1_Table(Enable,Data)); - END; - FUNCTION VitalIDENT ( - CONSTANT Data : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(To_UX01Z(Data)); - END; - - -- ------------------------------------------------------------------------ - -- Invertors - -- INV ......... standard inverting buffer - -- INVIF0 ......... inverting buffer Data passes thru if (Enable = '0') - -- INVIF1 ......... inverting buffer Data passes thru if (Enable = '1') - -- ------------------------------------------------------------------------ - FUNCTION VitalINV ( - CONSTANT Data : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(NOT Data); - END; --- - FUNCTION VitalINVIF0 ( - CONSTANT Data, Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(InvIf0_Table(Enable,Data)); - END; --- - FUNCTION VitalINVIF1 ( - CONSTANT Data, Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) RETURN std_ulogic IS - BEGIN - RETURN ResultMap(InvIf1_Table(Enable,Data)); - END; - - -- ------------------------------------------------------------------------ - -- Multiplexor - -- MUX .......... result := data(dselect) - -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), - -- data1 when (dselect = '1'), - -- 'X' when (dselect = 'X') and (data0 /= data1) - -- MUX4 .......... 4-input mux; result := data(dselect) - -- MUX8 .......... 8-input mux; result := data(dselect) - -- ------------------------------------------------------------------------ - FUNCTION VitalMUX2 ( - CONSTANT Data1, Data0 : IN std_ulogic; - CONSTANT dSelect : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - CASE To_X01(dSelect) IS - WHEN '0' => Result := To_UX01(Data0); - WHEN '1' => Result := To_UX01(Data1); - WHEN OTHERS => Result := VitalSame( Data1, Data0 ); - END CASE; - RETURN ResultMap(Result); - END; --- - FUNCTION VitalMUX4 ( - CONSTANT Data : IN std_logic_vector4; - CONSTANT dSelect : IN std_logic_vector2; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Slct : std_logic_vector2; - VARIABLE Result : UX01; - BEGIN - Slct := To_X01(dSelect); - CASE Slct IS - WHEN "00" => Result := To_UX01(Data(0)); - WHEN "01" => Result := To_UX01(Data(1)); - WHEN "10" => Result := To_UX01(Data(2)); - WHEN "11" => Result := To_UX01(Data(3)); - WHEN "0X" => Result := VitalSame( Data(1), Data(0) ); - WHEN "1X" => Result := VitalSame( Data(2), Data(3) ); - WHEN "X0" => Result := VitalSame( Data(2), Data(0) ); - WHEN "X1" => Result := VitalSame( Data(3), Data(1) ); - WHEN OTHERS => Result := VitalSame( VitalSame(Data(3),Data(2)), - VitalSame(Data(1),Data(0))); - END CASE; - RETURN ResultMap(Result); - END; --- - FUNCTION VitalMUX8 ( - CONSTANT Data : IN std_logic_vector8; - CONSTANT dSelect : IN std_logic_vector3; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - VARIABLE Result : UX01; - BEGIN - CASE To_X01(dSelect(2)) IS - WHEN '0' => Result := VitalMUX4( Data(3 DOWNTO 0), - dSelect(1 DOWNTO 0)); - WHEN '1' => Result := VitalMUX4( Data(7 DOWNTO 4), - dSelect(1 DOWNTO 0)); - WHEN OTHERS => Result := VitalSame( VitalMUX4( Data(3 DOWNTO 0), - dSelect(1 DOWNTO 0)), - VitalMUX4( Data(7 DOWNTO 4), - dSelect(1 DOWNTO 0))); - END CASE; - RETURN ResultMap(Result); - END; --- - FUNCTION VInterMux ( - CONSTANT Data : IN std_logic_vector; - CONSTANT dSelect : IN std_logic_vector - ) RETURN std_ulogic IS - - CONSTANT sMsb : INTEGER := dSelect'LENGTH; - CONSTANT dMsbHigh : INTEGER := Data'LENGTH; - CONSTANT dMsbLow : INTEGER := Data'LENGTH/2; - ALIAS DataAlias : std_logic_vector ( Data'LENGTH DOWNTO 1) IS Data; - ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect; - - VARIABLE Result : UX01; - BEGIN - IF dSelect'LENGTH = 1 THEN - Result := VitalMUX2( DataAlias(2), DataAlias(1), dSelAlias(1) ); - ELSIF dSelect'LENGTH = 2 THEN - Result := VitalMUX4( DataAlias, dSelAlias ); - ELSIF dSelect'LENGTH > 2 THEN - CASE To_X01(dSelect(sMsb)) IS - WHEN '0' => - Result := VInterMux( DataAlias(dMsbLow DOWNTO 1), - dSelAlias(sMsb-1 DOWNTO 1) ); - WHEN '1' => - Result := VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1), - dSelAlias(sMsb-1 DOWNTO 1) ); - WHEN OTHERS => - Result := VitalSame( - VInterMux( DataAlias(dMsbLow DOWNTO 1), - dSelAlias(sMsb-1 DOWNTO 1) ), - VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1), - dSelAlias(sMsb-1 DOWNTO 1) ) - ); - END CASE; - ELSE - Result := 'X'; -- dselect'LENGTH < 1 - END IF; - RETURN Result; - END; --- - FUNCTION VitalMUX ( - CONSTANT Data : IN std_logic_vector; - CONSTANT dSelect : IN std_logic_vector; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_ulogic IS - CONSTANT msb : INTEGER := 2**dSelect'LENGTH; - ALIAS DataAlias : std_logic_vector ( Data'LENGTH DOWNTO 1) IS Data; - ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect; - VARIABLE lDat : std_logic_vector(msb DOWNTO 1) := (OTHERS=>'X'); - VARIABLE Result : UX01; - BEGIN - IF Data'LENGTH <= msb THEN - FOR i IN Data'LENGTH DOWNTO 1 LOOP - lDat(i) := DataAlias(i); - END LOOP; - ELSE - FOR i IN msb DOWNTO 1 LOOP - lDat(i) := DataAlias(i); - END LOOP; - END IF; - Result := VInterMux( lDat, dSelAlias ); - RETURN ResultMap(Result); - END; - - -- ------------------------------------------------------------------------ - -- Decoder - -- General Algorithm : - -- (a) Result(...) := '0' when (enable = '0') - -- (b) Result(data) := '1'; all other subelements = '0' - -- ... Result array is decending (n-1 downto 0) - -- - -- DECODERn .......... n:2**n decoder - -- ------------------------------------------------------------------------ - FUNCTION VitalDECODER2 ( - CONSTANT Data : IN std_ulogic; - CONSTANT Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_logic_vector2 IS - VARIABLE Result : std_logic_vector2; - BEGIN - Result(1) := ResultMap(Enable AND ( Data)); - Result(0) := ResultMap(Enable AND (NOT Data)); - RETURN Result; - END; --- - FUNCTION VitalDECODER4 ( - CONSTANT Data : IN std_logic_vector2; - CONSTANT Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_logic_vector4 IS - VARIABLE Result : std_logic_vector4; - BEGIN - Result(3) := ResultMap(Enable AND ( Data(1)) AND ( Data(0))); - Result(2) := ResultMap(Enable AND ( Data(1)) AND (NOT Data(0))); - Result(1) := ResultMap(Enable AND (NOT Data(1)) AND ( Data(0))); - Result(0) := ResultMap(Enable AND (NOT Data(1)) AND (NOT Data(0))); - RETURN Result; - END; --- - FUNCTION VitalDECODER8 ( - CONSTANT Data : IN std_logic_vector3; - CONSTANT Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_logic_vector8 IS - VARIABLE Result : std_logic_vector8; - BEGIN - Result(7) := ( Data(2)) AND ( Data(1)) AND ( Data(0)); - Result(6) := ( Data(2)) AND ( Data(1)) AND (NOT Data(0)); - Result(5) := ( Data(2)) AND (NOT Data(1)) AND ( Data(0)); - Result(4) := ( Data(2)) AND (NOT Data(1)) AND (NOT Data(0)); - Result(3) := (NOT Data(2)) AND ( Data(1)) AND ( Data(0)); - Result(2) := (NOT Data(2)) AND ( Data(1)) AND (NOT Data(0)); - Result(1) := (NOT Data(2)) AND (NOT Data(1)) AND ( Data(0)); - Result(0) := (NOT Data(2)) AND (NOT Data(1)) AND (NOT Data(0)); - - Result(0) := ResultMap ( Enable AND Result(0) ); - Result(1) := ResultMap ( Enable AND Result(1) ); - Result(2) := ResultMap ( Enable AND Result(2) ); - Result(3) := ResultMap ( Enable AND Result(3) ); - Result(4) := ResultMap ( Enable AND Result(4) ); - Result(5) := ResultMap ( Enable AND Result(5) ); - Result(6) := ResultMap ( Enable AND Result(6) ); - Result(7) := ResultMap ( Enable AND Result(7) ); - - RETURN Result; - END; --- - FUNCTION VitalDECODER ( - CONSTANT Data : IN std_logic_vector; - CONSTANT Enable : IN std_ulogic; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) RETURN std_logic_vector IS - - CONSTANT DMsb : INTEGER := Data'LENGTH - 1; - ALIAS DataAlias : std_logic_vector ( DMsb DOWNTO 0 ) IS Data; - BEGIN - IF Data'LENGTH = 1 THEN - RETURN VitalDECODER2 (DataAlias( 0 ), Enable, ResultMap ); - ELSIF Data'LENGTH = 2 THEN - RETURN VitalDECODER4 (DataAlias(1 DOWNTO 0), Enable, ResultMap ); - ELSIF Data'LENGTH = 3 THEN - RETURN VitalDECODER8 (DataAlias(2 DOWNTO 0), Enable, ResultMap ); - ELSIF Data'LENGTH > 3 THEN - RETURN VitalDECODER (DataAlias(DMsb-1 DOWNTO 0), - Enable AND ( DataAlias(DMsb)), ResultMap ) - & VitalDECODER (DataAlias(DMsb-1 DOWNTO 0), - Enable AND (NOT DataAlias(DMsb)), ResultMap ); - ELSE RETURN "X"; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- N-bit wide Logical gates. - -- ------------------------------------------------------------------------ - PROCEDURE VitalAND ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE Data_Schd : SchedArray(Data'RANGE); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalAND(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := '1'; - new_schd := Data_Schd(Data_Schd'LEFT); - FOR i IN Data'RANGE LOOP - NewValue := NewValue AND Data(i); - new_schd := new_schd AND Data_Schd(i); - END LOOP; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; --SN - END; --- - PROCEDURE VitalOR ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE Data_Schd : SchedArray(Data'RANGE); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalOR(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := '0'; - new_schd := Data_Schd(Data_Schd'LEFT); - FOR i IN Data'RANGE LOOP - NewValue := NewValue OR Data(i); - new_schd := new_schd OR Data_Schd(i); - END LOOP; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; --SN - END; --- - PROCEDURE VitalXOR ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE DataB_Schd : SchedArray(1 TO Data'LENGTH); - VARIABLE DataI_Schd : SchedArray(1 TO Data'LENGTH); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd; - ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalXOR(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( DataB_Schd, Data_Edge, Atpd_data_q ); - InvPath ( DataI_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalXOR ( Data ); - new_schd := VitalXOR ( DataB_Schd, DataI_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; --SN - END; --- - PROCEDURE VitalNAND ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE Data_Schd : SchedArray(Data'RANGE); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalNAND(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - InvPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := '1'; - new_schd := Data_Schd(Data_Schd'LEFT); - FOR i IN Data'RANGE LOOP - NewValue := NewValue AND Data(i); - new_schd := new_schd AND Data_Schd(i); - END LOOP; - NewValue := NOT NewValue; - new_schd := NOT new_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNOR ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE Data_Schd : SchedArray(Data'RANGE); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalNOR(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - InvPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := '0'; - new_schd := Data_Schd(Data_Schd'LEFT); - FOR i IN Data'RANGE LOOP - NewValue := NewValue OR Data(i); - new_schd := new_schd OR Data_Schd(i); - END LOOP; - NewValue := NOT NewValue; - new_schd := NOT new_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; --SN - END; --- - PROCEDURE VitalXNOR ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE DataB_Schd : SchedArray(1 TO Data'LENGTH); - VARIABLE DataI_Schd : SchedArray(1 TO Data'LENGTH); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd; - ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN LOOP - q <= VitalXNOR(Data, ResultMap); - WAIT ON Data; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( DataB_Schd, Data_Edge, Atpd_data_q ); - InvPath ( DataI_Schd, Data_Edge, Atpd_data_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalXNOR ( Data ); - new_schd := VitalXNOR ( DataB_Schd, DataI_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data; - END LOOP; - END IF; --SN - END; --- - - -- ------------------------------------------------------------------------ - -- Commonly used 2-bit Logical gates. - -- ------------------------------------------------------------------------ - PROCEDURE VitalAND2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalAND2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a AND b; - new_schd := a_schd AND b_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; --- - PROCEDURE VitalOR2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalOR2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a OR b; - new_schd := a_schd OR b_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNAND2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNAND2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a NAND b; - new_schd := a_schd NAND b_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNOR2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNOR2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a NOR b; - new_schd := a_schd NOR b_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXOR2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd : SchedType; - VARIABLE ai_schd, bi_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXOR2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a XOR b; - new_schd := VitalXOR2 ( ab_schd,ai_schd, bb_schd,bi_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXNOR2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd : SchedType; - VARIABLE ai_schd, bi_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXNOR2 ( a, b, ResultMap ); - WAIT ON a, b; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := NOT (a XOR b); - new_schd := VitalXNOR2 ( ab_schd,ai_schd, bb_schd,bi_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Commonly used 3-bit Logical gates. - -- ------------------------------------------------------------------------ - PROCEDURE VitalAND3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN --- - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalAND3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - BufPath ( c_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - BufPath ( c_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a AND b AND c; - new_schd := a_schd AND b_schd AND c_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; --- - PROCEDURE VitalOR3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalOR3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - BufPath ( c_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - BufPath ( c_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a OR b OR c; - new_schd := a_schd OR b_schd OR c_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNAND3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNAND3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - InvPath ( c_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - InvPath ( c_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := (a AND b) NAND c; - new_schd := (a_schd AND b_schd) NAND c_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNOR3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNOR3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - InvPath ( c_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - InvPath ( c_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := (a OR b) NOR c; - new_schd := (a_schd OR b_schd) NOR c_schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXOR3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd, cb_schd : SchedType; - VARIABLE ai_schd, bi_schd, ci_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXOR3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); - InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - BufPath ( cb_schd, GetEdge(c), tpd_c_q ); - InvPath ( ci_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a XOR b XOR c; - new_schd := VitalXOR3 ( ab_schd,ai_schd, - bb_schd,bi_schd, - cb_schd,ci_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXNOR3 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd, cb_schd : SchedType; - VARIABLE ai_schd, bi_schd, ci_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXNOR3 ( a, b, c, ResultMap ); - WAIT ON a, b, c; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); - InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - BufPath ( cb_schd, GetEdge(c), tpd_c_q ); - InvPath ( ci_schd, GetEdge(c), tpd_c_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := NOT (a XOR b XOR c); - new_schd := VitalXNOR3 ( ab_schd, ai_schd, - bb_schd, bi_schd, - cb_schd, ci_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Commonly used 4-bit Logical gates. - -- ------------------------------------------------------------------------ - PROCEDURE VitalAND4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalAND4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - BufPath ( c_schd, InitialEdge(c), tpd_c_q ); - BufPath ( d_Schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - BufPath ( c_schd, GetEdge(c), tpd_c_q ); - BufPath ( d_Schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a AND b AND c AND d; - new_schd := a_schd AND b_schd AND c_schd AND d_Schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; --- - PROCEDURE VitalOR4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalOR4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( a_schd, InitialEdge(a), tpd_a_q ); - BufPath ( b_schd, InitialEdge(b), tpd_b_q ); - BufPath ( c_schd, InitialEdge(c), tpd_c_q ); - BufPath ( d_Schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( a_schd, GetEdge(a), tpd_a_q ); - BufPath ( b_schd, GetEdge(b), tpd_b_q ); - BufPath ( c_schd, GetEdge(c), tpd_c_q ); - BufPath ( d_Schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a OR b OR c OR d; - new_schd := a_schd OR b_schd OR c_schd OR d_Schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNAND4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNAND4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - InvPath ( c_schd, InitialEdge(c), tpd_c_q ); - InvPath ( d_Schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - InvPath ( c_schd, GetEdge(c), tpd_c_q ); - InvPath ( d_Schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := (a AND b) NAND (c AND d); - new_schd := (a_schd AND b_schd) NAND (c_schd AND d_Schd); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; --- - PROCEDURE VitalNOR4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalNOR4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( a_schd, InitialEdge(a), tpd_a_q ); - InvPath ( b_schd, InitialEdge(b), tpd_b_q ); - InvPath ( c_schd, InitialEdge(c), tpd_c_q ); - InvPath ( d_Schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( a_schd, GetEdge(a), tpd_a_q ); - InvPath ( b_schd, GetEdge(b), tpd_b_q ); - InvPath ( c_schd, GetEdge(c), tpd_c_q ); - InvPath ( d_Schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := (a OR b) NOR (c OR d); - new_schd := (a_schd OR b_schd) NOR (c_schd OR d_Schd); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXOR4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType; - VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXOR4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - - BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); - InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); - - BufPath ( DB_Schd, InitialEdge(d), tpd_d_q ); - InvPath ( di_schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - BufPath ( cb_schd, GetEdge(c), tpd_c_q ); - InvPath ( ci_schd, GetEdge(c), tpd_c_q ); - - BufPath ( DB_Schd, GetEdge(d), tpd_d_q ); - InvPath ( di_schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := a XOR b XOR c XOR d; - new_schd := VitalXOR4 ( ab_schd,ai_schd, bb_schd,bi_schd, - cb_schd,ci_schd, DB_Schd,di_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; --- - PROCEDURE VitalXNOR4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL a, b, c, d : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_b_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_c_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType; - VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType; - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_a_q = VitalZeroDelay01) - AND (tpd_b_q = VitalZeroDelay01) - AND (tpd_c_q = VitalZeroDelay01) - AND (tpd_d_q = VitalZeroDelay01)) THEN - LOOP - q <= VitalXNOR4 ( a, b, c, d, ResultMap ); - WAIT ON a, b, c, d; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( ab_schd, InitialEdge(a), tpd_a_q ); - InvPath ( ai_schd, InitialEdge(a), tpd_a_q ); - - BufPath ( bb_schd, InitialEdge(b), tpd_b_q ); - InvPath ( bi_schd, InitialEdge(b), tpd_b_q ); - - BufPath ( cb_schd, InitialEdge(c), tpd_c_q ); - InvPath ( ci_schd, InitialEdge(c), tpd_c_q ); - - BufPath ( DB_Schd, InitialEdge(d), tpd_d_q ); - InvPath ( di_schd, InitialEdge(d), tpd_d_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( ab_schd, GetEdge(a), tpd_a_q ); - InvPath ( ai_schd, GetEdge(a), tpd_a_q ); - - BufPath ( bb_schd, GetEdge(b), tpd_b_q ); - InvPath ( bi_schd, GetEdge(b), tpd_b_q ); - - BufPath ( cb_schd, GetEdge(c), tpd_c_q ); - InvPath ( ci_schd, GetEdge(c), tpd_c_q ); - - BufPath ( DB_Schd, GetEdge(d), tpd_d_q ); - InvPath ( di_schd, GetEdge(d), tpd_d_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := NOT (a XOR b XOR c XOR d); - new_schd := VitalXNOR4 ( ab_schd,ai_schd, bb_schd,bi_schd, - cb_schd,ci_schd, DB_Schd,di_schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON a, b, c, d; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Buffers - -- BUF ....... standard non-inverting buffer - -- BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0') - -- BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1') - -- ------------------------------------------------------------------------ - PROCEDURE VitalBUF ( - SIGNAL q : OUT std_ulogic; - SIGNAL a : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_a_q = VitalZeroDelay01) THEN - LOOP - q <= ResultMap(To_UX01(a)); - WAIT ON a; - END LOOP; - - ELSE - LOOP - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := To_UX01(a); -- convert to forcing strengths - CASE EdgeType'(GetEdge(a)) IS - WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr01); - WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr10); - WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); - END CASE; - - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode ); - - WAIT ON a; - END LOOP; - END IF; - END; --- - PROCEDURE VitalBUFIF1 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_ulogic; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) IS - VARIABLE NewValue : UX01Z; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_data_q = VitalZeroDelay01 ) - AND (tpd_enable_q = VitalZeroDelay01Z)) THEN - LOOP - q <= VitalBUFIF1( Data, Enable, ResultMap ); - WAIT ON Data, Enable; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( d_Schd, InitialEdge(Data), tpd_data_q ); - BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( d_Schd, GetEdge(Data), tpd_data_q ); - BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalBUFIF1( Data, Enable ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), - d_Schd, e1_Schd, e0_Schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; --- - PROCEDURE VitalBUFIF0 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_ulogic; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) IS - VARIABLE NewValue : UX01Z; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; - VARIABLE ne1_schd, ne0_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_data_q = VitalZeroDelay01 ) - AND (tpd_enable_q = VitalZeroDelay01Z)) THEN - LOOP - q <= VitalBUFIF0( Data, Enable, ResultMap ); - WAIT ON Data, Enable; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( d_Schd, InitialEdge(Data), tpd_data_q ); - InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( d_Schd, GetEdge(Data), tpd_data_q ); - InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalBUFIF0( Data, Enable ); - ne1_schd := NOT e1_Schd; - ne0_schd := NOT e0_Schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), - d_Schd, ne1_schd, ne0_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; - - PROCEDURE VitalIDENT ( - SIGNAL q : OUT std_ulogic; - SIGNAL a : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01Z := VitalDefDelay01Z; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) IS - SUBTYPE v2 IS std_logic_vector(0 TO 1); - VARIABLE NewValue : UX01Z; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_a_q = VitalZeroDelay01Z) THEN - LOOP - q <= ResultMap(To_UX01Z(a)); - WAIT ON a; - END LOOP; - - ELSE - LOOP - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - CASE v2'(To_X01Z(NewValue) & To_X01Z(a)) IS - WHEN "00" => Dly := tpd_a_q(tr10); - WHEN "01" => Dly := tpd_a_q(tr01); - WHEN "0Z" => Dly := tpd_a_q(tr0z); - WHEN "0X" => Dly := tpd_a_q(tr01); - WHEN "10" => Dly := tpd_a_q(tr10); - WHEN "11" => Dly := tpd_a_q(tr01); - WHEN "1Z" => Dly := tpd_a_q(tr1z); - WHEN "1X" => Dly := tpd_a_q(tr10); - WHEN "Z0" => Dly := tpd_a_q(trz0); - WHEN "Z1" => Dly := tpd_a_q(trz1); - WHEN "ZZ" => Dly := 0 ns; - WHEN "ZX" => Dly := Minimum (tpd_a_q(trz1), tpd_a_q(trz0)); - WHEN "X0" => Dly := tpd_a_q(tr10); - WHEN "X1" => Dly := tpd_a_q(tr01); - WHEN "XZ" => Dly := Minimum (tpd_a_q(tr0z), tpd_a_q(tr1z)); - WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); - END CASE; - NewValue := To_UX01Z(a); - - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode ); - - WAIT ON a; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Invertors - -- INV ......... standard inverting buffer - -- INVIF0 ......... inverting buffer Data passes thru if (Enable = '0') - -- INVIF1 ......... inverting buffer Data passes thru if (Enable = '1') - -- ------------------------------------------------------------------------ - PROCEDURE VitalINV ( - SIGNAL q : OUT std_ulogic; - SIGNAL a : IN std_ulogic ; - CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - IF (tpd_a_q = VitalZeroDelay01) THEN - LOOP - q <= ResultMap(NOT a); - WAIT ON a; - END LOOP; - - ELSE - LOOP - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := NOT a; - CASE EdgeType'(GetEdge(a)) IS - WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr10); - WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr01); - WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10)); - END CASE; - - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode ); - - WAIT ON a; - END LOOP; - END IF; - END; --- - PROCEDURE VitalINVIF1 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_ulogic; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) IS - VARIABLE NewValue : UX01Z; - VARIABLE new_schd : SchedType; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_data_q = VitalZeroDelay01 ) - AND (tpd_enable_q = VitalZeroDelay01Z)) THEN - LOOP - q <= VitalINVIF1( Data, Enable, ResultMap ); - WAIT ON Data, Enable; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( d_Schd, InitialEdge(Data), tpd_data_q ); - BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( d_Schd, GetEdge(Data), tpd_data_q ); - BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalINVIF1( Data, Enable ); - new_schd := NOT d_Schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), - new_schd, e1_Schd, e0_Schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; --- - PROCEDURE VitalINVIF0 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_ulogic; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_enable_q : IN VitalDelayType01Z := VitalDefDelay01Z; - CONSTANT ResultMap : IN VitalResultZMapType - := VitalDefaultResultZMap - ) IS - VARIABLE NewValue : UX01Z; - VARIABLE new_schd : SchedType; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType; - VARIABLE ne1_schd, ne0_schd : SchedType := DefSchedType; - VARIABLE Dly, Glch : TIME; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_data_q = VitalZeroDelay01 ) - AND (tpd_enable_q = VitalZeroDelay01Z)) THEN - LOOP - q <= VitalINVIF0( Data, Enable, ResultMap ); - WAIT ON Data, Enable; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - InvPath ( d_Schd, InitialEdge(Data), tpd_data_q ); - InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - InvPath ( d_Schd, GetEdge(Data), tpd_data_q ); - InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delay - -- ------------------------------------ - NewValue := VitalINVIF0( Data, Enable ); - ne1_schd := NOT e1_Schd; - ne0_schd := NOT e0_Schd; - new_schd := NOT d_Schd; - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), - new_schd, ne1_schd, ne0_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - -- Multiplexor - -- MUX .......... result := data(dselect) - -- MUX2 .......... 2-input mux; result := data0 when (dselect = '0'), - -- data1 when (dselect = '1'), - -- 'X' when (dselect = 'X') and (data0 /= data1) - -- MUX4 .......... 4-input mux; result := data(dselect) - -- MUX8 .......... 8-input mux; result := data(dselect) - -- ------------------------------------------------------------------------ - PROCEDURE VitalMUX2 ( - SIGNAL q : OUT std_ulogic; - SIGNAL d1, d0 : IN std_ulogic; - SIGNAL dSel : IN std_ulogic; - CONSTANT tpd_d1_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_d0_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_dsel_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - VARIABLE d1_Schd, d0_Schd : SchedType; - VARIABLE dSel_bSchd, dSel_iSchd : SchedType; - VARIABLE d1_Edge, d0_Edge, dSel_Edge : EdgeType; - BEGIN - - -- ------------------------------------------------------------------------ - -- For ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF ( (tpd_d1_q = VitalZeroDelay01) - AND (tpd_d0_q = VitalZeroDelay01) - AND (tpd_dsel_q = VitalZeroDelay01) ) THEN - LOOP - q <= VitalMUX2 ( d1, d0, dSel, ResultMap ); - WAIT ON d1, d0, dSel; - END LOOP; - - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( d1_Schd, InitialEdge(d1), tpd_d1_q ); - BufPath ( d0_Schd, InitialEdge(d0), tpd_d0_q ); - BufPath ( dSel_bSchd, InitialEdge(dSel), tpd_dsel_q ); - InvPath ( dSel_iSchd, InitialEdge(dSel), tpd_dsel_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( d1_Schd, GetEdge(d1), tpd_d1_q ); - BufPath ( d0_Schd, GetEdge(d0), tpd_d0_q ); - BufPath ( dSel_bSchd, GetEdge(dSel), tpd_dsel_q ); - InvPath ( dSel_iSchd, GetEdge(dSel), tpd_dsel_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalMUX2 ( d1, d0, dSel ); - new_schd := VitalMUX2 ( d1_Schd, d0_Schd, dSel_bSchd, dSel_iSchd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON d1, d0, dSel; - END LOOP; - END IF; - END; --- - PROCEDURE VitalMUX4 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector4; - SIGNAL dSel : IN std_logic_vector2; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - VARIABLE Data_Schd : SchedArray4; - VARIABLE Data_Edge : EdgeArray4; - VARIABLE dSel_Edge : EdgeArray2; - VARIABLE dSel_bSchd : SchedArray2; - VARIABLE dSel_iSchd : SchedArray2; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN dSel'RANGE LOOP - IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - - IF (AllZeroDelay) THEN LOOP - q <= VitalMUX(Data, dSel, ResultMap); - WAIT ON Data, dSel; - END LOOP; - END IF; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - FOR n IN dSel'RANGE LOOP - BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - GetEdge ( dSel, LastdSel, dSel_Edge ); - BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); - InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalMUX4 ( Data, dSel ); - new_schd := VitalMUX4 ( Data_Schd, dSel_bSchd, dSel_iSchd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, dSel; - END LOOP; - END IF; --SN - END; - - PROCEDURE VitalMUX8 ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector8; - SIGNAL dSel : IN std_logic_vector3; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - VARIABLE Data_Schd : SchedArray8; - VARIABLE Data_Edge : EdgeArray8; - VARIABLE dSel_Edge : EdgeArray3; - VARIABLE dSel_bSchd : SchedArray3; - VARIABLE dSel_iSchd : SchedArray3; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN dSel'RANGE LOOP - IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - - IF (AllZeroDelay) THEN LOOP - q <= VitalMUX(Data, dSel, ResultMap); - WAIT ON Data, dSel; - END LOOP; - END IF; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - FOR n IN dSel'RANGE LOOP - BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - GetEdge ( dSel, LastdSel, dSel_Edge ); - BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); - InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalMUX8 ( Data, dSel ); - new_schd := VitalMUX8 ( Data_Schd, dSel_bSchd, dSel_iSchd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, dSel; - END LOOP; - END IF; - END; --- - PROCEDURE VitalMUX ( - SIGNAL q : OUT std_ulogic; - SIGNAL Data : IN std_logic_vector; - SIGNAL dSel : IN std_logic_vector; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_dsel_q : IN VitalDelayArrayType01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE LastdSel : std_logic_vector(dSel'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : UX01; - VARIABLE Glitch_Data : GlitchDataType; - VARIABLE new_schd : SchedType; - VARIABLE Dly, Glch : TIME; - VARIABLE Data_Schd : SchedArray(Data'RANGE); - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE dSel_Edge : EdgeArray(dSel'RANGE); - VARIABLE dSel_bSchd : SchedArray(dSel'RANGE); - VARIABLE dSel_iSchd : SchedArray(dSel'RANGE); - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - FOR i IN dSel'RANGE LOOP - IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - IF (AllZeroDelay) THEN - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - - IF (AllZeroDelay) THEN LOOP - q <= VitalMUX(Data, dSel, ResultMap); - WAIT ON Data, dSel; - END LOOP; - END IF; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - FOR n IN dSel'RANGE LOOP - BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) ); - END LOOP; - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_Schd, Data_Edge, Atpd_data_q ); - - GetEdge ( dSel, LastdSel, dSel_Edge ); - BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q ); - InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalMUX ( Data, dSel ); - new_schd := VitalMUX ( Data_Schd, dSel_bSchd, dSel_iSchd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, dSel; - END LOOP; - END IF; --SN - END; - - -- ------------------------------------------------------------------------ - -- Decoder - -- General Algorithm : - -- (a) Result(...) := '0' when (enable = '0') - -- (b) Result(data) := '1'; all other subelements = '0' - -- ... Result array is decending (n-1 downto 0) - -- - -- DECODERn .......... n:2**n decoder - -- Caution: If 'ResultMap' defines other than strength mapping, the - -- delay selection is not defined. - -- ------------------------------------------------------------------------ - PROCEDURE VitalDECODER2 ( - SIGNAL q : OUT std_logic_vector2; - SIGNAL Data : IN std_ulogic; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE NewValue : std_logic_vector2; - VARIABLE Glitch_Data : GlitchArray2; - VARIABLE new_schd : SchedArray2; - VARIABLE Dly, Glch : TimeArray2; - VARIABLE Enable_Schd : SchedType := DefSchedType; - VARIABLE Data_BSchd, Data_ISchd : SchedType; - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_enable_q = VitalZeroDelay01) AND (tpd_data_q = VitalZeroDelay01) THEN - LOOP - q <= VitalDECODER2(Data, Enable, ResultMap); - WAIT ON Data, Enable; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - BufPath ( Data_BSchd, InitialEdge(Data), tpd_data_q ); - InvPath ( Data_ISchd, InitialEdge(Data), tpd_data_q ); - BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - BufPath ( Data_BSchd, GetEdge(Data), tpd_data_q ); - InvPath ( Data_ISchd, GetEdge(Data), tpd_data_q ); - - BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalDECODER2 ( Data, Enable, ResultMap ); - new_schd := VitalDECODER2 ( Data_BSchd, Data_ISchd, Enable_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; -- SN - END; --- - PROCEDURE VitalDECODER4 ( - SIGNAL q : OUT std_logic_vector4; - SIGNAL Data : IN std_logic_vector2; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : std_logic_vector4; - VARIABLE Glitch_Data : GlitchArray4; - VARIABLE new_schd : SchedArray4; - VARIABLE Dly, Glch : TimeArray4; - VARIABLE Enable_Schd : SchedType; - VARIABLE Enable_Edge : EdgeType; - VARIABLE Data_Edge : EdgeArray2; - VARIABLE Data_BSchd, Data_ISchd : SchedArray2; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_enable_q /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - ELSE - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - END IF; - IF (AllZeroDelay) THEN LOOP - q <= VitalDECODER4(Data, Enable, ResultMap); - WAIT ON Data, Enable; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); - InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); - - BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalDECODER4 ( Data, Enable, ResultMap ); - new_schd := VitalDECODER4 ( Data_BSchd, Data_ISchd, Enable_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; --- - PROCEDURE VitalDECODER8 ( - SIGNAL q : OUT std_logic_vector8; - SIGNAL Data : IN std_logic_vector3; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : std_logic_vector8; - VARIABLE Glitch_Data : GlitchArray8; - VARIABLE new_schd : SchedArray8; - VARIABLE Dly, Glch : TimeArray8; - VARIABLE Enable_Schd : SchedType; - VARIABLE Enable_Edge : EdgeType; - VARIABLE Data_Edge : EdgeArray3; - VARIABLE Data_BSchd, Data_ISchd : SchedArray3; - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; --SN - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_enable_q /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - ELSE - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - END IF; - IF (AllZeroDelay) THEN LOOP - q <= VitalDECODER(Data, Enable, ResultMap); - WAIT ON Data, Enable; - END LOOP; - ELSE - - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); - InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); - - BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalDECODER8 ( Data, Enable, ResultMap ); - new_schd := VitalDECODER8 ( Data_BSchd, Data_ISchd, Enable_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; --SN - END; --- - PROCEDURE VitalDECODER ( - SIGNAL q : OUT std_logic_vector; - SIGNAL Data : IN std_logic_vector; - SIGNAL Enable : IN std_ulogic; - CONSTANT tpd_data_q : IN VitalDelayArrayType01; - CONSTANT tpd_enable_q : IN VitalDelayType01 := VitalDefDelay01; - CONSTANT ResultMap : IN VitalResultMapType - := VitalDefaultResultMap - ) IS - VARIABLE LastData : std_logic_vector(Data'RANGE) := (OTHERS=>'U'); - VARIABLE NewValue : std_logic_vector(q'RANGE); - VARIABLE Glitch_Data : GlitchDataArrayType(q'RANGE); - VARIABLE new_schd : SchedArray(q'RANGE); - VARIABLE Dly, Glch : VitalTimeArray(q'RANGE); - VARIABLE Enable_Schd : SchedType; - VARIABLE Enable_Edge : EdgeType; - VARIABLE Data_Edge : EdgeArray(Data'RANGE); - VARIABLE Data_BSchd, Data_ISchd : SchedArray(Data'RANGE); - ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q; - VARIABLE AllZeroDelay : BOOLEAN := TRUE; - BEGIN - -- ------------------------------------------------------------------------ - -- Check if ALL zero delay paths, use simple model - -- ( No delay selection, glitch detection required ) - -- ------------------------------------------------------------------------ - IF (tpd_enable_q /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - ELSE - FOR i IN Data'RANGE LOOP - IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN - AllZeroDelay := FALSE; - EXIT; - END IF; - END LOOP; - END IF; - IF (AllZeroDelay) THEN LOOP - q <= VitalDECODER(Data, Enable, ResultMap); - WAIT ON Data, Enable; - END LOOP; - ELSE - -- -------------------------------------- - -- Initialize delay schedules - -- -------------------------------------- - FOR n IN Data'RANGE LOOP - BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) ); - END LOOP; - BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q ); - - LOOP - -- -------------------------------------- - -- Process input signals - -- get edge values - -- re-evaluate output schedules - -- -------------------------------------- - GetEdge ( Data, LastData, Data_Edge ); - BufPath ( Data_BSchd, Data_Edge, Atpd_data_q ); - InvPath ( Data_ISchd, Data_Edge, Atpd_data_q ); - - BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q ); - - -- ------------------------------------ - -- Compute function and propation delaq - -- ------------------------------------ - NewValue := VitalDECODER ( Data, Enable, ResultMap ); - new_schd := VitalDECODER ( Data_BSchd, Data_ISchd, Enable_Schd ); - - -- ------------------------------------------------------ - -- Assign Outputs - -- get delays to new value and possable glitch - -- schedule output change with On Event glitch detection - -- ------------------------------------------------------ - GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd ); - VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly, - PrimGlitchMode, GlitchDelay=>Glch ); - - WAIT ON Data, Enable; - END LOOP; - END IF; - END; - - -- ------------------------------------------------------------------------ - FUNCTION VitalTruthTable ( - CONSTANT TruthTable : IN VitalTruthTableType; - CONSTANT DataIn : IN std_logic_vector - ) RETURN std_logic_vector IS - - CONSTANT InputSize : INTEGER := DataIn'LENGTH; - CONSTANT OutSize : INTEGER := TruthTable'LENGTH(2) - InputSize; - VARIABLE ReturnValue : std_logic_vector(OutSize - 1 DOWNTO 0) - := (OTHERS => 'X'); - VARIABLE DataInAlias : std_logic_vector(0 TO InputSize - 1) - := To_X01(DataIn); - VARIABLE Index : INTEGER; - VARIABLE Err : BOOLEAN := FALSE; - - -- This needs to be done since the TableLookup arrays must be - -- ascending starting with 0 - VARIABLE TableAlias : VitalTruthTableType(0 TO (TruthTable'LENGTH(1)-1), - 0 TO (TruthTable'LENGTH(2)-1)) - := TruthTable; - - BEGIN - -- search through each row of the truth table - IF OutSize > 0 THEN - ColLoop: - FOR i IN TableAlias'RANGE(1) LOOP - - RowLoop: -- Check each input element of the entry - FOR j IN 0 TO InputSize LOOP - - IF (j = InputSize) THEN -- This entry matches - -- Return the Result - Index := 0; - FOR k IN TruthTable'LENGTH(2) - 1 DOWNTO InputSize LOOP - TruthOutputX01Z ( TableAlias(i,k), - ReturnValue(Index), Err); - EXIT WHEN Err; - Index := Index + 1; - END LOOP; - - IF Err THEN - ReturnValue := (OTHERS => 'X'); - END IF; - RETURN ReturnValue; - END IF; - IF NOT ValidTruthTableInput(TableAlias(i,j)) THEN - VitalError ( "VitalTruthTable", ErrInpSym, - To_TruthChar(TableAlias(i,j)) ); - EXIT ColLoop; - END IF; - EXIT RowLoop WHEN NOT ( TruthTableMatch( DataInAlias(j), - TableAlias(i, j))); - END LOOP RowLoop; - END LOOP ColLoop; - - ELSE - VitalError ( "VitalTruthTable", ErrTabWidSml ); - END IF; - RETURN ReturnValue; - END VitalTruthTable; - - FUNCTION VitalTruthTable ( - CONSTANT TruthTable : IN VitalTruthTableType; - CONSTANT DataIn : IN std_logic_vector - ) RETURN std_logic IS - - CONSTANT InputSize : INTEGER := DataIn'LENGTH; - CONSTANT OutSize : INTEGER := TruthTable'LENGTH(2) - InputSize; - VARIABLE TempResult : std_logic_vector(OutSize - 1 DOWNTO 0) - := (OTHERS => 'X'); - BEGIN - IF (OutSize > 0) THEN - TempResult := VitalTruthTable(TruthTable, DataIn); - IF ( 1 > OutSize) THEN - VitalError ( "VitalTruthTable", ErrTabResSml ); - ELSIF ( 1 < OutSize) THEN - VitalError ( "VitalTruthTable", ErrTabResLrg ); - END IF; - RETURN (TempResult(0)); - ELSE - VitalError ( "VitalTruthTable", ErrTabWidSml ); - RETURN 'X'; - END IF; - END VitalTruthTable; - - PROCEDURE VitalTruthTable ( - SIGNAL Result : OUT std_logic_vector; - CONSTANT TruthTable : IN VitalTruthTableType; - CONSTANT DataIn : IN std_logic_vector - ) IS - CONSTANT ResLeng : INTEGER := Result'LENGTH; - CONSTANT ActResLen : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH; - CONSTANT FinalResLen : INTEGER := Minimum(ActResLen, ResLeng); - VARIABLE TempResult : std_logic_vector(ActResLen - 1 DOWNTO 0) - := (OTHERS => 'X'); - - BEGIN - TempResult := VitalTruthTable(TruthTable, DataIn); - - IF (ResLeng > ActResLen) THEN - VitalError ( "VitalTruthTable", ErrTabResSml ); - ELSIF (ResLeng < ActResLen) THEN - VitalError ( "VitalTruthTable", ErrTabResLrg ); - END IF; - TempResult(FinalResLen-1 DOWNTO 0) := TempResult(FinalResLen-1 DOWNTO 0); - Result <= TempResult; - - END VitalTruthTable; - - PROCEDURE VitalTruthTable ( - SIGNAL Result : OUT std_logic; - CONSTANT TruthTable : IN VitalTruthTableType; - CONSTANT DataIn : IN std_logic_vector - ) IS - - CONSTANT ActResLen : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH; - VARIABLE TempResult : std_logic_vector(ActResLen - 1 DOWNTO 0) - := (OTHERS => 'X'); - - BEGIN - TempResult := VitalTruthTable(TruthTable, DataIn); - - IF ( 1 > ActResLen) THEN - VitalError ( "VitalTruthTable", ErrTabResSml ); - ELSIF ( 1 < ActResLen) THEN - VitalError ( "VitalTruthTable", ErrTabResLrg ); - END IF; - IF (ActResLen > 0) THEN - Result <= TempResult(0); - END IF; - - END VitalTruthTable; - - -- ------------------------------------------------------------------------ - PROCEDURE VitalStateTable ( - VARIABLE Result : INOUT std_logic_vector; - VARIABLE PreviousDataIn : INOUT std_logic_vector; - CONSTANT StateTable : IN VitalStateTableType; - CONSTANT DataIn : IN std_logic_vector; - CONSTANT NumStates : IN NATURAL - ) IS - - CONSTANT InputSize : INTEGER := DataIn'LENGTH; - CONSTANT OutSize : INTEGER - := StateTable'LENGTH(2) - InputSize - NumStates; - CONSTANT ResLeng : INTEGER := Result'LENGTH; - VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1) - := To_X01(DataIn); - VARIABLE PrevDataAlias : std_logic_vector(0 TO PreviousDataIn'LENGTH-1) - := To_X01(PreviousDataIn); - VARIABLE ResultAlias : std_logic_vector(0 TO ResLeng-1) - := To_X01(Result); - VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); - - BEGIN - IF (PreviousDataIn'LENGTH < DataIn'LENGTH) THEN - VitalError ( "VitalStateTable", ErrVctLng, "PreviousDataIn 'X'); - Result := ResultAlias; - - ELSIF (OutSize <= 0) THEN - VitalError ( "VitalStateTable", ErrTabWidSml ); - - ResultAlias := (OTHERS => 'X'); - Result := ResultAlias; - - ELSE - IF (ResLeng > OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResSml ); - ELSIF (ResLeng < OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResLrg ); - END IF; - - ExpResult := StateTableLookUp ( StateTable, DataInAlias, - PrevDataAlias, NumStates, - ResultAlias); - ResultAlias := (OTHERS => 'X'); - ResultAlias ( Maximum(0, ResLeng - OutSize) TO ResLeng - 1) - := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1); - - Result := ResultAlias; - PrevDataAlias(0 TO InputSize - 1) := DataInAlias; - PreviousDataIn := PrevDataAlias; - - END IF; - END VitalStateTable; - - - PROCEDURE VitalStateTable ( - VARIABLE Result : INOUT std_logic; -- states - VARIABLE PreviousDataIn : INOUT std_logic_vector; -- previous inputs and states - CONSTANT StateTable : IN VitalStateTableType; -- User's StateTable data - CONSTANT DataIn : IN std_logic_vector -- Inputs - ) IS - - VARIABLE ResultAlias : std_logic_vector(0 TO 0); - BEGIN - ResultAlias(0) := Result; - VitalStateTable ( StateTable => StateTable, - DataIn => DataIn, - NumStates => 1, - Result => ResultAlias, - PreviousDataIn => PreviousDataIn - ); - Result := ResultAlias(0); - - END VitalStateTable; - - PROCEDURE VitalStateTable ( - SIGNAL Result : INOUT std_logic_vector; - CONSTANT StateTable : IN VitalStateTableType; - SIGNAL DataIn : IN std_logic_vector; - CONSTANT NumStates : IN NATURAL - ) IS - - CONSTANT InputSize : INTEGER := DataIn'LENGTH; - CONSTANT OutSize : INTEGER - := StateTable'LENGTH(2) - InputSize - NumStates; - CONSTANT ResLeng : INTEGER := Result'LENGTH; - - VARIABLE PrevData : std_logic_vector(0 TO DataIn'LENGTH-1) - := (OTHERS => 'X'); - VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1); - VARIABLE ResultAlias : std_logic_vector(0 TO ResLeng-1); - VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); - - BEGIN - IF (OutSize <= 0) THEN - VitalError ( "VitalStateTable", ErrTabWidSml ); - - ResultAlias := (OTHERS => 'X'); - Result <= ResultAlias; - - ELSE - IF (ResLeng > OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResSml ); - ELSIF (ResLeng < OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResLrg ); - END IF; - - LOOP - DataInAlias := To_X01(DataIn); - ResultAlias := To_X01(Result); - ExpResult := StateTableLookUp ( StateTable, DataInAlias, - PrevData, NumStates, - ResultAlias); - ResultAlias := (OTHERS => 'X'); - ResultAlias(Maximum(0, ResLeng - OutSize) TO ResLeng-1) - := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1); - - Result <= ResultAlias; - PrevData := DataInAlias; - - WAIT ON DataIn; - END LOOP; - - END IF; - - END VitalStateTable; - - PROCEDURE VitalStateTable ( - SIGNAL Result : INOUT std_logic; - CONSTANT StateTable : IN VitalStateTableType; - SIGNAL DataIn : IN std_logic_vector - ) IS - - CONSTANT InputSize : INTEGER := DataIn'LENGTH; - CONSTANT OutSize : INTEGER := StateTable'LENGTH(2) - InputSize-1; - - VARIABLE PrevData : std_logic_vector(0 TO DataIn'LENGTH-1) - := (OTHERS => 'X'); - VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1); - VARIABLE ResultAlias : std_logic_vector(0 TO 0); - VARIABLE ExpResult : std_logic_vector(0 TO OutSize-1); - - BEGIN - IF (OutSize <= 0) THEN - VitalError ( "VitalStateTable", ErrTabWidSml ); - - Result <= 'X'; - - ELSE - IF ( 1 > OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResSml ); - ELSIF ( 1 < OutSize) THEN - VitalError ( "VitalStateTable", ErrTabResLrg ); - END IF; - - LOOP - ResultAlias(0) := To_X01(Result); - DataInAlias := To_X01(DataIn); - ExpResult := StateTableLookUp ( StateTable, DataInAlias, - PrevData, 1, ResultAlias); - - Result <= ExpResult(OutSize-1); - PrevData := DataInAlias; - - WAIT ON DataIn; - END LOOP; - END IF; - - END VitalStateTable; - - -- ------------------------------------------------------------------------ - -- std_logic resolution primitive - -- ------------------------------------------------------------------------ - PROCEDURE VitalResolve ( - SIGNAL q : OUT std_ulogic; - CONSTANT Data : IN std_logic_vector - ) IS - VARIABLE uData : std_ulogic_vector(Data'RANGE); - BEGIN - FOR i IN Data'RANGE LOOP - uData(i) := Data(i); - END LOOP; - q <= resolved(uData); - END; - -END VITAL_Primitives; 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; + diff --git a/libraries/vital95/vital_timing_body.vhdl b/libraries/vital95/vital_timing_body.vhdl deleted file mode 100644 index 49998bdb5..000000000 --- a/libraries/vital95/vital_timing_body.vhdl +++ /dev/null @@ -1,1275 +0,0 @@ -------------------------------------------------------------------------------- --- 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; - -- cgit v1.2.3