From 977ff5e02c6d2f9bfdabcf8b4e98b81e2d83e849 Mon Sep 17 00:00:00 2001 From: gingold Date: Sat, 24 Sep 2005 05:10:24 +0000 Subject: First import from sources --- libraries/Makefile.inc | 169 + libraries/README | 27 + libraries/ieee/math_complex-body.vhdl | 394 ++ libraries/ieee/math_complex.vhdl | 126 + libraries/ieee/math_real-body.vhdl | 410 ++ libraries/ieee/math_real.vhdl | 223 + libraries/ieee/numeric_bit-body.vhdl | 1818 +++++++ libraries/ieee/numeric_bit.vhdl | 813 +++ libraries/ieee/numeric_std-body.vhdl | 2545 +++++++++ libraries/ieee/numeric_std.vhdl | 853 +++ libraries/ieee/std_logic_1164.vhdl | 175 + libraries/ieee/std_logic_1164_body.vhdl | 830 +++ libraries/mentor/std_logic_arith.vhdl | 254 + libraries/mentor/std_logic_arith_body.vhdl | 2915 +++++++++++ libraries/std/textio.vhdl | 130 + libraries/std/textio_body.vhdl | 1320 +++++ libraries/synopsys/std_logic_arith.vhdl | 2391 +++++++++ libraries/synopsys/std_logic_misc-body.vhdl | 811 +++ libraries/synopsys/std_logic_misc.vhdl | 170 + libraries/synopsys/std_logic_signed.vhdl | 343 ++ libraries/synopsys/std_logic_textio.vhdl | 634 +++ libraries/synopsys/std_logic_unsigned.vhdl | 329 ++ libraries/vital2000/memory_b.vhdl | 7151 ++++++++++++++++++++++++++ libraries/vital2000/memory_p.vhdl | 1729 +++++++ libraries/vital2000/prmtvs_b.vhdl | 5622 ++++++++++++++++++++ libraries/vital2000/prmtvs_p.vhdl | 1413 +++++ libraries/vital2000/timing_b.vhdl | 2187 ++++++++ libraries/vital2000/timing_p.vhdl | 1202 +++++ libraries/vital95/vital_primitives.vhdl | 1410 +++++ libraries/vital95/vital_primitives_body.vhdl | 5614 ++++++++++++++++++++ libraries/vital95/vital_timing.vhdl | 880 ++++ libraries/vital95/vital_timing_body.vhdl | 1275 +++++ 32 files changed, 46163 insertions(+) create mode 100644 libraries/Makefile.inc create mode 100644 libraries/README create mode 100644 libraries/ieee/math_complex-body.vhdl create mode 100644 libraries/ieee/math_complex.vhdl create mode 100644 libraries/ieee/math_real-body.vhdl create mode 100644 libraries/ieee/math_real.vhdl create mode 100644 libraries/ieee/numeric_bit-body.vhdl create mode 100644 libraries/ieee/numeric_bit.vhdl create mode 100644 libraries/ieee/numeric_std-body.vhdl create mode 100644 libraries/ieee/numeric_std.vhdl create mode 100644 libraries/ieee/std_logic_1164.vhdl create mode 100644 libraries/ieee/std_logic_1164_body.vhdl create mode 100644 libraries/mentor/std_logic_arith.vhdl create mode 100644 libraries/mentor/std_logic_arith_body.vhdl create mode 100644 libraries/std/textio.vhdl create mode 100644 libraries/std/textio_body.vhdl create mode 100644 libraries/synopsys/std_logic_arith.vhdl create mode 100644 libraries/synopsys/std_logic_misc-body.vhdl create mode 100644 libraries/synopsys/std_logic_misc.vhdl create mode 100644 libraries/synopsys/std_logic_signed.vhdl create mode 100644 libraries/synopsys/std_logic_textio.vhdl create mode 100644 libraries/synopsys/std_logic_unsigned.vhdl create mode 100644 libraries/vital2000/memory_b.vhdl create mode 100644 libraries/vital2000/memory_p.vhdl create mode 100644 libraries/vital2000/prmtvs_b.vhdl create mode 100644 libraries/vital2000/prmtvs_p.vhdl create mode 100644 libraries/vital2000/timing_b.vhdl create mode 100644 libraries/vital2000/timing_p.vhdl create mode 100644 libraries/vital95/vital_primitives.vhdl create mode 100644 libraries/vital95/vital_primitives_body.vhdl create mode 100644 libraries/vital95/vital_timing.vhdl create mode 100644 libraries/vital95/vital_timing_body.vhdl (limited to 'libraries') diff --git a/libraries/Makefile.inc b/libraries/Makefile.inc new file mode 100644 index 000000000..e1557c603 --- /dev/null +++ b/libraries/Makefile.inc @@ -0,0 +1,169 @@ +# -*- Makefile -*- for the VHDL libraries. +# 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 COPYING. If not, write to the Free +# Software Foundation, 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# Variable to be defined: +# LIB93_DIR +# LIB87_DIR +# REL_DIR +# LIBSRC_DIR +# ANALYZE +# LN +# CP +# +# Note: the source files are analyzed in the LIBxx_DIR. So LIBSRC_DIR must be +# relative to the target directory. + +STD_SRCS := std/textio.vhdl std/textio_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 +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 +SYNOPSYS_BSRCS := synopsys/std_logic_arith.vhdl \ + synopsys/std_logic_textio.vhdl synopsys/std_logic_unsigned.vhdl \ + synopsys/std_logic_signed.vhdl \ + synopsys/std_logic_misc.vhdl synopsys/std_logic_misc-body.vhdl +MENTOR_BSRCS := mentor/std_logic_arith.vhdl mentor/std_logic_arith_body.vhdl + +STD87_BSRCS := $(STD_SRCS:.vhdl=.v87) +STD93_BSRCS := $(STD_SRCS:.vhdl=.v93) +IEEE87_BSRCS := $(IEEE_SRCS:.vhdl=.v87) +IEEE93_BSRCS := $(IEEE_SRCS:.vhdl=.v93) $(MATH_SRCS) +SYNOPSYS87_BSRCS := $(SYNOPSYS_BSRCS) +SYNOPSYS93_BSRCS := $(SYNOPSYS_BSRCS) +MENTOR93_BSRCS := $(MENTOR_BSRCS) + +.PREFIXES: .vhdl .v93 .v87 + +%.v93: %.vhdl + sed -e '/--V87/s/^/ --/' < $< > $@ + +%.v87: %.vhdl + sed -e '/--V93/s/^/ --/' -e '/--START-V93/,/--END-V93/s/^/--/' \ + < $< > $@ + +STD93_DIR:=$(LIB93_DIR)/std +IEEE93_DIR:=$(LIB93_DIR)/ieee +SYN93_DIR:=$(LIB93_DIR)/synopsys +MENTOR93_DIR:=$(LIB93_DIR)/mentor + +STD87_DIR:=$(LIB87_DIR)/std +IEEE87_DIR:=$(LIB87_DIR)/ieee +SYN87_DIR:=$(LIB87_DIR)/synopsys + +ANALYZE93:=$(ANALYZE) --std=93 +ANALYZE87:=$(ANALYZE) --std=87 + +STD87_SRCS=$(addprefix $(LIBSRC_DIR)/,$(STD87_BSRCS)) +STD93_SRCS=$(addprefix $(LIBSRC_DIR)/,$(STD93_BSRCS)) +IEEE93_SRCS=$(addprefix $(LIBSRC_DIR)/,$(IEEE93_BSRCS)) +IEEE87_SRCS=$(addprefix $(LIBSRC_DIR)/,$(IEEE87_BSRCS)) +SYNOPSYS_SRCS=$(addprefix $(LIBSRC_DIR)/,$(SYNOPSYS_BSRCS)) +MENTOR93_SRCS=$(addprefix $(LIBSRC_DIR)/,$(MENTOR93_BSRCS)) +VITAL95_SRCS=$(addprefix $(LIBSRC_DIR)/,$(VITAL95_BSRCS)) +VITAL2000_SRCS=$(addprefix $(LIBSRC_DIR)/,$(VITAL2000_BSRCS)) + +std.v93: $(LIB93_DIR) $(STD93_SRCS) force + $(RM) -rf $(STD93_DIR) + mkdir $(STD93_DIR) + prev=`pwd`; cd $(STD93_DIR); \ + for i in $(STD93_SRCS); do \ + echo $$i; \ + $(ANALYZE93) --bootstrap --work=std $(REL_DIR)/$$i || exit 1; \ + done; \ + cd $$prev + +ANALYZE_IEEE93=$(ANALYZE93) -P../std --work=ieee + +ieee.v93: $(LIB93_DIR) $(IEEE93_SRCS) force + $(RM) -rf $(IEEE93_DIR) + mkdir $(IEEE93_DIR) + prev=`pwd`; cd $(IEEE93_DIR); \ + for i in $(IEEE93_BSRCS) $(VITAL2000_BSRCS); do \ + cmd="$(ANALYZE_IEEE93) $(REL_DIR)/$(LIBSRC_DIR)/$$i"; \ + echo $$cmd; eval $$cmd || exit 1; \ + done; \ + cd $$prev + +synopsys.v93: $(LIB93_DIR) $(SYNOPSYS_SRCS) force + $(RM) -rf $(SYN93_DIR) + mkdir $(SYN93_DIR) + prev=`pwd`; cd $(SYN93_DIR); \ + $(CP) ../ieee/ieee-obj93.cf .; \ + for i in $(IEEE_SRCS) $(VITAL2000_SRCS); do \ + b=`basename $$i .vhdl`; $(LN) ../ieee/$$b.o $$b.o || exit 1; \ + done; \ + for i in $(SYNOPSYS93_BSRCS); do \ + cmd="$(ANALYZE_IEEE93) $(REL_DIR)/$(LIBSRC_DIR)/$$i"; \ + echo $$cmd; eval $$cmd || exit 1; \ + done; \ + cd $$prev + +mentor.v93: $(LIB93_DIR) $(MENTOR93_SRCS) force + $(RM) -rf $(MENTOR93_DIR) + mkdir $(MENTOR93_DIR) + prev=`pwd`; cd $(MENTOR93_DIR); \ + $(CP) ../ieee/ieee-obj93.cf . ;\ + for i in $(IEEE_SRCS) $(VITAL2000_SRCS); do \ + b=`basename $$i .vhdl`; $(LN) ../ieee/$$b.o $$b.o || exit 1; \ + done ; \ + for i in $(MENTOR93_BSRCS); do \ + cmd="$(ANALYZE_IEEE93) $(REL_DIR)/$(LIBSRC_DIR)/$$i";\ + echo $$cmd; eval $$cmd || exit 1; \ + done + +std.v87: $(LIB87_DIR) $(STD87_SRCS) force + $(RM) -rf $(STD87_DIR) + mkdir $(STD87_DIR) + prev=`pwd`; cd $(STD87_DIR); \ + for i in $(STD87_SRCS); do \ + echo $$i; \ + $(ANALYZE87) --bootstrap --work=std $(REL_DIR)/$$i || exit 1; \ + done; \ + cd $$prev + +ANALYZE_IEEE87=$(ANALYZE87) -P../std --work=ieee + +ieee.v87: $(LIB87_DIR) $(IEEE87_SRCS) force + $(RM) -rf $(IEEE87_DIR) + mkdir $(IEEE87_DIR) + prev=`pwd`; cd $(IEEE87_DIR); \ + for i in $(IEEE87_BSRCS) $(VITAL95_BSRCS); do \ + cmd="$(ANALYZE_IEEE87) $(REL_DIR)/$(LIBSRC_DIR)/$$i";\ + echo $$cmd; eval $$cmd || exit 1; \ + done; \ + cd $$prev + +synopsys.v87: $(LIB87_DIR) $(SYNOPSYS_SRCS) force + $(RM) -rf $(SYN87_DIR) + mkdir $(SYN87_DIR) + prev=`pwd`; cd $(SYN87_DIR); \ + $(CP) ../ieee/ieee-obj87.cf . ; \ + for i in $(IEEE_SRCS) $(VITAL95_SRCS); do \ + b=`basename $$i .vhdl`; $(LN) ../ieee/$$b.o $$b.o || exit 1; \ + done; \ + for i in $(SYNOPSYS87_BSRCS); do \ + cmd="$(ANALYZE_IEEE87) $(REL_DIR)/$(LIBSRC_DIR)/$$i";\ + echo $$cmd; eval $$cmd || exit 1; \ + done; \ + cd $$prev diff --git a/libraries/README b/libraries/README new file mode 100644 index 000000000..d569a25a1 --- /dev/null +++ b/libraries/README @@ -0,0 +1,27 @@ +VHDL libraries. +--------------- + +* Filename convention: + +For a package XXXX, the file containing the declaration must be named XXXX.vhdl +and the file containing the body must be named XXXX-body.vhdl + +Note: this is not completly followed! + + +* Using Vhdl-87 or Vhdl-93: + +Lines that must be compiled only for vhdl-87 must have a --V87 comment at the +end, lines for vhdl-93 must a a --V93 comment. +Example: + procedure readline (variable f: in text; l: out line) --V87 + procedure readline (file f: text; l: out line) --V93 +For group of lines that must be compiled only for vhdl-93 (such as xnor +functions), use this: + --START-V93 + ...[lines to compile only with vhdl-93]... + --END-V93 +Makefile rules create .v87 and .v93 files from .vhdl files, and compile them +with the correct version. + +# Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold diff --git a/libraries/ieee/math_complex-body.vhdl b/libraries/ieee/math_complex-body.vhdl new file mode 100644 index 000000000..9b8b75ad4 --- /dev/null +++ b/libraries/ieee/math_complex-body.vhdl @@ -0,0 +1,394 @@ +--------------------------------------------------------------- +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be included in this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE BODY MATH_COMPLEX +-- +-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX +-- which contains common complex constants and basic complex +-- functions and operations. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The package body uses package IEEE.MATH_REAL +-- +-- The 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. +-- +-- Source code for this package body comes from the following +-- following sources: +-- IEEE VHDL Math Package Study Group participants, +-- U. of Mississippi, Mentor Graphics, Synopsys, +-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol +-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable +-- Random Number Generators, Handbook of Mathematical Functions +-- by Milton Abramowitz and Irene A. Stegun (Dover). +-- +-- History: +-- Version 0.1 Jose A. Torres 4/23/93 First draft +-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code +-- +------------------------------------------------------------- +Library IEEE; + +Use IEEE.MATH_REAL.all; -- real trascendental operations + +Package body MATH_COMPLEX is + + function CABS(Z: in complex ) return real is + -- returns absolute value (magnitude) of Z + variable ztemp : complex_polar; + begin + ztemp := COMPLEX_TO_POLAR(Z); + return ztemp.mag; + end CABS; + + function CARG(Z: in complex ) return real is + -- returns argument (angle) in radians of a complex number + variable ztemp : complex_polar; + begin + ztemp := COMPLEX_TO_POLAR(Z); + return ztemp.arg; + end CARG; + + function CMPLX(X: in real; Y: in real := 0.0 ) return complex is + -- returns complex number X + iY + begin + return COMPLEX'(X, Y); + end CMPLX; + + function "-" (Z: in complex ) return complex is + -- unary minus; returns -x -jy for z= x + jy + begin + return COMPLEX'(-z.Re, -z.Im); + end "-"; + + function "-" (Z: in complex_polar ) return complex_polar is + -- unary minus; returns (z.mag, z.arg + MATH_PI) + begin + return COMPLEX_POLAR'(z.mag, z.arg + MATH_PI); + end "-"; + + function CONJ (Z: in complex) return complex is + -- returns complex conjugate (x-jy for z = x+ jy) + begin + return COMPLEX'(z.Re, -z.Im); + end CONJ; + + function CONJ (Z: in complex_polar) return complex_polar is + -- returns complex conjugate (z.mag, -z.arg) + begin + return COMPLEX_POLAR'(z.mag, -z.arg); + end CONJ; + + function CSQRT(Z: in complex ) return complex_vector is + -- returns square root of Z; 2 values + variable ztemp : complex_polar; + variable zout : complex_vector (0 to 1); + variable temp : real; + begin + ztemp := COMPLEX_TO_POLAR(Z); + temp := SQRT(ztemp.mag); + zout(0).re := temp*COS(ztemp.arg/2.0); + zout(0).im := temp*SIN(ztemp.arg/2.0); + + zout(1).re := temp*COS(ztemp.arg/2.0 + MATH_PI); + zout(1).im := temp*SIN(ztemp.arg/2.0 + MATH_PI); + + return zout; + end CSQRT; + + function CEXP(Z: in complex ) return complex is + -- returns e**Z + begin + return COMPLEX'(EXP(Z.re)*COS(Z.im), EXP(Z.re)*SIN(Z.im)); + end CEXP; + + function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar is + -- converts complex to complex_polar + begin + return COMPLEX_POLAR'(sqrt(z.re**2 + z.im**2),atan2(z.re,z.im)); + end COMPLEX_TO_POLAR; + + function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex is + -- converts complex_polar to complex + begin + return COMPLEX'( z.mag*cos(z.arg), z.mag*sin(z.arg) ); + end POLAR_TO_COMPLEX; + + + -- + -- arithmetic operators + -- + + function "+" ( L: in complex; R: in complex ) return complex is + begin + return COMPLEX'(L.Re + R.Re, L.Im + R.Im); + end "+"; + + function "+" (L: in complex_polar; R: in complex_polar) return complex is + variable zL, zR : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(zL.Re + zR.Re, zL.Im + zR.Im); + end "+"; + + function "+" ( L: in complex_polar; R: in complex ) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re + R.Re, zL.Im + R.Im); + end "+"; + + function "+" ( L: in complex; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L.Re + zR.Re, L.Im + zR.Im); + end "+"; + + function "+" ( L: in real; R: in complex ) return complex is + begin + return COMPLEX'(L + R.Re, R.Im); + end "+"; + + function "+" ( L: in complex; R: in real ) return complex is + begin + return COMPLEX'(L.Re + R, L.Im); + end "+"; + + function "+" ( L: in real; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L + zR.Re, zR.Im); + end "+"; + + function "+" ( L: in complex_polar; R: in real) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re + R, zL.Im); + end "+"; + + function "-" ( L: in complex; R: in complex ) return complex is + begin + return COMPLEX'(L.Re - R.Re, L.Im - R.Im); + end "-"; + + function "-" ( L: in complex_polar; R: in complex_polar) return complex is + variable zL, zR : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(zL.Re - zR.Re, zL.Im - zR.Im); + end "-"; + + function "-" ( L: in complex_polar; R: in complex ) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re - R.Re, zL.Im - R.Im); + end "-"; + + function "-" ( L: in complex; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L.Re - zR.Re, L.Im - zR.Im); + end "-"; + + function "-" ( L: in real; R: in complex ) return complex is + begin + return COMPLEX'(L - R.Re, -1.0 * R.Im); + end "-"; + + function "-" ( L: in complex; R: in real ) return complex is + begin + return COMPLEX'(L.Re - R, L.Im); + end "-"; + + function "-" ( L: in real; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L - zR.Re, -1.0*zR.Im); + end "-"; + + function "-" ( L: in complex_polar; R: in real) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re - R, zL.Im); + end "-"; + + function "*" ( L: in complex; R: in complex ) return complex is + begin + return COMPLEX'(L.Re * R.Re - L.Im * R.Im, L.Re * R.Im + L.Im * R.Re); + end "*"; + + function "*" ( L: in complex_polar; R: in complex_polar) return complex is + variable zout : complex_polar; + begin + zout.mag := L.mag * R.mag; + zout.arg := L.arg + R.arg; + return POLAR_TO_COMPLEX(zout); + end "*"; + + function "*" ( L: in complex_polar; R: in complex ) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re*R.Re - zL.Im * R.Im, zL.Re * R.Im + zL.Im*R.Re); + end "*"; + + function "*" ( L: in complex; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L.Re*zR.Re - L.Im * zR.Im, L.Re * zR.Im + L.Im*zR.Re); + end "*"; + + function "*" ( L: in real; R: in complex ) return complex is + begin + return COMPLEX'(L * R.Re, L * R.Im); + end "*"; + + function "*" ( L: in complex; R: in real ) return complex is + begin + return COMPLEX'(L.Re * R, L.Im * R); + end "*"; + + function "*" ( L: in real; R: in complex_polar) return complex is + variable zR : complex; + begin + zR := POLAR_TO_COMPLEX( R ); + return COMPLEX'(L * zR.Re, L * zR.Im); + end "*"; + + function "*" ( L: in complex_polar; R: in real) return complex is + variable zL : complex; + begin + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'(zL.Re * R, zL.Im * R); + end "*"; + + function "/" ( L: in complex; R: in complex ) return complex is + variable magrsq : REAL := R.Re ** 2 + R.Im ** 2; + begin + if (magrsq = 0.0) then + assert FALSE report "Attempt to divide by (0,0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + return COMPLEX'( (L.Re * R.Re + L.Im * R.Im) / magrsq, + (L.Im * R.Re - L.Re * R.Im) / magrsq); + end if; + end "/"; + + function "/" ( L: in complex_polar; R: in complex_polar) return complex is + variable zout : complex_polar; + begin + if (R.mag = 0.0) then + assert FALSE report "Attempt to divide by (0,0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + zout.mag := L.mag/R.mag; + zout.arg := L.arg - R.arg; + return POLAR_TO_COMPLEX(zout); + end if; + end "/"; + + function "/" ( L: in complex_polar; R: in complex ) return complex is + variable zL : complex; + variable temp : REAL := R.Re ** 2 + R.Im ** 2; + begin + if (temp = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + zL := POLAR_TO_COMPLEX( L ); + return COMPLEX'( (zL.Re * R.Re + zL.Im * R.Im) / temp, + (zL.Im * R.Re - zL.Re * R.Im) / temp); + end if; + end "/"; + + function "/" ( L: in complex; R: in complex_polar) return complex is + variable zR : complex := POLAR_TO_COMPLEX( R ); + variable temp : REAL := zR.Re ** 2 + zR.Im ** 2; + begin + if (R.mag = 0.0) or (temp = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + return COMPLEX'( (L.Re * zR.Re + L.Im * zR.Im) / temp, + (L.Im * zR.Re - L.Re * zR.Im) / temp); + end if; + end "/"; + + function "/" ( L: in real; R: in complex ) return complex is + variable temp : REAL := R.Re ** 2 + R.Im ** 2; + begin + if (temp = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + temp := L / temp; + return COMPLEX'( temp * R.Re, -temp * R.Im ); + end if; + end "/"; + + function "/" ( L: in complex; R: in real ) return complex is + begin + if (R = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + return COMPLEX'(L.Re / R, L.Im / R); + end if; + end "/"; + + function "/" ( L: in real; R: in complex_polar) return complex is + variable zR : complex := POLAR_TO_COMPLEX( R ); + variable temp : REAL := zR.Re ** 2 + zR.Im ** 2; + begin + if (R.mag = 0.0) or (temp = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + temp := L / temp; + return COMPLEX'( temp * zR.Re, -temp * zR.Im ); + end if; + end "/"; + + function "/" ( L: in complex_polar; R: in real) return complex is + variable zL : complex := POLAR_TO_COMPLEX( L ); + begin + if (R = 0.0) then + assert FALSE report "Attempt to divide by (0.0,0.0)" + severity ERROR; + return COMPLEX'(REAL'RIGHT, REAL'RIGHT); + else + return COMPLEX'(zL.Re / R, zL.Im / R); + end if; + end "/"; +end MATH_COMPLEX; diff --git a/libraries/ieee/math_complex.vhdl b/libraries/ieee/math_complex.vhdl new file mode 100644 index 000000000..2f9376bfb --- /dev/null +++ b/libraries/ieee/math_complex.vhdl @@ -0,0 +1,126 @@ +--------------------------------------------------------------- +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be included in this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE MATH_COMPLEX +-- +-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX +-- which contains common complex constants and basic complex +-- functions and operations. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The package body uses package IEEE.MATH_REAL +-- +-- The 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. +-- +-- History: +-- Version 0.1 (Strawman) Jose A. Torres 6/22/92 +-- Version 0.2 Jose A. Torres 1/15/93 +-- Version 0.3 Jose A. Torres 4/13/93 +-- Version 0.4 Jose A. Torres 4/19/93 +-- Version 0.5 Jose A. Torres 4/20/93 +-- Version 0.6 Jose A. Torres 4/23/93 Added unary minus +-- and CONJ for polar +-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility +-- with package body. +------------------------------------------------------------- +Library IEEE; + +Package MATH_COMPLEX is + + + type COMPLEX is record RE, IM: real; end record; + type COMPLEX_VECTOR is array (integer range <>) of COMPLEX; + type COMPLEX_POLAR is record MAG: real; ARG: real; end record; + + constant CBASE_1: complex := COMPLEX'(1.0, 0.0); + constant CBASE_j: complex := COMPLEX'(0.0, 1.0); + constant CZERO: complex := COMPLEX'(0.0, 0.0); + + function CABS(Z: in complex ) return real; + -- returns absolute value (magnitude) of Z + + function CARG(Z: in complex ) return real; + -- returns argument (angle) in radians of a complex number + + function CMPLX(X: in real; Y: in real:= 0.0 ) return complex; + -- returns complex number X + iY + + function "-" (Z: in complex ) return complex; + -- unary minus + + function "-" (Z: in complex_polar ) return complex_polar; + -- unary minus + + function CONJ (Z: in complex) return complex; + -- returns complex conjugate + + function CONJ (Z: in complex_polar) return complex_polar; + -- returns complex conjugate + + function CSQRT(Z: in complex ) return complex_vector; + -- returns square root of Z; 2 values + + function CEXP(Z: in complex ) return complex; + -- returns e**Z + + function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar; + -- converts complex to complex_polar + + function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex; + -- converts complex_polar to complex + + + -- arithmetic operators + + function "+" ( L: in complex; R: in complex ) return complex; + function "+" ( L: in complex_polar; R: in complex_polar) return complex; + function "+" ( L: in complex_polar; R: in complex ) return complex; + function "+" ( L: in complex; R: in complex_polar) return complex; + function "+" ( L: in real; R: in complex ) return complex; + function "+" ( L: in complex; R: in real ) return complex; + function "+" ( L: in real; R: in complex_polar) return complex; + function "+" ( L: in complex_polar; R: in real) return complex; + + function "-" ( L: in complex; R: in complex ) return complex; + function "-" ( L: in complex_polar; R: in complex_polar) return complex; + function "-" ( L: in complex_polar; R: in complex ) return complex; + function "-" ( L: in complex; R: in complex_polar) return complex; + function "-" ( L: in real; R: in complex ) return complex; + function "-" ( L: in complex; R: in real ) return complex; + function "-" ( L: in real; R: in complex_polar) return complex; + function "-" ( L: in complex_polar; R: in real) return complex; + + function "*" ( L: in complex; R: in complex ) return complex; + function "*" ( L: in complex_polar; R: in complex_polar) return complex; + function "*" ( L: in complex_polar; R: in complex ) return complex; + function "*" ( L: in complex; R: in complex_polar) return complex; + function "*" ( L: in real; R: in complex ) return complex; + function "*" ( L: in complex; R: in real ) return complex; + function "*" ( L: in real; R: in complex_polar) return complex; + function "*" ( L: in complex_polar; R: in real) return complex; + + + function "/" ( L: in complex; R: in complex ) return complex; + function "/" ( L: in complex_polar; R: in complex_polar) return complex; + function "/" ( L: in complex_polar; R: in complex ) return complex; + function "/" ( L: in complex; R: in complex_polar) return complex; + function "/" ( L: in real; R: in complex ) return complex; + function "/" ( L: in complex; R: in real ) return complex; + function "/" ( L: in real; R: in complex_polar) return complex; + function "/" ( L: in complex_polar; R: in real) return complex; +end MATH_COMPLEX; diff --git a/libraries/ieee/math_real-body.vhdl b/libraries/ieee/math_real-body.vhdl new file mode 100644 index 000000000..1473f6787 --- /dev/null +++ b/libraries/ieee/math_real-body.vhdl @@ -0,0 +1,410 @@ +--------------------------------------------------------------- +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be added to this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE BODY MATH_REAL +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Purpose: VHDL declarations for mathematical package MATH_REAL +-- which contains common real constants, common real +-- functions, and real trascendental functions. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The 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. +-- +-- Source code and algorithms for this package body comes from the +-- following sources: +-- IEEE VHDL Math Package Study Group participants, +-- U. of Mississippi, Mentor Graphics, Synopsys, +-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol +-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable +-- Random Number Generators), Handbook of Mathematical Functions +-- by Milton Abramowitz and Irene A. Stegun (Dover). +-- +-- History: +-- Version 0.1 Jose A. Torres 4/23/93 First draft +-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code +-- +-- GHDL history +-- 2005-04-07 Initial version. +------------------------------------------------------------- +Library IEEE; + +Package body MATH_REAL is + -- + -- non-trascendental functions + -- + function SIGN (X: real ) return real is + -- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0 + begin + assert false severity failure; + end SIGN; + + function CEIL (X : real ) return real is + begin + assert false severity failure; + end CEIL; + + function FLOOR (X : real ) return real is + begin + assert false severity failure; + end FLOOR; + + function ROUND (X : real ) return real is + begin + assert false severity failure; + end ROUND; + + function FMAX (X, Y : real ) return real is + begin + assert false severity failure; + end FMAX; + + function FMIN (X, Y : real ) return real is + begin + assert false severity failure; + end FMIN; + + -- + -- Pseudo-random number generators + -- + + procedure UNIFORM(variable Seed1,Seed2:inout integer;variable X:out real) is + -- returns a pseudo-random number with uniform distribution in the + -- interval (0.0, 1.0). + -- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must + -- be initialized to values in the range [1, 2147483562] and + -- [1, 2147483398] respectively. The seed values are modified after + -- each call to UNIFORM. + -- This random number generator is portable for 32-bit computers, and + -- it has period ~2.30584*(10**18) for each set of seed values. + -- + -- For VHDL-1992, the seeds will be global variables, functions to + -- initialize their values (INIT_SEED) will be provided, and the UNIFORM + -- procedure call will be modified accordingly. + + variable z, k: integer; + begin + k := Seed1/53668; + Seed1 := 40014 * (Seed1 - k * 53668) - k * 12211; + + if Seed1 < 0 then + Seed1 := Seed1 + 2147483563; + end if; + + + k := Seed2/52774; + Seed2 := 40692 * (Seed2 - k * 52774) - k * 3791; + + if Seed2 < 0 then + Seed2 := Seed2 + 2147483399; + end if; + + z := Seed1 - Seed2; + if z < 1 then + z := z + 2147483562; + end if; + + X := REAL(Z)*4.656613e-10; + end UNIFORM; + + + function SRAND (seed: in integer ) return integer is + begin + assert false severity failure; + end SRAND; + + function RAND return integer is + begin + assert false severity failure; + end RAND; + + function GET_RAND_MAX return integer is + -- The value this function returns should be the same as + -- RAND_MAX in /usr/include/stdlib.h + begin + assert false + report "Be sure to update GET_RAND_MAX in mathpack.vhd" + severity note; + return 2147483647; -- i386 linux + end GET_RAND_MAX; + + -- + -- trascendental and trigonometric functions + -- + function c_sqrt (x : real ) return real; + attribute foreign of c_sqrt : function is "VHPIDIRECT sqrt"; + + function c_sqrt (x : real ) return real is + begin + assert false severity failure; + end c_sqrt; + + function SQRT (X : real ) return real is + begin + -- check validity of argument + if ( X < 0.0 ) then + assert false report "X < 0 in SQRT(X)" + severity ERROR; + return (0.0); + end if; + return c_sqrt(X); + end SQRT; + + function CBRT (X : real ) return real is + begin + assert false severity failure; + end CBRT; + + function "**" (X : integer; Y : real) return real is + -- returns Y power of X ==> X**Y; + -- error if X = 0 and Y <= 0.0 + -- error if X < 0 and Y does not have an integer value + begin + -- check validity of argument + if ( X = 0 ) and ( Y <= 0.0 ) then + assert false report "X = 0 and Y <= 0.0 in X**Y" + severity ERROR; + return (0.0); + end if; + + if ( X < 0 ) and ( Y /= REAL(INTEGER(Y)) ) then + assert false + report "X < 0 and Y \= integer in X**Y" + severity ERROR; + return (0.0); + end if; + + -- compute the result + return EXP (Y * LOG (REAL(X))); + end "**"; + + function "**" (X : real; Y : real) return real is + -- returns Y power of X ==> X**Y; + -- error if X = 0.0 and Y <= 0.0 + -- error if X < 0.0 and Y does not have an integer value + begin + -- check validity of argument + if ( X = 0.0 ) and ( Y <= 0.0 ) then + assert false report "X = 0.0 and Y <= 0.0 in X**Y" + severity ERROR; + return (0.0); + end if; + + if ( X < 0.0 ) and ( Y /= REAL(INTEGER(Y)) ) then + assert false report "X < 0.0 and Y \= integer in X**Y" + severity ERROR; + return (0.0); + end if; + + -- compute the result + return EXP (Y * LOG (X)); + end "**"; + + function EXP (X : real ) return real is + begin + assert false severity failure; + end EXP; + + function c_log (x : real ) return real; + attribute foreign of c_log : function is "VHPIDIRECT log"; + + function c_log (x : real ) return real is + begin + assert false severity failure; + end c_log; + + function LOG (X : real ) return real is + -- returns natural logarithm of X; X > 0 + -- + -- This function computes the exponential using the following series: + -- log(x) = 2[ (x-1)/(x+1) + (((x-1)/(x+1))**3)/3.0 + ...] ; x > 0 + -- + begin + -- check validity of argument + if ( x <= 0.0 ) then + assert false report "X <= 0 in LOG(X)" + severity ERROR; + return(REAL'LOW); + end if; + return c_log(x); + end LOG; + + function LOG (BASE: positive; X : real) return real is + -- returns logarithm base BASE of X; X > 0 + begin + -- check validity of argument + if ( BASE <= 0 ) or ( x <= 0.0 ) then + assert false report "BASE <= 0 or X <= 0.0 in LOG(BASE, X)" + severity ERROR; + return(REAL'LOW); + end if; + -- compute the value + return (LOG(X)/LOG(REAL(BASE))); + end LOG; + + function SIN (X : real ) return real is + begin + assert false severity failure; + end SIN; + + + function COS (x : REAL) return REAL is + begin + assert false severity failure; + end COS; + + function TAN (x : REAL) return REAL is + begin + assert false severity failure; + end TAN; + + function c_asin (x : real ) return real; + attribute foreign of c_asin : function is "VHPIDIRECT asin"; + + function c_asin (x : real ) return real is + begin + assert false severity failure; + end c_asin; + + function ASIN (x : real ) return real is + -- returns -PI/2 < asin X < PI/2; | X | <= 1 + begin + if abs x > 1.0 then + assert false + report "Out of range parameter passed to ASIN" + severity ERROR; + return x; + else + return c_asin(x); + end if; + end ASIN; + + function c_acos (x : real ) return real; + attribute foreign of c_acos : function is "VHPIDIRECT acos"; + + function c_acos (x : real ) return real is + begin + assert false severity failure; + end c_acos; + + function ACOS (x : REAL) return REAL is + -- returns 0 < acos X < PI; | X | <= 1 + begin + if abs x > 1.0 then + assert false + report "Out of range parameter passed to ACOS" + severity ERROR; + return x; + else + return c_acos(x); + end if; + end ACOS; + + function ATAN (x : REAL) return REAL is + -- returns -PI/2 < atan X < PI/2 + begin + assert false severity failure; + end ATAN; + + function c_atan2 (x : real; y : real) return real; + attribute foreign of c_atan2 : function is "VHPIDIRECT atan2"; + + function c_atan2 (x : real; y: real) return real is + begin + assert false severity failure; + end c_atan2; + + function ATAN2 (x : REAL; y : REAL) return REAL is + -- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0 + begin + if y = 0.0 and x = 0.0 then + assert false + report "atan2(0.0, 0.0) is undetermined, returned 0,0" + severity NOTE; + return 0.0; + else + return c_atan2(x,y); + end if; + end ATAN2; + + + function SINH (X : real) return real is + -- hyperbolic sine; returns (e**X - e**(-X))/2 + begin + assert false severity failure; + end SINH; + + function COSH (X : real) return real is + -- hyperbolic cosine; returns (e**X + e**(-X))/2 + begin + assert false severity failure; + end COSH; + + function TANH (X : real) return real is + -- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X)) + begin + assert false severity failure; + end TANH; + + function ASINH (X : real) return real is + -- returns ln( X + sqrt( X**2 + 1)) + begin + assert false severity failure; + end ASINH; + + function c_acosh (x : real ) return real; + attribute foreign of c_acosh : function is "VHPIDIRECT acosh"; + + function c_acosh (x : real ) return real is + begin + assert false severity failure; + end c_acosh; + + function ACOSH (X : real) return real is + -- returns ln( X + sqrt( X**2 - 1)); X >= 1 + begin + if abs x >= 1.0 then + assert false report "Out of range parameter passed to ACOSH" + severity ERROR; + return x; + end if; + return c_acosh(x); + end ACOSH; + + function c_atanh (x : real ) return real; + attribute foreign of c_atanh : function is "VHPIDIRECT atanh"; + + function c_atanh (x : real ) return real is + begin + assert false severity failure; + end c_atanh; + + function ATANH (X : real) return real is + -- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1 + begin + if abs x < 1.0 then + assert false report "Out of range parameter passed to ATANH" + severity ERROR; + return x; + end if; + return c_atanh(x); + end ATANH; + +end MATH_REAL; diff --git a/libraries/ieee/math_real.vhdl b/libraries/ieee/math_real.vhdl new file mode 100644 index 000000000..c70d2160b --- /dev/null +++ b/libraries/ieee/math_real.vhdl @@ -0,0 +1,223 @@ +------------------------------------------------------------------------ +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be added to this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE MATH_REAL +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Purpose: VHDL declarations for mathematical package MATH_REAL +-- which contains common real constants, common real +-- functions, and real trascendental functions. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The 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. +-- +-- History: +-- Version 0.1 (Strawman) Jose A. Torres 6/22/92 +-- Version 0.2 Jose A. Torres 1/15/93 +-- Version 0.3 Jose A. Torres 4/13/93 +-- Version 0.4 Jose A. Torres 4/19/93 +-- Version 0.5 Jose A. Torres 4/20/93 Added RANDOM() +-- Version 0.6 Jose A. Torres 4/23/93 Renamed RANDOM as +-- UNIFORM. Modified +-- rights banner. +-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility +-- with package body. +-- +-- GHDL history +-- 2005-04-07 Initial version. +-- 2005-09-01 Some PI constants added. +------------------------------------------------------------- +Library IEEE; + +Package MATH_REAL is + + -- + -- commonly used constants + -- + constant MATH_E : real := 2.71828_18284_59045_23536; -- e + constant MATH_1_OVER_E : real := 0.36787_94411_71442_32160; -- 1/e + constant MATH_PI : real := 3.14159_26535_89793_23846; -- pi + constant MATH_2_PI : real := 2.0 * MATH_PI; -- 2 * pi + constant MATH_1_OVER_PI : real := 0.31830_98861_83790_67154; -- 1/pi + constant MATH_PI_OVER_2 : real := 1.57079_63267_94896_61923; -- pi / 2 + constant MATH_PI_OVER_4 : real := 0.78539_81633_97448_30962; -- pi / 4 + constant MATH_LOG_OF_2 : real := 0.69314_71805_59945_30942; + -- natural log of 2 + constant MATH_LOG_OF_10: real := 2.30258_50929_94045_68402; + -- natural log of10 + constant MATH_LOG2_OF_E: real := 1.44269_50408_88963_4074; + -- log base 2 of e + constant MATH_LOG10_OF_E: real := 0.43429_44819_03251_82765; + -- log base 10 of e + constant MATH_SQRT2: real := 1.41421_35623_73095_04880; + -- sqrt of 2 + constant MATH_SQRT1_2: real := 0.70710_67811_86547_52440; + -- sqrt of 1/2 + constant MATH_SQRT_PI: real := 1.77245_38509_05516_02730; + -- sqrt of pi + constant MATH_DEG_TO_RAD: real := 0.01745_32925_19943_29577; + -- conversion factor from degree to radian + constant MATH_RAD_TO_DEG: real := 57.29577_95130_82320_87685; + -- conversion factor from radian to degree + + -- + -- function declarations + -- + function SIGN (X: real ) return real; + -- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0 + + function CEIL (X : real ) return real; + attribute foreign of ceil : function is "VHPIDIRECT ceil"; + -- returns smallest integer value (as real) not less than X + + function FLOOR (X : real ) return real; + attribute foreign of floor : function is "VHPIDIRECT floor"; + -- returns largest integer value (as real) not greater than X + + function ROUND (X : real ) return real; + attribute foreign of round : function is "VHPIDIRECT round"; + -- returns integer FLOOR(X + 0.5) if X > 0; + -- return integer CEIL(X - 0.5) if X < 0 + + function FMAX (X, Y : real ) return real; + attribute foreign of fmax : function is "VHPIDIRECT fmax"; + -- returns the algebraically larger of X and Y + + function FMIN (X, Y : real ) return real; + attribute foreign of fmin : function is "VHPIDIRECT fmin"; + -- returns the algebraically smaller of X and Y + + procedure UNIFORM (variable Seed1,Seed2:inout integer; variable X:out real); + -- returns a pseudo-random number with uniform distribution in the + -- interval (0.0, 1.0). + -- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must + -- be initialized to values in the range [1, 2147483562] and + -- [1, 2147483398] respectively. The seed values are modified after + -- each call to UNIFORM. + -- This random number generator is portable for 32-bit computers, and + -- it has period ~2.30584*(10**18) for each set of seed values. + -- + -- For VHDL-1992, the seeds will be global variables, functions to + -- initialize their values (INIT_SEED) will be provided, and the UNIFORM + -- procedure call will be modified accordingly. + + function SRAND (seed: in integer ) return integer; + attribute foreign of srand : function is "VHPIDIRECT srand"; + -- + -- sets value of seed for sequence of + -- pseudo-random numbers. + -- It uses the foreign native C function srand(). + + function RAND return integer; + attribute foreign of rand : function is "VHPIDIRECT rand"; + -- + -- returns an integer pseudo-random number with uniform distribution. + -- It uses the foreign native C function rand(). + -- Seed for the sequence is initialized with the + -- SRAND() function and value of the seed is changed every + -- time SRAND() is called, but it is not visible. + -- The range of generated values is platform dependent. + + function GET_RAND_MAX return integer; + -- + -- returns the upper bound of the range of the + -- pseudo-random numbers generated by RAND(). + -- The support for this function is platform dependent, and + -- it uses foreign native C functions or constants. + -- It may not be available in some platforms. + -- Note: the value of (RAND() / GET_RAND_MAX()) is a + -- pseudo-random number distributed between 0 & 1. + + function SQRT (X : real ) return real; + -- returns square root of X; X >= 0 + + function CBRT (X : real ) return real; + attribute foreign of cbrt : function is "VHPIDIRECT cbrt"; + -- returns cube root of X + + function "**" (X : integer; Y : real) return real; + -- returns Y power of X ==> X**Y; + -- error if X = 0 and Y <= 0.0 + -- error if X < 0 and Y does not have an integer value + + function "**" (X : real; Y : real) return real; + -- returns Y power of X ==> X**Y; + -- error if X = 0.0 and Y <= 0.0 + -- error if X < 0.0 and Y does not have an integer value + + function EXP (X : real ) return real; + attribute foreign of exp : function is "VHPIDIRECT exp"; + -- returns e**X; where e = MATH_E + + function LOG (X : real ) return real; + -- returns natural logarithm of X; X > 0 + + function LOG (BASE: positive; X : real) return real; + -- returns logarithm base BASE of X; X > 0 + + function SIN (X : real ) return real; + attribute foreign of sin : function is "VHPIDIRECT sin"; + -- returns sin X; X in radians + + function COS ( X : real ) return real; + attribute foreign of cos : function is "VHPIDIRECT cos"; + -- returns cos X; X in radians + + function TAN (X : real ) return real; + attribute foreign of tan : function is "VHPIDIRECT tan"; + -- returns tan X; X in radians + -- X /= ((2k+1) * PI/2), where k is an integer + + function ASIN (X : real ) return real; + -- returns -PI/2 < asin X < PI/2; | X | <= 1 + + function ACOS (X : real ) return real; + -- returns 0 < acos X < PI; | X | <= 1 + + function ATAN (X : real) return real; + attribute foreign of atan : function is "VHPIDIRECT atan"; + -- returns -PI/2 < atan X < PI/2 + + function ATAN2 (X : real; Y : real) return real; + -- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0 + + function SINH (X : real) return real; + attribute foreign of sinh : function is "VHPIDIRECT sinh"; + -- hyperbolic sine; returns (e**X - e**(-X))/2 + + function COSH (X : real) return real; + attribute foreign of cosh : function is "VHPIDIRECT cosh"; + -- hyperbolic cosine; returns (e**X + e**(-X))/2 + + function TANH (X : real) return real; + attribute foreign of tanh : function is "VHPIDIRECT tanh"; + -- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X)) + + function ASINH (X : real) return real; + attribute foreign of asinh : function is "VHPIDIRECT asinh"; + -- returns ln( X + sqrt( X**2 + 1)) + + function ACOSH (X : real) return real; + -- returns ln( X + sqrt( X**2 - 1)); X >= 1 + + function ATANH (X : real) return real; + -- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1 + +end MATH_REAL; diff --git a/libraries/ieee/numeric_bit-body.vhdl b/libraries/ieee/numeric_bit-body.vhdl new file mode 100644 index 000000000..895594631 --- /dev/null +++ b/libraries/ieee/numeric_bit-body.vhdl @@ -0,0 +1,1818 @@ +-- ----------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT 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. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- + +--============================================================================== +--======================= Package Body ========================================= +--============================================================================== + +package body NUMERIC_BIT is + + -- null range array constants + + constant NAU: UNSIGNED(0 downto 1) := (others => '0'); + constant NAS: SIGNED(0 downto 1) := (others => '0'); + + -- implementation controls + + constant NO_WARNING: BOOLEAN := FALSE; -- default to emit warnings + + --=========================Local Subprograms ================================= + + function MAX (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end MAX; + + function MIN (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end MIN; + + function SIGNED_NUM_BITS (ARG: INTEGER) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + if ARG >= 0 then + N := ARG; + else + N := -(ARG+1); + end if; + NBITS := 1; + while N > 0 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end SIGNED_NUM_BITS; + + function UNSIGNED_NUM_BITS (ARG: NATURAL) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + N := ARG; + NBITS := 1; + while N > 1 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end UNSIGNED_NUM_BITS; + + ------------------------------------------------------------------------------ + -- this internal function computes the addition of two UNSIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_UNSIGNED (L, R: UNSIGNED; C: BIT) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(L_LEFT downto 0) is R; + variable RESULT: UNSIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_SIGNED (L, R: SIGNED; C: BIT) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(L_LEFT downto 0) is R; + variable RESULT: SIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_SIGNED; + + ------------------------------------------------------------------------------ + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure DIVMOD (NUM, XDENOM: UNSIGNED; XQUOT, XREMAIN: out UNSIGNED) is + variable TEMP: UNSIGNED(NUM'LENGTH downto 0); + variable QUOT: UNSIGNED(MAX(NUM'LENGTH, XDENOM'LENGTH)-1 downto 0); + alias DENOM: UNSIGNED(XDENOM'LENGTH-1 downto 0) is XDENOM; + variable TOPBIT: INTEGER; + begin + TEMP := "0"&NUM; + QUOT := (others => '0'); + TOPBIT := -1; + for J in DENOM'RANGE loop + if DENOM(J)='1' then + TOPBIT := J; + exit; + end if; + end loop; + assert TOPBIT >= 0 report "DIV, MOD, or REM by zero" severity ERROR; + + for J in NUM'LENGTH-(TOPBIT+1) downto 0 loop + if TEMP(TOPBIT+J+1 downto J) >= "0"&DENOM(TOPBIT downto 0) then + TEMP(TOPBIT+J+1 downto J) := (TEMP(TOPBIT+J+1 downto J)) + -("0"&DENOM(TOPBIT downto 0)); + QUOT(J) := '1'; + end if; + assert TEMP(TOPBIT+J+1)='0' + report "internal error in the division algorithm" + severity ERROR; + end loop; + XQUOT := RESIZE(QUOT, XQUOT'LENGTH); + XREMAIN := RESIZE(TEMP, XREMAIN'LENGTH); + end DIVMOD; + + -----------------Local Subprograms - shift/rotate ops------------------------- + + function XSLL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT) := XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; + end XSLL; + + function XSRL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0) := XARG(ARG_L downto COUNT); + end if; + return RESULT; + end XSRL; + + function XSRA (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0); + variable XCOUNT: NATURAL := COUNT; + begin + if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then XCOUNT := ARG_L; + end if; + RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); + end if; + return RESULT; + end XSRA; + + function XROL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM) := XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0) := XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end XROL; + + function XROR (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0) := XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1) := XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end XROR; + + ---------------- Local Subprograms - Relational Operators -------------------- + + -- General "=" for UNSIGNED vectors, same length + -- + function UNSIGNED_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end UNSIGNED_EQUAL; + + -- + -- General "=" for SIGNED vectors, same length + -- + function SIGNED_EQUAL (L, R: SIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end SIGNED_EQUAL; + + -- + -- General "<" for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) < BIT_VECTOR(R); + end UNSIGNED_LESS; + + -- + -- General "<" function for SIGNED vectors, same length + -- + function SIGNED_LESS (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) < BIT_VECTOR(INTERN_R); + end SIGNED_LESS; + + -- + -- General "<=" function for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS_OR_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) <= BIT_VECTOR(R); + end UNSIGNED_LESS_OR_EQUAL; + + -- + -- General "<=" function for SIGNED vectors, same length + -- + function SIGNED_LESS_OR_EQUAL (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) <= BIT_VECTOR(INTERN_R); + end SIGNED_LESS_OR_EQUAL; + + --====================== Exported Functions ================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + variable RESULT: SIGNED(ARG_LEFT downto 0); + begin + if ARG'LENGTH < 1 then return NAS; + end if; + RESULT := ARG; + if RESULT(RESULT'LEFT) = '1' then + RESULT := -RESULT; + end if; + return RESULT; + end "abs"; + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: SIGNED(ARG_LEFT downto 0); + variable CBIT: BIT := '1'; + begin + if ARG'LENGTH < 1 then return NAS; + end if; + for I in 0 to RESULT'LEFT loop + RESULT(I) := not(XARG(I)) xor CBIT; + CBIT := CBIT and not(XARG(I)); + end loop; + return RESULT; + end "-"; + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L + TO_UNSIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) + R; + end "+"; + + -- Id: A.7 + function "+" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L + TO_SIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.8 + function "+" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) + R; + end "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L - TO_UNSIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) - R; + end "-"; + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L - TO_SIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) - R; + end "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable RESULT: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0) := (others => '0'); + variable ADVAL: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + return RESULT; + end "*"; + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable RESULT: SIGNED((L_LEFT+R_LEFT+1) downto 0) := (others => '0'); + variable ADVAL: SIGNED((L_LEFT+R_LEFT+1) downto 0); + begin + if ((L_LEFT < 0) or (R_LEFT < 0)) then return NAS; + end if; + XL := L; + XR := R; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT-1 loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + if XL(L_LEFT)='1' then + RESULT := RESULT - ADVAL; + end if; + return RESULT; + end "*"; + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L * TO_UNSIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) * R; + end "*"; + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L * TO_SIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) * R; + end "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FQUOT; + end "/"; + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable QNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + QNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + QNEG := not QNEG; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if QNEG then FQUOT := "0"-FQUOT; + end if; + return SIGNED(FQUOT); + end "/"; + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, QUOT: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH + and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, QUOT: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_SIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => QUOT(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "rem"; + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + RNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG then + FREMAIN := "0"-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "rem"; + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "mod"; + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + RNEG := TRUE; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG and L(L'LEFT)='1' then + FREMAIN := "0"-FREMAIN; + elsif RNEG and FREMAIN/="0" then + FREMAIN := FREMAIN-XDENOM; + elsif L(L'LEFT)='1' and FREMAIN/="0" then + FREMAIN := XDENOM-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "mod"; + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end ">"; + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end "<"; + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "<="; + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end ">="; + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "="; + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH))); + end "/="; + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH))); + end "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSRL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSRA(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + --============================================================================ + +--START-V93 + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), -COUNT)); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + +--END-V93 + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: NATURAL := 0; + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + for I in XARG'RANGE loop + RESULT := RESULT+RESULT; + if XARG(I) = '1' then + RESULT := RESULT + 1; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER is + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + if ARG(ARG'LEFT) = '0' then + return TO_INTEGER(UNSIGNED(ARG)); + else + return (- (TO_INTEGER(UNSIGNED(- (ARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED(SIZE-1 downto 0); + variable I_VAL: NATURAL := ARG; + begin + if (SIZE < 1) then return NAU; + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := '0'; + else RESULT(I) := '1'; + end if; + I_VAL := I_VAL/2; + end loop; + if not(I_VAL =0) then + assert NO_WARNING + report "NUMERIC_BIT.TO_UNSIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_UNSIGNED; + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; + SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED(SIZE-1 downto 0); + variable B_VAL: BIT := '0'; + variable I_VAL: INTEGER := ARG; + begin + if (SIZE < 1) then return NAS; + end if; + if (ARG < 0) then + B_VAL := '1'; + I_VAL := -(ARG+1); + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := B_VAL; + else + RESULT(I) := not B_VAL; + end if; + I_VAL := I_VAL/2; + end loop; + if ((I_VAL/=0) or (B_VAL/=RESULT(RESULT'LEFT))) then + assert NO_WARNING + report "NUMERIC_BIT.TO_SIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_SIGNED; + + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is + alias INVEC: SIGNED(ARG'LENGTH-1 downto 0) is ARG; + variable RESULT: SIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + constant BOUND: INTEGER := MIN(ARG'LENGTH, RESULT'LENGTH)-2; + begin + if (NEW_SIZE < 1) then return NAS; + end if; + if (ARG'LENGTH = 0) then return RESULT; + end if; + RESULT := (others => ARG(ARG'LEFT)); + if BOUND >= 0 then + RESULT(BOUND downto 0) := INVEC(BOUND downto 0); + end if; + return RESULT; + end RESIZE; + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + begin + if (NEW_SIZE < 1) then return NAU; + end if; + if XARG'LENGTH =0 then return RESULT; + end if; + if (RESULT'LENGTH < ARG'LENGTH) then + RESULT(RESULT'LEFT downto 0) := XARG(RESULT'LEFT downto 0); + else + RESULT(RESULT'LEFT downto XARG'LEFT+1) := (others => '0'); + RESULT(XARG'LEFT downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + +--START-V93 + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; +--END-V93 + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + +--START-V93 + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; +--END-V93 + + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '1'; + end RISING_EDGE; + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '0'; + end FALLING_EDGE; + + --============================================================================ +end NUMERIC_BIT; diff --git a/libraries/ieee/numeric_bit.vhdl b/libraries/ieee/numeric_bit.vhdl new file mode 100644 index 000000000..8f049f21a --- /dev/null +++ b/libraries/ieee/numeric_bit.vhdl @@ -0,0 +1,813 @@ +-- ----------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT 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. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- + +package NUMERIC_BIT is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --============================================================================ + -- Numeric array type definitions + --============================================================================ + + type UNSIGNED is array (NATURAL range <> ) of BIT; + type SIGNED is array (NATURAL range <> ) of BIT; + + --============================================================================ + -- Arithmetic Operators: + --============================================================================ + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- size L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- size R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of size L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of size R'LENGTH before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit, ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED vector COUNT times. + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified size. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified size. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; --V93 + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --============================================================================ + -- Edge Detection Functions + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '0' to a '1'. + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '1' to a '0'. + +end NUMERIC_BIT; diff --git a/libraries/ieee/numeric_std-body.vhdl b/libraries/ieee/numeric_std-body.vhdl new file mode 100644 index 000000000..a5d609dc3 --- /dev/null +++ b/libraries/ieee/numeric_std-body.vhdl @@ -0,0 +1,2545 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_STD) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_STD. The NUMERIC_STD 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: 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- + +--============================================================================== +--============================= Package Body =================================== +--============================================================================== + +package body NUMERIC_STD is + + -- null range array constants + + constant NAU: UNSIGNED(0 downto 1) := (others => '0'); + constant NAS: SIGNED(0 downto 1) := (others => '0'); + + -- implementation controls + + constant NO_WARNING: BOOLEAN := FALSE; -- default to emit warnings + + --=========================Local Subprograms ================================= + + function MAX (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end MAX; + + function MIN (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end MIN; + + function SIGNED_NUM_BITS (ARG: INTEGER) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + if ARG >= 0 then + N := ARG; + else + N := -(ARG+1); + end if; + NBITS := 1; + while N > 0 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end SIGNED_NUM_BITS; + + function UNSIGNED_NUM_BITS (ARG: NATURAL) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + N := ARG; + NBITS := 1; + while N > 1 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end UNSIGNED_NUM_BITS; + + ------------------------------------------------------------------------ + + -- this internal function computes the addition of two UNSIGNED + -- with input CARRY + -- * the two arguments are of the same length + + function ADD_UNSIGNED (L, R: UNSIGNED; C: STD_LOGIC) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(L_LEFT downto 0) is R; + variable RESULT: UNSIGNED(L_LEFT downto 0); + variable CBIT: STD_LOGIC := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input CARRY + -- * the two arguments are of the same length + + function ADD_SIGNED (L, R: SIGNED; C: STD_LOGIC) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(L_LEFT downto 0) is R; + variable RESULT: SIGNED(L_LEFT downto 0); + variable CBIT: STD_LOGIC := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_SIGNED; + + ----------------------------------------------------------------------------- + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure DIVMOD (NUM, XDENOM: UNSIGNED; XQUOT, XREMAIN: out UNSIGNED) is + variable TEMP: UNSIGNED(NUM'LENGTH downto 0); + variable QUOT: UNSIGNED(MAX(NUM'LENGTH, XDENOM'LENGTH)-1 downto 0); + alias DENOM: UNSIGNED(XDENOM'LENGTH-1 downto 0) is XDENOM; + variable TOPBIT: INTEGER; + begin + TEMP := "0"&NUM; + QUOT := (others => '0'); + TOPBIT := -1; + for J in DENOM'RANGE loop + if DENOM(J)='1' then + TOPBIT := J; + exit; + end if; + end loop; + assert TOPBIT >= 0 report "DIV, MOD, or REM by zero" severity ERROR; + + for J in NUM'LENGTH-(TOPBIT+1) downto 0 loop + if TEMP(TOPBIT+J+1 downto J) >= "0"&DENOM(TOPBIT downto 0) then + TEMP(TOPBIT+J+1 downto J) := (TEMP(TOPBIT+J+1 downto J)) + -("0"&DENOM(TOPBIT downto 0)); + QUOT(J) := '1'; + end if; + assert TEMP(TOPBIT+J+1)='0' + report "internal error in the division algorithm" + severity ERROR; + end loop; + XQUOT := RESIZE(QUOT, XQUOT'LENGTH); + XREMAIN := RESIZE(TEMP, XREMAIN'LENGTH); + end DIVMOD; + + -----------------Local Subprograms - shift/rotate ops------------------------- + + function XSLL (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR + is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT) := XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; + end XSLL; + + function XSRL (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR + is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0) := XARG(ARG_L downto COUNT); + end if; + return RESULT; + end XSRL; + + function XSRA (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR + is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0); + variable XCOUNT: NATURAL := COUNT; + begin + if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then XCOUNT := ARG_L; + end if; + RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); + end if; + return RESULT; + end XSRA; + + function XROL (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR + is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM) := XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0) := XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end XROL; + + function XROR (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR + is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0) := XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1) := XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end XROR; + + -----------------Local Subprograms - Relational ops--------------------------- + + -- + -- General "=" for UNSIGNED vectors, same length + -- + function UNSIGNED_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return STD_LOGIC_VECTOR(L) = STD_LOGIC_VECTOR(R); + end UNSIGNED_EQUAL; + + -- + -- General "=" for SIGNED vectors, same length + -- + function SIGNED_EQUAL (L, R: SIGNED) return BOOLEAN is + begin + return STD_LOGIC_VECTOR(L) = STD_LOGIC_VECTOR(R); + end SIGNED_EQUAL; + + -- + -- General "<" for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS (L, R: UNSIGNED) return BOOLEAN is + begin + return STD_LOGIC_VECTOR(L) < STD_LOGIC_VECTOR(R); + end UNSIGNED_LESS; + + -- + -- General "<" function for SIGNED vectors, same length + -- + function SIGNED_LESS (L, R: SIGNED) return BOOLEAN is + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return STD_LOGIC_VECTOR(INTERN_L) < STD_LOGIC_VECTOR(INTERN_R); + end SIGNED_LESS; + + -- + -- General "<=" function for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS_OR_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return STD_LOGIC_VECTOR(L) <= STD_LOGIC_VECTOR(R); + end UNSIGNED_LESS_OR_EQUAL; + + -- + -- General "<=" function for SIGNED vectors, same length + -- + function SIGNED_LESS_OR_EQUAL (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return STD_LOGIC_VECTOR(INTERN_L) <= STD_LOGIC_VECTOR(INTERN_R); + end SIGNED_LESS_OR_EQUAL; + + --=========================Exported Functions ========================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: SIGNED(ARG_LEFT downto 0); + begin + if ARG'LENGTH < 1 then return NAS; + end if; + RESULT := TO_01(XARG, 'X'); + if (RESULT(RESULT'LEFT)='X') then return RESULT; + end if; + if RESULT(RESULT'LEFT) = '1' then + RESULT := -RESULT; + end if; + return RESULT; + end "abs"; + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT, XARG01 : SIGNED(ARG_LEFT downto 0); + variable CBIT: STD_LOGIC := '1'; + begin + if ARG'LENGTH < 1 then return NAS; + end if; + XARG01 := TO_01(ARG, 'X'); + if (XARG01(XARG01'LEFT)='X') then return XARG01; + end if; + for I in 0 to RESULT'LEFT loop + RESULT(I) := not(XARG01(I)) xor CBIT; + CBIT := CBIT and not(XARG01(I)); + end loop; + return RESULT; + end "-"; + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED is + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(SIZE-1 downto 0); + variable R01 : UNSIGNED(SIZE-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'LEFT)='X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'LEFT)='X') then return R01; + end if; + return ADD_UNSIGNED(L01, R01, '0'); + end "+"; + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED is + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(SIZE-1 downto 0); + variable R01 : SIGNED(SIZE-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'LEFT)='X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'LEFT)='X') then return R01; + end if; + return ADD_SIGNED(L01, R01, '0'); + end "+"; + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L + TO_UNSIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) + R; + end "+"; + + -- Id: A.7 + function "+" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L + TO_SIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.8 + function "+" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) + R; + end "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED is + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(SIZE-1 downto 0); + variable R01 : UNSIGNED(SIZE-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'LEFT)='X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'LEFT)='X') then return R01; + end if; + return ADD_UNSIGNED(L01, not(R01), '1'); + end "-"; + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED is + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(SIZE-1 downto 0); + variable R01 : SIGNED(SIZE-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + L01 := TO_01(RESIZE(L, SIZE), 'X'); + if (L01(L01'LEFT)='X') then return L01; + end if; + R01 := TO_01(RESIZE(R, SIZE), 'X'); + if (R01(R01'LEFT)='X') then return R01; + end if; + return ADD_SIGNED(L01, not(R01), '1'); + end "-"; + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L - TO_UNSIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) - R; + end "-"; + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L - TO_SIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) - R; + end "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: UNSIGNED(L_LEFT downto 0) is L; + alias XXR: UNSIGNED(R_LEFT downto 0) is R; + variable XL: UNSIGNED(L_LEFT downto 0); + variable XR: UNSIGNED(R_LEFT downto 0); + variable RESULT: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0) := + (others => '0'); + variable ADVAL: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + RESULT := (others => 'X'); + return RESULT; + end if; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + return RESULT; + end "*"; + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable RESULT: SIGNED((L_LEFT+R_LEFT+1) downto 0) := (others => '0'); + variable ADVAL: SIGNED((L_LEFT+R_LEFT+1) downto 0); + begin + if ((L_LEFT < 0) or (R_LEFT < 0)) then return NAS; + end if; + XL := TO_01(L, 'X'); + XR := TO_01(R, 'X'); + if ((XL(L_LEFT)='X') or (XR(R_LEFT)='X')) then + RESULT := (others => 'X'); + return RESULT; + end if; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT-1 loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + if XL(L_LEFT)='1' then + RESULT := RESULT - ADVAL; + end if; + return RESULT; + end "*"; + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L * TO_UNSIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) * R; + end "*"; + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L * TO_SIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) * R; + end "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: UNSIGNED(L_LEFT downto 0) is L; + alias XXR: UNSIGNED(R_LEFT downto 0) is R; + variable XL: UNSIGNED(L_LEFT downto 0); + variable XR: UNSIGNED(R_LEFT downto 0); + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + FQUOT := (others => 'X'); + return FQUOT; + end if; + DIVMOD(XL, XR, FQUOT, FREMAIN); + return FQUOT; + end "/"; + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: SIGNED(L_LEFT downto 0) is L; + alias XXR: SIGNED(R_LEFT downto 0) is R; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable QNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + FQUOT := (others => 'X'); + return SIGNED(FQUOT); + end if; + if XL(XL'LEFT)='1' then + XNUM := UNSIGNED(-XL); + QNEG := TRUE; + else + XNUM := UNSIGNED(XL); + end if; + if XR(XR'LEFT)='1' then + XDENOM := UNSIGNED(-XR); + QNEG := not QNEG; + else + XDENOM := UNSIGNED(XR); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if QNEG then FQUOT := "0"-FQUOT; + end if; + return SIGNED(FQUOT); + end "/"; + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, QUOT: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH and QUOT(0)/='X' + and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_STD.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, QUOT: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_SIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH and QUOT(0)/='X' + and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => QUOT(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_STD.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: UNSIGNED(L_LEFT downto 0) is L; + alias XXR: UNSIGNED(R_LEFT downto 0) is R; + variable XL: UNSIGNED(L_LEFT downto 0); + variable XR: UNSIGNED(R_LEFT downto 0); + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + FREMAIN := (others => 'X'); + return FREMAIN; + end if; + DIVMOD(XL, XR, FQUOT, FREMAIN); + return FREMAIN; + end "rem"; + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: SIGNED(L_LEFT downto 0) is L; + alias XXR: SIGNED(R_LEFT downto 0) is R; + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + XNUM := UNSIGNED(TO_01(XXL, 'X')); + XDENOM := UNSIGNED(TO_01(XXR, 'X')); + if ((XNUM(XNUM'LEFT)='X') or (XDENOM(XDENOM'LEFT)='X')) then + FREMAIN := (others => 'X'); + return SIGNED(FREMAIN); + end if; + if XNUM(XNUM'LEFT)='1' then + XNUM := UNSIGNED(-SIGNED(XNUM)); + RNEG := TRUE; + else + XNUM := UNSIGNED(XNUM); + end if; + if XDENOM(XDENOM'LEFT)='1' then + XDENOM := UNSIGNED(-SIGNED(XDENOM)); + else + XDENOM := UNSIGNED(XDENOM); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG then + FREMAIN := "0"-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "rem"; + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := L rem XR; + if R_LENGTH > L'LENGTH and XREM(0)/='X' + and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_STD.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := XL rem R; + if L_LENGTH > R'LENGTH and XREM(0)/='X' + and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_STD.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(0)/='X' + and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_STD.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(0)/='X' + and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_STD.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: UNSIGNED(L_LEFT downto 0) is L; + alias XXR: UNSIGNED(R_LEFT downto 0) is R; + variable XL: UNSIGNED(L_LEFT downto 0); + variable XR: UNSIGNED(R_LEFT downto 0); + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + FREMAIN := (others => 'X'); + return FREMAIN; + end if; + DIVMOD(XL, XR, FQUOT, FREMAIN); + return FREMAIN; + end "mod"; + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XXL: SIGNED(L_LEFT downto 0) is L; + alias XXR: SIGNED(R_LEFT downto 0) is R; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + XL := TO_01(XXL, 'X'); + XR := TO_01(XXR, 'X'); + if ((XL(XL'LEFT)='X') or (XR(XR'LEFT)='X')) then + FREMAIN := (others => 'X'); + return SIGNED(FREMAIN); + end if; + if XL(XL'LEFT)='1' then + XNUM := UNSIGNED(-XL); + else + XNUM := UNSIGNED(XL); + end if; + if XR(XR'LEFT)='1' then + XDENOM := UNSIGNED(-XR); + RNEG := TRUE; + else + XDENOM := UNSIGNED(XR); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG and L(L'LEFT)='1' then + FREMAIN := "0"-FREMAIN; + elsif RNEG and FREMAIN/="0" then + FREMAIN := FREMAIN-XDENOM; + elsif L(L'LEFT)='1' and FREMAIN/="0" then + FREMAIN := XDENOM-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "mod"; + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(0)/='X' + and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_STD.""mod"": Modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(0)/='X' + and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_STD.""mod"": Modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(0)/='X' + and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_STD.""mod"": Modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(0)/='X' + and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_STD.""mod"": Modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end ">"; + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS_OR_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end ">"; + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R01'LENGTH), R01); + end ">"; + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R01'LENGTH), R01); + end ">"; + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(L01, TO_UNSIGNED(R, L01'LENGTH)); + end ">"; + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS_OR_EQUAL(L01, TO_SIGNED(R, L01'LENGTH)); + end ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "<"; + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "<"; + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS(TO_UNSIGNED(L, R01'LENGTH), R01); + end "<"; + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS(TO_SIGNED(L, R01'LENGTH), R01); + end "<"; + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS(L01, TO_UNSIGNED(R, L01'LENGTH)); + end "<"; + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<"": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS(L01, TO_SIGNED(R, L01'LENGTH)); + end "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS_OR_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "<="; + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS_OR_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "<="; + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R01'LENGTH), R01); + end "<="; + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R01'LENGTH), R01); + end "<="; + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L_LEFT < 0) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS_OR_EQUAL(L01, TO_UNSIGNED(R, L01'LENGTH)); + end "<="; + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L_LEFT < 0) then + assert NO_WARNING + report "NUMERIC_STD.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""<="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS_OR_EQUAL(L01, TO_SIGNED(R, L01'LENGTH)); + end "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end ">="; + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end ">="; + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not UNSIGNED_LESS(TO_UNSIGNED(L, R01'LENGTH), R01); + end ">="; + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS(TO_SIGNED(L, R01'LENGTH), R01); + end ">="; + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not UNSIGNED_LESS(L01, TO_UNSIGNED(R, L01'LENGTH)); + end ">="; + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD."">="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS(L01, TO_SIGNED(R, L01'LENGTH)); + end ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "="; + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)); + end "="; + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(TO_UNSIGNED(L, R01'LENGTH), R01); + end "="; + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(TO_SIGNED(L, R01'LENGTH), R01); + end "="; + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(L01, TO_UNSIGNED(R, L01'LENGTH)); + end "="; + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""="": metavalue detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(L01, TO_SIGNED(R, L01'LENGTH)); + end "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(L_LEFT downto 0); + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(UNSIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE))); + end "/="; + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(R_LEFT downto 0) is R; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(L_LEFT downto 0); + variable R01 : SIGNED(R_LEFT downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + L01 := TO_01(XL, 'X'); + R01 := TO_01(XR, 'X'); + if ((L01(L01'LEFT)='X') or (R01(R01'LEFT)='X')) then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(SIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE))); + end "/="; + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable R01 : UNSIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(TO_UNSIGNED(L, R01'LENGTH), R01)); + end "/="; + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN is + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XR: SIGNED(R_LEFT downto 0) is R; + variable R01 : SIGNED(R_LEFT downto 0); + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + R01 := TO_01(XR, 'X'); + if (R01(R01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(TO_SIGNED(L, R01'LENGTH), R01)); + end "/="; + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + variable L01 : UNSIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(L01, TO_UNSIGNED(R, L01'LENGTH))); + end "/="; + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + variable L01 : SIGNED(L_LEFT downto 0); + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + L01 := TO_01(XL, 'X'); + if (L01(L01'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.""/="": metavalue detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(L01, TO_SIGNED(R, L01'LENGTH))); + end "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSLL(STD_LOGIC_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSLL(STD_LOGIC_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSRA(STD_LOGIC_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROL(STD_LOGIC_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROR(STD_LOGIC_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROL(STD_LOGIC_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROR(STD_LOGIC_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + --============================================================================ +--START-V93 + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), -COUNT)); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + +--END-V93 + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XXARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable XARG: UNSIGNED(ARG_LEFT downto 0); + variable RESULT: NATURAL := 0; + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + XARG := TO_01(XXARG, 'X'); + if (XARG(XARG'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0" + severity WARNING; + return 0; + end if; + for I in XARG'RANGE loop + RESULT := RESULT+RESULT; + if XARG(I) = '1' then + RESULT := RESULT + 1; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER is + variable XARG: SIGNED(ARG'LENGTH-1 downto 0); + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + XARG := TO_01(ARG, 'X'); + if (XARG(XARG'LEFT)='X') then + assert NO_WARNING + report "NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0" + severity WARNING; + return 0; + end if; + if XARG(XARG'LEFT) = '0' then + return TO_INTEGER(UNSIGNED(XARG)); + else + return (- (TO_INTEGER(UNSIGNED(- (XARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED(SIZE-1 downto 0); + variable I_VAL: NATURAL := ARG; + begin + if (SIZE < 1) then return NAU; + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := '0'; + else RESULT(I) := '1'; + end if; + I_VAL := I_VAL/2; + end loop; + if not(I_VAL =0) then + assert NO_WARNING + report "NUMERIC_STD.TO_UNSIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_UNSIGNED; + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED(SIZE-1 downto 0); + variable B_VAL: STD_LOGIC := '0'; + variable I_VAL: INTEGER := ARG; + begin + if (SIZE < 1) then return NAS; + end if; + if (ARG < 0) then + B_VAL := '1'; + I_VAL := -(ARG+1); + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := B_VAL; + else + RESULT(I) := not B_VAL; + end if; + I_VAL := I_VAL/2; + end loop; + if ((I_VAL/=0) or (B_VAL/=RESULT(RESULT'LEFT))) then + assert NO_WARNING + report "NUMERIC_STD.TO_SIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_SIGNED; + + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is + alias INVEC: SIGNED(ARG'LENGTH-1 downto 0) is ARG; + variable RESULT: SIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + constant BOUND: INTEGER := MIN(ARG'LENGTH, RESULT'LENGTH)-2; + begin + if (NEW_SIZE < 1) then return NAS; + end if; + if (ARG'LENGTH = 0) then return RESULT; + end if; + RESULT := (others => ARG(ARG'LEFT)); + if BOUND >= 0 then + RESULT(BOUND downto 0) := INVEC(BOUND downto 0); + end if; + return RESULT; + end RESIZE; + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + begin + if (NEW_SIZE < 1) then return NAU; + end if; + if XARG'LENGTH =0 then return RESULT; + end if; + if (RESULT'LENGTH < ARG'LENGTH) then + RESULT(RESULT'LEFT downto 0) := XARG(RESULT'LEFT downto 0); + else + RESULT(RESULT'LEFT downto XARG'LEFT+1) := (others => '0'); + RESULT(XARG'LEFT downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +--START-V93 + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xnor"; +--END-V93 + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +--START-V93 + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xnor"; +--END-V93 + + --============================================================================ + + -- support constants for STD_MATCH: + + type BOOLEAN_TABLE is array(STD_ULOGIC, STD_ULOGIC) of BOOLEAN; + + constant MATCH_TABLE: BOOLEAN_TABLE := ( + -------------------------------------------------------------------------- + -- U X 0 1 Z W L H - + -------------------------------------------------------------------------- + (FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE), -- | U | + (FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE), -- | X | + (FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE), -- | 0 | + (FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE), -- | 1 | + (FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE), -- | Z | + (FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE), -- | W | + (FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE), -- | L | + (FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE), -- | H | + ( TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) -- | - | + ); + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN is + variable VALUE: STD_ULOGIC; + begin + return MATCH_TABLE(L, R); + end STD_MATCH; + + -- Id: M.2 + function STD_MATCH (L, R: UNSIGNED) return BOOLEAN is + alias LV: UNSIGNED(1 to L'LENGTH) is L; + alias RV: UNSIGNED(1 to R'LENGTH) is R; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: null detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: L'LENGTH /= R'LENGTH, returning FALSE" + severity WARNING; + return FALSE; + else + for I in LV'LOW to LV'HIGH loop + if not (MATCH_TABLE(LV(I), RV(I))) then + return FALSE; + end if; + end loop; + return TRUE; + end if; + end STD_MATCH; + + -- Id: M.3 + function STD_MATCH (L, R: SIGNED) return BOOLEAN is + alias LV: SIGNED(1 to L'LENGTH) is L; + alias RV: SIGNED(1 to R'LENGTH) is R; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: null detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: L'LENGTH /= R'LENGTH, returning FALSE" + severity WARNING; + return FALSE; + else + for I in LV'LOW to LV'HIGH loop + if not (MATCH_TABLE(LV(I), RV(I))) then + return FALSE; + end if; + end loop; + return TRUE; + end if; + end STD_MATCH; + + -- Id: M.4 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN is + alias LV: STD_LOGIC_VECTOR(1 to L'LENGTH) is L; + alias RV: STD_LOGIC_VECTOR(1 to R'LENGTH) is R; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: null detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: L'LENGTH /= R'LENGTH, returning FALSE" + severity WARNING; + return FALSE; + else + for I in LV'LOW to LV'HIGH loop + if not (MATCH_TABLE(LV(I), RV(I))) then + return FALSE; + end if; + end loop; + return TRUE; + end if; + end STD_MATCH; + + -- Id: M.5 + function STD_MATCH (L, R: STD_ULOGIC_VECTOR) return BOOLEAN is + alias LV: STD_ULOGIC_VECTOR(1 to L'LENGTH) is L; + alias RV: STD_ULOGIC_VECTOR(1 to R'LENGTH) is R; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: null detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "NUMERIC_STD.STD_MATCH: L'LENGTH /= R'LENGTH, returning FALSE" + severity WARNING; + return FALSE; + else + for I in LV'LOW to LV'HIGH loop + if not (MATCH_TABLE(LV(I), RV(I))) then + return FALSE; + end if; + end loop; + return TRUE; + end if; + end STD_MATCH; + + --============================================================================ + + -- function TO_01 is used to convert vectors to the + -- correct form for exported functions, + -- and to report if there is an element which + -- is not in (0, 1, H, L). + + -- Id: T.1 + function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED is + variable RESULT: UNSIGNED(S'LENGTH-1 downto 0); + variable BAD_ELEMENT: BOOLEAN := FALSE; + alias XS: UNSIGNED(S'LENGTH-1 downto 0) is S; + begin + if (S'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.TO_01: null detected, returning NAU" + severity WARNING; + return NAU; + end if; + for I in RESULT'RANGE loop + case XS(I) is + when '0' | 'L' => RESULT(I) := '0'; + when '1' | 'H' => RESULT(I) := '1'; + when others => BAD_ELEMENT := TRUE; + end case; + end loop; + if BAD_ELEMENT then + for I in RESULT'RANGE loop + RESULT(I) := XMAP; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + + -- Id: T.2 + function TO_01 (S: SIGNED; XMAP: STD_LOGIC := '0') return SIGNED is + variable RESULT: SIGNED(S'LENGTH-1 downto 0); + variable BAD_ELEMENT: BOOLEAN := FALSE; + alias XS: SIGNED(S'LENGTH-1 downto 0) is S; + begin + if (S'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_STD.TO_01: null detected, returning NAS" + severity WARNING; + return NAS; + end if; + for I in RESULT'RANGE loop + case XS(I) is + when '0' | 'L' => RESULT(I) := '0'; + when '1' | 'H' => RESULT(I) := '1'; + when others => BAD_ELEMENT := TRUE; + end case; + end loop; + if BAD_ELEMENT then + for I in RESULT'RANGE loop + RESULT(I) := XMAP; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + + --============================================================================ + +end NUMERIC_STD; diff --git a/libraries/ieee/numeric_std.vhdl b/libraries/ieee/numeric_std.vhdl new file mode 100644 index 000000000..da22c32b0 --- /dev/null +++ b/libraries/ieee/numeric_std.vhdl @@ -0,0 +1,853 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_STD) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_STD. The NUMERIC_STD 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: 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +package NUMERIC_STD is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --============================================================================ + -- Numeric array type definitions + --============================================================================ + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + + --============================================================================ + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED;R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of SIZE L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of SIZE R'LENGTH before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost + -- element, ARG'LEFT. The COUNT rightmost elements are lost. + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED + -- vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED + -- vector COUNT times. + + --============================================================================ + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; --V93 + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified SIZE. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- --------------------------------------------------------------------------- + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- --------------------------------------------------------------------------- + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; --V93 + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- --------------------------------------------------------------------------- + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- --------------------------------------------------------------------------- + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; --V93 + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --============================================================================ + -- Match Functions + --============================================================================ + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.2 + function STD_MATCH (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.3 + function STD_MATCH (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.4 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.5 + function STD_MATCH (L, R: STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + --============================================================================ + -- Translation Functions + --============================================================================ + + -- Id: T.1 + function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED; + -- Result subtype: UNSIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + + -- Id: T.2 + function TO_01 (S: SIGNED; XMAP: STD_LOGIC := '0') return SIGNED; + -- Result subtype: SIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + +end NUMERIC_STD; diff --git a/libraries/ieee/std_logic_1164.vhdl b/libraries/ieee/std_logic_1164.vhdl new file mode 100644 index 000000000..c53113be9 --- /dev/null +++ b/libraries/ieee/std_logic_1164.vhdl @@ -0,0 +1,175 @@ +-- -------------------------------------------------------------------- +-- +-- 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/92 | +-- -------------------------------------------------------------------- + +PACKAGE std_logic_1164 IS + + ------------------------------------------------------------------- + -- logic state system (unresolved) + ------------------------------------------------------------------- + TYPE std_ulogic IS ( 'U', -- Uninitialized + 'X', -- Forcing Unknown + '0', -- Forcing 0 + '1', -- Forcing 1 + 'Z', -- High Impedance + 'W', -- Weak Unknown + 'L', -- Weak 0 + 'H', -- Weak 1 + '-' -- Don't care + ); + ------------------------------------------------------------------- + -- unconstrained array of std_ulogic for use with the resolution function + ------------------------------------------------------------------- + TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic; + + ------------------------------------------------------------------- + -- *** industry standard logic type *** + ------------------------------------------------------------------- + SUBTYPE std_logic IS resolved std_ulogic; + + ------------------------------------------------------------------- + -- unconstrained array of std_logic for use in declaring signal arrays + ------------------------------------------------------------------- + TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic; + + ------------------------------------------------------------------- + -- common subtypes + ------------------------------------------------------------------- + SUBTYPE X01 IS resolved std_ulogic RANGE 'X' TO '1'; -- ('X','0','1') + SUBTYPE X01Z IS resolved std_ulogic RANGE 'X' TO 'Z'; -- ('X','0','1','Z') + SUBTYPE UX01 IS resolved std_ulogic RANGE 'U' TO '1'; -- ('U','X','0','1') + SUBTYPE UX01Z IS resolved std_ulogic RANGE 'U' TO 'Z'; -- ('U','X','0','1','Z') + + ------------------------------------------------------------------- + -- overloaded logical operators + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; --V93 + FUNCTION "not" ( l : std_ulogic ) RETURN UX01; + + ------------------------------------------------------------------- + -- vectorized overloaded logical operators + ------------------------------------------------------------------- + FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nand" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nand" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "or" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "or" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "xor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + +-- ----------------------------------------------------------------------- +-- 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. +-- ----------------------------------------------------------------------- + FUNCTION "xnor" ( l, r : std_logic_vector ) RETURN std_logic_vector; --V93 + FUNCTION "xnor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;--V93 + + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') RETURN BIT; + FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') RETURN BIT_VECTOR; + FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR; + + FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic; + FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector; + FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( b : BIT ) RETURN X01; + + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z; + + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( b : BIT ) RETURN UX01; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN; + +END std_logic_1164; diff --git a/libraries/ieee/std_logic_1164_body.vhdl b/libraries/ieee/std_logic_1164_body.vhdl new file mode 100644 index 000000000..65c5965e0 --- /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-V93 + FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + BEGIN + RETURN not_table(xor_table(l, r)); + END "xnor"; +--END-V93 + + 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-V93 + 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-V93 + ------------------------------------------------------------------- + -- 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.vhdl b/libraries/mentor/std_logic_arith.vhdl new file mode 100644 index 000000000..7bbd1d80b --- /dev/null +++ b/libraries/mentor/std_logic_arith.vhdl @@ -0,0 +1,254 @@ +---------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1993 by Mentor Graphics -- +-- -- +-- This source file is proprietary information of Mentor Graphics,Inc. -- +-- It may be distributed in whole without restriction provided that -- +-- this copyright statement is not removed from the file and that -- +-- any derivative work contains this copyright notice. -- +-- -- +-- Package Name : std_logic_arith -- +-- -- +-- Purpose : This package is to allow the synthesis of the 1164 package. -- +-- This package add the capability of SIGNED/UNSIGNED math. -- +-- -- +---------------------------------------------------------------------------- + +LIBRARY ieee ; + +PACKAGE std_logic_arith IS + + + USE ieee.std_logic_1164.ALL; + + TYPE SIGNED IS ARRAY (Natural RANGE <>) OF STD_LOGIC ; + TYPE UNSIGNED IS ARRAY (Natural RANGE <>) OF STD_LOGIC ; + + FUNCTION std_ulogic_wired_or ( input : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION std_ulogic_wired_and ( input : std_ulogic_vector ) RETURN std_ulogic; + + ------------------------------------------------------------------------------- + -- Note that all functions that take two vector arguments will + -- handle unequal argument lengths + ------------------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- Conversion Functions + ------------------------------------------------------------------- + + -- Except for the to_integer and conv_integer functions for the + -- signed argument all others assume the input vector to be of + -- magnitude representation. The signed functions assume + -- a 2's complement representation. + FUNCTION to_integer ( arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER; + FUNCTION to_integer ( arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER; + FUNCTION to_integer ( arg1 : STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL; + FUNCTION to_integer ( arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL; + FUNCTION to_integer ( arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER; + + FUNCTION conv_integer ( arg1 : STD_ULOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER; + FUNCTION conv_integer ( arg1 : STD_LOGIC_VECTOR; x : INTEGER := 0 ) RETURN INTEGER; + FUNCTION conv_integer ( arg1 : STD_LOGIC; x : INTEGER := 0 ) RETURN NATURAL; + FUNCTION conv_integer ( arg1 : UNSIGNED; x : INTEGER := 0 ) RETURN NATURAL; + FUNCTION conv_integer ( arg1 : SIGNED; x : INTEGER := 0 ) RETURN INTEGER; + + -- Following functions will return the natural argument in magnitude representation. + FUNCTION to_stdlogic ( arg1 : BOOLEAN ) RETURN STD_LOGIC; + FUNCTION to_stdlogicvector ( arg1 : INTEGER; size : NATURAL ) RETURN STD_LOGIC_VECTOR; + FUNCTION to_stdulogicvector ( arg1 : INTEGER; size : NATURAL ) RETURN STD_ULOGIC_VECTOR; + + FUNCTION to_unsigned ( arg1 : NATURAL; size : NATURAL ) RETURN UNSIGNED; + FUNCTION conv_unsigned ( arg1 : NATURAL; size : NATURAL ) RETURN UNSIGNED; + + -- The integer argument is returned in 2's complement representation. + FUNCTION to_signed ( arg1 : INTEGER; size : NATURAL ) RETURN SIGNED; + FUNCTION conv_signed ( arg1 : INTEGER; size : NATURAL ) RETURN SIGNED; + + + ------------------------------------------------------------------------------- + -- sign/zero extend FUNCTIONs + ------------------------------------------------------------------------------- + + -- The zero_extend functions will perform zero padding to the input vector, + -- returning a vector of length equal to size (the second argument). Note that + -- if size is less than the length of the input argument an assertion will occur. + FUNCTION zero_extend ( arg1 : STD_ULOGIC_VECTOR; size : NATURAL ) RETURN STD_ULOGIC_VECTOR; + FUNCTION zero_extend ( arg1 : STD_LOGIC_VECTOR; size : NATURAL ) RETURN STD_LOGIC_VECTOR; + FUNCTION zero_extend ( arg1 : STD_LOGIC; size : NATURAL ) RETURN STD_LOGIC_VECTOR; + FUNCTION zero_extend ( arg1 : UNSIGNED; size : NATURAL ) RETURN UNSIGNED; + FUNCTION sign_extend ( arg1 : SIGNED; size : NATURAL ) RETURN SIGNED; + + + ------------------------------------------------------------------------------- + -- Arithmetic functions + ------------------------------------------------------------------------------- + + -- All arithmetic functions except multiplication will return a vector + -- of size equal to the size of its largest argument. For multiplication, + -- the resulting vector has a size equal to the sum of the size of its inputs. + -- Note that arguments of unequal lengths are allowed. + FUNCTION "+" ( arg1, arg2 : STD_LOGIC ) RETURN STD_LOGIC; + FUNCTION "+" ( arg1, arg2 : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "+" ( arg1, arg2 : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "+" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED ; + FUNCTION "+" ( arg1, arg2 : SIGNED ) RETURN SIGNED ; + + FUNCTION "-" ( arg1, arg2 : STD_LOGIC ) RETURN STD_LOGIC; + FUNCTION "-" ( arg1, arg2 : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "-" ( arg1, arg2 : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "-" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED; + FUNCTION "-" ( arg1, arg2 : SIGNED ) RETURN SIGNED; + + FUNCTION "+" ( arg1 : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "+" ( arg1 : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "+" ( arg1 : UNSIGNED ) RETURN UNSIGNED; + FUNCTION "+" ( arg1 : SIGNED ) RETURN SIGNED; + FUNCTION "-" ( arg1 : SIGNED ) RETURN SIGNED; + + FUNCTION "*" ( arg1, arg2 : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "*" ( arg1, arg2 : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "*" ( arg1, arg2 : UNSIGNED ) RETURN UNSIGNED ; + FUNCTION "*" ( arg1, arg2 : SIGNED ) RETURN SIGNED ; + + FUNCTION "abs" ( arg1 : SIGNED) RETURN SIGNED; + + -- Vectorized Overloaded Arithmetic Operators, not supported for synthesis. + -- The following operators are not supported for synthesis. + FUNCTION "/" ( l, r : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "/" ( l, r : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "/" ( l, r : UNSIGNED ) RETURN UNSIGNED; + FUNCTION "/" ( l, r : SIGNED ) RETURN SIGNED; + FUNCTION "MOD" ( l, r : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "MOD" ( l, r : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "MOD" ( l, r : UNSIGNED ) RETURN UNSIGNED; + FUNCTION "REM" ( l, r : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "REM" ( l, r : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "REM" ( l, r : UNSIGNED ) RETURN UNSIGNED; + FUNCTION "**" ( l, r : STD_ULOGIC_VECTOR ) RETURN STD_ULOGIC_VECTOR; + FUNCTION "**" ( l, r : STD_LOGIC_VECTOR ) RETURN STD_LOGIC_VECTOR; + FUNCTION "**" ( l, r : UNSIGNED ) RETURN UNSIGNED; + + + ------------------------------------------------------------------------------- + -- Shift and rotate functions. + ------------------------------------------------------------------------------- + + -- Note that all the shift and rotate functions below will change to overloaded + -- operators in the train1 release. + FUNCTION "sla" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "sla" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "sla" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "sla" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + FUNCTION "sra" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "sra" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "sra" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "sra" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + FUNCTION "sll" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "sll" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "sll" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "sll" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + FUNCTION "srl" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "srl" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "srl" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "srl" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + FUNCTION "rol" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "rol" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "rol" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "rol" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + FUNCTION "ror" (arg1:UNSIGNED ; arg2:NATURAL) RETURN UNSIGNED ; + FUNCTION "ror" (arg1:SIGNED ; arg2:NATURAL) RETURN SIGNED ; + FUNCTION "ror" (arg1:STD_ULOGIC_VECTOR ; arg2:NATURAL) RETURN STD_ULOGIC_VECTOR ; + FUNCTION "ror" (arg1:STD_LOGIC_VECTOR ; arg2:NATURAL) RETURN STD_LOGIC_VECTOR ; + + + ------------------------------------------------------------------------------- + -- Comparision functions and operators. + ------------------------------------------------------------------------------- + + -- For all comparision operators, the default operator for signed and unsigned + -- types has been overloaded to perform logical comparisions. Note that for + -- other types the default operator is not overloaded and the use will result + -- in literal comparisions which is not supported for synthesis. + -- + -- Unequal operator widths are supported for all the comparision functions. + FUNCTION eq ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION eq ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION eq ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION eq ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION eq ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION "=" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION "=" ( l, r : SIGNED ) RETURN BOOLEAN ; + + FUNCTION ne ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION ne ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION ne ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION ne ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION ne ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION "/=" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION "/=" ( l, r : SIGNED ) RETURN BOOLEAN ; + + FUNCTION lt ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION lt ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION lt ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION lt ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION lt ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION "<" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION "<" ( l, r : SIGNED ) RETURN BOOLEAN ; + + FUNCTION gt ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION gt ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION gt ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION gt ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION gt ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION ">" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION ">" ( l, r : SIGNED ) RETURN BOOLEAN ; + + FUNCTION le ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION le ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION le ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION le ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION le ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION "<=" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION "<=" ( l, r : SIGNED ) RETURN BOOLEAN ; + + FUNCTION ge ( l, r : STD_LOGIC ) RETURN BOOLEAN; + FUNCTION ge ( l, r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION ge ( l, r : STD_LOGIC_VECTOR ) RETURN BOOLEAN; + FUNCTION ge ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION ge ( l, r : SIGNED ) RETURN BOOLEAN ; + FUNCTION ">=" ( l, r : UNSIGNED ) RETURN BOOLEAN ; + FUNCTION ">=" ( l, r : SIGNED ) RETURN BOOLEAN ; + + ------------------------------------------------------------------------------- + -- Logical operators. + ------------------------------------------------------------------------------- + + -- allows operands of unequal lengths, return vector is + -- equal to the size of the largest argument. + + FUNCTION "and" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "and" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + FUNCTION "nand" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "nand" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + FUNCTION "or" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "or" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + FUNCTION "nor" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "nor" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + FUNCTION "xor" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "xor" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + FUNCTION "not" (arg1:SIGNED) RETURN SIGNED; + FUNCTION "not" (arg1:UNSIGNED) RETURN UNSIGNED; + + FUNCTION "xnor" (arg1, arg2:STD_ULOGIC_VECTOR) RETURN STD_ULOGIC_VECTOR; + FUNCTION "xnor" (arg1, arg2:STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + FUNCTION "xnor" (arg1, arg2:SIGNED) RETURN SIGNED; + FUNCTION "xnor" (arg1, arg2:UNSIGNED) RETURN UNSIGNED; + +END std_logic_arith ; + + 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/std/textio.vhdl b/libraries/std/textio.vhdl new file mode 100644 index 000000000..71b3ca72e --- /dev/null +++ b/libraries/std/textio.vhdl @@ -0,0 +1,130 @@ +-- Std.Textio package declaration. This file is part of GHDL. +-- This file was written from the clause 14.3 of the VHDL LRM. +-- 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 COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. + +package textio is + +-- type definitions for text i/o + + -- a LINE is a pointer to a string value. + type line is access string; + + -- A file of variable-length ASCII records. + -- Note: in order to work correctly, the TEXT file type must be declared in + -- the textio package of library std. Otherwise, a file of string has a + -- non-ASCII format. + type text is file of string; + + type side is (right, left); -- For justifying ouput data within fields. + subtype width is natural; -- For specifying widths of output fields. + +-- standard text files + + file input: text is in "STD_INPUT"; --V87 + file output: text is out "STD_OUTPUT"; --V87 + file input : text open read_mode is "STD_INPUT"; --V93 + file output : text open write_mode is "STD_OUTPUT"; --V93 + +-- input routines for standard types + + procedure readline (variable f: in text; l: inout line); --V87 + procedure readline (file f: text; l: inout line); --V93 + + -- For READ procedures: + -- In this implementation, any L is accepted (ie, there is no constraints + -- on direction, or left bound). Therefore, even variable of type LINE + -- not initialized by READLINE are accepted. Strictly speaking, this is + -- not required by LRM, nor prevented. However, other implementations may + -- fail at parsing such strings. + -- + -- Also, in case of error (GOOD is false), this implementation do not + -- modify L (as specified by the LRM) nor VALUE. + -- + -- For READ procedures without a GOOD argument, an assertion fails in case + -- of error. + -- + -- In case of overflow (ie, if the number is out of the bounds of the type), + -- the procedure will fail with an execution error. + -- FIXME: this should not occur for a bad string. + + procedure read (l: inout line; value: out bit; good: out boolean); + procedure read (l: inout line; value: out bit); + + procedure read (l: inout line; value: out bit_vector; good: out boolean); + procedure read (l: inout line; value: out bit_vector); + + procedure read (l: inout line; value: out boolean; good: out boolean); + procedure read (l: inout line; value: out boolean); + + procedure read (l: inout line; value: out character; good: out boolean); + procedure read (l: inout line; value: out character); + + procedure read (l: inout line; value: out integer; good: out boolean); + procedure read (l: inout line; value: out integer); + + procedure read (l: inout line; value: out real; good: out boolean); + procedure read (l: inout line; value: out real); + + procedure read (l: inout line; value: out string; good: out boolean); + procedure read (l: inout line; value: out string); + + -- This implementation requires no space after the unit identifier, + -- ie "7.5 nsv" is parsed as 7.5 ns. + -- The unit identifier can be in lower case, upper case or mixed case. + procedure read (l: inout line; value: out time; good: out boolean); + procedure read (l: inout line; value: out time); + +-- output routines for standard types + + procedure writeline (variable f: out text; l: inout line); --V87 + procedure writeline (file f: text; l: inout line); --V93 + + -- This implementation accept any value for all the types. + procedure write + (l: inout line; value: in bit; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in bit_vector; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in boolean; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in character; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in integer; + justified: in side := right; field: in width := 0); + procedure write + (L: inout line; value: in real; + justified: in side := right; field: in width := 0; + digits: in natural := 0); + procedure write + (l: inout line; value: in string; + justified: in side := right; field: in width := 0); + + -- UNIT must be a unit name declared in std.standard. Of course, no rules + -- in the core VHDL language prevent you from using a value that is not a + -- unit (eg: 10 ns or even 5 fs). + -- An assertion error message is generated in this case, and question mark + -- (?) is written at the place of the unit name. + procedure write + (l: inout line; value : in time; + justified: in side := right; field: in width := 0; unit : in TIME := ns); + +end textio; diff --git a/libraries/std/textio_body.vhdl b/libraries/std/textio_body.vhdl new file mode 100644 index 000000000..0362ef61a --- /dev/null +++ b/libraries/std/textio_body.vhdl @@ -0,0 +1,1320 @@ +-- 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 COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. + +package body textio is + -- 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. --V93 + constant nbsp : character := character'val (160); --V93 + + procedure writeline (f: out text; l: inout line) is --V87 + procedure writeline (file f: text; l: inout line) is --V93 + 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. + write (f, ""); + 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; + end writeline; + + 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; + + -- 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); + + -- POS is the index of the next character to be put in STR. + variable pos : positive := str'left; + + -- VAL contains the value to be converted. + variable val : real; + + -- The exponent or mantissa computed is stored in MANTISSA. This is + -- a signed number. + variable mantissa : integer; + + variable b : boolean; + variable d : natural; + + -- Append character C in STR. + procedure add_char (c : character) is + begin + str (pos) := c; + pos := pos + 1; + end add_char; + + -- Add digit V in STR. + procedure add_digit (v : natural) is + begin + add_char (character'val (character'pos ('0') + v)); + end add_digit; + + -- Add leading digit and substract it. + procedure extract_leading_digit is + variable d : natural range 0 to 10; + begin + -- Note: We need truncation but type conversion does rounding. + -- FIXME: should consider precision. + d := natural (val); + if real (d) > val then + d := d - 1; + end if; + + val := (val - real (d)) * 10.0; + + add_digit (d); + end extract_leading_digit; + begin + -- Handle sign. + -- There is no overflow here, since with IEEE implementations, sign is + -- independant of the mantissa. + -- LRM93 14.3 + -- The sign is never written if the value is non-negative. + if value < 0.0 then + add_char ('-'); + val := -value; + else + val := value; + end if; + + -- Compute the mantissa. + -- FIXME: should do a dichotomy. + if val = 0.0 then + mantissa := 0; + elsif val < 1.0 then + mantissa := -1; + while val * (10.0 ** (-mantissa)) < 1.0 loop + mantissa := mantissa - 1; + end loop; + else + mantissa := 0; + while val / (10.0 ** mantissa) >= 10.0 loop + mantissa := mantissa + 1; + end loop; + end if; + + -- Normalize VAL: in [0; 10[ + if mantissa >= 0 then + val := val / (10.0 ** mantissa); + else + val := val * 10.0 ** (-mantissa); + end if; + + if digits = 0 then + for i in 0 to 15 loop + extract_leading_digit; + + if i = 0 then + add_char ('.'); + end if; + exit when i > 0 and val < 10.0 ** (i + 1 - 15); + end loop; + + -- LRM93 14.3 + -- if the exponent is present, the `e' is written as a lower case + -- character. + add_char ('e'); + + if mantissa < 0 then + add_char ('-'); + mantissa := -mantissa; + end if; + b := false; + for i in 4 downto 0 loop + d := (mantissa / 10000) mod 10; + if d /= 0 or b or i = 0 then + add_digit (d); + b := true; + end if; + mantissa := (mantissa - d * 10000) * 10; + end loop; + else + if mantissa < 0 then + add_char ('0'); + mantissa := mantissa + 1; + else + loop + extract_leading_digit; + exit when mantissa = 0; + mantissa := mantissa - 1; + end loop; + end if; + add_char ('.'); + for i in 1 to digits loop + if mantissa = 0 then + extract_leading_digit; + else + add_char ('0'); + mantissa := mantissa + 1; + end if; + end loop; + end if; + write (l, str (1 to pos - 1), justified, field); + end write; + + procedure untruncated_text_read --V87 + (variable f : text; str : out string; len : out natural); --V87 + procedure untruncated_text_read --V93 + (file f : text; str : out string; len : out natural); --V93 + + attribute foreign : string; --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 --V93 + 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) --V93 + 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; + + -- 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 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; + 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'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 --V93 + | 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 --V93 + | 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; + begin + -- By default, it is a failure. + good := false; + state := blank; + for i in l'range loop + case state is + when blank => + if l (i) = ' ' + or l (i) = nbsp --V93 + or l (i) = HT + then + null; + elsif to_lower (l (i)) = 't' then + res := true; + state := l_tf; + elsif to_lower (l (i)) = 'f' then + res := false; + state := l_tf; + else + return; + end if; + when l_tf => + if res = true and to_lower (l (i)) = 'r' then + state := l_ra; + elsif res = false and to_lower (l (i)) = 'a' then + state := l_ra; + else + return; + end if; + when l_ra => + if res = true and to_lower (l (i)) = 'u' then + state := l_ul; + elsif res = false and to_lower (l (i)) = 'l' then + state := l_ul; + else + return; + end if; + when l_ul => + if res = true and to_lower (l (i)) = 'e' then + trim_next (l, i); + good := true; + value := true; + return; + elsif res = false and to_lower (l (i)) = 's' then + state := l_es; + else + return; + end if; + when l_es => + if res = false and to_lower (l (i)) = '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 --V93 + | 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; + + procedure read (l: inout line; value: out real; good: out boolean) + is + -- The result. + variable val : real; + -- True if the result is negative. + variable val_neg : boolean; + + -- Number of digits after the dot. + variable nbr_dec : natural; + + -- Value of the exponent. + variable exp : integer; + -- True if the exponent is negative. + variable exp_neg : boolean; + + -- The parsing is done with a state machine. + -- LEADING: leading blank suppression. + -- SIGN: a sign has been found. + -- DIGITS: integer parts + -- DECIMALS: 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, + exponent_sign, exponent_1, exponent); + variable cur_state : state_t := leading; + + -- Set VALUE to the result, and set GOOD to TRUE. + procedure set_value is + begin + good := true; + + if exp_neg then + val := val * 10.0 ** (-exp); + else + val := val * 10.0 ** exp; + end if; + if val_neg then + value := -val; + else + value := val; + end if; + end set_value; + + begin + -- Initialization. + val_neg := false; + nbr_dec := 1; + exp := 0; + exp_neg := false; + + -- 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 cur_state is + when leading => + case l(i) is + when ' ' + | NBSP --V93 + | ht => + null; + when '+' => + cur_state := sign; + when '-' => + val_neg := true; + cur_state := sign; + when '0' to '9' => + val := real (char_to_nat (l(i))); + cur_state := digits; + when others => + return; + end case; + when sign => + case l(i) is + when '0' to '9' => + val := real (char_to_nat (l(i))); + cur_state := digits; + when others => + return; + end case; + when digits => + case l(i) is + when '0' to '9' => + val := val * 10.0 + real (char_to_nat (l(i))); + when '.' => + cur_state := decimals; + when others => + -- A "." (dot) is required in the string. + return; + end case; + when decimals => + case l(i) is + when '0' to '9' => + val := val + real (char_to_nat (l(i))) / (10.0 ** nbr_dec); + nbr_dec := nbr_dec + 1; + when 'e' | 'E' => + -- "nnn.E" is erroneous. + if nbr_dec = 1 then + return; + end if; + cur_state := exponent_sign; + when others => + -- "nnn.XX" is erroneous. + if nbr_dec = 1 then + return; + end if; + trim (l, i); + set_value; + return; + end case; + when exponent_sign => + case l(i) is + when '+' => + cur_state := exponent_1; + when '-' => + exp_neg := true; + cur_state := exponent_1; + when '0' to '9' => + exp := char_to_nat (l(i)); + cur_state := exponent; + when others => + -- Error. + return; + end case; + when exponent_1 | exponent => + case l(i) is + when '0' to '9' => + exp := exp * 10 + char_to_nat (l(i)); + cur_state := exponent; + when others => + trim (l, i); + set_value; + return; + end case; + end case; + end loop; + + -- End of string. + case cur_state is + when leading | sign | digits => + -- Erroneous. + return; + when decimals => + -- "nnn.XX" is erroneous. + if nbr_dec = 1 then + return; + end if; + when exponent_sign => + -- Erroneous ("NNN.NNNE") + return; + when exponent_1 => + -- "NNN.NNNE-" + return; + when exponent => + null; + end case; + + deallocate (l); + l := new string'(""); + set_value; + 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 --V93 + | 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 => + return; + end case; + when others => + return; + 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 --V93 + | 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 + value := l (l'left to l'left + len - 1); + trim (l, l'left + len); + else + 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; + +end textio; diff --git a/libraries/synopsys/std_logic_arith.vhdl b/libraries/synopsys/std_logic_arith.vhdl new file mode 100644 index 000000000..685b64732 --- /dev/null +++ b/libraries/synopsys/std_logic_arith.vhdl @@ -0,0 +1,2391 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in integer range 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in integer range 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 296 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 295 + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 297 + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 298 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 301 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 300 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_UNSIGNED(L, L'length), CONV_UNSIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 302 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length+1), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 303 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length+1))); + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 236 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 237 + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 238 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 239 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 240 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 241 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 242 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 243 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 244 + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 245 + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 246 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 247 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 260 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 261 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 262 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 263 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 264 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 265 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 266 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 267 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 268 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))) ; + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 269 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 270 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 271 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 248 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 249 + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 250 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 251 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 252 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 253 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 254 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 255 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 256 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 257 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 258 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 259 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 272 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_minus(-- pragma label minus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 273 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 274 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 275 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 276 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 277 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 278 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 279 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 280 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 281 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 282 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 283 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 284 + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 285 + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 286 + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 287 + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 289 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 290 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 292 + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 294 + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 305 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 306 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 307 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 308 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 309 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 310 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 311 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 312 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 314 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 315 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 316 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 317 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 318 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 319 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 320 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 321 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 323 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 324 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 325 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 326 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 327 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 328 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 329 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 330 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 332 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 333 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 334 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 335 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 336 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 337 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 338 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 339 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 341 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 342 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 343 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 344 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 345 + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 346 + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 347 + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 348 + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 350 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 351 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 352 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 353 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 354 + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 355 + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 356 + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 357 + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 358 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 359 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 360 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 361 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + -- synopsys subpgm_id 365 + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + -- synopsys subpgm_id 366 + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + -- synopsys subpgm_id 367 + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + -- synopsys subpgm_id 370 + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + -- synopsys subpgm_id 371 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 372 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 373 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 375 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 376 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 377 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 378 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 380 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 381 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 382 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 383 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 384 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 385 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 386 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/libraries/synopsys/std_logic_misc-body.vhdl b/libraries/synopsys/std_logic_misc-body.vhdl new file mode 100644 index 000000000..531328c3f --- /dev/null +++ b/libraries/synopsys/std_logic_misc-body.vhdl @@ -0,0 +1,811 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: std_logic_misc +-- +-- Purpose: This package defines supplemental types, subtypes, +-- constants, and functions for the Std_logic_1164 Package. +-- +-- Author: GWH +-- +-------------------------------------------------------------------------- + +package body std_logic_misc is + +--synopsys synthesis_off + + type STRN_STD_ULOGIC_TABLE is array (STD_ULOGIC,STRENGTH) of STD_ULOGIC; + + -------------------------------------------------------------------- + -- + -- Truth tables for output strength --> STD_ULOGIC lookup + -- + -------------------------------------------------------------------- + + -- truth table for output strength --> STD_ULOGIC lookup + constant tbl_STRN_STD_ULOGIC: STRN_STD_ULOGIC_TABLE := + -- ------------------------------------------------------------------ + -- | X01 X0H XL1 X0Z XZ1 WLH WLZ WZH W0H WL1 | strn/ output| + -- ------------------------------------------------------------------ + (('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | X | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | 0 | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | 1 | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | Z | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | W | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | L | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | H | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W')); -- | - | + + + + -------------------------------------------------------------------- + -- + -- Truth tables for strength --> STD_ULOGIC mapping ('Z' pass through) + -- + -------------------------------------------------------------------- + + -- truth table for output strength --> STD_ULOGIC lookup + constant tbl_STRN_STD_ULOGIC_Z: STRN_STD_ULOGIC_TABLE := + -- ------------------------------------------------------------------ + -- | X01 X0H XL1 X0Z XZ1 WLH WLZ WZH W0H WL1 | strn/ output| + -- ------------------------------------------------------------------ + (('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | X | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | 0 | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | 1 | + ('Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z'), -- | Z | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | W | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | L | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | H | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W')); -- | - | + + + + --------------------------------------------------------------------- + -- + -- functions for mapping the STD_(U)LOGIC according to STRENGTH + -- + --------------------------------------------------------------------- + + function strength_map(input: STD_ULOGIC; strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 387 + begin + return tbl_STRN_STD_ULOGIC(input, strn); + end strength_map; + + + function strength_map_z(input:STD_ULOGIC; strn:STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 388 + begin + return tbl_STRN_STD_ULOGIC_Z(input, strn); + end strength_map_z; + + + --------------------------------------------------------------------- + -- + -- conversion functions for STD_LOGIC_VECTOR and STD_ULOGIC_VECTOR + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function Drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 389 +--synopsys synthesis_off + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; +--synopsys synthesis_on + begin +--synopsys synthesis_off + return STD_ULOGIC_VECTOR(Value); +--synopsys synthesis_on + end Drive; + + + function Drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 390 +--synopsys synthesis_off + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; +--synopsys synthesis_on + begin +--synopsys synthesis_off + return STD_LOGIC_VECTOR(Value); +--synopsys synthesis_on + end Drive; +--synopsys synthesis_off + + + --------------------------------------------------------------------- + -- + -- conversion functions for sensing various types + -- + -- (the second argument allows the user to specify the value to + -- be returned when the network is undriven) + -- + --------------------------------------------------------------------- + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC is + -- pragma subpgm_id 391 + begin + if V = 'Z' then + return vZ; + elsif V = 'U' then + return vU; + elsif V = '-' then + return vDC; + else + return V; + end if; + end Sense; + + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR is + -- pragma subpgm_id 392 + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_LOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + -- pragma subpgm_id 393 + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_ULOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR is + -- pragma subpgm_id 394 + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_LOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + -- pragma subpgm_id 395 + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_ULOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + --------------------------------------------------------------------- + -- + -- Function: STD_LOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_LOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function STD_LOGIC_VECTORtoBIT_VECTOR (V: STD_LOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 396 +--synopsys synthesis_off + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: BIT_VECTOR (V'length-1 downto 0); +--synopsys synthesis_on + begin +--synopsys synthesis_off + for i in Value'range loop + case Value(i) is + when '0' | 'L' => + Result(i) := '0'; + when '1' | 'H' => + Result(i) := '1'; + when 'X' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result(i) := vZ; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result(i) := vU; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result(i) := vDC; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: - --> 0" + severity WARNING; + end if; + end case; + end loop; + return Result; +--synopsys synthesis_on + end STD_LOGIC_VECTORtoBIT_VECTOR; + + + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_ULOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGIC_VECTORtoBIT_VECTOR (V: STD_ULOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 397 +--synopsys synthesis_off + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: BIT_VECTOR (V'length-1 downto 0); +--synopsys synthesis_on + begin +--synopsys synthesis_off + for i in Value'range loop + case Value(i) is + when '0' | 'L' => + Result(i) := '0'; + when '1' | 'H' => + Result(i) := '1'; + when 'X' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result(i) := vZ; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result(i) := vU; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result(i) := vDC; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: - --> 0" + severity WARNING; + end if; + end case; + end loop; + return Result; +--synopsys synthesis_on + end STD_ULOGIC_VECTORtoBIT_VECTOR; + + + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGICtoBIT + -- + -- Purpose: Conversion function from STD_ULOGIC to BIT + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGICtoBIT (V: STD_ULOGIC +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 398 + variable Result: BIT; + begin +--synopsys synthesis_off + case V is + when '0' | 'L' => + Result := '0'; + when '1' | 'H' => + Result := '1'; + when 'X' => + if ( Xflag ) then + Result := vX; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result := vX; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result := vZ; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result := vU; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result := vDC; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: - --> 0" + severity WARNING; + end if; + end case; + return Result; +--synopsys synthesis_on + end STD_ULOGICtoBIT; + + + -------------------------------------------------------------------------- + + function AND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 399 + variable result: STD_LOGIC; + begin + result := '1'; + for i in ARG'range loop + result := result and ARG(i); + end loop; + return result; + end; + + function NAND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 400 + begin + return not AND_REDUCE(ARG); + end; + + function OR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 401 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result or ARG(i); + end loop; + return result; + end; + + function NOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 402 + begin + return not OR_REDUCE(ARG); + end; + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + + function XNOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 404 + begin + return not XOR_REDUCE(ARG); + end; + + function AND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 405 + variable result: STD_LOGIC; + begin + result := '1'; + for i in ARG'range loop + result := result and ARG(i); + end loop; + return result; + end; + + function NAND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 406 + begin + return not AND_REDUCE(ARG); + end; + + function OR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 407 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result or ARG(i); + end loop; + return result; + end; + + function NOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 408 + begin + return not OR_REDUCE(ARG); + end; + + function XOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 409 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + + function XNOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 410 + begin + return not XOR_REDUCE(ARG); + end; + +--synopsys synthesis_off + + function fun_BUF3S(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 411 + type TRISTATE_TABLE is array(STRENGTH, UX01, UX01) of STD_LOGIC; + + -- truth table for tristate "buf" function (Enable active Low) + constant tbl_BUF3S: TRISTATE_TABLE := + -- ---------------------------------------------------- + -- | Input U X 0 1 | Enable Strength | + -- ---------------------------------|-----------------| + ((('U', 'U', 'U', 'U'), --| U X01 | + ('U', 'X', 'X', 'X'), --| X X01 | + ('Z', 'Z', 'Z', 'Z'), --| 0 X01 | + ('U', 'X', '0', '1')), --| 1 X01 | + (('U', 'U', 'U', 'U'), --| U X0H | + ('U', 'X', 'X', 'X'), --| X X0H | + ('Z', 'Z', 'Z', 'Z'), --| 0 X0H | + ('U', 'X', '0', 'H')), --| 1 X0H | + (('U', 'U', 'U', 'U'), --| U XL1 | + ('U', 'X', 'X', 'X'), --| X XL1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 XL1 | + ('U', 'X', 'L', '1')), --| 1 XL1 | + (('U', 'U', 'U', 'Z'), --| U X0Z | + ('U', 'X', 'X', 'Z'), --| X X0Z | + ('Z', 'Z', 'Z', 'Z'), --| 0 X0Z | + ('U', 'X', '0', 'Z')), --| 1 X0Z | + (('U', 'U', 'U', 'U'), --| U XZ1 | + ('U', 'X', 'X', 'X'), --| X XZ1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 XZ1 | + ('U', 'X', 'Z', '1')), --| 1 XZ1 | + (('U', 'U', 'U', 'U'), --| U WLH | + ('U', 'W', 'W', 'W'), --| X WLH | + ('Z', 'Z', 'Z', 'Z'), --| 0 WLH | + ('U', 'W', 'L', 'H')), --| 1 WLH | + (('U', 'U', 'U', 'U'), --| U WLZ | + ('U', 'W', 'W', 'Z'), --| X WLZ | + ('Z', 'Z', 'Z', 'Z'), --| 0 WLZ | + ('U', 'W', 'L', 'Z')), --| 1 WLZ | + (('U', 'U', 'U', 'U'), --| U WZH | + ('U', 'W', 'W', 'W'), --| X WZH | + ('Z', 'Z', 'Z', 'Z'), --| 0 WZH | + ('U', 'W', 'Z', 'H')), --| 1 WZH | + (('U', 'U', 'U', 'U'), --| U W0H | + ('U', 'W', 'W', 'W'), --| X W0H | + ('Z', 'Z', 'Z', 'Z'), --| 0 W0H | + ('U', 'W', '0', 'H')), --| 1 W0H | + (('U', 'U', 'U', 'U'), --| U WL1 | + ('U', 'W', 'W', 'W'), --| X WL1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 WL1 | + ('U', 'W', 'L', '1')));--| 1 WL1 | + begin + return tbl_BUF3S(Strn, Enable, Input); + end fun_BUF3S; + + + function fun_BUF3SL(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 412 + type TRISTATE_TABLE is array(STRENGTH, UX01, UX01) of STD_LOGIC; + + -- truth table for tristate "buf" function (Enable active Low) + constant tbl_BUF3SL: TRISTATE_TABLE := + -- ---------------------------------------------------- + -- | Input U X 0 1 | Enable Strength | + -- ---------------------------------|-----------------| + ((('U', 'U', 'U', 'U'), --| U X01 | + ('U', 'X', 'X', 'X'), --| X X01 | + ('U', 'X', '0', '1'), --| 0 X01 | + ('Z', 'Z', 'Z', 'Z')), --| 1 X01 | + (('U', 'U', 'U', 'U'), --| U X0H | + ('U', 'X', 'X', 'X'), --| X X0H | + ('U', 'X', '0', 'H'), --| 0 X0H | + ('Z', 'Z', 'Z', 'Z')), --| 1 X0H | + (('U', 'U', 'U', 'U'), --| U XL1 | + ('U', 'X', 'X', 'X'), --| X XL1 | + ('U', 'X', 'L', '1'), --| 0 XL1 | + ('Z', 'Z', 'Z', 'Z')), --| 1 XL1 | + (('U', 'U', 'U', 'Z'), --| U X0Z | + ('U', 'X', 'X', 'Z'), --| X X0Z | + ('U', 'X', '0', 'Z'), --| 0 X0Z | + ('Z', 'Z', 'Z', 'Z')), --| 1 X0Z | + (('U', 'U', 'U', 'U'), --| U XZ1 | + ('U', 'X', 'X', 'X'), --| X XZ1 | + ('U', 'X', 'Z', '1'), --| 0 XZ1 | + ('Z', 'Z', 'Z', 'Z')), --| 1 XZ1 | + (('U', 'U', 'U', 'U'), --| U WLH | + ('U', 'W', 'W', 'W'), --| X WLH | + ('U', 'W', 'L', 'H'), --| 0 WLH | + ('Z', 'Z', 'Z', 'Z')), --| 1 WLH | + (('U', 'U', 'U', 'U'), --| U WLZ | + ('U', 'W', 'W', 'Z'), --| X WLZ | + ('U', 'W', 'L', 'Z'), --| 0 WLZ | + ('Z', 'Z', 'Z', 'Z')), --| 1 WLZ | + (('U', 'U', 'U', 'U'), --| U WZH | + ('U', 'W', 'W', 'W'), --| X WZH | + ('U', 'W', 'Z', 'H'), --| 0 WZH | + ('Z', 'Z', 'Z', 'Z')), --| 1 WZH | + (('U', 'U', 'U', 'U'), --| U W0H | + ('U', 'W', 'W', 'W'), --| X W0H | + ('U', 'W', '0', 'H'), --| 0 W0H | + ('Z', 'Z', 'Z', 'Z')), --| 1 W0H | + (('U', 'U', 'U', 'U'), --| U WL1 | + ('U', 'W', 'W', 'W'), --| X WL1 | + ('U', 'W', 'L', '1'), --| 0 WL1 | + ('Z', 'Z', 'Z', 'Z')));--| 1 WL1 | + begin + return tbl_BUF3SL(Strn, Enable, Input); + end fun_BUF3SL; + + + function fun_MUX2x1(Input0, Input1, Sel: UX01) return UX01 is + -- pragma subpgm_id 413 + type MUX_TABLE is array (UX01, UX01, UX01) of UX01; + + -- truth table for "MUX2x1" function + constant tbl_MUX2x1: MUX_TABLE := + -------------------------------------------- + --| In0 'U' 'X' '0' '1' | Sel In1 | + -------------------------------------------- + ((('U', 'U', 'U', 'U'), --| 'U' 'U' | + ('U', 'U', 'U', 'U'), --| 'X' 'U' | + ('U', 'X', '0', '1'), --| '0' 'U' | + ('U', 'U', 'U', 'U')), --| '1' 'U' | + (('U', 'X', 'U', 'U'), --| 'U' 'X' | + ('U', 'X', 'X', 'X'), --| 'X' 'X' | + ('U', 'X', '0', '1'), --| '0' 'X' | + ('X', 'X', 'X', 'X')), --| '1' 'X' | + (('U', 'U', '0', 'U'), --| 'U' '0' | + ('U', 'X', '0', 'X'), --| 'X' '0' | + ('U', 'X', '0', '1'), --| '0' '0' | + ('0', '0', '0', '0')), --| '1' '0' | + (('U', 'U', 'U', '1'), --| 'U' '1' | + ('U', 'X', 'X', '1'), --| 'X' '1' | + ('U', 'X', '0', '1'), --| '0' '1' | + ('1', '1', '1', '1')));--| '1' '1' | + begin + return tbl_MUX2x1(Input1, Sel, Input0); + end fun_MUX2x1; + + + function fun_MAJ23(Input0, Input1, Input2: UX01) return UX01 is + -- pragma subpgm_id 414 + type MAJ23_TABLE is array (UX01, UX01, UX01) of UX01; + + ---------------------------------------------------------------------------- + -- The "tbl_MAJ23" truth table return 1 if the majority of three + -- inputs is 1, a 0 if the majority is 0, a X if unknown, and a U if + -- uninitialized. + ---------------------------------------------------------------------------- + constant tbl_MAJ23: MAJ23_TABLE := + -------------------------------------------- + --| In0 'U' 'X' '0' '1' | In1 In2 | + -------------------------------------------- + ((('U', 'U', 'U', 'U'), --| 'U' 'U' | + ('U', 'U', 'U', 'U'), --| 'X' 'U' | + ('U', 'U', '0', 'U'), --| '0' 'U' | + ('U', 'U', 'U', '1')), --| '1' 'U' | + (('U', 'U', 'U', 'U'), --| 'U' 'X' | + ('U', 'X', 'X', 'X'), --| 'X' 'X' | + ('U', 'X', '0', 'X'), --| '0' 'X' | + ('U', 'X', 'X', '1')), --| '1' 'X' | + (('U', 'U', '0', 'U'), --| 'U' '0' | + ('U', 'X', '0', 'X'), --| 'X' '0' | + ('0', '0', '0', '0'), --| '0' '0' | + ('U', 'X', '0', '1')), --| '1' '0' | + (('U', 'U', 'U', '1'), --| 'U' '1' | + ('U', 'X', 'X', '1'), --| 'X' '1' | + ('U', 'X', '0', '1'), --| '0' '1' | + ('1', '1', '1', '1')));--| '1' '1' | + + begin + return tbl_MAJ23(Input0, Input1, Input2); + end fun_MAJ23; + + + function fun_WiredX(Input0, Input1: STD_ULOGIC) return STD_LOGIC is + -- pragma subpgm_id 415 + TYPE stdlogic_table IS ARRAY(STD_ULOGIC, STD_ULOGIC) OF STD_LOGIC; + + -- truth table for "WiredX" function + ------------------------------------------------------------------- + -- 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' ));-- | - | + begin + return resolution_table(Input0, Input1); + end fun_WiredX; + +--synopsys synthesis_on + +end; diff --git a/libraries/synopsys/std_logic_misc.vhdl b/libraries/synopsys/std_logic_misc.vhdl new file mode 100644 index 000000000..999aa8391 --- /dev/null +++ b/libraries/synopsys/std_logic_misc.vhdl @@ -0,0 +1,170 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: std_logic_misc +-- +-- Purpose: This package defines supplemental types, subtypes, +-- constants, and functions for the Std_logic_1164 Package. +-- +-- Author: GWH +-- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +--library SYNOPSYS; +--use SYNOPSYS.attributes.all; + + +package std_logic_misc is + + -- output-strength types + + type STRENGTH is (strn_X01, strn_X0H, strn_XL1, strn_X0Z, strn_XZ1, + strn_WLH, strn_WLZ, strn_WZH, strn_W0H, strn_WL1); + + +--synopsys synthesis_off + + type MINOMAX is array (1 to 3) of TIME; + + + --------------------------------------------------------------------- + -- + -- functions for mapping the STD_(U)LOGIC according to STRENGTH + -- + --------------------------------------------------------------------- + + function strength_map(input: STD_ULOGIC; strn: STRENGTH) return STD_LOGIC; + + function strength_map_z(input:STD_ULOGIC; strn:STRENGTH) return STD_LOGIC; + + --------------------------------------------------------------------- + -- + -- conversion functions for STD_ULOGIC_VECTOR and STD_LOGIC_VECTOR + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function Drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function Drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR; +--synopsys synthesis_off + + --attribute CLOSELY_RELATED_TCF of Drive: function is TRUE; + + --------------------------------------------------------------------- + -- + -- conversion functions for sensing various types + -- (the second argument allows the user to specify the value to + -- be returned when the network is undriven) + -- + --------------------------------------------------------------------- + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_LOGIC; + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +--synopsys synthesis_on + + + --------------------------------------------------------------------- + -- + -- Function: STD_LOGIC_VECTORtoBIT_VECTOR STD_ULOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_(U)LOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_LOGIC_VECTORtoBIT_VECTOR (V: STD_LOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR; + + function STD_ULOGIC_VECTORtoBIT_VECTOR (V: STD_ULOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR; + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGICtoBIT + -- + -- Purpose: Conversion function from STD_(U)LOGIC to BIT + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGICtoBIT (V: STD_ULOGIC +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT; + + -------------------------------------------------------------------- + function AND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function NAND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function OR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function NOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function XNOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + + function AND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function NAND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function OR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function NOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function XOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function XNOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + +--synopsys synthesis_off + + function fun_BUF3S(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC; + function fun_BUF3SL(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC; + function fun_MUX2x1(Input0, Input1, Sel: UX01) return UX01; + + function fun_MAJ23(Input0, Input1, Input2: UX01) return UX01; + function fun_WiredX(Input0, Input1: std_ulogic) return STD_LOGIC; + +--synopsys synthesis_on + +end; diff --git a/libraries/synopsys/std_logic_signed.vhdl b/libraries/synopsys/std_logic_signed.vhdl new file mode 100644 index 000000000..27d211be5 --- /dev/null +++ b/libraries/synopsys/std_logic_signed.vhdl @@ -0,0 +1,343 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_SIGNED -- +-- -- +-- -- +-- Date: 09/11/91 KN -- +-- 10/08/92 AMT change std_ulogic to signed std_logic -- +-- 10/28/92 AMT added signed functions, -, ABS -- +-- -- +-- Purpose: -- +-- A set of signed arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: Comparision of same length std_logic_vector is defined -- +-- in the LRM. The interpretation is for unsigned vectors -- +-- This package will "overload" that definition. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_SIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_SIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_SIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + SIGNED(L); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := - SIGNED(L); -- pragma label minus + return std_logic_vector(result); + end; + + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := ABS( SIGNED(L)); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := SIGNED(L) * SIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return SIGNED(L) < SIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return SIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < SIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= SIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= SIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > SIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > SIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= SIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= SIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) = SIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) /= SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= SIGNED(R); + end; + + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + + +-- This function converts std_logic_vector to a signed integer value +-- using a conversion function in std_logic_arith + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : SIGNED(ARG'range); + begin + result := SIGNED(ARG); + return CONV_INTEGER(result); + end; +end STD_LOGIC_SIGNED; + + diff --git a/libraries/synopsys/std_logic_textio.vhdl b/libraries/synopsys/std_logic_textio.vhdl new file mode 100644 index 000000000..d69a87e37 --- /dev/null +++ b/libraries/synopsys/std_logic_textio.vhdl @@ -0,0 +1,634 @@ +---------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: STD_LOGIC_TEXTIO +-- +-- Purpose: This package overloads the standard TEXTIO procedures +-- READ and WRITE. +-- +-- Author: CRC, TS +-- +---------------------------------------------------------------------------- + +use STD.textio.all; +library IEEE; +use IEEE.std_logic_1164.all; + +package STD_LOGIC_TEXTIO is +--synopsys synthesis_off + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- + -- Read and Write procedures for Hex and Octal values. + -- The values appear in the file as a series of characters + -- between 0-F (Hex), or 0-7 (Octal) respectively. + -- + + -- Hex + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Octal + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; + +package body STD_LOGIC_TEXTIO is +--synopsys synthesis_off + + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; + type MVL9_indexed_by_char is array (character) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (character) of MVL9plus; + + constant MVL9_to_char: char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9: MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus: MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); + + + -- Overloaded procedures. + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD:out BOOLEAN) is + variable c: character; + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + good := FALSE; + else + value := char_to_MVL9(c); + good := TRUE; + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD:out BOOLEAN) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + + read(l, s); + for i in integer range 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in integer range 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + good := TRUE; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC) is + variable c: character; + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + assert FALSE report "READ(STD_ULOGIC) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + else + value := char_to_MVL9(c); + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + return; + end if; + + read(l, s); + for i in integer range 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal."; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in integer range 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + write(l, MVL9_to_char(value), justified, field); + end WRITE; + + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable s: string(1 to value'length); + variable m: STD_ULOGIC_VECTOR(1 to value'length) := value; + begin + for i in 1 to value'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end WRITE; + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + WRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end WRITE; + + + -- + -- Hex Read and Write procedures. + -- + + -- + -- Hex, and Octal Read and Write procedures for BIT_VECTOR + -- (these procedures are not exported, they are only used + -- by the STD_ULOGIC hex/octal reads and writes below. + -- + -- + + procedure Char2QuadBits(C: Character; + RESULT: out Bit_Vector(3 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := x"0"; good := TRUE; + when '1' => result := x"1"; good := TRUE; + when '2' => result := x"2"; good := TRUE; + when '3' => result := x"3"; good := TRUE; + when '4' => result := x"4"; good := TRUE; + when '5' => result := x"5"; good := TRUE; + when '6' => result := x"6"; good := TRUE; + when '7' => result := x"7"; good := TRUE; + when '8' => result := x"8"; good := TRUE; + when '9' => result := x"9"; good := TRUE; + when 'A' => result := x"A"; good := TRUE; + when 'B' => result := x"B"; good := TRUE; + when 'C' => result := x"C"; good := TRUE; + when 'D' => result := x"D"; good := TRUE; + when 'E' => result := x"E"; good := TRUE; + when 'F' => result := x"F"; good := TRUE; + + when 'a' => result := x"A"; good := TRUE; + when 'b' => result := x"B"; good := TRUE; + when 'c' => result := x"C"; good := TRUE; + when 'd' => result := x"D"; good := TRUE; + when 'e' => result := x"E"; good := TRUE; + when 'f' => result := x"F"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)."; + end if; + good := FALSE; + end case; + end; + + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HREAD Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "HREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end HREAD; + + + procedure HWRITE(L:inout LINE; VALUE:in BIT_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable quad: bit_vector(0 to 3); + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HWRITE Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + for i in 0 to ne-1 loop + quad := bv(4*i to 4*i+3); + case quad is + when x"0" => s(i+1) := '0'; + when x"1" => s(i+1) := '1'; + when x"2" => s(i+1) := '2'; + when x"3" => s(i+1) := '3'; + when x"4" => s(i+1) := '4'; + when x"5" => s(i+1) := '5'; + when x"6" => s(i+1) := '6'; + when x"7" => s(i+1) := '7'; + when x"8" => s(i+1) := '8'; + when x"9" => s(i+1) := '9'; + when x"A" => s(i+1) := 'A'; + when x"B" => s(i+1) := 'B'; + when x"C" => s(i+1) := 'C'; + when x"D" => s(i+1) := 'D'; + when x"E" => s(i+1) := 'E'; + when x"F" => s(i+1) := 'F'; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end HWRITE; + + procedure Char2TriBits(C: Character; + RESULT: out bit_vector(2 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := o"0"; good := TRUE; + when '1' => result := o"1"; good := TRUE; + when '2' => result := o"2"; good := TRUE; + when '3' => result := o"3"; good := TRUE; + when '4' => result := o"4"; good := TRUE; + when '5' => result := o"5"; good := TRUE; + when '6' => result := o"6"; good := TRUE; + when '7' => result := o"7"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)."; + end if; + good := FALSE; + end case; + end; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable c: character; + variable ok: boolean; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OREAD Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "OREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end OREAD; + + + procedure OWRITE(L:inout LINE; VALUE:in BIT_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable tri: bit_vector(0 to 2); + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OWRITE Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + for i in 0 to ne-1 loop + tri := bv(3*i to 3*i+2); + case tri is + when o"0" => s(i+1) := '0'; + when o"1" => s(i+1) := '1'; + when o"2" => s(i+1) := '2'; + when o"3" => s(i+1) := '3'; + when o"4" => s(i+1) := '4'; + when o"5" => s(i+1) := '5'; + when o"6" => s(i+1) := '6'; + when o"7" => s(i+1) := '7'; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end OWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := To_X01(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := To_X01(tmp); + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + HWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); + end HWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + HWRITE(L, To_bitvector(VALUE), JUSTIFIED, FIELD); + end HWRITE; + + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := To_X01(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := To_X01(tmp); + end OREAD; + + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + OWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); + end OWRITE; + + -- Octal Read and Write procedures for STD_LOGIC_VECTOR + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + OWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end OWRITE; + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; diff --git a/libraries/synopsys/std_logic_unsigned.vhdl b/libraries/synopsys/std_logic_unsigned.vhdl new file mode 100644 index 000000000..3e29847a8 --- /dev/null +++ b/libraries/synopsys/std_logic_unsigned.vhdl @@ -0,0 +1,329 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_UNSIGNED -- +-- -- +-- -- +-- Date: 09/11/92 KN -- +-- 10/08/92 AMT -- +-- -- +-- Purpose: -- +-- A set of unsigned arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: comparision of same length discrete arrays is defined -- +-- by the LRM. This package will "overload" those -- +-- definitions -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_UNSIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_UNSIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_UNSIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + UNSIGNED(L); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := UNSIGNED(L) * UNSIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return UNSIGNED(L) < UNSIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return UNSIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < UNSIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= UNSIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= UNSIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > UNSIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > UNSIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= UNSIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= UNSIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : UNSIGNED(ARG'range); + begin + result := UNSIGNED(ARG); + return CONV_INTEGER(result); + end; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + +-- remove this since it is already in std_logic_arith + --function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + --variable result1 : UNSIGNED (SIZE-1 downto 0); + --variable result2 : STD_LOGIC_VECTOR (SIZE-1 downto 0); + --begin + --result1 := CONV_UNSIGNED(ARG,SIZE); + --return std_logic_vector(result1); + --end; + + +end STD_LOGIC_UNSIGNED; + + diff --git a/libraries/vital2000/memory_b.vhdl b/libraries/vital2000/memory_b.vhdl new file mode 100644 index 000000000..0376ee4d3 --- /dev/null +++ b/libraries/vital2000/memory_b.vhdl @@ -0,0 +1,7151 @@ +-- ---------------------------------------------------------------------------- +-- Title : Standard VITAL Memory Package +-- : +-- Library : Vital_Memory +-- : +-- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 +-- : Ekambaram Balaji, LSI Logic Corporation +-- : Jose De Castro, Consultant +-- : Prakash Bare, GDA Technologies +-- : William Yam, LSI Logic Corporation +-- : Dennis Brophy, Model Technology +-- : +-- Purpose : This packages defines standard types, constants, functions +-- : and procedures for use in developing ASIC memory models. +-- : +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Ver:|Auth:| Date:| Changes Made: +-- 0.1 | eb |071796| First prototye as part of VITAL memory proposal +-- 0.2 | jdc |012897| Initial prototyping with proposed MTM scheme +-- 0.3 | jdc |090297| Extensive updates for TAG review (functional) +-- 0.4 | eb |091597| Changed naming conventions for VitalMemoryTable +-- | | | Added interface of VitalMemoryCrossPorts() & +-- | | | VitalMemoryViolation(). +-- 0.5 | jdc |092997| Completed naming changes thoughout package body. +-- | | | Testing with simgle port test model looks ok. +-- 0.6 | jdc |121797| Major updates to the packages: +-- | | | - Implement VitalMemoryCrossPorts() +-- | | | - Use new VitalAddressValueType +-- | | | - Use new VitalCrossPortModeType enum +-- | | | - Overloading without SamePort args +-- | | | - Honor erroneous address values +-- | | | - Honor ports disabled with 'Z' +-- | | | - Implement implicit read 'M' table symbol +-- | | | - Cleanup buses to use (H DOWNTO L) +-- | | | - Message control via MsgOn,HeaderMsg,PortName +-- | | | - Tested with 1P1RW,2P2RW,4P2R2W,4P4RW cases +-- 0.7 | jdc |052698| Bug fixes to the packages: +-- | | | - Fix failure with negative Address values +-- | | | - Added debug messages for VMT table search +-- | | | - Remove 'S' for action column (only 's') +-- | | | - Remove 's' for response column (only 'S') +-- | | | - Remove 'X' for action and response columns +-- 0.8 | jdc |061298| Implemented VitalMemoryViolation() +-- | | | - Minimal functionality violation tables +-- | | | - Missing: +-- | | | - Cannot handle wide violation variables +-- | | | - Cannot handle sub-word cases +-- | | | Fixed IIC version of MemoryMatch +-- | | | Fixed 'M' vs 'm' switched on debug output +-- | | | TO BE DONE: +-- | | | - Implement 'd' corrupting a single bit +-- | | | - Implement 'D' corrupting a single bit +-- 0.9 |eb/sc|080498| Added UNDEF value for VitalPortFlagType +-- 0.10|eb/sc|080798| Added CORRUPT value for VitalPortFlagType +-- 0.11|eb/sc|081798| Added overloaded function interface for +-- | | | VitalDeclareMemory +-- 0.14| jdc |113198| Merging of memory functionality and version +-- | | | 1.4 9/17/98 of timing package from Prakash +-- 0.15| jdc |120198| Major development of VMV functionality +-- 0.16| jdc |120298| Complete VMV functionlality for initial testing +-- | | | - New ViolationTableCorruptMask() procedure +-- | | | - New MemoryTableCorruptMask() procedure +-- | | | - HandleMemoryAction(): +-- | | | - Removed DataOutBus bogus output +-- | | | - Replaced DataOutTmp with DataInTmp +-- | | | - Added CorruptMask input handling +-- | | | - Implemented 'd','D' using CorruptMask +-- | | | - CorruptMask on 'd','C','L','D','E' +-- | | | - CorruptMask ignored on 'c','l','e' +-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT +-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT +-- | | | - Changed 'c','l','d','e' to ignore HighBit, LowBit +-- | | | - Changed 'C','L','D','E' to use HighBit, LowBit +-- | | | - HandleDataAction(): +-- | | | - Added CorruptMask input handling +-- | | | - Implemented 'd','D' using CorruptMask +-- | | | - CorruptMask on 'd','C','L','D','E' +-- | | | - CorruptMask ignored on 'l','e' +-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT +-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT +-- | | | - Changed 'l','d','e' to ignore HighBit, LowBit +-- | | | - Changed 'L','D','E' to use HighBit, LowBit +-- | | | - MemoryTableLookUp(): +-- | | | - Added MsgOn table debug output +-- | | | - Uses new MemoryTableCorruptMask() +-- | | | - ViolationTableLookUp(): +-- | | | - Uses new ViolationTableCorruptMask() +-- 0.17| jdc |120898| - Added VitalMemoryViolationSymbolType, +-- | | | VitalMemoryViolationTableType data +-- | | | types but not used yet (need to discuss) +-- | | | - Added overload for VitalMemoryViolation() +-- | | | which does not have array flags +-- | | | - Bug fixes for VMV functionality: +-- | | | - ViolationTableLookUp() not handling '-' in +-- | | | scalar violation matching +-- | | | - VitalMemoryViolation() now normalizes +-- | | | VFlagArrayTmp'LEFT as LSB before calling +-- | | | ViolationTableLookUp() for proper scanning +-- | | | - ViolationTableCorruptMask() had to remove +-- | | | normalization of CorruptMaskTmp and +-- | | | ViolMaskTmp for proper MSB:LSB corruption +-- | | | - HandleMemoryAction(), HandleDataAction() +-- | | | - Removed 'D','E' since not being used +-- | | | - Use XOR instead of OR for corrupt masks +-- | | | - Now 'd' is sensitive to HighBit, LowBit +-- | | | - Fixed LowBit overflow in bit writeable case +-- | | | - MemoryTableCorruptMask() +-- | | | - ViolationTableCorruptMask() +-- | | | - VitalMemoryTable() +-- | | | - VitalMemoryCrossPorts() +-- | | | - Fixed VitalMemoryViolation() failing on +-- | | | error AddressValue from earlier VMT() +-- | | | - Minor cleanup of code formatting +-- 0.18| jdc |032599| - In VitalDeclareMemory() +-- | | | - Added BinaryLoadFile formal arg and +-- | | | modified LoadMemory() to handle bin +-- | | | - Added NOCHANGE to VitalPortFlagType +-- | | | - For VitalCrossPortModeType +-- | | | - Added CpContention enum +-- | | | - In HandleDataAction() +-- | | | - Set PortFlag := NOCHANGE for 'S' +-- | | | - In HandleMemoryAction() +-- | | | - Set PortFlag := NOCHANGE for 's' +-- | | | - In VitalMemoryTable() and +-- | | | VitalMemoryViolation() +-- | | | - Honor PortFlag = NOCHANGE returned +-- | | | from HandleMemoryAction() +-- | | | - In VitalMemoryCrossPorts() +-- | | | - Fixed Address = AddressJ for all +-- | | | conditions of DoWrCont & DoCpRead +-- | | | - Handle CpContention like WrContOnly +-- | | | under CpReadOnly conditions, with +-- | | | associated memory message changes +-- | | | - Handle PortFlag = NOCHANGE like +-- | | | PortFlag = READ for actions +-- | | | - Modeling change: +-- | | | - Need to init PortFlag every delta +-- | | | PortFlag_A := (OTHES => UNDEF); +-- | | | - Updated InternalTimingCheck code +-- 0.19| jdc |042599| - Fixes for bit-writeable cases +-- | | | - Check PortFlag after HandleDataAction +-- | | | in VitalMemoryViolation() +-- 0.20| jdc |042599| - Merge PortFlag changes from Prakash +-- | | | and Willian: +-- | | | VitalMemorySchedulePathDelay() +-- | | | VitalMemoryExpandPortFlag() +-- 0.21| jdc |072199| - Changed VitalCrossPortModeType enums, +-- | | | added new CpReadAndReadContention. +-- | | | - Fixed VitalMemoryCrossPorts() parameter +-- | | | SamePortFlag to INOUT so that it can +-- | | | set CORRUPT or READ value. +-- | | | - Fixed VitalMemoryTable() where PortFlag +-- | | | setting by HandleDataAction() is being +-- | | | ignored when HandleMemoryAction() sets +-- | | | PortFlagTmp to NOCHANGE. +-- | | | - Fixed VitalMemoryViolation() to set +-- | | | all bits of PortFlag when violating. +-- 0.22| jdc |072399| - Added HIGHZ to PortFlagType. HandleData +-- | | | checks whether the previous state is HIGHZ. +-- | | | If yes then portFlag should be NOCHANGE +-- | | | for VMPD to ignore IORetain corruption. +-- | | | The idea is that the first Z should be +-- | | | propagated but later ones should be ignored. +-- | | | +-- 0.23| jdc |100499| - Took code checked in by Dennis 09/28/99 +-- | | | - Changed VitalPortFlagType to record of +-- | | | new VitalPortStateType to hold current, +-- | | | previous values and separate disable. +-- | | | Also created VitalDefaultPortFlag const. +-- | | | Removed usage of PortFlag NOCHANGE +-- | | | - VitalMemoryTable() changes: +-- | | | Optimized return when all curr = prev +-- | | | AddressValue is now INOUT to optimize +-- | | | Transfer PF.MemoryCurrent to MemoryPrevious +-- | | | Transfer PF.DataCurrent to DataPrevious +-- | | | Reset PF.OutputDisable to FALSE +-- | | | Expects PortFlag init in declaration +-- | | | No need to init PortFlag every delta +-- | | | - VitalMemorySchedulePathDelay() changes: +-- | | | Initialize with VitalDefaultPortFlag +-- | | | Check PortFlag.OutputDisable +-- | | | - HandleMemoryAction() changes: +-- | | | Set value of PortFlag.MemoryCurrent +-- | | | Never set PortFlag.OutputDisable +-- | | | - HandleDataAction() changes: +-- | | | Set value of PortFlag.DataCurrent +-- | | | Set PortFlag.DataCurrent for HIGHZ +-- | | | - VitalMemoryCrossPorts() changes: +-- | | | Check/set value of PF.MemoryCurrent +-- | | | Check value of PF.OutputDisable +-- | | | - VitalMemoryViolation() changes: +-- | | | Fixed bug - not reading inout PF value +-- | | | Clean up setting of PortFlag +-- 0.24| jdc |100899| - Modified update of PF.OutputDisable +-- | | | to correctly accomodate 2P1W1R case: +-- | | | the read port should not exhibit +-- | | | IO retain corrupt when reading +-- | | | addr unrelated to addr being written. +-- 0.25| jdc |100999| - VitalMemoryViolation() change: +-- | | | Fixed bug with RDNWR mode incorrectly +-- | | | updating the PF.OutputDisable +-- 0.26| jdc |100999| - VitalMemoryCrossPorts() change: +-- | | | Fixed bugs with update of PF +-- 0.27| jdc |101499| - VitalMemoryCrossPorts() change: +-- | | | Added DoRdWrCont message (ErrMcpRdWrCo, +-- | | | Memory cross port read/write data only +-- | | | contention) +-- | | | - VitalMemoryTable() change: +-- | | | Set PF.OutputDisable := TRUE for the +-- | | | optimized cases. +-- 0.28| pb |112399| - Added 8 VMPD procedures for vector +-- | | | PathCondition support. Now the total +-- | | | number of overloadings for VMPD is 24. +-- | | | - Number of overloadings for SetupHold +-- | | | procedures increased to 5. Scalar violations +-- | | | are not supported anymore. Vector checkEnabled +-- | | | support is provided through the new overloading +-- 0.29| jdc |120999| - HandleMemoryAction() HandleDataAction() +-- | | | Reinstated 'D' and 'E' actions but +-- | | | with new PortFlagType +-- | | | - Updated file handling syntax, must compile +-- | | | with -93 syntax now. +-- 0.30| jdc |022300| - Formated for 80 column max width +-- ---------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.Vital_Timing.all; +USE IEEE.Vital_Primitives.all; + +LIBRARY STD; +USE STD.TEXTIO.ALL; + +-- ---------------------------------------------------------------------------- +PACKAGE BODY Vital_Memory IS + +-- ---------------------------------------------------------------------------- +-- Timing Section +-- ---------------------------------------------------------------------------- + +FILE LogFile : TEXT OPEN write_mode IS "delayLog"; +FILE Output : TEXT OPEN write_mode IS "STD_OUTPUT"; + +-- Added for turning off the debug msg.. +CONSTANT PrintDebugMsg : STD_ULOGIC := '0'; + -- '0' - don't print in STD OUTPUT + -- '1' - print in STD OUTPUT + +-- Type and constant definitions for type conversion. +TYPE MVL9_TO_CHAR_TBL IS ARRAY (STD_ULOGIC) OF character; + +--constant MVL9_to_char: MVL9_TO_CHAR_TBL := "UX01ZWLH-"; +CONSTANT MVL9_to_char: MVL9_TO_CHAR_TBL := "XX01ZX010"; + +-- ---------------------------------------------------------------------------- +-- STD_LOGIC WRITE UTILITIES +-- ---------------------------------------------------------------------------- +PROCEDURE WRITE( + l : INOUT line; + val : IN std_logic_vector; + justify : IN side := right; + field : IN width := 0 +) IS + VARIABLE invect : std_logic_vector(val'LENGTH DOWNTO 1); + VARIABLE ins : STRING(val'LENGTH DOWNTO 1); +BEGIN + invect := val; + FOR I IN invect'length DOWNTO 1 LOOP + ins(I) := MVL9_to_char(invect(I)); + END LOOP; + WRITE(L, ins, justify, field); +END; + +PROCEDURE WRITE( + l : INOUT line; + val : IN std_ulogic; + justify : IN side := right; + field : in width := 0 +) IS + VARIABLE ins : CHARACTER; +BEGIN + ins := MVL9_to_char(val); + WRITE(L, ins, justify, field); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE DelayValue( + InputTime : IN TIME ; + outline : INOUT LINE +) IS + CONSTANT header : STRING := "TIME'HIGH"; +BEGIN + IF(InputTime = TIME'HIGH) THEN + WRITE(outline, header); + ELSE + WRITE(outline, InputTime); + END IF; +END DelayValue; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintScheduleDataArray ( + ScheduleDataArray : IN VitalMemoryScheduleDataVectorType +) IS + VARIABLE outline1 : LINE; + VARIABLE outline2 : LINE; + VARIABLE value : TIME; + CONSTANT empty : STRING := " "; + CONSTANT header1 : STRING := "i Age PropDly RetainDly"; + CONSTANT header2 : STRING := "i Sc.Value Output Lastvalue Sc.Time"; +BEGIN + WRITE (outline1, empty); + WRITE (outline1, NOW); + outline2 := outline1; + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITE (outline1, header1); + outline2 := outline1; + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + FOR i IN ScheduleDataArray'RANGE LOOP + WRITE (outline1, i ); + WRITE (outline1, empty); + DelayValue(ScheduleDataArray(i).InputAge, outline1); + WRITE (outline1, empty); + DelayValue(ScheduleDataArray(i).PropDelay, outline1); + WRITE (outline1, empty); + DelayValue(ScheduleDataArray(i).OutputRetainDelay, outline1); + outline2 := outline1; + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + END LOOP; + WRITE (outline1, header2); + outline2 := outline1; + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + FOR i IN ScheduleDataArray'RANGE LOOP + WRITE (outline1, i ); + WRITE (outline1, empty); + WRITE (outline1, ScheduleDataArray(i).ScheduleValue); + WRITE (outline1, empty); + WRITE (outline1, ScheduleDataArray(i).OutputData); + WRITE (outline1, empty); + WRITE (outline1, ScheduleDataArray(i).LastOutputValue ); + WRITE (outline1, empty); + DelayValue(ScheduleDataArray(i).ScheduleTime, outline1); + outline2 := outline1; + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + END LOOP; + WRITE (outline1, empty); + WRITE (outline2, empty); + WRITELINE (LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (Output, outline2); + END IF; +END PrintScheduleDataArray; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintArcType ( + ArcType : IN VitalMemoryArcType +) IS + VARIABLE outline1, outline2 : LINE; + CONSTANT empty : STRING := " "; + CONSTANT cross : STRING := "CrossArc"; + CONSTANT para : STRING := "ParallelArc"; + CONSTANT sub : STRING := "SubWordArc"; + CONSTANT Header1 : STRING := "Path considered @ "; + CONSTANT Header2 : STRING := " is "; +BEGIN + WRITELINE (LogFile, outline1); + WRITE (outline1, header1); + WRITE (outline1, NOW); + WRITE (outline1, empty); + WRITE (outline1, header2); + WRITE (outline1, empty); + case ArcType is + WHEN CrossArc => + WRITE (outline1, cross); + WHEN ParallelArc => + WRITE (outline1, para); + WHEN SubwordArc => + WRITE (outline1, sub); + END CASE; + outline2 := outline1 ; + -- Appears on STD OUT + IF (PrintDebugMsg = '1') THEN + WRITELINE (Output, outline1); + END IF; + WRITELINE (LogFile, outline2); +END PrintArcType; + +-- ---------------------------------------------------------------------------- +-- This returns the value picked from the delay array +-- ---------------------------------------------------------------------------- +PROCEDURE PrintDelay ( + outbitpos : IN INTEGER; + InputArrayLow : IN INTEGER; + InputArrayHigh : IN INTEGER; + debugprop : IN VitalTimeArrayT; + debugretain : IN VitalTimeArrayT +) IS + VARIABLE outline1 : LINE; + VARIABLE outline2 : LINE; + VARIABLE outline3 : LINE; + VARIABLE outline4 : LINE; + VARIABLE outline5 : LINE; + VARIABLE outline6 : LINE; + CONSTANT empty : STRING := " "; + CONSTANT empty5 : STRING := " "; + CONSTANT header1 : STRING := "Prop. delays : "; + CONSTANT header2 : STRING := "Retain delays : "; + CONSTANT header3 : STRING := "output bit : "; +BEGIN + WRITE(outline1, header3); + WRITE(outline1, outbitpos); + outline2 := outline1; + WRITELINE(LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE(output, outline2); + END IF; + WRITE(outline1, header1); + WRITE (outline1, empty5); + FOR i IN InputArrayHigh DOWNTO InputArrayLow LOOP + DelayValue(debugprop(i), outline1); + WRITE(outline1, empty); + END LOOP; + outline2 := outline1; + WRITELINE(LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE(output, outline2); + END IF; + WRITE(outline1, header2); + WRITE (outline1, empty5); + FOR i in InputArrayHigh DOWNTO InputArrayLow LOOP + DelayValue(debugretain(i), outline1); + WRITE(outline1, empty); + END LOOP; + outline2 := outline1; + WRITELINE(LogFile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE(output, outline2); + END IF; +END PrintDelay; + +-- ---------------------------------------------------------------------------- +PROCEDURE DebugMsg1 IS + CONSTANT header1:STRING:= "******************************************"; + CONSTANT header2 :STRING:="Entering the process because of an i/p change"; + variable outline1, outline2 : LINE; +BEGIN + WRITE(outline1, header1); + outline2 := outline1; + WRITELINE (Logfile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITE(outline1, header2); + outline2 := outline1; + WRITELINE (Logfile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITE(outline1, header1); + outline2 := outline1; + WRITELINE (Logfile, outline1); + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; +END DebugMsg1; + +-- ---------------------------------------------------------------------------- +PROCEDURE ScheduleDebugMsg IS + CONSTANT header1 : STRING := "******************************************"; + CONSTANT header2 : STRING := "Finished executing all the procedures"; + VARIABLE outline1 : LINE; + VARIABLE outline2 : LINE; +BEGIN + WRITE(outline1, header1); + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); + WRITE(outline1, header2); + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); + WRITE(outline1, header1); + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); +END ScheduleDebugMsg; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintInputName( + InputSignalName : IN STRING +) IS + VARIABLE outline1 : LINE; + VARIABLE outline2 : LINE; + CONSTANT header1 : STRING := "***Changing input is "; + CONSTANT header2 : STRING := "("; + CONSTANT header3 : STRING := ")"; + CONSTANT header4 : STRING := "****"; + CONSTANT header5 : STRING := "******************************************"; + CONSTANT header6 : STRING:="Entering the process because of an i/p change"; + CONSTANT empty : STRING := " "; +BEGIN + WRITE(outline1, header5); + outline2 := outline1; + WRITELINE (output, outline1); + WRITELINE (Logfile, outline2); + WRITE(outline1, header6); + outline2 := outline1; + WRITELINE (output, outline1); + WRITELINE (Logfile, outline2); + WRITE(outline1, header5); + outline2 := outline1; + WRITELINE (output, outline1); + WRITELINE (Logfile, outline2); + WRITE(outline1, header1); + WRITE(outline1, InputSignalName); + WRITE(outline1, empty); + WRITE(outline1, now); + WRITE(outline1, empty); + WRITE(outline1, header4); + WRITELINE (output, outline1); + WRITELINE (Logfile, outline2); +END PrintInputName; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintInputChangeTime( + ChangeTimeArray : IN VitalTimeArrayT +) IS + VARIABLE outline1 : LINE; + VARIABLE outline2 : LINE; + CONSTANT header5 : STRING := "*************************************"; + CONSTANT header6 : STRING:="ChangeTime Array : "; + CONSTANT empty : STRING := " "; +BEGIN + WRITE(outline1, header5); + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); + WRITE(outline1, header6); + FOR i in ChangeTimeArray'range LOOP + WRITE(outline1, ChangeTimeArray(i)); + WRITE(outline1, empty); + END LOOP; + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); + WRITE(outline1, header5); + outline2 := outline1; + IF (PrintDebugMsg = '1') THEN + WRITELINE (output, outline2); + END IF; + WRITELINE (Logfile, outline1); +END PrintInputChangeTime; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintInputChangeTime( + ChangeTime : IN Time +) IS + VARIABLE ChangeTimeArray : VitalTimeArrayT(0 DOWNTO 0); +BEGIN + ChangeTimeArray(0) := ChangeTime; + PrintInputChangeTime(ChangeTimeArray); +END PrintInputChangeTime; + +-- ---------------------------------------------------------------------------- +-- for debug purpose +CONSTANT MaxNoInputBits : INTEGER := 1000; + +TYPE VitalMemoryDelayType IS RECORD + PropDelay : TIME; + OutputRetainDelay : TIME; +END RECORD; + +-- ---------------------------------------------------------------------------- +-- PROCEDURE: IntToStr +-- +-- PARAMETERS: InputInt - Integer to be converted to String. +-- ResultStr - String buffer for converted Integer +-- AppendPos - Position in buffer to place result +-- +-- DESCRIPTION: This procedure is used to convert an input integer +-- into a string representation. The converted string +-- may be placed at a specific position in the result +-- buffer. +-- +-- ---------------------------------------------------------------------------- + +PROCEDURE IntToStr ( + InputInt : IN INTEGER ; + ResultStr : INOUT STRING ( 1 TO 256) ; + AppendPos : INOUT NATURAL +) IS + -- Look-up table. Given an int, we can get the character. + TYPE integer_table_type IS ARRAY (0 TO 9) OF CHARACTER ; + CONSTANT integer_table : integer_table_type := + ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ; + -- Local variables used in this function. + VARIABLE inpVal : INTEGER := inputInt ; + VARIABLE divisor : INTEGER := 10 ; + VARIABLE tmpStrIndex : INTEGER := 1 ; + VARIABLE tmpStr : STRING ( 1 TO 256 ) ; +BEGIN + IF ( inpVal = 0 ) THEN + tmpStr(tmpStrIndex) := integer_table ( 0 ) ; + tmpStrIndex := tmpStrIndex + 1 ; + ELSE + WHILE ( inpVal > 0 ) LOOP + tmpStr(tmpStrIndex) := integer_table (inpVal mod divisor); + tmpStrIndex := tmpStrIndex + 1 ; + inpVal := inpVal / divisor ; + END LOOP ; + END IF ; + IF (appendPos /= 1 ) THEN + resultStr(appendPos) := ',' ; + appendPos := appendPos + 1 ; + END IF ; + + FOR i IN tmpStrIndex-1 DOWNTO 1 LOOP + resultStr(appendPos) := tmpStr(i) ; + appendPos := appendPos + 1 ; + END LOOP ; +END IntToStr ; + +-- ---------------------------------------------------------------------------- +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 ) + ) + ); + +-- ---------------------------------------------------------------------------- +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 (t2); ELSE RETURN (t1); END IF; +END Maximum; + +-- ---------------------------------------------------------------------------- +-- FUNCTION: VitalMemoryCalcDelay +-- Description: Select Transition dependent Delay. +-- Used internally by VitalMemorySelectDelay. +-- ---------------------------------------------------------------------------- +FUNCTION VitalMemoryCalcDelay ( + CONSTANT NewVal : IN STD_ULOGIC := 'X'; + CONSTANT OldVal : IN STD_ULOGIC := 'X'; + CONSTANT Delay : IN VitalDelayType01ZX +) RETURN VitalMemoryDelayType IS + VARIABLE Result : VitalMemoryDelayType; +BEGIN + CASE Oldval IS + WHEN '0' | 'L' => + CASE Newval IS + WHEN '0' | 'L' => + Result.PropDelay := Delay(tr10); + WHEN '1' | 'H' => + Result.PropDelay := Delay(tr01); + WHEN 'Z' => + Result.PropDelay := Delay(tr0Z); + WHEN OTHERS => + Result.PropDelay := Minimum(Delay(tr01), Delay(tr0Z)); + END CASE; + Result.OutputRetainDelay := Delay(tr0X); + WHEN '1' | 'H' => + CASE Newval IS + WHEN '0' | 'L' => + Result.PropDelay := Delay(tr10); + WHEN '1' | 'H' => + Result.PropDelay := Delay(tr01); + WHEN 'Z' => + Result.PropDelay := Delay(tr1Z); + WHEN OTHERS => + Result.PropDelay := Minimum(Delay(tr10), Delay(tr1Z)); + END CASE; + Result.OutputRetainDelay := Delay(tr1X); + WHEN 'Z' => + CASE Newval IS + WHEN '0' | 'L' => + Result.PropDelay := Delay(trZ0); + WHEN '1' | 'H' => + Result.PropDelay := Delay(trZ1); + WHEN 'Z' => + Result.PropDelay := Maximum(Delay(tr1Z), Delay(tr0Z)); + WHEN OTHERS => + Result.PropDelay := Minimum(Delay(trZ1), Delay(trZ0)); + END CASE; + Result.OutputRetainDelay := Delay(trZX); + WHEN OTHERS => + CASE Newval IS + WHEN '0' | 'L' => + Result.PropDelay := Maximum(Delay(tr10), Delay(trZ0)); + WHEN '1' | 'H' => + Result.PropDelay := Maximum(Delay(tr01), Delay(trZ1)); + WHEN 'Z' => + Result.PropDelay := Maximum(Delay(tr1Z), Delay(tr0Z)); + WHEN OTHERS => + Result.PropDelay := Maximum(Delay(tr10), Delay(tr01)); + END CASE; + Result.OutputRetainDelay := Minimum(Delay(tr1X), Delay(tr0X)); + END CASE; + RETURN Result; +END VitalMemoryCalcDelay; + +-- ---------------------------------------------------------------------------- +FUNCTION VitalMemoryCalcDelay ( + CONSTANT NewVal : IN STD_ULOGIC := 'X'; + CONSTANT OldVal : IN STD_ULOGIC := 'X'; + CONSTANT Delay : IN VitalDelayType01Z +) RETURN VitalMemoryDelayType IS + VARIABLE Result : VitalMemoryDelayType; +BEGIN +CASE Oldval IS + WHEN '0' | 'L' => + CASE Newval IS + WHEN '0' | 'L' => Result.PropDelay := Delay(tr10); + WHEN '1' | 'H' => Result.PropDelay := Delay(tr01); + WHEN OTHERS => + Result.PropDelay := Minimum(Delay(tr01), Delay(tr10)); + END CASE; + Result.OutputRetainDelay := Delay(tr0Z); + WHEN '1' | 'H' => + CASE Newval IS + WHEN '0' | 'L' => Result.PropDelay := Delay(tr10); + WHEN '1' | 'H' => Result.PropDelay := Delay(tr01); + WHEN OTHERS => + Result.PropDelay := Minimum(Delay(tr10), Delay(tr01)); + END CASE; + Result.OutputRetainDelay := Delay(tr1Z); + WHEN OTHERS => + Result.PropDelay := Maximum(Delay(tr10),Delay(tr01)); + Result.OutputRetainDelay := Minimum(Delay(tr1Z),Delay(tr0Z)); + END CASE; + RETURN Result; +END VitalMemoryCalcDelay; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryUpdateInputChangeTime ( + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + VARIABLE NumBitsPerSubword : INTEGER +) IS + VARIABLE LastInputValue : STD_LOGIC_VECTOR(InputSignal'LENGTH-1 downto 0); + VARIABLE InSignalNorm : STD_LOGIC_VECTOR(InputSignal'LENGTH-1 downto 0); + VARIABLE ChangeTimeNorm : VitalTimeArrayT(InputSignal'LENGTH-1 downto 0); + VARIABLE BitsPerWord : INTEGER; +BEGIN + LastInputValue := InputSignal'LAST_VALUE; + IF NumBitsPerSubword = DefaultNumBitsPerSubword THEN + BitsPerWord := InputSignal'LENGTH; + ELSE + BitsPerWord := NumBitsPerSubword; + END IF; + + FOR i IN InSignalNorm'RANGE LOOP + IF (InSignalNorm(i) /= LastInputValue(i)) THEN + ChangeTimeNorm(i/BitsPerWord) := NOW - InputSignal'LAST_EVENT; + ELSE + ChangeTimeNorm(i/BitsPerWord) := InputChangeTimeArray(i); + END IF; + END LOOP; + + FOR i IN ChangeTimeNorm'RANGE LOOP + ChangeTimeNorm(i) := ChangeTimeNorm(i/BitsPerword); + END LOOP; + + InputChangeTimeArray := ChangeTimeNorm; + + -- for debug purpose only + PrintInputChangeTime(InputChangeTimeArray); +END VitalMemoryUpdateInputChangeTime; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryUpdateInputChangeTime +-- Description: Time since previous event for each bit of the input +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryUpdateInputChangeTime ( + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR +) IS + VARIABLE LastInputValue : STD_LOGIC_VECTOR(InputSignal'RANGE) ; +BEGIN + LastInputValue := InputSignal'LAST_VALUE; + FOR i IN InputSignal'RANGE LOOP + IF (InputSignal(i) /= LastInputValue(i)) THEN + InputChangeTimeArray(i) := NOW - InputSignal'LAST_EVENT; + END IF; + END LOOP; + -- for debug purpose only + PrintInputChangeTime(InputChangeTimeArray); +END VitalMemoryUpdateInputChangeTime; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryUpdateInputChangeTime ( + VARIABLE InputChangeTime : INOUT TIME; + SIGNAL InputSignal : IN STD_ULOGIC +) IS +BEGIN + InputChangeTime := NOW - InputSignal'LAST_EVENT; + -- for debug purpose only + PrintInputChangeTime(InputChangeTime); +END VitalMemoryUpdateInputChangeTime; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryExpandPortFlag ( + CONSTANT PortFlag : IN VitalPortFlagVectorType; + CONSTANT NumBitsPerSubword : IN INTEGER; + VARIABLE ExpandedPortFlag : OUT VitalPortFlagVectorType +) IS + VARIABLE PortFlagNorm : VitalPortFlagVectorType( + PortFlag'LENGTH-1 downto 0) := PortFlag; + VARIABLE ExpandedPortFlagNorm : VitalPortFlagVectorType( + ExpandedPortFlag'LENGTH-1 downto 0); + VARIABLE SubwordIndex : INTEGER; +BEGIN + FOR Index IN INTEGER RANGE 0 to ExpandedPortFlag'LENGTH-1 LOOP + IF NumBitsPerSubword = DefaultNumBitsPerSubword THEN + SubwordIndex := 0; + ELSE + SubwordIndex := Index / NumBitsPerSubword; + END IF; + ExpandedPortFlagNorm(Index) := PortFlagNorm(SubWordIndex); + END LOOP; + ExpandedPortFlag := ExpandedPortFlagNorm; +END VitalMemoryExpandPortFlag; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemorySelectDelay +-- Description : Select Propagation Delay. Used internally by +-- VitalMemoryAddPathDelay. +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- VitalDelayArrayType01ZX +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySelectDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE InputChangeTimeArray : IN VitalTimeArrayT; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN +) IS + VARIABLE InputArrayLow : INTEGER := 0; + VARIABLE InputArrayHigh : INTEGER := 0; + VARIABLE DelayArrayIndex : INTEGER := 0; + VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword; + VARIABLE NewValue : STD_ULOGIC; + VARIABLE OldValue : STD_ULOGIC; + VARIABLE OutputLength : INTEGER := 0; + VARIABLE OutArrayIndex : INTEGER; + VARIABLE PropDelay : TIME; + VARIABLE RetainDelay : TIME; + VARIABLE CurPropDelay : TIME; + VARIABLE CurRetainDelay : TIME; + VARIABLE InputAge : TIME; + VARIABLE CurInputAge : TIME; + VARIABLE InputChangeTimeNorm : VitalTimeArrayT( + InputChangeTimeArray'LENGTH-1 downto 0):=InputChangeTimeArray; + VARIABLE DelayArrayNorm : VitalDelayArrayType01ZX( + PathDelayArray'LENGTH-1 downto 0):= PathDelayArray; + VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType + (ScheduleDataArray'LENGTH-1 downto 0):= ScheduleDataArray; + + -- for debug purpose + VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0); + VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0); + +BEGIN + + -- for debug purpose + PrintArcType(ArcType); + + OutputLength := ScheduleDataArray'LENGTH; + FOR OutBitPos IN 0 to (OutputLength -1) LOOP + NEXT WHEN PathConditionArray(OutBitPos) = FALSE; + + NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue + = ScheduleDataArrayNorm(OutBitPos).OutputData) AND + (ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW) AND + (OutputRetainFlag = FALSE )); + + NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData; + OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue; + PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay; + InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge; + RetainDelay:=ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay; + NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord; + + CASE ArcType IS + WHEN ParallelArc => + InputArrayLow := OutBitPos; + InputArrayHigh := OutBitPos; + DelayArrayIndex := OutBitPos; + WHEN CrossArc => + InputArrayLow := 0; + InputArrayHigh := InputChangeTimeArray'LENGTH - 1 ; + DelayArrayIndex := OutBitPos; + WHEN SubwordArc => + InputArrayLow := OutBitPos / NumBitsPerSubWord; + InputArrayHigh := OutBitPos / NumBitsPerSubWord; + DelayArrayIndex := OutBitPos + + (OutputLength * (OutBitPos / NumBitsPerSubWord)); + END CASE; + + FOR i IN InputArrayLow TO InputArrayHigh LOOP + (CurPropDelay,CurRetainDelay) := + VitalMemoryCalcDelay ( + NewValue, OldValue, DelayArrayNorm(DelayArrayIndex) + ); + IF (OutputRetainFlag = FALSE) THEN + CurRetainDelay := TIME'HIGH; + END IF; + + -- for debug purpose + debugprop(i) := CurPropDelay; + debugretain(i) := CurRetainDelay; + + IF ArcType = CrossArc THEN + DelayArrayIndex := DelayArrayIndex + OutputLength; + END IF; + + -- If there is one input change at a time, then choose the + -- delay from that input. If there is simultaneous input + -- change, then choose the minimum of propagation delays + + IF (InputChangeTimeNorm(i) < 0 ns)THEN + CurInputAge := TIME'HIGH; + ELSE + CurInputAge := NOW - InputChangeTimeNorm(i); + END IF; + + IF (CurInputAge < InputAge)THEN + PropDelay := CurPropDelay; + RetainDelay := CurRetainDelay; + InputAge := CurInputAge; + ELSIF (CurInputAge = InputAge)THEN + IF (CurPropDelay < PropDelay) THEN + PropDelay := CurPropDelay; + END IF; + IF (OutputRetainFlag = TRUE) THEN + IF (CurRetainDelay < RetainDelay) THEN + RetainDelay := CurRetainDelay; + END IF; + END IF; + END IF; + END LOOP; + + -- Store it back to data strucutre + ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay; + ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay:= RetainDelay; + ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge; + + -- for debug purpose + PrintDelay(outbitPos,InputArrayLow, InputArrayHigh, + debugprop, debugretain); + END LOOP; + + ScheduleDataArray := ScheduleDataArrayNorm; + +END VitalMemorySelectDelay; + +-- ---------------------------------------------------------------------------- +-- VitalDelayArrayType01Z +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySelectDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE InputChangeTimeArray : IN VitalTimeArrayT; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN +) IS + VARIABLE InputArrayLow : INTEGER := 0; + VARIABLE InputArrayHigh : INTEGER := 0; + VARIABLE DelayArrayIndex : INTEGER := 0; + VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword; + VARIABLE NewValue : STD_ULOGIC; + VARIABLE OldValue : STD_ULOGIC; + VARIABLE OutputLength : INTEGER := 0; + VARIABLE OutArrayIndex : INTEGER; + VARIABLE PropDelay : TIME; + VARIABLE RetainDelay : TIME; + VARIABLE CurPropDelay : TIME; + VARIABLE CurRetainDelay : TIME; + VARIABLE InputAge : TIME; + VARIABLE CurInputAge : TIME; + VARIABLE InputChangeTimeNorm : VitalTimeArrayT( + InputChangeTimeArray'LENGTH-1 downto 0):=InputChangeTimeArray; + VARIABLE DelayArrayNorm : VitalDelayArrayType01Z( + PathDelayArray'LENGTH-1 downto 0):= PathDelayArray; + VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType + (ScheduleDataArray'LENGTH-1 downto 0):=ScheduleDataArray; + + -- for debug purpose + VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0); + VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0); +BEGIN + + -- for debug purpose + PrintArcType(ArcType); + + OutputLength := ScheduleDataArray'LENGTH; + FOR OutBitPos IN 0 to (OutputLength -1) LOOP + NEXT WHEN PathConditionArray(OutBitPos) = FALSE; + + NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue + = ScheduleDataArrayNorm(OutBitPos).OutputData) AND + (ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW) AND + (OutputRetainFlag = FALSE)); + + NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData; + OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue; + PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay; + InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge; + RetainDelay:=ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay; + NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord; + + CASE ArcType IS + WHEN ParallelArc => + InputArrayLow := OutBitPos; + InputArrayHigh := OutBitPos; + DelayArrayIndex := OutBitPos; + WHEN CrossArc => + InputArrayLow := 0; + InputArrayHigh := InputChangeTimeArray'LENGTH-1; + DelayArrayIndex := OutBitPos; + WHEN SubwordArc => + InputArrayLow := OutBitPos / NumBitsPerSubWord; + InputArrayHigh := OutBitPos / NumBitsPerSubWord; + DelayArrayIndex := OutBitPos + + (OutputLength * (OutBitPos / NumBitsPerSubWord)); + END CASE; + + FOR i IN InputArrayLow TO InputArrayHigh LOOP + (CurPropDelay, CurRetainDelay) := + VitalMemoryCalcDelay ( + NewValue, OldValue, DelayArrayNorm(DelayArrayIndex) + ); + IF (OutputRetainFlag = FALSE) THEN + CurRetainDelay := TIME'HIGH; + END IF; + + -- for debug purpose + debugprop(i) := CurPropDelay; + debugretain(i) := CurRetainDelay; + + IF (ArcType = CrossArc) THEN + DelayArrayIndex := DelayArrayIndex + OutputLength; + END IF; + + -- If there is one input change at a time, then choose the + -- delay from that input. If there is simultaneous input + -- change, then choose the minimum of propagation delays + + IF (InputChangeTimeNorm(i) < 0 ns) THEN + CurInputAge := TIME'HIGH; + ELSE + CurInputAge := NOW - InputChangeTimeNorm(i); + END IF; + + IF (CurInputAge < InputAge) THEN + PropDelay := CurPropDelay; + RetainDelay := CurRetainDelay; + InputAge := CurInputAge; + ELSIF (CurInputAge = InputAge) THEN + IF (CurPropDelay < PropDelay) THEN + PropDelay := CurPropDelay; + END IF; + IF (OutputRetainFlag = TRUE) THEN + IF (CurRetainDelay < RetainDelay) THEN + RetainDelay := CurRetainDelay; + END IF; + END IF; + END IF; + END LOOP; + + -- Store it back to data strucutre + ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay; + ScheduleDataArrayNorm(OutBitPos).OutputRetainDelay:= RetainDelay; + ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge; + + -- for debug purpose + PrintDelay(outbitPos, InputArrayLow, InputArrayHigh, + debugprop, debugretain); + END LOOP; + + ScheduleDataArray := ScheduleDataArrayNorm; + +END VitalMemorySelectDelay; + +-- ---------------------------------------------------------------------------- +-- VitalDelayArrayType01 +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySelectDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE InputChangeTimeArray : IN VitalTimeArrayT; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType; + CONSTANT PathConditionArray : IN VitalBoolArrayT +) IS + VARIABLE CurPathDelay : VitalMemoryDelayType; + VARIABLE InputArrayLow : INTEGER := 0; + VARIABLE InputArrayHigh : INTEGER := 0; + VARIABLE DelayArrayIndex : INTEGER := 0; + VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword; + VARIABLE NewValue : STD_ULOGIC; + VARIABLE OldValue : STD_ULOGIC; + VARIABLE OutputLength : INTEGER := 0; + VARIABLE OutArrayIndex : INTEGER; + VARIABLE PropDelay : TIME; + VARIABLE CurPropDelay : TIME; + VARIABLE InputAge : TIME; + VARIABLE CurInputAge : TIME; + VARIABLE InputChangeTimeNorm : VitalTimeArrayT( + InputChangeTimeArray'LENGTH-1 downto 0):= InputChangeTimeArray; + VARIABLE DelayArrayNorm : VitalDelayArrayType01( + PathDelayArray'LENGTH-1 downto 0):= PathDelayArray; + VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType + (ScheduleDataArray'LENGTH-1 downto 0):=ScheduleDataArray; + + -- for debug purpose + VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0); + VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0); +BEGIN + + -- for debug purpose + PrintArcType(ArcType); + + OutputLength := ScheduleDataArray'LENGTH; + FOR OutBitPos IN 0 to (OutputLength -1) LOOP + NEXT WHEN PathConditionArray(OutBitPos) = FALSE; + + NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue + = ScheduleDataArrayNorm(OutBitPos).OutputData) AND + (ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW)); + + NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData; + OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue; + PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay; + InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge; + NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord; + + CASE ArcType IS + WHEN ParallelArc => + InputArrayLow := OutBitPos; + InputArrayHigh := OutBitPos; + DelayArrayIndex := OutBitPos; + WHEN CrossArc => + InputArrayLow := 0; + InputArrayHigh := InputChangeTimeArray'LENGTH-1; + DelayArrayIndex := OutBitPos; + WHEN SubwordArc => + InputArrayLow := OutBitPos / NumBitsPerSubWord; + InputArrayHigh := OutBitPos / NumBitsPerSubWord; + DelayArrayIndex := OutBitPos + + (OutputLength * (OutBitPos / NumBitsPerSubWord)); + END CASE; + + FOR i IN InputArrayLow TO InputArrayHigh LOOP + CurPropDelay:= VitalCalcDelay (NewValue, + OldValue, DelayArrayNorm(DelayArrayIndex)); + + -- for debug purpose + debugprop(i) := CurPropDelay; + debugretain(i) := TIME'HIGH; + + IF (ArcType = CrossArc) THEN + DelayArrayIndex := DelayArrayIndex + OutputLength; + END IF; + + -- If there is one input change at a time, then choose the + -- delay from that input. If there is simultaneous input + -- change, then choose the minimum of propagation delays + + IF (InputChangeTimeNorm(i) < 0 ns) THEN + CurInputAge := TIME'HIGH; + ELSE + CurInputAge := NOW - InputChangeTimeNorm(i); + END IF; + IF (CurInputAge < InputAge) THEN + PropDelay := CurPropDelay; + InputAge := CurInputAge; + ELSIF (CurInputAge = InputAge) THEN + IF (CurPropDelay < PropDelay) THEN + PropDelay := CurPropDelay; + END IF; + END IF; + END LOOP; + + -- Store it back to data strucutre + ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay; + ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge; + + -- for debug purpose + PrintDelay(outbitPos, InputArrayLow, InputArrayHigh, + debugprop, debugretain); + END LOOP; + + ScheduleDataArray := ScheduleDataArrayNorm; + +END VitalMemorySelectDelay; + +-- ---------------------------------------------------------------------------- +-- VitalDelayArrayType +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySelectDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE InputChangeTimeArray : IN VitalTimeArrayT; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType; + CONSTANT PathConditionArray : IN VitalBoolArrayT +) IS + VARIABLE InputArrayLow : INTEGER := 0; + VARIABLE InputArrayHigh : INTEGER := 0; + VARIABLE DelayArrayIndex : INTEGER := 0; + VARIABLE NumBitsPerSubWord : INTEGER := DefaultNumBitsPerSubword; + VARIABLE NewValue : STD_ULOGIC; + VARIABLE OldValue : STD_ULOGIC; + VARIABLE OutputLength : INTEGER := 0; + VARIABLE OutArrayIndex : INTEGER; + VARIABLE PropDelay : TIME; + VARIABLE CurPropDelay : TIME; + VARIABLE InputAge : TIME; + VARIABLE CurInputAge : TIME; + VARIABLE InputChangeTimeNorm : VitalTimeArrayT( + InputChangeTimeArray'LENGTH-1 downto 0) := InputChangeTimeArray; + VARIABLE DelayArrayNorm : VitalDelayArrayType( + PathDelayArray'LENGTH-1 downto 0) := PathDelayArray; + VARIABLE ScheduleDataArrayNorm : VitalMemoryScheduleDatavectorType + (ScheduleDataArray'LENGTH-1 downto 0) := ScheduleDataArray; + + -- for debug purpose + VARIABLE debugprop : VitalTimeArrayT(MaxNoInputBits-1 downto 0); + VARIABLE debugretain : VitalTimeArrayT(MaxNoInputBits-1 downto 0); +BEGIN + + -- for debug purpose + PrintArcType(ArcType); + + OutputLength := ScheduleDataArray'LENGTH; + FOR OutBitPos IN 0 to (OutputLength -1) LOOP + NEXT WHEN PathConditionArray(OutBitPos) = FALSE; + + NEXT WHEN ((ScheduleDataArrayNorm(OutBitPos).ScheduleValue + = ScheduleDataArrayNorm(OutBitPos).OutputData) AND + (ScheduleDataArrayNorm(OutBitPos).ScheduleTime <= NOW)); + + NewValue := ScheduleDataArrayNorm(OutBitPos).OutputData; + OldValue := ScheduleDataArrayNorm(OutBitPos).LastOutputValue; + PropDelay :=ScheduleDataArrayNorm(OutBitPos).PropDelay; + InputAge := ScheduleDataArrayNorm(OutBitPos).InputAge; + NumBitsPerSubWord:=ScheduleDataArrayNorm(OutBitPos).NumBitsPerSubWord; + + CASE ArcType IS + WHEN ParallelArc => + InputArrayLow := OutBitPos; + InputArrayHigh := OutBitPos; + DelayArrayIndex := OutBitPos; + WHEN CrossArc => + InputArrayLow := 0; + InputArrayHigh := InputChangeTimeArray'LENGTH-1; + DelayArrayIndex := OutBitPos; + WHEN SubwordArc => + InputArrayLow := OutBitPos / NumBitsPerSubWord; + InputArrayHigh := OutBitPos / NumBitsPerSubWord; + DelayArrayIndex := OutBitPos + + (OutputLength * (OutBitPos / NumBitsPerSubWord)); + END CASE; + + FOR i IN InputArrayLow TO InputArrayHigh LOOP + CurPropDelay := VitalCalcDelay (NewValue, + OldValue, DelayArrayNorm(DelayArrayIndex)); + + -- for debug purpose + debugprop(i) := CurPropDelay; + debugretain(i) := TIME'HIGH; + + IF (ArcType = CrossArc) THEN + DelayArrayIndex := DelayArrayIndex + OutputLength; + END IF; + + -- If there is one input change at a time, then choose the + -- delay from that input. If there is simultaneous input + -- change, then choose the minimum of propagation delays + + IF (InputChangeTimeNorm(i) < 0 ns) THEN + CurInputAge := TIME'HIGH; + ELSE + CurInputAge := NOW - InputChangeTimeNorm(i); + END IF; + + IF (CurInputAge < InputAge) THEN + PropDelay := CurPropDelay; + InputAge := CurInputAge; + ELSIF (CurInputAge = InputAge) THEN + IF (CurPropDelay < PropDelay) THEN + PropDelay := CurPropDelay; + END IF; + END IF; + END LOOP; + + -- Store it back to data strucutre + ScheduleDataArrayNorm(OutBitPos).PropDelay := PropDelay; + ScheduleDataArrayNorm(OutBitPos).InputAge := InputAge; + + -- for debug purpose + PrintDelay(outbitPos, InputArrayLow, InputArrayHigh, + debugprop, debugretain); + END LOOP; + + ScheduleDataArray := ScheduleDataArrayNorm; + +END VitalMemorySelectDelay; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryInitPathDelay +-- Description: To initialize Schedule Data structure for an +-- output. +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryInitPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE OutputDataArray : IN STD_LOGIC_VECTOR; + CONSTANT NumBitsPerSubWord : IN INTEGER := DefaultNumBitsPerSubword +) IS +BEGIN + -- Initialize the ScheduleData Structure. + FOR i IN OutputDataArray'RANGE LOOP + ScheduleDataArray(i).OutputData := OutputDataArray(i); + ScheduleDataArray(i).PropDelay := TIME'HIGH; + ScheduleDataArray(i).OutputRetainDelay := TIME'HIGH; + ScheduleDataArray(i).InputAge := TIME'HIGH; + ScheduleDataArray(i).NumBitsPerSubWord := NumBitsPerSubWord; + + -- Update LastOutputValue of Output if the Output has + -- already been scheduled. + IF ((ScheduleDataArray(i).ScheduleValue /= OutputDataArray(i)) AND + (ScheduleDataArray(i).ScheduleTime <= NOW)) THEN + ScheduleDataArray(i).LastOutputValue + := ScheduleDataArray(i).ScheduleValue; + END IF; + END LOOP; + + -- for debug purpose + DebugMsg1; + PrintScheduleDataArray(ScheduleDataArray); + +END VitalMemoryInitPathDelay; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryInitPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + VARIABLE OutputData : IN STD_ULOGIC +) IS + VARIABLE ScheduledataArray: VitalMemoryScheduleDataVectorType + (0 downto 0); + VARIABLE OutputDataArray : STD_LOGIC_VECTOR(0 downto 0); +BEGIN + ScheduledataArray(0) := ScheduleData; + OutputDataArray(0) := OutputData; + VitalMemoryInitPathDelay ( + ScheduleDataArray => ScheduleDataArray, + OutputDataArray => OutputDataArray, + NumBitsPerSubWord => DefaultNumBitsPerSubword + ); + + -- for debug purpose + DebugMsg1; + PrintScheduleDataArray( ScheduleDataArray); + +END VitalMemoryInitPathDelay; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryAddPathDelay +-- Description: Declare a path for one scalar/vector input to +-- the output for which Schedule Data has been +-- initialized previously. +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- #1 +-- DelayType - VitalMemoryDelayType +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelay : IN VitalDelayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathDelayArray : VitalDelayArrayType(0 downto 0); + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + PathDelayArray(0) := PathDelay; + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #2 +-- DelayType - VitalMemoryDelayType +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray + ); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #3 +-- DelayType - VitalMemoryDelayType +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR Mem400 + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #4 +-- DelayType - VitalMemoryDelayType +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE ScheduleDataArray : VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + + ScheduleDataArray(0) := ScheduleData; + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #5 +-- DelayType - VitalMemoryDelayType +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #6 +-- DelayType - VitalMemoryDelayType +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT +) IS + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400; + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #7 +-- DelayType - VitalMemoryDelayType01 +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelay : IN VitalDelayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathDelayArray : VitalDelayArrayType01(0 downto 0); + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + PathDelayArray(0) := PathDelay; + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #8 +-- DelayType - VitalMemoryDelayType01 +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #9 +-- DelayType - VitalMemoryDelayType01 +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400; + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #10 +-- DelayType - VitalMemoryDelayType01 +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray: INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +)IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #11 +-- DelayType - VitalMemoryDelayType01 +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +) IS + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #12 +-- DelayType - VitalMemoryDelayType01 +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT +) IS + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400; + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #13 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelay : IN VitalDelayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathDelayArray : VitalDelayArrayType01Z(0 downto 0); + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + PathDelayArray(0) := PathDelay; + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #14 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); + +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #15 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0); + VARIABLE PathConditionArrayExp : VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #16 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + NumBitsPerSubword := ScheduleDataArray(0).NumBitsPerSubword; + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, + InputSignal, + NumBitsPerSubword + ); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #17 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword; + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, + InputSignal, + NumBitsPerSubword + ); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #18 +-- DelayType - VitalMemoryDelayType01Z +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS +VARIABLE NumBitsPerSubword : INTEGER; +VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0); +VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, InputSignal, + NumBitsPerSubword); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #19 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelay : IN VitalDelayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE PathDelayArray : VitalDelayArrayType01ZX(0 downto 0); + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + PathDelayArray(0) := PathDelay; + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #20 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray :INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #21 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray :INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTime : INOUT TIME; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +) IS + VARIABLE InputChangeTimeArray : VitalTimeArrayT(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400; + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + VitalMemoryUpdateInputChangeTime(InputChangeTime, InputSignal); + InputChangeTimeArray(0) := InputChangeTime; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #22 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS + VARIABLE ScheduleDataArray : + VitalMemoryScheduleDataVectorType(0 downto 0); + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArray : VitalBoolArrayT(0 downto 0); +BEGIN + PathConditionArray(0) := PathCondition; + ScheduleDataArray(0) := ScheduleData; + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword; + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, InputSignal, + NumBitsPerSubword); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #23 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArray : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + FOR i IN PathConditionArray'RANGE LOOP + PathConditionArray(i) := PathCondition; + END LOOP; + + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword; + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, InputSignal, + NumBitsPerSubword); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArray, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- #24 +-- DelayType - VitalMemoryDelayType01XZ +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +) IS + VARIABLE NumBitsPerSubword : INTEGER; + VARIABLE PathConditionArrayNorm : + VitalBoolArrayT(PathConditionArray'LENGTH-1 downto 0) := PathConditionArray; -- IR MEM400; + VARIABLE PathConditionArrayExp : + VitalBoolArrayT(ScheduleDataArray'LENGTH-1 downto 0); +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'RIGHT).NumBitsPerSubword; + FOR i IN PathConditionArrayExp'RANGE LOOP + PathConditionArrayExp(i) := PathConditionArrayNorm(i/NumBitsPerSubword); + END LOOP; + + IF (OutputRetainBehavior = WordCorrupt AND + ArcType = ParallelArc AND + OutputRetainFlag = TRUE) THEN + VitalMemoryUpdateInputChangeTime( + InputChangeTimeArray, InputSignal, + NumBitsPerSubword); + ELSE + VitalMemoryUpdateInputChangeTime(InputChangeTimeArray, InputSignal); + END IF; + + VitalMemorySelectDelay( + ScheduleDataArray, InputChangeTimeArray, + OutputSignalName, PathDelayArray, + ArcType, PathConditionArrayExp, OutputRetainFlag); +END VitalMemoryAddPathDelay; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemorySchedulePathDelay +-- Description: Schedule Output after Propagation Delay selected +-- by checking all the paths added thru' +-- VitalMemoryAddPathDelay. +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag; + CONSTANT OutputMap : IN VitalOutputMapType:= VitalDefaultOutputMap; + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType +) IS + VARIABLE Age : TIME; + VARIABLE PropDelay : TIME; + VARIABLE RetainDelay : TIME; + VARIABLE Data : STD_ULOGIC; +BEGIN + IF (PortFlag.OutputDisable /= TRUE) THEN + FOR i IN ScheduleDataArray'RANGE LOOP + PropDelay := ScheduleDataArray(i).PropDelay; + RetainDelay := ScheduleDataArray(i).OutputRetainDelay; + + NEXT WHEN PropDelay = TIME'HIGH; + + Age := ScheduleDataArray(i).InputAge; + Data := ScheduleDataArray(i).OutputData; + + IF (Age < RetainDelay and RetainDelay < PropDelay) THEN + OutSignal(i) <= TRANSPORT 'X' AFTER (RetainDelay - Age); + END IF; + + IF (Age <= PropDelay) THEN + OutSignal(i)<= TRANSPORT OutputMap(Data)AFTER (PropDelay-Age); + ScheduleDataArray(i).ScheduleValue := Data; + ScheduleDataArray(i).ScheduleTime := NOW + PropDelay - Age; + END IF; + END LOOP; + END IF; + + -- for debug purpose + PrintScheduleDataArray(ScheduleDataArray); + + -- for debug purpose + ScheduleDebugMsg; +END VitalMemorySchedulePathDelay; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemorySchedulePathDelay +-- Description: Schedule Output after Propagation Delay selected +-- by checking all the paths added thru' +-- VitalMemoryAddPathDelay. +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING :=""; + CONSTANT PortFlag : IN VitalPortFlagVectorType; + CONSTANT OutputMap : IN VitalOutputMapType:= VitalDefaultOutputMap; + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType +) IS + VARIABLE Age : TIME; + VARIABLE PropDelay : TIME; + VARIABLE RetainDelay : TIME; + VARIABLE Data : STD_ULOGIC; + VARIABLE ExpandedPortFlag : + VitalPortFlagVectorType(ScheduleDataArray'RANGE); + VARIABLE NumBitsPerSubword : INTEGER; +BEGIN + NumBitsPerSubword := + ScheduleDataArray(ScheduleDataArray'LEFT).NumBitsPerSubword; + VitalMemoryExpandPortFlag( PortFlag, NumBitsPerSubword, ExpandedPortFlag ); + FOR i IN ScheduleDataArray'RANGE LOOP + NEXT WHEN ExpandedPortFlag(i).OutputDisable = TRUE; + + PropDelay := ScheduleDataArray(i).PropDelay; + RetainDelay := ScheduleDataArray(i).OutputRetainDelay; + + NEXT WHEN PropDelay = TIME'HIGH; + + Age := ScheduleDataArray(i).InputAge; + Data := ScheduleDataArray(i).OutputData; + + IF (Age < RetainDelay and RetainDelay < PropDelay) THEN + OutSignal(i) <= TRANSPORT 'X' AFTER (RetainDelay - Age); + END IF; + + IF (Age <= PropDelay) THEN + OutSignal(i)<= TRANSPORT OutputMap(Data)AFTER (PropDelay-Age); + ScheduleDataArray(i).ScheduleValue := Data; + ScheduleDataArray(i).ScheduleTime := NOW + PropDelay - Age; + END IF; + END LOOP; + + -- for debug purpose + PrintScheduleDataArray(ScheduleDataArray); + + -- for debug purpose + ScheduleDebugMsg; +END VitalMemorySchedulePathDelay; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT STD_ULOGIC; + CONSTANT OutputSignalName: IN STRING :=""; + CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType +) IS + VARIABLE Age : TIME; + VARIABLE PropDelay : TIME; + VARIABLE RetainDelay : TIME; + VARIABLE Data : STD_ULOGIC; + VARIABLE ScheduleDataArray : VitalMemoryScheduleDataVectorType (0 downto 0); +BEGIN + IF (PortFlag.OutputDisable /= TRUE) THEN + ScheduledataArray(0) := ScheduleData; + PropDelay := ScheduleDataArray(0).PropDelay; + RetainDelay := ScheduleDataArray(0).OutputRetainDelay; + Age := ScheduleDataArray(0).InputAge; + Data := ScheduleDataArray(0).OutputData; + + IF (Age < RetainDelay and RetainDelay < PropDelay) THEN + OutSignal <= TRANSPORT 'X' AFTER (RetainDelay - Age); + END IF; + + IF (Age <= PropDelay and PropDelay /= TIME'HIGH) THEN + OutSignal <= TRANSPORT OutputMap(Data) AFTER (PropDelay - Age); + ScheduleDataArray(0).ScheduleValue := Data; + ScheduleDataArray(0).ScheduleTime := NOW + PropDelay - Age; + END IF; + END IF; + + -- for debug purpose + PrintScheduleDataArray(ScheduleDataArray); + + -- for debug purpose + ScheduleDebugMsg; + +END VitalMemorySchedulePathDelay; + +-- ---------------------------------------------------------------------------- +-- Procedure : InternalTimingCheck +-- ---------------------------------------------------------------------------- +PROCEDURE InternalTimingCheck ( + CONSTANT TestSignal : IN std_ulogic; + CONSTANT RefSignal : IN std_ulogic; + CONSTANT TestDelay : IN TIME := 0 ns; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + VARIABLE RefTime : IN TIME; + VARIABLE RefEdge : IN BOOLEAN; + VARIABLE TestTime : IN TIME; + VARIABLE TestEvent : IN BOOLEAN; + VARIABLE SetupEn : INOUT BOOLEAN; + VARIABLE HoldEn : INOUT BOOLEAN; + VARIABLE CheckInfo : INOUT CheckInfoType; + CONSTANT MsgOn : IN BOOLEAN +) IS + VARIABLE bias : TIME; + VARIABLE actualObsTime : TIME; + VARIABLE BC : TIME; + VARIABLE Message :LINE; +BEGIN + -- Check SETUP constraint + IF (RefEdge) THEN + IF (SetupEn) THEN + CheckInfo.ObsTime := RefTime - TestTime; + CheckInfo.State := To_X01(TestSignal); + CASE CheckInfo.State IS + WHEN '0' => + CheckInfo.ExpTime := SetupLow; + -- start of new code IR245-246 + BC := HoldHigh; + -- end of new code IR245-246 + WHEN '1' => + CheckInfo.ExpTime := SetupHigh; + -- start of new code IR245-246 + BC := HoldLow; + -- end of new code IR245-246 + WHEN 'X' => + CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); + -- start of new code IR245-246 + BC := Maximum(HoldHigh,HoldLow); + -- end of new code IR245-246 + END CASE; + -- added the second condition for IR 245-246 + CheckInfo.Violation := + ((CheckInfo.ObsTime < CheckInfo.ExpTime) + AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns)))); + -- start of new code IR245-246 + IF (CheckInfo.ExpTime = 0 ns) THEN + CheckInfo.CheckKind := HoldCheck; + ELSE + CheckInfo.CheckKind := SetupCheck; + END IF; + -- end of new code IR245-246 + SetupEn := FALSE; + ELSE + CheckInfo.Violation := FALSE; + END IF; + + -- Check HOLD constraint + ELSIF (TestEvent) THEN + IF HoldEn THEN + CheckInfo.ObsTime := TestTime - RefTime; + CheckInfo.State := To_X01(TestSignal); + CASE CheckInfo.State IS + WHEN '0' => + CheckInfo.ExpTime := HoldHigh; + -- new code for unnamed IR + CheckInfo.State := '1'; + -- start of new code IR245-246 + BC := SetupLow; + -- end of new code IR245-246 + WHEN '1' => + CheckInfo.ExpTime := HoldLow; + -- new code for unnamed IR + CheckInfo.State := '0'; + -- start of new code IR245-246 + BC := SetupHigh; + -- end of new code IR245-246 + WHEN 'X' => + CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); + -- start of new code IR245-246 + BC := Maximum(SetupHigh,SetupLow); + -- end of new code IR245-246 + END CASE; + -- added the second condition for IR 245-246 + CheckInfo.Violation := + ((CheckInfo.ObsTime < CheckInfo.ExpTime) + AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns)))); + -- start of new code IR245-246 + IF (CheckInfo.ExpTime = 0 ns) THEN + CheckInfo.CheckKind := SetupCheck; + ELSE + CheckInfo.CheckKind := HoldCheck; + END IF; + -- end of new code IR245-246 + HoldEn := NOT CheckInfo.Violation; + ELSE + CheckInfo.Violation := FALSE; + END IF; + ELSE + CheckInfo.Violation := FALSE; + END IF; + + -- Adjust report values to account for internal model delays + -- Note: TestDelay, RefDelay, TestTime, RefTime are non-negative + -- Note: bias may be negative or positive + IF MsgOn AND CheckInfo.Violation THEN + -- modified the code for correct reporting of violation in case of + -- order of signals being reversed because of internal delays + -- new variable + actualObsTime := (TestTime-TestDelay)-(RefTime-RefDelay); + bias := TestDelay - RefDelay; + IF (actualObsTime < 0 ns) THEN -- It should be a setup check + IF ( CheckInfo.CheckKind = HoldCheck) THEN + CheckInfo.CheckKind := SetupCheck; + CASE CheckInfo.State IS + WHEN '0' => CheckInfo.ExpTime := SetupLow; + WHEN '1' => CheckInfo.ExpTime := SetupHigh; + WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); + END CASE; + END IF; + CheckInfo.ObsTime := -actualObsTime; + CheckInfo.ExpTime := CheckInfo.ExpTime + bias; + CheckInfo.DetTime := RefTime - RefDelay; + ELSE -- It should be a hold check + IF (CheckInfo.CheckKind = SetupCheck) THEN + CheckInfo.CheckKind := HoldCheck; + CASE CheckInfo.State IS + WHEN '0' => + CheckInfo.ExpTime := HoldHigh; + CheckInfo.State := '1'; + WHEN '1' => + CheckInfo.ExpTime := HoldLow; + CheckInfo.State := '0'; + WHEN 'X' => + CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); + END CASE; + END IF; + CheckInfo.ObsTime := actualObsTime; + CheckInfo.ExpTime := CheckInfo.ExpTime - bias; + CheckInfo.DetTime := TestTime - TestDelay; + END IF; + END IF; +END InternalTimingCheck; + + +-- ---------------------------------------------------------------------------- +-- Setup and Hold Time Check Routine +-- ---------------------------------------------------------------------------- +PROCEDURE TimingArrayIndex ( + SIGNAL InputSignal : IN Std_logic_vector; + CONSTANT ArrayIndexNorm : IN INTEGER; + VARIABLE Index : OUT INTEGER +) IS +BEGIN + IF (InputSignal'LEFT > InputSignal'RIGHT) THEN + Index := ArrayIndexNorm + InputSignal'RIGHT; + ELSE + Index := InputSignal'RIGHT - ArrayIndexNorm; + END IF; +END TimingArrayIndex; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryReportViolation ( + 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 VitalMemoryReportViolation; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryReportViolation ( + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT TestArrayIndex : IN INTEGER; + CONSTANT RefArrayIndex : IN INTEGER; + SIGNAL TestSignal : IN std_logic_vector; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT CheckInfo : IN CheckInfoType; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) IS + VARIABLE Message : LINE; + VARIABLE i, j : INTEGER; +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 PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH ")); + WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") ); + WHEN OTHERS => Write ( Message, STRING'(" UNKNOWN ") ); + END CASE; + Write ( Message, HiLoStr(CheckInfo.State) ); + Write ( Message, STRING'(" VIOLATION ON ") ); + Write ( Message, TestSignalName ); + TimingArrayIndex(TestSignal, TestArrayIndex, i); + CASE MsgFormat IS + WHEN Scalar => + NULL; + WHEN VectorEnum => + Write ( Message, '_'); + Write ( Message, i); + WHEN Vector => + Write ( Message, '('); + Write ( Message, i); + Write ( Message, ')'); + END CASE; + + IF (RefSignalName'LENGTH > 0) THEN + Write ( Message, STRING'(" WITH RESPECT TO ") ); + Write ( Message, RefSignalName ); + END IF; + + IF(RefSignal'LENGTH > 0) THEN + TimingArrayIndex(RefSignal, RefArrayIndex, j); + CASE MsgFormat IS + WHEN Scalar => + NULL; + WHEN VectorEnum => + Write ( Message, '_'); + Write ( Message, j); + WHEN Vector => + Write ( Message, '('); + Write ( Message, j); + Write ( Message, ')'); + END CASE; + 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 VitalMemoryReportViolation; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryReportViolation ( + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT TestArrayIndex : IN INTEGER; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT CheckInfo : IN CheckInfoType; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + 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 PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH ")); + WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") ); + WHEN OTHERS => Write ( Message, STRING'(" UNKNOWN ") ); + END CASE; + + Write ( Message, HiLoStr(CheckInfo.State) ); + Write ( Message, STRING'(" VIOLATION ON ") ); + Write ( Message, TestSignalName ); + + CASE MsgFormat IS + WHEN Scalar => + NULL; + WHEN VectorEnum => + Write ( Message, '_'); + Write ( Message, TestArrayIndex); + WHEN Vector => + Write ( Message, '('); + Write ( Message, TestArrayIndex); + Write ( Message, ')'); + END CASE; + + 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 VitalMemoryReportViolation; + +-- ---------------------------------------------------------------------------- +FUNCTION VitalMemoryTimingDataInit +RETURN VitalMemoryTimingDataType IS +BEGIN + RETURN (FALSE, 'X', 0 ns, FALSE, 'X', 0 ns, FALSE, + NULL, NULL, NULL, NULL, NULL, NULL); +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalSetupHoldCheck +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + 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 VitalDelayType; + CONSTANT SetupLow : IN VitalDelayType; + CONSTANT HoldHigh : IN VitalDelayType; + CONSTANT HoldLow : IN VitalDelayType; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE CheckEnScalar : BOOLEAN := FALSE; + VARIABLE ViolationInt : X01ArrayT(CheckEnabled'RANGE); + VARIABLE RefEdge : BOOLEAN; + VARIABLE TestEvent : BOOLEAN; + VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; +BEGIN + + -- Initialization of working area. + 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.HoldEnA.all := (TestSignal'RANGE=>TRUE); + --IR252 3/23/98 + TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef; + TimingData.HoldEn := EnableHoldOnRef; + 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.SetupEn := EnableSetupOnTest ; --IR252 3/23/98 + TimingData.HoldEn := TimingData.HoldEn AND EnableHoldOnTest ; + --IR252 3/23/98 + TimingData.TestTime := NOW; + END IF; + + FOR i IN CheckEnabled'RANGE LOOP + IF CheckEnabled(i) = TRUE THEN + CheckEnScalar := TRUE; + END IF; + ViolationInt(i) := '0'; + END LOOP; + + IF (CheckEnScalar) 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 + VitalMemoryReportViolation (TestSignalName, RefSignalName, + HeaderMsg, CheckInfo, MsgSeverity ); + END IF; + IF (XOn) THEN + FOR i IN CheckEnabled'RANGE LOOP + IF CheckEnabled(i) = TRUE THEN + ViolationInt(i) := 'X'; + END IF; + END LOOP; + END IF; + END IF; + END IF; + Violation := ViolationInt; +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : BOOLEAN; + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; +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); + --IR252 3/23/98 + FOR i IN TestSignal'RANGE LOOP + TimingData.SetupEnA(i) + := TimingData.SetupEnA(i) AND EnableSetupOnRef; + TimingData.HoldEnA(i) := EnableHoldOnRef; + END LOOP; + 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.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98 + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ; + --IR252 3/23/98 + TimingData.TestTimeA(i) := NOW; + --TimingData.SetupEnA(i) := TRUE; + TimingData.TestTime := NOW; + END IF; + END LOOP; + + FOR i IN TestSignal'RANGE LOOP + Violation(i) := '0'; + + IF (CheckEnabled) THEN + TestDly := Maximum(0 ns, TestDelay(i)); + InternalTimingCheck ( + TestSignal => TestSignal(i), + RefSignal => RefSignal, + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHigh(i), + SetupLow => SetupLow(i), + HoldHigh => HoldHigh(i), + HoldLow => HoldLow(i), + 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 + VitalMemoryReportViolation (TestSignalName, RefSignalName, i , + HeaderMsg, CheckInfo, MsgFormat, MsgSeverity ); + END IF; + IF (XOn) THEN + Violation(i) := 'X'; + END IF; + END IF; + END IF; + END LOOP; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE ViolationInt : X01ArrayT(TestSignal'RANGE); + VARIABLE ViolationIntNorm: X01ArrayT(TestSignal'LENGTH-1 downto 0); + VARIABLE ViolationNorm : X01ArrayT(Violation'LENGTH-1 downto 0); + VARIABLE CheckEnInt : VitalBoolArrayT(TestSignal'RANGE); + VARIABLE CheckEnIntNorm : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0); + VARIABLE CheckEnScalar : BOOLEAN := FALSE; --Mem IR 401 + VARIABLE CheckEnabledNorm: VitalBoolArrayT(CheckEnabled'LENGTH-1 downto 0); + VARIABLE RefEdge : BOOLEAN; + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; +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); + --IR252 3/23/98 + FOR i IN TestSignal'RANGE LOOP + TimingData.SetupEnA(i) + := TimingData.SetupEnA(i) AND EnableSetupOnRef; + TimingData.HoldEnA(i) := EnableHoldOnRef; + END LOOP; + 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.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98 + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ; + --IR252 3/23/98 + TimingData.TestTimeA(i) := NOW; + --TimingData.SetupEnA(i) := TRUE; + TimingData.TestTime := NOW; + END IF; + END LOOP; + + IF ArcType = CrossArc THEN + CheckEnScalar := FALSE; + FOR i IN CheckEnabled'RANGE LOOP + IF CheckEnabled(i) = TRUE THEN + CheckEnScalar := TRUE; + END IF; + END LOOP; + FOR i IN CheckEnInt'RANGE LOOP + CheckEnInt(i) := CheckEnScalar; + END LOOP; + ELSE + FOR i IN CheckEnIntNorm'RANGE LOOP + CheckEnIntNorm(i) := CheckEnabledNorm(i / NumBitsPerSubWord ); + END LOOP; + CheckEnInt := CheckEnIntNorm; + END IF; + + FOR i IN TestSignal'RANGE LOOP + ViolationInt(i) := '0'; + + IF (CheckEnInt(i)) THEN + TestDly := Maximum(0 ns, TestDelay(i)); + InternalTimingCheck ( + TestSignal => TestSignal(i), + RefSignal => RefSignal, + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHigh(i), + SetupLow => SetupLow(i), + HoldHigh => HoldHigh(i), + HoldLow => HoldLow(i), + 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 + VitalMemoryReportViolation (TestSignalName, RefSignalName, i , + HeaderMsg, CheckInfo, MsgFormat, MsgSeverity ); + END IF; + IF (XOn) THEN + ViolationInt(i) := 'X'; + END IF; + END IF; + END IF; + END LOOP; + + IF (ViolationInt'LENGTH = Violation'LENGTH) THEN + Violation := ViolationInt; + ELSE + ViolationIntNorm := ViolationInt; + FOR i IN ViolationNorm'RANGE LOOP + ViolationNorm(i) := '0'; + END LOOP; + FOR i IN ViolationIntNorm'RANGE LOOP + IF (ViolationIntNorm(i) = 'X') THEN + ViolationNorm(i / NumBitsPerSubWord) := 'X'; + END IF; + END LOOP; + Violation := ViolationNorm; + END IF; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArraytype; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0); + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME; + VARIABLE bias : TIME; + VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH; + VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH; + VARIABLE NumChecks : NATURAL; + + VARIABLE ViolationTest : X01ArrayT(NumTestBits-1 downto 0); + VARIABLE ViolationRef : X01ArrayT(NumRefBits-1 downto 0); + + VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0) + := TestSignal; + VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0) + := TestDelay; + VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0) + := RefSignal; + VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0) + := RefDelay; + VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0) + := SetupHigh; + VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0) + := SetupLow; + VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0) + := HoldHigh; + VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0) + := HoldLow; + + VARIABLE RefBitLow : NATURAL; + VARIABLE RefBitHigh : NATURAL; + VARIABLE EnArrayIndex : NATURAL; + VARIABLE TimingArrayIndex: NATURAL; +BEGIN + + -- Initialization of working area. + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0); + TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0); + TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0); + TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0); + IF (ArcType = CrossArc) THEN + NumChecks := RefSignal'LENGTH * TestSignal'LENGTH; + ELSE + NumChecks := TestSignal'LENGTH; + END IF; + TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + + FOR i IN TestSignalNorm'RANGE LOOP + TimingData.TestLastA(i) := To_X01(TestSignalNorm(i)); + END LOOP; + + FOR i IN RefSignalNorm'RANGE LOOP + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + END LOOP; + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + FOR i IN RefSignalNorm'RANGE LOOP + RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i), + To_X01(RefSignalNorm(i)), RefTransition); + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + IF (RefEdge(i)) THEN + TimingData.RefTimeA(i) := NOW; + END IF; + END LOOP; + + -- Detect test (data) changes and record the time of the last change + FOR i IN TestSignalNorm'RANGE LOOP + TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i)); + TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i)); + IF (TestEvent(i)) THEN + TimingData.TestTimeA(i) := NOW; + END IF; + END LOOP; + + FOR i IN ViolationTest'RANGE LOOP + ViolationTest(i) := '0'; + END LOOP; + FOR i IN ViolationRef'RANGE LOOP + ViolationRef(i) := '0'; + END LOOP; + + FOR i IN TestSignalNorm'RANGE LOOP + IF (ArcType = CrossArc) THEN + FOR j IN RefSignalNorm'RANGE LOOP + IF (TestEvent(i)) THEN + --TimingData.SetupEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest; + TimingData.HoldEnA(i*NumRefBits+j) + := TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest; + END IF; + IF (RefEdge(j)) THEN + --TimingData.HoldEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef; + TimingData.SetupEnA(i*NumRefBits+j) + := TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef; + END IF; + END LOOP; + RefBitLow := 0; + RefBitHigh := NumRefBits-1; + TimingArrayIndex := i; + ELSE + IF ArcType = SubwordArc THEN + RefBitLow := i / NumBitsPerSubWord; + TimingArrayIndex := i + NumTestBits * RefBitLow; + ELSE + RefBitLow := i; + TimingArrayIndex := i; + END IF; + RefBitHigh := RefBitLow; + IF TestEvent(i) THEN + --TimingData.SetupEnA(i) := TRUE; + --IR252 + TimingData.SetupEnA(i) := EnableSetupOnTest; + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest; + END IF; + IF RefEdge(RefBitLow) THEN + --TimingData.HoldEnA(i) := TRUE; + --IR252 + TimingData.HoldEnA(i) := EnableHoldOnRef; + TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef; + END IF; + END IF; + + EnArrayIndex := i; + FOR j IN RefBitLow to RefBitHigh LOOP + + IF (CheckEnabled) THEN + TestDly := Maximum(0 ns, TestDelayNorm(i)); + RefDly := Maximum(0 ns, RefDelayNorm(j)); + + InternalTimingCheck ( + TestSignal => TestSignalNorm(i), + RefSignal => RefSignalNorm(j), + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHighNorm(TimingArrayIndex), + SetupLow => SetupLowNorm(TimingArrayIndex), + HoldHigh => HoldHighNorm(TimingArrayIndex), + HoldLow => HoldLowNorm(TimingArrayIndex), + RefTime => TimingData.RefTimeA(j), + RefEdge => RefEdge(j), + TestTime => TimingData.TestTimeA(i), + TestEvent => TestEvent(i), + SetupEn => TimingData.SetupEnA(EnArrayIndex), + HoldEn => TimingData.HoldEnA(EnArrayIndex), + CheckInfo => CheckInfo, + MsgOn => MsgOn + ); + + -- Report any detected violations and set return violation flag + IF (CheckInfo.Violation) THEN + IF (MsgOn) THEN + VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j, + TestSignal, RefSignal, HeaderMsg, CheckInfo, + MsgFormat, MsgSeverity ); + END IF; + IF (XOn) THEN + ViolationTest(i) := 'X'; + ViolationRef(j) := 'X'; + END IF; + END IF; + END IF; + + TimingArrayIndex := TimingArrayIndex + NumRefBits; + EnArrayIndex := EnArrayIndex + NumRefBits; + + END LOOP; + END LOOP; + + IF (ArcType = CrossArc) THEN + Violation := ViolationRef; + ELSE + IF (Violation'LENGTH = ViolationRef'LENGTH) THEN + Violation := ViolationRef; + ELSE + Violation := ViolationTest; + END IF; + END IF; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArraytype; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0); + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME; + VARIABLE bias : TIME; + VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH; + VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH; + VARIABLE NumChecks : NATURAL; + + VARIABLE ViolationTest : X01ArrayT(NumTestBits-1 downto 0); + VARIABLE ViolationRef : X01ArrayT(NumRefBits-1 downto 0); + + VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0) + := TestSignal; + VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0) + := TestDelay; + VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0) + := RefSignal; + VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0) + := RefDelay; + VARIABLE CheckEnNorm : VitalBoolArrayT(NumRefBits-1 downto 0) + := CheckEnabled; + VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0) + := SetupHigh; + VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0) + := SetupLow; + VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0) + := HoldHigh; + VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0) + := HoldLow; + + VARIABLE RefBitLow : NATURAL; + VARIABLE RefBitHigh : NATURAL; + VARIABLE EnArrayIndex : NATURAL; + VARIABLE TimingArrayIndex: NATURAL; +BEGIN + + -- Initialization of working area. + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0); + TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0); + TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0); + TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0); + IF ArcType = CrossArc THEN + NumChecks := RefSignal'LENGTH * TestSignal'LENGTH; + ELSE + NumChecks := TestSignal'LENGTH; + END IF; + TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + + FOR i IN TestSignalNorm'RANGE LOOP + TimingData.TestLastA(i) := To_X01(TestSignalNorm(i)); + END LOOP; + + FOR i IN RefSignalNorm'RANGE LOOP + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + END LOOP; + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + FOR i IN RefSignalNorm'RANGE LOOP + RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i), + To_X01(RefSignalNorm(i)), RefTransition); + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + IF RefEdge(i) THEN + TimingData.RefTimeA(i) := NOW; + END IF; + END LOOP; + + -- Detect test (data) changes and record the time of the last change + FOR i IN TestSignalNorm'RANGE LOOP + TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i)); + TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i)); + IF TestEvent(i) THEN + TimingData.TestTimeA(i) := NOW; + END IF; + END LOOP; + + FOR i IN ViolationTest'RANGE LOOP + ViolationTest(i) := '0'; + END LOOP; + FOR i IN ViolationRef'RANGE LOOP + ViolationRef(i) := '0'; + END LOOP; + + FOR i IN TestSignalNorm'RANGE LOOP + IF (ArcType = CrossArc) THEN + FOR j IN RefSignalNorm'RANGE LOOP + IF (TestEvent(i)) THEN + --TimingData.SetupEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest; + TimingData.HoldEnA(i*NumRefBits+j) + := TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest; + END IF; + IF (RefEdge(j)) THEN + --TimingData.HoldEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef; + TimingData.SetupEnA(i*NumRefBits+j) + := TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef; + END IF; + END LOOP; + RefBitLow := 0; + RefBitHigh := NumRefBits-1; + TimingArrayIndex := i; + ELSE + IF (ArcType = SubwordArc) THEN + RefBitLow := i / NumBitsPerSubWord; + TimingArrayIndex := i + NumTestBits * RefBitLow; + ELSE + RefBitLow := i; + TimingArrayIndex := i; + END IF; + RefBitHigh := RefBitLow; + IF (TestEvent(i)) THEN + --TimingData.SetupEnA(i) := TRUE; + --IR252 + TimingData.SetupEnA(i) := EnableSetupOnTest; + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest; + END IF; + IF (RefEdge(RefBitLow)) THEN + --TimingData.HoldEnA(i) := TRUE; + --IR252 + TimingData.HoldEnA(i) := EnableHoldOnRef; + TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef; + END IF; + END IF; + + EnArrayIndex := i; + FOR j IN RefBitLow to RefBitHigh LOOP + IF (CheckEnNorm(j)) THEN + TestDly := Maximum(0 ns, TestDelayNorm(i)); + RefDly := Maximum(0 ns, RefDelayNorm(j)); + + InternalTimingCheck ( + TestSignal => TestSignalNorm(i), + RefSignal => RefSignalNorm(j), + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHighNorm(TimingArrayIndex), + SetupLow => SetupLowNorm(TimingArrayIndex), + HoldHigh => HoldHighNorm(TimingArrayIndex), + HoldLow => HoldLowNorm(TimingArrayIndex), + RefTime => TimingData.RefTimeA(j), + RefEdge => RefEdge(j), + TestTime => TimingData.TestTimeA(i), + TestEvent => TestEvent(i), + SetupEn => TimingData.SetupEnA(EnArrayIndex), + HoldEn => TimingData.HoldEnA(EnArrayIndex), + CheckInfo => CheckInfo, + MsgOn => MsgOn + ); + + -- Report any detected violations and set return violation flag + IF (CheckInfo.Violation) THEN + IF (MsgOn) THEN + VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j, + TestSignal, RefSignal, HeaderMsg, CheckInfo, + MsgFormat, MsgSeverity ); + END IF; + + IF (XOn) THEN + ViolationTest(i) := 'X'; + ViolationRef(j) := 'X'; + END IF; + END IF; + END IF; + + TimingArrayIndex := TimingArrayIndex + NumRefBits; + EnArrayIndex := EnArrayIndex + NumRefBits; + END LOOP; + END LOOP; + + IF (ArcType = CrossArc) THEN + Violation := ViolationRef; + ELSE + IF (Violation'LENGTH = ViolationRef'LENGTH) THEN + Violation := ViolationRef; + ELSE + Violation := ViolationTest; + END IF; + END IF; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +-- scalar violations not needed +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : BOOLEAN; + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; + +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); + --IR252 3/23/98 + FOR i IN TestSignal'RANGE LOOP + TimingData.SetupEnA(i) + := TimingData.SetupEnA(i) AND EnableSetupOnRef; + TimingData.HoldEnA(i) := EnableHoldOnRef; + END LOOP; + 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.SetupEnA(i) := EnableSetupOnTest ; --IR252 3/23/98 + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest ; + --IR252 3/23/98 + TimingData.TestTimeA(i) := NOW; + --TimingData.SetupEnA(i) := TRUE; + TimingData.TestTime := NOW; + END IF; + END LOOP; + + Violation := '0'; + FOR i IN TestSignal'RANGE LOOP + IF (CheckEnabled) THEN + TestDly := Maximum(0 ns, TestDelay(i)); + InternalTimingCheck ( + TestSignal => TestSignal(i), + RefSignal => RefSignal, + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHigh(i), + SetupLow => SetupLow(i), + HoldHigh => HoldHigh(i), + HoldLow => HoldLow(i), + 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 + VitalMemoryReportViolation (TestSignalName, RefSignalName, i , + HeaderMsg, CheckInfo, MsgFormat, MsgSeverity ); + END IF; + IF (XOn) THEN + Violation := 'X'; + END IF; + END IF; + END IF; + END LOOP; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArraytype; + CONSTANT SetupHigh : IN VitalDelayArraytype; + CONSTANT SetupLow : IN VitalDelayArraytype; + CONSTANT HoldHigh : IN VitalDelayArraytype; + CONSTANT HoldLow : IN VitalDelayArraytype; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + --IR252 3/23/98 + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : VitalBoolArrayT(RefSignal'LENGTH-1 downto 0); + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'LENGTH-1 downto 0); + VARIABLE TestDly : TIME; + VARIABLE RefDly : TIME; + VARIABLE bias : TIME; + VARIABLE NumTestBits : NATURAL := TestSignal'LENGTH; + VARIABLE NumRefBits : NATURAL := RefSignal'LENGTH; + VARIABLE NumChecks : NATURAL; + + VARIABLE TestSignalNorm : std_logic_vector(NumTestBits-1 downto 0) + := TestSignal; + VARIABLE TestDelayNorm : VitalDelayArraytype(NumTestBits-1 downto 0) + := TestDelay; + VARIABLE RefSignalNorm : std_logic_vector(NumRefBits-1 downto 0) + := RefSignal; + VARIABLE RefDelayNorm : VitalDelayArraytype(NumRefBits-1 downto 0) + := RefDelay; + VARIABLE SetupHighNorm : VitalDelayArraytype(SetupHigh'LENGTH-1 downto 0) + := SetupHigh; + VARIABLE SetupLowNorm : VitalDelayArraytype(SetupLow'LENGTH-1 downto 0) + := SetupLow; + VARIABLE HoldHighNorm : VitalDelayArraytype(HoldHigh'LENGTH-1 downto 0) + := HoldHigh; + VARIABLE HoldLowNorm : VitalDelayArraytype(HoldLow'LENGTH-1 downto 0) + := HoldLow; + + VARIABLE RefBitLow : NATURAL; + VARIABLE RefBitHigh : NATURAL; + VARIABLE EnArrayIndex : NATURAL; + VARIABLE TimingArrayIndex: NATURAL; +BEGIN + + -- Initialization of working area. + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLastA := NEW std_logic_vector(NumTestBits-1 downto 0); + TimingData.TestTimeA := NEW VitalTimeArrayT(NumTestBits-1 downto 0); + TimingData.RefTimeA := NEW VitalTimeArrayT(NumRefBits-1 downto 0); + TimingData.RefLastA := NEW X01ArrayT(NumRefBits-1 downto 0); + IF (ArcType = CrossArc) THEN + NumChecks := RefSignal'LENGTH * TestSignal'LENGTH; + ELSE + NumChecks := TestSignal'LENGTH; + END IF; + TimingData.HoldEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + TimingData.SetupEnA := NEW VitalBoolArrayT(NumChecks-1 downto 0); + + FOR i IN TestSignalNorm'RANGE LOOP + TimingData.TestLastA(i) := To_X01(TestSignalNorm(i)); + END LOOP; + + FOR i IN RefSignalNorm'RANGE LOOP + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + END LOOP; + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + FOR i IN RefSignalNorm'RANGE LOOP + RefEdge(i) := EdgeSymbolMatch(TimingData.RefLastA(i), + To_X01(RefSignalNorm(i)), RefTransition); + TimingData.RefLastA(i) := To_X01(RefSignalNorm(i)); + IF (RefEdge(i)) THEN + TimingData.RefTimeA(i) := NOW; + END IF; + END LOOP; + + -- Detect test (data) changes and record the time of the last change + FOR i IN TestSignalNorm'RANGE LOOP + TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignalNorm(i)); + TimingData.TestLastA(i) := To_X01Z(TestSignalNorm(i)); + IF (TestEvent(i)) THEN + TimingData.TestTimeA(i) := NOW; + END IF; + END LOOP; + + FOR i IN TestSignalNorm'RANGE LOOP + IF (ArcType = CrossArc) THEN + FOR j IN RefSignalNorm'RANGE LOOP + IF (TestEvent(i)) THEN + --TimingData.SetupEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.SetupEnA(i*NumRefBits+j) := EnableSetupOnTest; + TimingData.HoldEnA(i*NumRefBits+j) + := TimingData.HoldEnA(i*NumRefBits+j) AND EnableHoldOnTest; + END IF; + IF (RefEdge(j)) THEN + --TimingData.HoldEnA(i*NumRefBits+j) := TRUE; + --IR252 + TimingData.HoldEnA(i*NumRefBits+j) := EnableHoldOnRef; + TimingData.SetupEnA(i*NumRefBits+j) + := TimingData.SetupEnA(i*NumRefBits+j) AND EnableSetupOnRef; + END IF; + END LOOP; + RefBitLow := 0; + RefBitHigh := NumRefBits-1; + TimingArrayIndex := i; + ELSE + IF (ArcType = SubwordArc) THEN + RefBitLow := i / NumBitsPerSubWord; + TimingArrayIndex := i + NumTestBits * RefBitLow; + ELSE + RefBitLow := i; + TimingArrayIndex := i; + END IF; + RefBitHigh := RefBitLow; + IF (TestEvent(i)) THEN + --TimingData.SetupEnA(i) := TRUE; + --IR252 + TimingData.SetupEnA(i) := EnableSetupOnTest; + TimingData.HoldEnA(i) := TimingData.HoldEnA(i) AND EnableHoldOnTest; + END IF; + IF (RefEdge(RefBitLow)) THEN + --TimingData.HoldEnA(i) := TRUE; + --IR252 + TimingData.HoldEnA(i) := EnableHoldOnRef; + TimingData.SetupEnA(i) := TimingData.SetupEnA(i) AND EnableSetupOnRef; + END IF; + END IF; + + EnArrayIndex := i; + Violation := '0'; + FOR j IN RefBitLow to RefBitHigh LOOP + + IF (CheckEnabled) THEN + TestDly := Maximum(0 ns, TestDelayNorm(i)); + RefDly := Maximum(0 ns, RefDelayNorm(j)); + + InternalTimingCheck ( + TestSignal => TestSignalNorm(i), + RefSignal => RefSignalNorm(j), + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHighNorm(TimingArrayIndex), + SetupLow => SetupLowNorm(TimingArrayIndex), + HoldHigh => HoldHighNorm(TimingArrayIndex), + HoldLow => HoldLowNorm(TimingArrayIndex), + RefTime => TimingData.RefTimeA(j), + RefEdge => RefEdge(j), + TestTime => TimingData.TestTimeA(i), + TestEvent => TestEvent(i), + SetupEn => TimingData.SetupEnA(EnArrayIndex), + HoldEn => TimingData.HoldEnA(EnArrayIndex), + CheckInfo => CheckInfo, + MsgOn => MsgOn + ); + + -- Report any detected violations and set return violation flag + IF (CheckInfo.Violation) THEN + IF (MsgOn) THEN + VitalMemoryReportViolation (TestSignalName, RefSignalName, i, j, + TestSignal, RefSignal, HeaderMsg, CheckInfo, + MsgFormat, MsgSeverity ); + END IF; + + IF (XOn) THEN + Violation := 'X'; + END IF; + END IF; + END IF; + + TimingArrayIndex := TimingArrayIndex + NumRefBits; + EnArrayIndex := EnArrayIndex + NumRefBits; + + END LOOP; + END LOOP; + +END VitalMemorySetupHoldCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryPeriodPulseCheck ( + VARIABLE Violation : OUT X01; + VARIABLE PeriodData : INOUT VitalPeriodDataArrayType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + CONSTANT Period : IN VitalDelayArraytype; + CONSTANT PulseWidthHigh : IN VitalDelayArraytype; + CONSTANT PulseWidthLow : IN VitalDelayArraytype; + 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; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType +) IS + VARIABLE TestDly : VitalDelayType; + VARIABLE CheckInfo : CheckInfoType; + VARIABLE PeriodObs : VitalDelayType; + VARIABLE PulseTest : BOOLEAN; + VARIABLE PeriodTest: BOOLEAN; + VARIABLE TestValue : X01; +BEGIN + + -- Initialize for no violation + Violation := '0'; --MEM IR 402 + + FOR i IN TestSignal'RANGE LOOP + TestDly := Maximum(0 ns, TestDelay(i)); + TestValue := To_X01(TestSignal(i)); + + IF (PeriodData(i).NotFirstFlag = FALSE) THEN + PeriodData(i).Rise := -Maximum(Period(i), + Maximum(PulseWidthHigh(i),PulseWidthLow(i))); + PeriodData(i).Fall := -Maximum(Period(i), + Maximum(PulseWidthHigh(i),PulseWidthLow(i))); + PeriodData(i).Last := TestValue; + PeriodData(i).NotFirstFlag := TRUE; + END IF; + + -- Initialize for no violation + -- Violation := '0'; --Mem IR 402 + + -- No violation possible if no test signal change + NEXT WHEN (PeriodData(i).Last = TestValue); + + -- record starting pulse times + IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'P')) THEN + -- Compute period times, then record the High Rise Time + PeriodObs := NOW - PeriodData(i).Rise; + PeriodData(i).Rise := NOW; + PeriodTest := TRUE; + ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'N')) THEN + -- Compute period times, then record the Low Fall Time + PeriodObs := NOW - PeriodData(i).Fall; + PeriodData(i).Fall := NOW; + PeriodTest := TRUE; + ELSE + PeriodTest := FALSE; + END IF; + + -- do checks on pulse ends + IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'p')) THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData(i).Fall; + CheckInfo.ExpTime := PulseWidthLow(i); + PulseTest := TRUE; + ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'n')) THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData(i).Rise; + CheckInfo.ExpTime := PulseWidthHigh(i); + 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(i).Last; + VitalMemoryReportViolation (TestSignalName, "", i, + HeaderMsg, CheckInfo, MsgFormat, 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(i); + 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; + VitalMemoryReportViolation (TestSignalName, "", i, + HeaderMsg, CheckInfo, MsgFormat, MsgSeverity ); + END IF; -- MsgOn + END IF; + END IF; + + PeriodData(i).Last := TestValue; + END LOOP; + +END VitalMemoryPeriodPulseCheck; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryPeriodPulseCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE PeriodData : INOUT VitalPeriodDataArrayType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArraytype; + CONSTANT Period : IN VitalDelayArraytype; + CONSTANT PulseWidthHigh : IN VitalDelayArraytype; + CONSTANT PulseWidthLow : IN VitalDelayArraytype; + 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; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType +)IS + VARIABLE TestDly : VitalDelayType; + VARIABLE CheckInfo : CheckInfoType; + VARIABLE PeriodObs : VitalDelayType; + VARIABLE PulseTest : BOOLEAN; + VARIABLE PeriodTest: BOOLEAN; + VARIABLE TestValue : X01; +BEGIN + + FOR i IN TestSignal'RANGE LOOP + TestDly := Maximum(0 ns, TestDelay(i)); + TestValue := To_X01(TestSignal(i)); + + IF (PeriodData(i).NotFirstFlag = FALSE) THEN + PeriodData(i).Rise := -Maximum(Period(i), + Maximum(PulseWidthHigh(i),PulseWidthLow(i))); + PeriodData(i).Fall := -Maximum(Period(i), + Maximum(PulseWidthHigh(i),PulseWidthLow(i))); + PeriodData(i).Last := TestValue; + PeriodData(i).NotFirstFlag := TRUE; + END IF; + + -- Initialize for no violation + Violation(i) := '0'; + + -- No violation possible if no test signal change + NEXT WHEN (PeriodData(i).Last = TestValue); + + -- record starting pulse times + IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'P')) THEN + -- Compute period times, then record the High Rise Time + PeriodObs := NOW - PeriodData(i).Rise; + PeriodData(i).Rise := NOW; + PeriodTest := TRUE; + ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'N')) THEN + -- Compute period times, then record the Low Fall Time + PeriodObs := NOW - PeriodData(i).Fall; + PeriodData(i).Fall := NOW; + PeriodTest := TRUE; + ELSE + PeriodTest := FALSE; + END IF; + + -- do checks on pulse ends + IF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'p')) THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData(i).Fall; + CheckInfo.ExpTime := PulseWidthLow(i); + PulseTest := TRUE; + ELSIF (EdgeSymbolMatch(PeriodData(i).Last, TestValue, 'n')) THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData(i).Rise; + CheckInfo.ExpTime := PulseWidthHigh(i); + 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(i) := 'X'; + END IF; + IF (MsgOn) THEN + CheckInfo.Violation := TRUE; + CheckInfo.CheckKind := PulseWidCheck; + CheckInfo.DetTime := NOW - TestDly; + CheckInfo.State := PeriodData(i).Last; + VitalMemoryReportViolation (TestSignalName, "", i, + HeaderMsg, CheckInfo, MsgFormat, 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(i); + IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN + IF (XOn) THEN + Violation(i) := 'X'; + END IF; + IF (MsgOn) THEN + CheckInfo.Violation := TRUE; + CheckInfo.CheckKind := PeriodCheck; + CheckInfo.DetTime := NOW - TestDly; + CheckInfo.State := TestValue; + VitalMemoryReportViolation (TestSignalName, "", i, + HeaderMsg, CheckInfo, MsgFOrmat, MsgSeverity ); + END IF; -- MsgOn + END IF; + END IF; + + PeriodData(i).Last := TestValue; + END LOOP; + +END VitalMemoryPeriodPulseCheck; + +-- ---------------------------------------------------------------------------- +-- Functionality Section +-- ---------------------------------------------------------------------------- + +-- Look-up table. Given an int, we can get the 4-bit bit_vector. +TYPE HexToBitvTableType IS ARRAY (NATURAL RANGE <>) OF + std_logic_vector(3 DOWNTO 0) ; + +CONSTANT HexToBitvTable : HexToBitvTableType (0 TO 15) := + ( + "0000", "0001", "0010", "0011", + "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", + "1100", "1101", "1110", "1111" + ) ; + +-- ---------------------------------------------------------------------------- +-- Misc Utilities Local Utilities +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- Procedure: IsSpace +-- Parameters: ch -- input character +-- Description: Returns TRUE or FALSE depending on the input character +-- being white space or not. +-- ---------------------------------------------------------------------------- +FUNCTION IsSpace (ch : character) +RETURN boolean IS +BEGIN + RETURN ((ch = ' ') OR (ch = CR) OR (ch = HT) OR (ch = NUL)); +END IsSpace; + +-- ---------------------------------------------------------------------------- +-- Procedure: LenOfString +-- Parameters: Str -- input string +-- Description: Returns the NATURAL length of the input string. +-- as terminated by the first NUL character. +-- ---------------------------------------------------------------------------- +FUNCTION LenOfString (Str : STRING) +RETURN NATURAL IS + VARIABLE StrRight : NATURAL; +BEGIN + StrRight := Str'RIGHT; + FOR i IN Str'RANGE LOOP + IF (Str(i) = NUL) THEN + StrRight := i - 1; + EXIT; + END IF; + END LOOP; + RETURN (StrRight); +END LenOfString; + +-- ---------------------------------------------------------------------------- +-- Procedure: HexToInt +-- Parameters: Hex -- input character or string +-- Description: Converts input character or string interpreted as a +-- hexadecimal representation to integer value. +-- ---------------------------------------------------------------------------- +FUNCTION HexToInt(Hex : CHARACTER) RETURN INTEGER IS + CONSTANT HexChars : STRING := "0123456789ABCDEFabcdef"; + CONSTANT XHiChar : CHARACTER := 'X'; + CONSTANT XLoChar : CHARACTER := 'x'; +BEGIN + IF (Hex = XLoChar OR Hex = XHiChar) THEN + RETURN (23); + END IF; + FOR i IN 1 TO 16 LOOP + IF(Hex = HexChars(i)) THEN + RETURN (i-1); + END IF; + END LOOP; + FOR i IN 17 TO 22 LOOP + IF (Hex = HexChars(i)) THEN + RETURN (i-7); + END IF; + END LOOP; + ASSERT FALSE REPORT + "Invalid character received by HexToInt function" + SEVERITY WARNING; + RETURN (0); +END HexToInt; + +-- ---------------------------------------------------------------------------- +FUNCTION HexToInt (Hex : STRING) RETURN INTEGER IS + VARIABLE Value : INTEGER := 0; + VARIABLE Length : INTEGER; +BEGIN + Length := LenOfString(hex); + IF (Length > 8) THEN + ASSERT FALSE REPORT + "Invalid string length received by HexToInt function" + SEVERITY WARNING; + ELSE + FOR i IN 1 TO Length LOOP + Value := Value + HexToInt(Hex(i)) * 16 ** (Length - i); + END LOOP; + END IF; + RETURN (Value); +END HexToInt; + +-- ---------------------------------------------------------------------------- +-- Procedure: HexToBitv +-- Parameters: Hex -- Input hex string +-- Description: Converts input hex string to a std_logic_vector +-- ---------------------------------------------------------------------------- +FUNCTION HexToBitv( + Hex : STRING +) RETURN std_logic_vector is + VARIABLE Index : INTEGER := 0 ; + VARIABLE ValHexToInt : INTEGER ; + VARIABLE BitsPerHex : INTEGER := 4 ; -- Denotes no. of bits per hex char. + VARIABLE HexLen : NATURAL := (BitsPerHex * LenOfString(Hex)) ; + VARIABLE TableVal : std_logic_vector(3 DOWNTO 0) ; + VARIABLE Result : std_logic_vector(HexLen-1 DOWNTO 0) ; +BEGIN + -- Assign 4-bit wide bit vector to result directly from a look-up table. + Index := 0 ; + WHILE ( Index < HexLen ) LOOP + ValHexToInt := HexToInt( Hex((HexLen - Index)/BitsPerHex ) ); + IF ( ValHexToInt = 23 ) THEN + TableVal := "XXXX"; + ELSE + -- Look up from the table. + TableVal := HexToBitvTable( ValHexToInt ) ; + END IF; + -- Assign now. + Result(Index+3 DOWNTO Index) := TableVal ; + -- Get ready for next block of 4-bits. + Index := Index + 4 ; + END LOOP ; + RETURN Result ; +END HexToBitv ; + +-- ---------------------------------------------------------------------------- +-- Procedure: BinToBitv +-- Parameters: Bin -- Input bin string +-- Description: Converts input bin string to a std_logic_vector +-- ---------------------------------------------------------------------------- +FUNCTION BinToBitv( + Bin : STRING +) RETURN std_logic_vector is + VARIABLE Index : INTEGER := 0 ; + VARIABLE Length : NATURAL := LenOfString(Bin); + VARIABLE BitVal : std_ulogic; + VARIABLE Result : std_logic_vector(Length-1 DOWNTO 0) ; +BEGIN + Index := 0 ; + WHILE ( Index < Length ) LOOP + IF (Bin(Length-Index) = '0') THEN + BitVal := '0'; + ELSIF (Bin(Length-Index) = '1') THEN + BitVal := '1'; + ELSE + BitVal := 'X'; + END IF ; + -- Assign now. + Result(Index) := BitVal ; + Index := Index + 1 ; + END LOOP ; + RETURN Result ; +END BinToBitv ; + +-- ---------------------------------------------------------------------------- +-- For Memory Table Modeling +-- ---------------------------------------------------------------------------- + +TYPE To_MemoryCharType IS ARRAY (VitalMemorySymbolType) OF CHARACTER; +CONSTANT To_MemoryChar : To_MemoryCharType := + ( '/', '\', 'P', 'N', 'r', 'f', 'p', 'n', 'R', 'F', '^', 'v', + 'E', 'A', 'D', '*', 'X', '0', '1', '-', 'B', 'Z', 'S', + 'g', 'u', 'i', 'G', 'U', 'I', + 'w', 's', + 'c', 'l', 'd', 'e', 'C', 'L', + 'M', 'm', 't' ); + +TYPE ValidMemoryTableInputType IS ARRAY (VitalMemorySymbolType) OF BOOLEAN; +CONSTANT ValidMemoryTableInput : ValidMemoryTableInputType := + -- '/', '\', '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, + -- 'g', 'u', 'i', 'G', 'U', 'I', + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + -- 'w', 's', + FALSE, FALSE, + -- 'c', 'l', 'd', 'e', 'C', 'L', + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + -- 'M', 'm', 't' + FALSE, FALSE, FALSE); + +TYPE MemoryTableMatchType IS ARRAY (X01,X01,VitalMemorySymbolType) OF BOOLEAN; +-- last value, present value, table symbol +CONSTANT MemoryTableMatch : MemoryTableMatchType := ( + ( -- X (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + -- g u i G U I + -- w s + -- c l d e, C L + -- m t + ( 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,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + 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,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,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, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE) + ), + + (-- 0 (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + -- g u i G U I + -- w s + -- c l d e, C L + -- m t + ( 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), + ( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE, + FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,TRUE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE), + ( TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, + TRUE, FALSE,TRUE, FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,TRUE, + FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE) + ), + + (-- 1 (lastvalue) + -- / \ P N r f + -- p n R F ^ v + -- E A D * + -- X 0 1 - B Z S + -- g u i G U I + -- w s + -- c l d e, C L + -- m t + ( FALSE,FALSE,FALSE,FALSE,FALSE,TRUE , + FALSE,TRUE, FALSE,TRUE, FALSE,FALSE, + FALSE,FALSE,TRUE, 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), + ( 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,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,TRUE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE, + FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, + FALSE,FALSE,FALSE) + ) + ); + + +-- ---------------------------------------------------------------------------- +-- Error Message Types and Tables +-- ---------------------------------------------------------------------------- + +TYPE VitalMemoryErrorType IS ( + ErrGoodAddr, -- 'g' Good address (no transition) + ErrUnknAddr, -- 'u' 'X' levels in address (no transition) + ErrInvaAddr, -- 'i' Invalid address (no transition) + ErrGoodTrAddr, -- 'G' Good address (with transition) + ErrUnknTrAddr, -- 'U' 'X' levels in address (with transition) + ErrInvaTrAddr, -- 'I' Invalid address (with transition) + ErrWrDatMem, -- 'w' Writing data to memory + ErrNoChgMem, -- 's' Retaining previous memory contents + ErrCrAllMem, -- 'c' Corrupting entire memory with 'X' + ErrCrWrdMem, -- 'l' Corrupting a word in memory with 'X' + ErrCrBitMem, -- 'd' Corrupting a single bit in memory with 'X' + ErrCrDatMem, -- 'e' Corrupting a word with 'X' based on data in + ErrCrAllSubMem,-- 'C' Corrupting a sub-word entire memory with 'X' + ErrCrWrdSubMem,-- 'L' Corrupting a sub-word in memory with 'X' + ErrCrBitSubMem,-- 'D' Corrupting a single bit of a memory sub-word with 'X' + ErrCrDatSubMem,-- 'E' Corrupting a sub-word with 'X' based on data in + ErrCrWrdOut, -- 'l' Corrupting data out with 'X' + ErrCrBitOut, -- 'd' Corrupting a single bit of data out with 'X' + ErrCrDatOut, -- 'e' Corrupting data out with 'X' based on data in + ErrCrWrdSubOut,-- 'L' Corrupting data out sub-word with 'X' + ErrCrBitSubOut,-- 'D' Corrupting a single bit of data out sub-word with 'X' + ErrCrDatSubOut,-- 'E' Corrupting data out sub-word with 'X' based on data in + ErrImplOut, -- 'M' Implicit read from memory to data out + ErrReadOut, -- 'm' Reading data from memory to data out + ErrAssgOut, -- 't' Transfering from data in to data out + ErrAsgXOut, -- 'X' Assigning unknown level to data out + ErrAsg0Out, -- '0' Assigning low level to data out + ErrAsg1Out, -- '1' Assigning high level to data out + ErrAsgZOut, -- 'Z' Assigning high impedence to data out + ErrAsgSOut, -- 'S' Keeping data out at steady value + ErrAsgXMem, -- 'X' Assigning unknown level to memory location + ErrAsg0Mem, -- '0' Assigning low level to memory location + ErrAsg1Mem, -- '1' Assigning high level to memory location + ErrAsgZMem, -- 'Z' Assigning high impedence to memory location + ErrDefMemAct, -- No memory table match, using default action + ErrInitMem, -- Initialize memory contents + ErrMcpWrCont, -- Memory cross port to same port write contention + ErrMcpCpCont, -- Memory cross port read/write data/memory contention + ErrMcpCpRead, -- Memory cross port read to same port + ErrMcpRdWrCo, -- Memory cross port read/write data only contention + ErrMcpCpWrCont,-- Memory cross port to cross port write contention + ErrUnknMemDo, -- Unknown memory action + ErrUnknDatDo, -- Unknown data action + ErrUnknSymbol, -- Illegal memory symbol + ErrLdIlgArg, + ErrLdAddrRng, + ErrLdMemInfo, + ErrLdFileEmpty, + ErrPrintString +); + +TYPE VitalMemoryErrorSeverityType IS +ARRAY (VitalMemoryErrorType) OF SEVERITY_LEVEL; +CONSTANT VitalMemoryErrorSeverity : + VitalMemoryErrorSeverityType := ( + ErrGoodAddr => NOTE, + ErrUnknAddr => WARNING, + ErrInvaAddr => WARNING, + ErrGoodTrAddr => NOTE, + ErrUnknTrAddr => WARNING, + ErrInvaTrAddr => WARNING, + ErrWrDatMem => NOTE, + ErrNoChgMem => NOTE, + ErrCrAllMem => WARNING, + ErrCrWrdMem => WARNING, + ErrCrBitMem => WARNING, + ErrCrDatMem => WARNING, + ErrCrAllSubMem => WARNING, + ErrCrWrdSubMem => WARNING, + ErrCrBitSubMem => WARNING, + ErrCrDatSubMem => WARNING, + ErrCrWrdOut => WARNING, + ErrCrBitOut => WARNING, + ErrCrDatOut => WARNING, + ErrCrWrdSubOut => WARNING, + ErrCrBitSubOut => WARNING, + ErrCrDatSubOut => WARNING, + ErrImplOut => NOTE, + ErrReadOut => NOTE, + ErrAssgOut => NOTE, + ErrAsgXOut => NOTE, + ErrAsg0Out => NOTE, + ErrAsg1Out => NOTE, + ErrAsgZOut => NOTE, + ErrAsgSOut => NOTE, + ErrAsgXMem => NOTE, + ErrAsg0Mem => NOTE, + ErrAsg1Mem => NOTE, + ErrAsgZMem => NOTE, + ErrDefMemAct => NOTE, + ErrInitMem => NOTE, + ErrMcpWrCont => WARNING, + ErrMcpCpCont => WARNING, + ErrMcpCpRead => WARNING, + ErrMcpRdWrCo => WARNING, + ErrMcpCpWrCont => WARNING, + ErrUnknMemDo => ERROR, + ErrUnknDatDo => ERROR, + ErrUnknSymbol => ERROR, + ErrLdIlgArg => ERROR, + ErrLdAddrRng => WARNING, + ErrLdMemInfo => NOTE, + ErrLdFileEmpty => ERROR, + ErrPrintString => WARNING + ); + +-- ---------------------------------------------------------------------------- +CONSTANT MsgGoodAddr : STRING + := "Good address (no transition)"; +CONSTANT MsgUnknAddr : STRING + := "Unknown address (no transition)"; +CONSTANT MsgInvaAddr : STRING + := "Invalid address (no transition)"; +CONSTANT MsgGoodTrAddr : STRING + := "Good address (with transition)"; +CONSTANT MsgUnknTrAddr : STRING + := "Unknown address (with transition)"; +CONSTANT MsgInvaTrAddr : STRING + := "Invalid address (with transition)"; +CONSTANT MsgNoChgMem : STRING + := "Retaining previous memory contents"; +CONSTANT MsgWrDatMem : STRING + := "Writing data to memory"; +CONSTANT MsgCrAllMem : STRING + := "Corrupting entire memory with 'X'"; +CONSTANT MsgCrWrdMem : STRING + := "Corrupting a word in memory with 'X'"; +CONSTANT MsgCrBitMem : STRING + := "Corrupting a single bit in memory with 'X'"; +CONSTANT MsgCrDatMem : STRING + := "Corrupting a word with 'X' based on data in"; +CONSTANT MsgCrAllSubMem : STRING + := "Corrupting a sub-word entire memory with 'X'"; +CONSTANT MsgCrWrdSubMem : STRING + := "Corrupting a sub-word in memory with 'X'"; +CONSTANT MsgCrBitSubMem : STRING + := "Corrupting a single bit of a sub-word with 'X'"; +CONSTANT MsgCrDatSubMem : STRING + := "Corrupting a sub-word with 'X' based on data in"; +CONSTANT MsgCrWrdOut : STRING + := "Corrupting data out with 'X'"; +CONSTANT MsgCrBitOut : STRING + := "Corrupting a single bit of data out with 'X'"; +CONSTANT MsgCrDatOut : STRING + := "Corrupting data out with 'X' based on data in"; +CONSTANT MsgCrWrdSubOut : STRING + := "Corrupting data out sub-word with 'X'"; +CONSTANT MsgCrBitSubOut : STRING + := "Corrupting a single bit of data out sub-word with 'X'"; +CONSTANT MsgCrDatSubOut : STRING + := "Corrupting data out sub-word with 'X' based on data in"; +CONSTANT MsgImplOut : STRING + := "Implicit read from memory to data out"; +CONSTANT MsgReadOut : STRING + := "Reading data from memory to data out"; +CONSTANT MsgAssgOut : STRING + := "Transfering from data in to data out"; +CONSTANT MsgAsgXOut : STRING + := "Assigning unknown level to data out"; +CONSTANT MsgAsg0Out : STRING + := "Assigning low level to data out"; +CONSTANT MsgAsg1Out : STRING + := "Assigning high level to data out"; +CONSTANT MsgAsgZOut : STRING + := "Assigning high impedance to data out"; +CONSTANT MsgAsgSOut : STRING + := "Keeping data out at steady value"; +CONSTANT MsgAsgXMem : STRING + := "Assigning unknown level to memory location"; +CONSTANT MsgAsg0Mem : STRING + := "Assigning low level to memory location"; +CONSTANT MsgAsg1Mem : STRING + := "Assigning high level to memory location"; +CONSTANT MsgAsgZMem : STRING + := "Assigning high impedance to memory location"; +CONSTANT MsgDefMemAct : STRING + := "No memory table match, using default action"; +CONSTANT MsgInitMem : STRING + := "Initializing memory contents"; +CONSTANT MsgMcpWrCont : STRING + := "Same port write contention"; +CONSTANT MsgMcpCpCont : STRING + := "Cross port read/write data/memory contention"; +CONSTANT MsgMcpCpRead : STRING + := "Cross port read to same port"; +CONSTANT MsgMcpRdWrCo : STRING + := "Cross port read/write data only contention"; +CONSTANT MsgMcpCpWrCont : STRING + := "Cross port write contention"; +CONSTANT MsgUnknMemDo : STRING + := "Unknown memory action"; +CONSTANT MsgUnknDatDo : STRING + := "Unknown data action"; +CONSTANT MsgUnknSymbol : STRING + := "Illegal memory symbol"; + +CONSTANT MsgLdIlgArg : STRING + := "Illegal bit arguments while loading memory."; +CONSTANT MsgLdMemInfo : STRING + := "Loading data from the file into memory."; +CONSTANT MsgLdAddrRng : STRING + := "Address out of range while loading memory."; +CONSTANT MsgLdFileEmpty : STRING + := "Memory load file is empty."; +CONSTANT MsgPrintString : STRING + := ""; + +CONSTANT MsgUnknown : STRING + := "Unknown error message."; + +CONSTANT MsgVMT : STRING + := "VitalMemoryTable"; +CONSTANT MsgVMV : STRING + := "VitalMemoryViolation"; +CONSTANT MsgVDM : STRING + := "VitalDeclareMemory"; +CONSTANT MsgVMCP : STRING + := "VitalMemoryCrossPorts"; + +-- ---------------------------------------------------------------------------- +-- LOCAL Utilities +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- Procedure: MemoryMessage +-- Parameters: ErrorId -- Input error code +-- Description: This function looks up the input error code and returns +-- the string value of the associated message. +-- ---------------------------------------------------------------------------- + +FUNCTION MemoryMessage ( + CONSTANT ErrorId : IN VitalMemoryErrorType +) RETURN STRING IS +BEGIN + CASE ErrorId IS + WHEN ErrGoodAddr => RETURN MsgGoodAddr ; + WHEN ErrUnknAddr => RETURN MsgUnknAddr ; + WHEN ErrInvaAddr => RETURN MsgInvaAddr ; + WHEN ErrGoodTrAddr => RETURN MsgGoodTrAddr ; + WHEN ErrUnknTrAddr => RETURN MsgUnknTrAddr ; + WHEN ErrInvaTrAddr => RETURN MsgInvaTrAddr ; + WHEN ErrWrDatMem => RETURN MsgWrDatMem ; + WHEN ErrNoChgMem => RETURN MsgNoChgMem ; + WHEN ErrCrAllMem => RETURN MsgCrAllMem ; + WHEN ErrCrWrdMem => RETURN MsgCrWrdMem ; + WHEN ErrCrBitMem => RETURN MsgCrBitMem ; + WHEN ErrCrDatMem => RETURN MsgCrDatMem ; + WHEN ErrCrAllSubMem => RETURN MsgCrAllSubMem; + WHEN ErrCrWrdSubMem => RETURN MsgCrWrdSubMem; + WHEN ErrCrBitSubMem => RETURN MsgCrBitSubMem; + WHEN ErrCrDatSubMem => RETURN MsgCrDatSubMem; + WHEN ErrCrWrdOut => RETURN MsgCrWrdOut ; + WHEN ErrCrBitOut => RETURN MsgCrBitOut ; + WHEN ErrCrDatOut => RETURN MsgCrDatOut ; + WHEN ErrCrWrdSubOut => RETURN MsgCrWrdSubOut; + WHEN ErrCrBitSubOut => RETURN MsgCrBitSubOut; + WHEN ErrCrDatSubOut => RETURN MsgCrDatSubOut; + WHEN ErrImplOut => RETURN MsgImplOut ; + WHEN ErrReadOut => RETURN MsgReadOut ; + WHEN ErrAssgOut => RETURN MsgAssgOut ; + WHEN ErrAsgXOut => RETURN MsgAsgXOut ; + WHEN ErrAsg0Out => RETURN MsgAsg0Out ; + WHEN ErrAsg1Out => RETURN MsgAsg1Out ; + WHEN ErrAsgZOut => RETURN MsgAsgZOut ; + WHEN ErrAsgSOut => RETURN MsgAsgSOut ; + WHEN ErrAsgXMem => RETURN MsgAsgXMem ; + WHEN ErrAsg0Mem => RETURN MsgAsg0Mem ; + WHEN ErrAsg1Mem => RETURN MsgAsg1Mem ; + WHEN ErrAsgZMem => RETURN MsgAsgZMem ; + WHEN ErrDefMemAct => RETURN MsgDefMemAct ; + WHEN ErrInitMem => RETURN MsgInitMem ; + WHEN ErrMcpWrCont => RETURN MsgMcpWrCont ; + WHEN ErrMcpCpCont => RETURN MsgMcpCpCont ; + WHEN ErrMcpCpRead => RETURN MsgMcpCpRead ; + WHEN ErrMcpRdWrCo => RETURN MsgMcpRdWrCo ; + WHEN ErrMcpCpWrCont => RETURN MsgMcpCpWrCont; + WHEN ErrUnknMemDo => RETURN MsgUnknMemDo ; + WHEN ErrUnknDatDo => RETURN MsgUnknDatDo ; + WHEN ErrUnknSymbol => RETURN MsgUnknSymbol ; + WHEN ErrLdIlgArg => RETURN MsgLdIlgArg ; + WHEN ErrLdAddrRng => RETURN MsgLdAddrRng ; + WHEN ErrLdMemInfo => RETURN MsgLdMemInfo ; + WHEN ErrLdFileEmpty => RETURN MsgLdFileEmpty; + WHEN ErrPrintString => RETURN MsgPrintString; + WHEN OTHERS => RETURN MsgUnknown ; + END CASE; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: PrintMemoryMessage +-- Parameters: Routine -- String identifying the calling routine +-- ErrorId -- Input error code for message lookup +-- Info -- Output string or character +-- InfoStr -- Additional output string +-- Info1 -- Additional output integer +-- Info2 -- Additional output integer +-- Info3 -- Additional output integer +-- Description: This procedure prints out a memory status message +-- given the input error id and other status information. +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType +) IS +BEGIN + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT Info : IN STRING +) IS +BEGIN + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT Info1 : IN STRING; + CONSTANT Info2 : IN STRING +) IS +BEGIN + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info1 & " " & Info2 + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT Info : IN CHARACTER +) IS +BEGIN + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & Info + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT InfoStr : IN STRING; + CONSTANT Info1 : IN NATURAL +) IS + VARIABLE TmpStr : STRING ( 1 TO 256 ) ; + VARIABLE TmpInt : INTEGER := 1; +BEGIN + IntToStr(Info1,TmpStr,TmpInt); + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT InfoStr : IN STRING; + CONSTANT Info1 : IN NATURAL; + CONSTANT Info2 : IN NATURAL +) IS + VARIABLE TmpStr : STRING ( 1 TO 256 ) ; + VARIABLE TmpInt : INTEGER := 1; +BEGIN + IntToStr(Info1,TmpStr,TmpInt); + IntToStr(Info2,TmpStr,TmpInt); + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalMemoryErrorType; + CONSTANT InfoStr : IN STRING; + CONSTANT Info1 : IN NATURAL; + CONSTANT Info2 : IN NATURAL; + CONSTANT Info3 : IN NATURAL +) IS + VARIABLE TmpStr : STRING ( 1 TO 256 ) ; + VARIABLE TmpInt : INTEGER := 1; +BEGIN + IntToStr(Info1,TmpStr,TmpInt); + IntToStr(Info2,TmpStr,TmpInt); + IntToStr(Info3,TmpStr,TmpInt); + ASSERT FALSE + REPORT Routine & ": " & MemoryMessage(ErrorId) & " " & InfoStr & " " & TmpStr + SEVERITY VitalMemoryErrorSeverity(ErrorId); +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE PrintMemoryMessage ( + CONSTANT Routine : IN STRING; + CONSTANT Table : IN VitalMemoryTableType; + CONSTANT Index : IN INTEGER; + CONSTANT InfoStr : IN STRING +) IS + CONSTANT TableEntries : INTEGER := Table'LENGTH(1); + CONSTANT TableWidth : INTEGER := Table'LENGTH(2); + VARIABLE TmpStr : STRING ( 1 TO 256 ) ; + VARIABLE TmpInt : INTEGER := 1; +BEGIN + IF (Index < 0 AND Index > TableEntries-1) THEN + ASSERT FALSE + REPORT Routine & ": Memory table search failure" + SEVERITY ERROR; + END IF; + ColLoop: + FOR i IN 0 TO TableWidth-1 LOOP + IF (i >= 64) THEN + TmpStr(TmpInt) := '.'; + TmpInt := TmpInt + 1; + TmpStr(TmpInt) := '.'; + TmpInt := TmpInt + 1; + TmpStr(TmpInt) := '.'; + TmpInt := TmpInt + 1; + EXIT ColLoop; + END IF; + TmpStr(TmpInt) := '''; + TmpInt := TmpInt + 1; + TmpStr(TmpInt) := To_MemoryChar(Table(Index,i)); + TmpInt := TmpInt + 1; + TmpStr(TmpInt) := '''; + TmpInt := TmpInt + 1; + IF (i < TableWidth-1) THEN + TmpStr(TmpInt) := ','; + TmpInt := TmpInt + 1; + END IF; + END LOOP; + ASSERT FALSE + REPORT Routine & ": Port=" & InfoStr & " TableRow=" & TmpStr + SEVERITY NOTE; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: DecodeAddress +-- Parameters: Address - Converted address. +-- AddrFlag - Flag to indicte address match +-- MemoryData - Information about memory characteristics +-- PrevAddressBus - Previous input address value +-- AddressBus - Input address value. +-- Description: This procedure is used for transforming a valid +-- address value to an integer in order to access memory. +-- It performs address bound checking as well. +-- Sets Address to -1 for unknowns +-- Sets Address to -2 for out of range +-- ---------------------------------------------------------------------------- + +PROCEDURE DecodeAddress ( + VARIABLE Address : INOUT INTEGER; + VARIABLE AddrFlag : INOUT VitalMemorySymbolType; + VARIABLE MemoryData : IN VitalMemoryDataType; + CONSTANT PrevAddressBus : IN std_logic_vector; + CONSTANT AddressBus : IN std_logic_vector +) IS + VARIABLE Power : NATURAL; + VARIABLE AddrUnkn : BOOLEAN; +BEGIN + Power := 0; + AddrUnkn := FALSE; + -- It is assumed that always Address'LEFT represents the Most significant bit. + FOR i IN AddressBus'RANGE LOOP + Power := Power * 2; + IF (AddressBus(i) /= '1' AND AddressBus(i) /= '0') THEN + AddrUnkn := TRUE; + Power := 0; + EXIT; + ELSIF (AddressBus(i) = '1') THEN + Power := Power + 1; + END IF; + END LOOP; + Address := Power; + AddrFlag := 'g'; + IF (AddrUnkn) THEN + AddrFlag := 'u'; -- unknown addr + Address := -1; + END IF; + IF ( Power > (MemoryData.NoOfWords - 1)) THEN + AddrFlag := 'i'; -- invalid addr + Address := -2; + END IF; + IF (PrevAddressBus /= AddressBus) THEN + CASE AddrFlag IS + WHEN 'g' => AddrFlag := 'G'; + WHEN 'u' => AddrFlag := 'U'; + WHEN 'i' => AddrFlag := 'I'; + WHEN OTHERS => + ASSERT FALSE REPORT + "DecodeAddress: Internal error. [AddrFlag]=" + & To_MemoryChar(AddrFlag) + SEVERITY ERROR; + END CASE; + END IF; +END DecodeAddress; + +-- ---------------------------------------------------------------------------- +-- Procedure: DecodeData +-- Parameters: DataFlag - Flag to indicte data match +-- PrevDataInBus - Previous input data value +-- DataInBus - Input data value. +-- HighBit - High bit offset value. +-- LowBit - Low bit offset value. +-- Description: This procedure is used for interpreting the input data +-- as a data flag for subsequent table matching. +-- ---------------------------------------------------------------------------- +PROCEDURE DecodeData ( + VARIABLE DataFlag : INOUT VitalMemorySymbolType; + CONSTANT PrevDataInBus : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT HighBit : IN NATURAL; + CONSTANT LowBit : IN NATURAL +) IS + VARIABLE DataUnkn : BOOLEAN := FALSE; +BEGIN + FOR i IN LowBit TO HighBit LOOP + IF DataInBus(i) /= '1' AND DataInBus(i) /= '0' THEN + DataUnkn := TRUE; + EXIT; + END IF; + END LOOP; + DataFlag := 'g'; + IF (DataUnkn) THEN + DataFlag := 'u'; -- unknown addr + END IF; + IF (PrevDataInBus(HighBit DOWNTO LowBit) /= + DataInBus(HighBit DOWNTO LowBit)) THEN + CASE DataFlag IS + WHEN 'g' => DataFlag := 'G'; + WHEN 'u' => DataFlag := 'U'; + WHEN OTHERS => + ASSERT FALSE REPORT + "DecodeData: Internal error. [DataFlag]=" + & To_MemoryChar(DataFlag) + SEVERITY ERROR; + END CASE; + END IF; +END DecodeData; + +-- ---------------------------------------------------------------------------- +-- Procedure: WriteMemory +-- Parameters: MemoryPtr - Pointer to the memory array. +-- DataInBus - Input Data to be written. +-- Address - Address of the memory location. +-- BitPosition - Position of bit in memory location. +-- HighBit - High bit offset value. +-- LowBit - Low bit offset value. +-- Description: This procedure is used to write to a memory location +-- on a bit/byte/word basis. +-- The high bit and low bit offset are used for byte write +-- operations.These parameters specify the data byte for write. +-- In the case of word write the complete memory word is used. +-- This procedure is overloaded for bit,byte and word write +-- memory operations.The number of parameters may vary. +-- ---------------------------------------------------------------------------- +PROCEDURE WriteMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT HighBit : IN NATURAL; + CONSTANT LowBit : IN NATURAL +) IS + VARIABLE TmpData : std_logic_vector(DataInBus'LENGTH - 1 DOWNTO 0); +BEGIN + -- Address bound checking. + IF ( Address < 0 OR Address > (MemoryPtr.NoOfWords - 1)) THEN + PrintMemoryMessage ( "WriteMemory", ErrPrintString, + "Aborting write operation as address is out of range.") ; + RETURN; + END IF; + TmpData := To_UX01(DataInBus); + FOR i in LowBit to HighBit LOOP + MemoryPtr.MemoryArrayPtr(Address).all(i) := TmpData(i); + END LOOP; +END WriteMemory; + +-- ---------------------------------------------------------------------------- +PROCEDURE WriteMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT BitPosition : IN NATURAL +) IS + VARIABLE HighBit : NATURAL; + VARIABLE LowBit : NATURAL; +BEGIN + HighBit := BitPosition; + LowBit := BitPosition; + WriteMemory (MemoryPtr, DataInBus, Address, HighBit, LowBit); +END WriteMemory; + +-- ---------------------------------------------------------------------------- +PROCEDURE WriteMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT Address : IN INTEGER +) IS + VARIABLE HighBit : NATURAL; + VARIABLE LowBit : NATURAL; +BEGIN + HighBit := MemoryPtr.NoOfBitsPerWord - 1; + LowBit := 0; + WriteMemory (MemoryPtr, DataInBus, Address, HighBit, LowBit); +END WriteMemory; + +-- ---------------------------------------------------------------------------- +-- Procedure: ReadMemory +-- Parameters: MemoryPtr - Pointer to the memory array. +-- DataOut - Output Data to be read in this. +-- Address - Address of the memory location. +-- BitPosition - Position of bit in memory location. +-- HighBit - High bit offset value. +-- LowBit - Low bit offset value. +-- Description: This procedure is used to read from a memory location +-- on a bit/byte/word basis. +-- The high bit and low bit offset are used for byte write +-- operations.These parameters specify the data byte for +-- read.In the case of word write the complete memory word +-- is used.This procedure is overloaded for bit,byte and +-- word write memory operations.The number of parameters +-- may vary. +-- ---------------------------------------------------------------------------- +PROCEDURE ReadMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + VARIABLE DataOut : OUT std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT HighBit : IN NATURAL; + CONSTANT LowBit : IN NATURAL +) IS + VARIABLE DataOutTmp : std_logic_vector(MemoryPtr.NoOfBitsPerWord-1 DOWNTO 0); + VARIABLE length : NATURAL := (HighBit - LowBit + 1); +BEGIN + -- Address bound checking. + IF ( Address > (MemoryPtr.NoOfWords - 1)) THEN + PrintMemoryMessage ( + "ReadMemory",ErrInvaAddr, + "[Address,NoOfWords]=",Address,MemoryPtr.NoOfWords + ); + FOR i in LowBit to HighBit LOOP + DataOutTmp(i) := 'X'; + END LOOP; + ELSE + FOR i in LowBit to HighBit LOOP + DataOutTmp(i) := MemoryPtr.MemoryArrayPtr (Address).all(i); + END LOOP; + END IF; + DataOut := DataOutTmp; +END ReadMemory; + +-- ---------------------------------------------------------------------------- +PROCEDURE ReadMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + VARIABLE DataOut : OUT std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT BitPosition : IN NATURAL +) IS + VARIABLE HighBit : NATURAL; + VARIABLE LowBit : NATURAL; +BEGIN + HighBit := BitPosition; + LowBit := BitPosition; + ReadMemory (MemoryPtr, DataOut, Address, HighBit, LowBit); +END ReadMemory; + +-- ---------------------------------------------------------------------------- +PROCEDURE ReadMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + VARIABLE DataOut : OUT std_logic_vector; + CONSTANT Address : IN INTEGER +) IS + VARIABLE HighBit : NATURAL; + VARIABLE LowBit : NATURAL; +BEGIN + HighBit := MemoryPtr.NoOfBitsPerWord - 1; + LowBit := 0; + ReadMemory (MemoryPtr, DataOut, Address, HighBit, LowBit); +END ReadMemory; + + +-- ---------------------------------------------------------------------------- +-- Procedure: LoadMemory +-- Parameters: MemoryPtr - Pointer to the memory array. +-- FileName - Name of the output file. +-- HighBit - High bit offset value. +-- LowBit - Low bit offset value. +-- Description: This procedure is used to load the contents of the memory +-- from a specified input file. +-- The high bit and low bit offset are used so that same task +-- can be used for all bit/byte/word write operations. +-- In the case of a bit write RAM the HighBit and LowBit have +-- the same value. +-- This procedure is overloaded for word write operations. +-- ---------------------------------------------------------------------------- +PROCEDURE LoadMemory ( + VARIABLE MemoryPtr : INOUT VitalMemoryDataType; + CONSTANT FileName : IN STRING; + CONSTANT BinaryFile : IN BOOLEAN := FALSE +) IS + FILE Fptr : TEXT OPEN read_mode IS FileName; + VARIABLE OneLine : LINE; + VARIABLE Ignore : CHARACTER; + VARIABLE Index : NATURAL := 1; + VARIABLE LineNo : NATURAL := 0; + VARIABLE Address : INTEGER := 0; + VARIABLE DataInBus : std_logic_vector(MemoryPtr.NoOfBitsPerWord-1 DOWNTO 0); + VARIABLE AddrStr : STRING(1 TO 80) ; + VARIABLE DataInStr : STRING(1 TO 255) ; +BEGIN + IF (ENDFILE(fptr)) THEN + PrintMemoryMessage (MsgVDM, ErrLdFileEmpty, + "[FileName]="&FileName); + RETURN; + END IF ; + PrintMemoryMessage ( + MsgVDM,ErrLdMemInfo, "[FileName]="&FileName + ); + WHILE (NOT ENDFILE(fptr)) LOOP + ReadLine(Fptr, OneLine); + LineNo := LineNo + 1 ; + -- First ignoring leading spaces. + WHILE (OneLine'LENGTH /= 0 and IsSpace(OneLine(1))) LOOP + READ (OneLine, Ignore) ; -- Ignoring the space character. + END LOOP ; + -- Note that, by now oneline has been "stripped" of its leading spaces. + IF ( OneLine(1) = '@' ) THEN + READ (OneLine, Ignore); -- Ignore the '@' character and read the string. + -- Now strip off spaces, if any, between '@' and Address string. + WHILE (OneLine'LENGTH /= 0 and IsSpace(OneLine(1))) LOOP + READ (OneLine, Ignore) ; -- Ignoring the space character. + END LOOP ; + -- Now get the string which represents the address into string variable. + Index := 1; + WHILE (OneLine'LENGTH /= 0 AND (NOT(IsSpace(OneLine(1))))) LOOP + READ(OneLine, AddrStr(Index)); + Index := Index + 1; + END LOOP ; + AddrStr(Index) := NUL; + -- Now convert the hex string into a hex integer + Address := HexToInt(AddrStr) ; + ELSE + IF ( LineNo /= 1 ) THEN + Address := Address + 1; + END IF; + END IF ; + IF ( Address > (MemoryPtr.NoOfWords - 1) ) THEN + PrintMemoryMessage (MsgVDM, ErrLdAddrRng, + "[Address,lineno]=", Address, LineNo) ; + EXIT ; + END IF; + -- Now strip off spaces, between Address string and DataInBus string. + WHILE (OneLine'LENGTH /= 0 AND IsSpace(OneLine(1))) LOOP + READ (OneLine, Ignore) ; -- Ignoring the space character. + END LOOP ; + Index := 1; + WHILE (OneLine'LENGTH /= 0 AND (NOT(IsSpace(OneLine(1))))) LOOP + READ(OneLine, DataInStr(Index)); + Index := Index + 1; + END LOOP ; + DataInStr(Index) := NUL; + IF (BinaryFile) THEN + DataInBus := BinToBitv (DataInStr); + ELSE + DataInBus := HexToBitv (DataInStr); + END IF ; + WriteMemory (MemoryPtr, DataInBus, Address); + END LOOP ; +END LoadMemory; + +-- ---------------------------------------------------------------------------- +-- Procedure: MemoryMatch +-- Parameters: Symbol - Symbol from memory table +-- TestFlag - Interpreted data or address symbol +-- In2 - input from VitalMemoryTable procedure +-- to memory table +-- In2LastValue - Previous value of input +-- 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 memory 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 memory +-- table. +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryMatch ( + CONSTANT Symbol : IN VitalMemorySymbolType; + CONSTANT In2 : IN std_ulogic; + CONSTANT In2LastValue : IN std_ulogic; + VARIABLE Err : OUT BOOLEAN; + VARIABLE ReturnValue : OUT BOOLEAN +) IS +BEGIN + IF (NOT ValidMemoryTableInput(Symbol) ) THEN + PrintMemoryMessage(MsgVMT,ErrUnknSymbol,To_MemoryChar(Symbol)); + Err := TRUE; + ReturnValue := FALSE; + ELSE + ReturnValue := MemoryTableMatch(To_X01(In2LastValue), To_X01(In2), Symbol); + Err := FALSE; + END IF; +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryMatch ( + CONSTANT Symbol : IN VitalMemorySymbolType; + CONSTANT TestFlag : IN VitalMemorySymbolType; + VARIABLE Err : OUT BOOLEAN; + VARIABLE ReturnValue : OUT BOOLEAN +) IS +BEGIN + Err := FALSE; + ReturnValue := FALSE; + CASE Symbol IS + WHEN 'g'|'u'|'i'|'G'|'U'|'I'|'-'|'*'|'S' => + IF (Symbol = TestFlag) THEN + ReturnValue := TRUE; + ELSE + CASE Symbol IS + WHEN '-' => + ReturnValue := TRUE; + Err := FALSE; + WHEN '*' => + IF (TestFlag = 'G' OR + TestFlag = 'U' OR + TestFlag = 'I') THEN + ReturnValue := TRUE; + Err := FALSE; + END IF; + WHEN 'S' => + IF (TestFlag = 'g' OR + TestFlag = 'u' OR + TestFlag = 'i') THEN + ReturnValue := TRUE; + Err := FALSE; + END IF; + WHEN OTHERS => + ReturnValue := FALSE; + END CASE; + END IF; + WHEN OTHERS => + Err := TRUE; + RETURN; + END CASE; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: MemoryTableCorruptMask +-- Description: Compute memory and data corruption masks for memory table +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryTableCorruptMask ( + VARIABLE CorruptMask : OUT std_logic_vector; + CONSTANT Action : IN VitalMemorySymbolType; + CONSTANT EnableIndex : IN INTEGER; + CONSTANT BitsPerWord : IN INTEGER; + CONSTANT BitsPerSubWord : IN INTEGER; + CONSTANT BitsPerEnable : IN INTEGER +) IS + VARIABLE CorruptMaskTmp : std_logic_vector (CorruptMask'RANGE) + := (OTHERS => '0'); + VARIABLE ViolFlAryPosn : INTEGER; + VARIABLE HighBit : INTEGER; + VARIABLE LowBit : INTEGER; +BEGIN + CASE (Action) IS + WHEN 'c'|'l'|'e' => + -- Corrupt whole word + CorruptMaskTmp := (OTHERS => 'X'); + CorruptMask := CorruptMaskTmp; + RETURN; + WHEN 'd'|'C'|'L'|'D'|'E' => + -- Process corruption below + WHEN OTHERS => + -- No data or memory corruption + CorruptMaskTmp := (OTHERS => '0'); + CorruptMask := CorruptMaskTmp; + RETURN; + END CASE; + IF (Action = 'd') THEN + CorruptMaskTmp := (OTHERS => 'X'); + CorruptMask := CorruptMaskTmp; + RETURN; + END IF; + -- Remaining are subword cases 'C', 'L', 'D', 'E' + CorruptMaskTmp := (OTHERS => '0'); + LowBit := 0; + HighBit := BitsPerSubWord-1; + SubWordLoop: + FOR i IN 0 TO BitsPerEnable-1 LOOP + IF (i = EnableIndex) THEN + FOR j IN HighBit TO LowBit LOOP + CorruptMaskTmp(j) := 'X'; + END LOOP; + END IF; + -- Calculate HighBit and LowBit + LowBit := LowBit + BitsPerSubWord; + IF (LowBit > BitsPerWord) THEN + LowBit := BitsPerWord; + END IF; + HighBit := LowBit + BitsPerSubWord; + IF (HighBit > BitsPerWord) THEN + HighBit := BitsPerWord; + ELSE + HighBit := HighBit - 1; + END IF; + END LOOP; + CorruptMask := CorruptMaskTmp; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryTableCorruptMask ( + VARIABLE CorruptMask : OUT std_logic_vector; + CONSTANT Action : IN VitalMemorySymbolType +) IS + VARIABLE CorruptMaskTmp : std_logic_vector (0 TO CorruptMask'LENGTH-1) + := (OTHERS => '0'); + VARIABLE ViolFlAryPosn : INTEGER; + VARIABLE HighBit : INTEGER; + VARIABLE LowBit : INTEGER; +BEGIN + CASE (Action) IS + WHEN 'c'|'l'|'d'|'e'|'C'|'L'|'D'|'E' => + -- Corrupt whole word + CorruptMaskTmp := (OTHERS => 'X'); + CorruptMask := CorruptMaskTmp; + RETURN; + WHEN OTHERS => + -- No data or memory corruption + CorruptMaskTmp := (OTHERS => '0'); + CorruptMask := CorruptMaskTmp; + RETURN; + END CASE; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: MemoryTableCorruptMask +-- Description: Compute memory and data corruption masks for violation table +-- ---------------------------------------------------------------------------- +PROCEDURE ViolationTableCorruptMask ( + VARIABLE CorruptMask : OUT std_logic_vector; + CONSTANT Action : IN VitalMemorySymbolType; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationFlagsArray : IN std_logic_vector; + CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT TableIndex : IN INTEGER; + CONSTANT BitsPerWord : IN INTEGER; + CONSTANT BitsPerSubWord : IN INTEGER; + CONSTANT BitsPerEnable : IN INTEGER +) IS + VARIABLE CorruptMaskTmp : std_logic_vector (CorruptMask'RANGE) + := (OTHERS => '0'); + VARIABLE ViolMaskTmp : std_logic_vector (CorruptMask'RANGE) + := (OTHERS => '0'); + VARIABLE ViolFlAryPosn : INTEGER; + VARIABLE HighBit : INTEGER; + VARIABLE LowBit : INTEGER; + CONSTANT ViolFlagsSize : INTEGER := ViolationFlags'LENGTH; + CONSTANT ViolFlArySize : INTEGER := ViolationFlagsArray'LENGTH; + CONSTANT TableEntries : INTEGER := ViolationTable'LENGTH(1); + CONSTANT TableWidth : INTEGER := ViolationTable'LENGTH(2); + CONSTANT DatActionNdx : INTEGER := TableWidth - 1; + CONSTANT MemActionNdx : INTEGER := TableWidth - 2; +BEGIN + CASE (Action) IS + WHEN 'c'|'l'|'e' => + -- Corrupt whole word + CorruptMaskTmp := (OTHERS => 'X'); + CorruptMask := CorruptMaskTmp; + RETURN; + WHEN 'd'|'C'|'L'|'D'|'E' => + -- Process corruption below + WHEN OTHERS => + -- No data or memory corruption + CorruptMaskTmp := (OTHERS => '0'); + CorruptMask := CorruptMaskTmp; + RETURN; + END CASE; + RowLoop: -- Check each element of the ViolationFlags + FOR j IN 0 TO ViolFlagsSize LOOP + IF (j = ViolFlagsSize) THEN + ViolFlAryPosn := 0; + RowLoop2: -- Check relevant elements of the ViolationFlagsArray + FOR k IN 0 TO MemActionNdx - ViolFlagsSize - 1 LOOP + IF (ViolationTable(TableIndex, k + ViolFlagsSize) = 'X') THEN + MaskLoop: -- Set the 'X' bits in the violation mask + FOR m IN INTEGER RANGE 0 TO CorruptMask'LENGTH-1 LOOP + IF (m <= ViolationSizesArray(k)-1) THEN + ViolMaskTmp(m) := ViolMaskTmp(m) XOR + ViolationFlagsArray(ViolFlAryPosn+m); + ELSE + EXIT MaskLoop; + END IF; + END LOOP; + END IF; + ViolFlAryPosn := ViolFlAryPosn + ViolationSizesArray(k); + END LOOP; + ELSE + IF (ViolationTable(TableIndex, j) = 'X') THEN + ViolMaskTmp(0) := ViolMaskTmp(0) XOR ViolationFlags(j); + END IF; + END IF; + END LOOP; + IF (Action = 'd') THEN + CorruptMask := ViolMaskTmp; + RETURN; + END IF; + -- Remaining are subword cases 'C', 'L', 'D', 'E' + CorruptMaskTmp := (OTHERS => '0'); + LowBit := 0; + HighBit := BitsPerSubWord-1; + SubWordLoop: + FOR i IN 0 TO BitsPerEnable-1 LOOP + IF (ViolMaskTmp(i) = 'X') THEN + FOR j IN HighBit TO LowBit LOOP + CorruptMaskTmp(j) := 'X'; + END LOOP; + END IF; + -- Calculate HighBit and LowBit + LowBit := LowBit + BitsPerSubWord; + IF (LowBit > BitsPerWord) THEN + LowBit := BitsPerWord; + END IF; + HighBit := LowBit + BitsPerSubWord; + IF (HighBit > BitsPerWord) THEN + HighBit := BitsPerWord; + ELSE + HighBit := HighBit - 1; + END IF; + END LOOP; + CorruptMask := CorruptMaskTmp; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: MemoryTableLookUp +-- Parameters: MemoryAction - Output memory action to be performed +-- DataAction - Output data action to be performed +-- PrevControls - Previous data in for edge detection +-- PrevEnableBus - Previous enables for edge detection +-- Controls - Agregate of scalar control lines +-- EnableBus - Concatenation of vector control lines +-- EnableIndex - Current slice of vector control lines +-- AddrFlag - Matching symbol from address decoding +-- DataFlag - Matching symbol from data decoding +-- MemoryTable - Input memory action table +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control message output +-- +-- Description: This function is used to find the output of the +-- MemoryTable corresponding to a given set of inputs. +-- +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryTableLookUp ( + VARIABLE MemoryAction : OUT VitalMemorySymbolType; + VARIABLE DataAction : OUT VitalMemorySymbolType; + VARIABLE MemoryCorruptMask : OUT std_logic_vector; + VARIABLE DataCorruptMask : OUT std_logic_vector; + CONSTANT PrevControls : IN std_logic_vector; + CONSTANT Controls : IN std_logic_vector; + CONSTANT AddrFlag : IN VitalMemorySymbolType; + CONSTANT DataFlag : IN VitalMemorySymbolType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + CONSTANT ControlsSize : INTEGER := Controls'LENGTH; + CONSTANT TableEntries : INTEGER := MemoryTable'LENGTH(1); + CONSTANT TableWidth : INTEGER := MemoryTable'LENGTH(2); + CONSTANT DatActionNdx : INTEGER := TableWidth - 1; + CONSTANT MemActionNdx : INTEGER := TableWidth - 2; + CONSTANT DataInBusNdx : INTEGER := TableWidth - 3; + CONSTANT AddressBusNdx : INTEGER := TableWidth - 4; + VARIABLE AddrFlagTable : VitalMemorySymbolType; + VARIABLE Match : BOOLEAN; + VARIABLE Err : BOOLEAN := FALSE; + VARIABLE TableAlias : VitalMemoryTableType( + 0 TO TableEntries - 1, + 0 TO TableWidth - 1) + := MemoryTable; +BEGIN + ColLoop: -- Compare each entry in the table + FOR i IN TableAlias'RANGE(1) LOOP + RowLoop: -- Check each element of the Controls + FOR j IN 0 TO ControlsSize LOOP + IF (j = ControlsSize) THEN + -- a match occurred, now check AddrFlag, DataFlag + MemoryMatch(TableAlias(i,AddressBusNdx),AddrFlag,Err,Match); + IF (Match) THEN + MemoryMatch(TableAlias(i,DataInBusNdx),DataFlag,Err,Match); + IF (Match) THEN + MemoryTableCorruptMask ( + CorruptMask => MemoryCorruptMask , + Action => TableAlias(i, MemActionNdx) + ); + MemoryTableCorruptMask ( + CorruptMask => DataCorruptMask , + Action => TableAlias(i, DatActionNdx) + ); + -- get the return memory and data actions + MemoryAction := TableAlias(i, MemActionNdx); + DataAction := TableAlias(i, DatActionNdx); + -- DEBUG: The lines below report table search + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMT,TableAlias,i,PortName); + END IF; + -- DEBUG: The lines above report table search + RETURN; + END IF; + END IF; + ELSE + -- Match memory table inputs + MemoryMatch ( TableAlias(i,j), + Controls(j), PrevControls(j), + Err, Match); + END IF; + EXIT RowLoop WHEN NOT(Match); + EXIT ColLoop WHEN Err; + END LOOP RowLoop; + END LOOP ColLoop; + -- no match found, return default action + MemoryAction := 's'; -- no change to memory + DataAction := 'S'; -- no change to dataout + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMT,ErrDefMemAct,HeaderMsg,PortName); + END IF; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +PROCEDURE MemoryTableLookUp ( + VARIABLE MemoryAction : OUT VitalMemorySymbolType; + VARIABLE DataAction : OUT VitalMemorySymbolType; + VARIABLE MemoryCorruptMask : OUT std_logic_vector; + VARIABLE DataCorruptMask : OUT std_logic_vector; + CONSTANT PrevControls : IN std_logic_vector; + CONSTANT PrevEnableBus : IN std_logic_vector; + CONSTANT Controls : IN std_logic_vector; + CONSTANT EnableBus : IN std_logic_vector; + CONSTANT EnableIndex : IN INTEGER; + CONSTANT BitsPerWord : IN INTEGER; + CONSTANT BitsPerSubWord : IN INTEGER; + CONSTANT BitsPerEnable : IN INTEGER; + CONSTANT AddrFlag : IN VitalMemorySymbolType; + CONSTANT DataFlag : IN VitalMemorySymbolType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + CONSTANT ControlsSize : INTEGER := Controls'LENGTH; + CONSTANT TableEntries : INTEGER := MemoryTable'LENGTH(1); + CONSTANT TableWidth : INTEGER := MemoryTable'LENGTH(2); + CONSTANT DatActionNdx : INTEGER := TableWidth - 1; + CONSTANT MemActionNdx : INTEGER := TableWidth - 2; + CONSTANT DataInBusNdx : INTEGER := TableWidth - 3; + CONSTANT AddressBusNdx : INTEGER := TableWidth - 4; + VARIABLE AddrFlagTable : VitalMemorySymbolType; + VARIABLE Match : BOOLEAN; + VARIABLE Err : BOOLEAN := FALSE; + VARIABLE TableAlias : VitalMemoryTableType( + 0 TO TableEntries - 1, + 0 TO TableWidth - 1) + := MemoryTable; +BEGIN + ColLoop: -- Compare each entry in the table + FOR i IN TableAlias'RANGE(1) LOOP + RowLoop: -- Check each element of the Controls + FOR j IN 0 TO ControlsSize LOOP + IF (j = ControlsSize) THEN + -- a match occurred, now check EnableBus, AddrFlag, DataFlag + IF (EnableIndex >= 0) THEN + RowLoop2: -- Check relevant elements of the EnableBus + FOR k IN 0 TO AddressBusNdx - ControlsSize - 1 LOOP + MemoryMatch ( TableAlias(i,k + ControlsSize), + EnableBus(k * BitsPerEnable + EnableIndex), + PrevEnableBus(k * BitsPerEnable + EnableIndex), + Err, Match); + EXIT RowLoop2 WHEN NOT(Match); + END LOOP; + END IF; + IF (Match) THEN + MemoryMatch(TableAlias(i,AddressBusNdx),AddrFlag,Err,Match); + IF (Match) THEN + MemoryMatch(TableAlias(i,DataInBusNdx),DataFlag,Err,Match); + IF (Match) THEN + MemoryTableCorruptMask ( + CorruptMask => MemoryCorruptMask , + Action => TableAlias(i, MemActionNdx), + EnableIndex => EnableIndex , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable + ); + MemoryTableCorruptMask ( + CorruptMask => DataCorruptMask , + Action => TableAlias(i, DatActionNdx), + EnableIndex => EnableIndex , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable + ); + -- get the return memory and data actions + MemoryAction := TableAlias(i, MemActionNdx); + DataAction := TableAlias(i, DatActionNdx); + -- DEBUG: The lines below report table search + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMT,TableAlias,i,PortName); + END IF; + -- DEBUG: The lines above report table search + RETURN; + END IF; + END IF; + END IF; + ELSE + -- Match memory table inputs + MemoryMatch ( TableAlias(i,j), + Controls(j), PrevControls(j), + Err, Match); + END IF; + EXIT RowLoop WHEN NOT(Match); + EXIT ColLoop WHEN Err; + END LOOP RowLoop; + END LOOP ColLoop; + -- no match found, return default action + MemoryAction := 's'; -- no change to memory + DataAction := 'S'; -- no change to dataout + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMT,ErrDefMemAct,HeaderMsg,PortName); + END IF; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: ViolationTableLookUp +-- Parameters: MemoryAction - Output memory action to be performed +-- DataAction - Output data action to be performed +-- TimingDataArray - This is currently not used (comment out) +-- ViolationArray - Aggregation of violation variables +-- ViolationTable - Input memory violation table +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control message output +-- Description: This function is used to find the output of the +-- ViolationTable corresponding to a given set of inputs. +-- ---------------------------------------------------------------------------- +PROCEDURE ViolationTableLookUp ( + VARIABLE MemoryAction : OUT VitalMemorySymbolType; + VARIABLE DataAction : OUT VitalMemorySymbolType; + VARIABLE MemoryCorruptMask : OUT std_logic_vector; + VARIABLE DataCorruptMask : OUT std_logic_vector; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationFlagsArray : IN std_logic_vector; + CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT BitsPerWord : IN INTEGER; + CONSTANT BitsPerSubWord : IN INTEGER; + CONSTANT BitsPerEnable : IN INTEGER; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + CONSTANT ViolFlagsSize : INTEGER := ViolationFlags'LENGTH; + CONSTANT ViolFlArySize : INTEGER := ViolationFlagsArray'LENGTH; + VARIABLE ViolFlAryPosn : INTEGER; + VARIABLE ViolFlAryItem : std_ulogic; + CONSTANT ViolSzArySize : INTEGER := ViolationSizesArray'LENGTH; + CONSTANT TableEntries : INTEGER := ViolationTable'LENGTH(1); + CONSTANT TableWidth : INTEGER := ViolationTable'LENGTH(2); + CONSTANT DatActionNdx : INTEGER := TableWidth - 1; + CONSTANT MemActionNdx : INTEGER := TableWidth - 2; + VARIABLE HighBit : NATURAL := 0; + VARIABLE LowBit : NATURAL := 0; + VARIABLE Match : BOOLEAN; + VARIABLE Err : BOOLEAN := FALSE; + VARIABLE TableAlias : VitalMemoryTableType( + 0 TO TableEntries - 1, + 0 TO TableWidth - 1) + := ViolationTable; +BEGIN + ColLoop: -- Compare each entry in the table + FOR i IN TableAlias'RANGE(1) LOOP + RowLoop: -- Check each element of the ViolationFlags + FOR j IN 0 TO ViolFlagsSize LOOP + IF (j = ViolFlagsSize) THEN + ViolFlAryPosn := 0; + RowLoop2: -- Check relevant elements of the ViolationFlagsArray + FOR k IN 0 TO MemActionNdx - ViolFlagsSize - 1 LOOP + ViolFlAryItem := '0'; + SubwordLoop: -- Check for 'X' in ViolationFlagsArray chunk + FOR s IN ViolFlAryPosn TO ViolFlAryPosn+ViolationSizesArray(k)-1 LOOP + IF (ViolationFlagsArray(s) = 'X') THEN + ViolFlAryItem := 'X'; + EXIT SubwordLoop; + END IF; + END LOOP; + MemoryMatch ( TableAlias(i,k + ViolFlagsSize), + ViolFlAryItem,ViolFlAryItem, + Err, Match); + ViolFlAryPosn := ViolFlAryPosn + ViolationSizesArray(k); + EXIT RowLoop2 WHEN NOT(Match); + END LOOP; + IF (Match) THEN + -- Compute memory and data corruption masks + ViolationTableCorruptMask( + CorruptMask => MemoryCorruptMask , + Action => TableAlias(i, MemActionNdx), + ViolationFlags => ViolationFlags , + ViolationFlagsArray => ViolationFlagsArray , + ViolationSizesArray => ViolationSizesArray , + ViolationTable => ViolationTable , + TableIndex => i , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable + ); + ViolationTableCorruptMask( + CorruptMask => DataCorruptMask , + Action => TableAlias(i, DatActionNdx), + ViolationFlags => ViolationFlags , + ViolationFlagsArray => ViolationFlagsArray , + ViolationSizesArray => ViolationSizesArray , + ViolationTable => ViolationTable , + TableIndex => i , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable + ); + -- get the return memory and data actions + MemoryAction := TableAlias(i, MemActionNdx); + DataAction := TableAlias(i, DatActionNdx); + -- DEBUG: The lines below report table search + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMV,TableAlias,i,PortName); + END IF; + -- DEBUG: The lines above report table search + RETURN; + END IF; + ELSE + -- Match violation table inputs + Err := FALSE; + Match := FALSE; + IF (TableAlias(i,j) /= 'X' AND + TableAlias(i,j) /= '0' AND + TableAlias(i,j) /= '-') THEN + Err := TRUE; + ELSIF (TableAlias(i,j) = '-' OR + (TableAlias(i,j) = 'X' AND ViolationFlags(j) = 'X') OR + (TableAlias(i,j) = '0' AND ViolationFlags(j) = '0')) THEN + Match := TRUE; + END IF; + END IF; + EXIT RowLoop WHEN NOT(Match); + EXIT ColLoop WHEN Err; + END LOOP RowLoop; + END LOOP ColLoop; + -- no match found, return default action + MemoryAction := 's'; -- no change to memory + DataAction := 'S'; -- no change to dataout + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMV,ErrDefMemAct,HeaderMsg,PortName); + END IF; + RETURN; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: HandleMemoryAction +-- Parameters: MemoryData - Pointer to memory data structure +-- PortFlag - Indicates read/write mode of port +-- CorruptMask - XOR'ed with DataInBus when corrupting +-- DataInBus - Current data bus in +-- Address - Current address integer +-- HighBit - Current address high bit +-- LowBit - Current address low bit +-- MemoryTable - Input memory action table +-- MemoryAction - Memory action to be performed +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control message output +-- Description: This procedure performs the specified memory action on +-- the input memory data structure. +-- ---------------------------------------------------------------------------- +PROCEDURE HandleMemoryAction ( + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagType; + CONSTANT CorruptMask : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT HighBit : IN NATURAL; + CONSTANT LowBit : IN NATURAL; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT MemoryAction : IN VitalMemorySymbolType; + CONSTANT CallerName : IN STRING; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + VARIABLE DataInTmp : std_logic_vector(DataInBus'RANGE) + := DataInBus; + BEGIN + + -- Handle the memory action + CASE MemoryAction IS + + WHEN 'w' => + -- Writing data to memory + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrWrDatMem,HeaderMsg,PortName); + END IF; + WriteMemory(MemoryData,DataInBus,Address,HighBit,LowBit); + PortFlag.MemoryCurrent := WRITE; + + WHEN 's' => + -- Retaining previous memory contents + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrNoChgMem,HeaderMsg,PortName); + END IF; + -- Set memory current to quiet state + PortFlag.MemoryCurrent := READ; + + WHEN 'c' => + -- Corrupting entire memory with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrAllMem,HeaderMsg,PortName); + END IF; + DataInTmp := (OTHERS => 'X'); + -- No need to CorruptMask + FOR i IN 0 TO MemoryData.NoOfWords-1 LOOP + WriteMemory(MemoryData,DataInTmp,i); + END LOOP; + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'l' => + -- Corrupting a word in memory with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrWrdMem,HeaderMsg,PortName); + END IF; + DataInTmp := (OTHERS => 'X'); + -- No need to CorruptMask + WriteMemory(MemoryData,DataInTmp,Address); + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'd' => + -- Corrupting a single bit in memory with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrBitMem,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataInTmp,Address); + DataInTmp := DataInTmp XOR CorruptMask; + WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit); + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'e' => + -- Corrupting a word with 'X' based on data in + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrDatMem,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataInTmp,Address); + IF (DataInTmp /= DataInBus) THEN + DataInTmp := (OTHERS => 'X'); + -- No need to CorruptMask + WriteMemory(MemoryData,DataInTmp,Address); + END IF; + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'C' => + -- Corrupting a sub-word entire memory with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrAllSubMem,HeaderMsg,PortName); + END IF; + FOR i IN 0 TO MemoryData.NoOfWords-1 LOOP + ReadMemory(MemoryData,DataInTmp,i); + DataInTmp := DataInTmp XOR CorruptMask; + WriteMemory(MemoryData,DataInTmp,i,HighBit,LowBit); + END LOOP; + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'L' => + -- Corrupting a sub-word in memory with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrWrdSubMem,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataInTmp,Address); + DataInTmp := DataInTmp XOR CorruptMask; + WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit); + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'D' => + -- Corrupting a single bit of a memory sub-word with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrBitSubMem,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataInTmp,Address); + DataInTmp := DataInTmp XOR CorruptMask; + WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit); + PortFlag.MemoryCurrent := CORRUPT; + + WHEN 'E' => + -- Corrupting a sub-word with 'X' based on data in + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrDatSubMem,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataInTmp,Address); + IF (DataInBus(HighBit DOWNTO LowBit) /= + DataInTmp(HighBit DOWNTO LowBit)) THEN + DataInTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + WriteMemory(MemoryData,DataInTmp,Address,HighBit,LowBit); + END IF; + --PortFlag := WRITE; + PortFlag.MemoryCurrent := CORRUPT; + + WHEN '0' => + -- Assigning low level to memory location + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsg0Mem,HeaderMsg,PortName); + END IF; + DataInTmp := (OTHERS => '0'); + WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit); + PortFlag.MemoryCurrent := WRITE; + + WHEN '1' => + -- Assigning high level to memory location + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsg1Mem,HeaderMsg,PortName); + END IF; + DataInTmp := (OTHERS => '1'); + WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit); + PortFlag.MemoryCurrent := WRITE; + + WHEN 'Z' => + -- Assigning high impedence to memory location + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsgZMem,HeaderMsg,PortName); + END IF; + DataInTmp := (OTHERS => 'Z'); + WriteMemory(MemoryData,DataInTmp,Address, HighBit, LowBit); + PortFlag.MemoryCurrent := WRITE; + + WHEN OTHERS => + -- Unknown memory action + PortFlag.MemoryCurrent := UNDEF; + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrUnknMemDo,HeaderMsg,PortName); + END IF; + + END CASE; + + -- Note: HandleMemoryAction does not change the PortFlag.OutputDisable +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: HandleDataAction +-- Parameters: DataOutBus - Output result of the data action +-- MemoryData - Input pointer to memory data structure +-- PortFlag - Indicates read/write mode of port +-- CorruptMask - XOR'ed with DataInBus when corrupting +-- DataInBus - Current data bus in +-- Address - Current address integer +-- HighBit - Current address high bit +-- LowBit - Current address low bit +-- MemoryTable - Input memory action table +-- DataAction - Data action to be performed +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control message output +-- Description: This procedure performs the specified data action based +-- on the input memory data structure. Checks whether +-- the previous state is HighZ. If yes then portFlag +-- should be NOCHANGE for VMPD to ignore IORetain +-- corruption. The idea is that the first Z should be +-- propagated but later ones should be ignored. +-- ---------------------------------------------------------------------------- +PROCEDURE HandleDataAction ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagType; + CONSTANT CorruptMask : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT Address : IN INTEGER; + CONSTANT HighBit : IN NATURAL; + CONSTANT LowBit : IN NATURAL; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT DataAction : IN VitalMemorySymbolType; + CONSTANT CallerName : IN STRING; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + + VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) + := DataOutBus; + +BEGIN + + -- Handle the data action + CASE DataAction IS + + WHEN 'l' => + -- Corrupting data out with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrWrdOut,HeaderMsg,PortName); + END IF; + DataOutTmp := (OTHERS => 'X'); + -- No need to CorruptMask + PortFlag.DataCurrent := CORRUPT; + + WHEN 'd' => + -- Corrupting a single bit of data out with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrBitOut,HeaderMsg,PortName); + END IF; + DataOutTmp(HighBit DOWNTO LowBit) := + DataOutTmp(HighBit DOWNTO LowBit) XOR + CorruptMask(HighBit DOWNTO LowBit); + PortFlag.DataCurrent := CORRUPT; + + WHEN 'e' => + -- Corrupting data out with 'X' based on data in + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrDatOut,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataOutTmp,Address); + IF (DataOutTmp /= DataInBus) THEN + DataOutTmp := (OTHERS => 'X'); + -- No need to CorruptMask + END IF; + PortFlag.DataCurrent := CORRUPT; + + WHEN 'L' => + -- Corrupting data out sub-word with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrWrdSubOut,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataOutTmp,Address); + DataOutTmp(HighBit DOWNTO LowBit) := + DataOutTmp(HighBit DOWNTO LowBit) XOR + CorruptMask(HighBit DOWNTO LowBit); + PortFlag.DataCurrent := CORRUPT; + + WHEN 'D' => + -- Corrupting a single bit of data out sub-word with 'X' + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrBitSubOut,HeaderMsg,PortName); + END IF; + DataOutTmp(HighBit DOWNTO LowBit) := + DataOutTmp(HighBit DOWNTO LowBit) XOR + CorruptMask(HighBit DOWNTO LowBit); + PortFlag.DataCurrent := CORRUPT; + + WHEN 'E' => + -- Corrupting data out sub-word with 'X' based on data in + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrCrDatSubOut,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataOutTmp,Address); + IF (DataInBus(HighBit DOWNTO LowBit) /= + DataOutTmp(HighBit DOWNTO LowBit)) THEN + DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + -- No need to CorruptMask + END IF; + PortFlag.DataCurrent := CORRUPT; + + WHEN 'M' => + -- Implicit read from memory to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrImplOut,HeaderMsg,PortName); + END IF; + PortFlag.DataCurrent := READ; + + WHEN 'm' => + -- Reading data from memory to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrReadOut,HeaderMsg,PortName); + END IF; + ReadMemory(MemoryData,DataOutTmp,Address); + PortFlag.DataCurrent := READ; + + WHEN 't' => + -- Transfering from data in to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAssgOut,HeaderMsg,PortName); + END IF; + DataOutTmp := DataInBus; + PortFlag.DataCurrent := READ; + + WHEN '0' => + -- Assigning low level to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsg0Out,HeaderMsg,PortName); + END IF; + DataOutTmp := (OTHERS => '0'); + PortFlag.DataCurrent := READ; + + WHEN '1' => + -- Assigning high level to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsg1Out,HeaderMsg,PortName); + END IF; + DataOutTmp := (OTHERS => '1'); + PortFlag.DataCurrent := READ; + + WHEN 'Z' => + -- Assigning high impedence to data out + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsgZOut,HeaderMsg,PortName); + END IF; + DataOutTmp := (OTHERS => 'Z'); + PortFlag.DataCurrent := HIGHZ; + + WHEN 'S' => + -- Keeping data out at steady value + PortFlag.OutputDisable := TRUE; + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrAsgSOut,HeaderMsg,PortName); + END IF; + + WHEN OTHERS => + -- Unknown data action + PortFlag.DataCurrent := UNDEF; + IF (MsgOn) THEN + PrintMemoryMessage(CallerName,ErrUnknDatDo,HeaderMsg,PortName); + END IF; + + END CASE; + + DataOutBus(HighBit DOWNTO LowBit) := DataOutTmp(HighBit DOWNTO LowBit); + +END; + + +-- ---------------------------------------------------------------------------- +-- Memory Table Modeling Primitives +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalDeclareMemory +-- Parameters: NoOfWords - Number of words in the memory +-- NoOfBitsPerWord - Number of bits per word in memory +-- NoOfBitsPerSubWord - Number of bits per sub word +-- MemoryLoadFile - Name of data file to load +-- Description: This function is intended to be used to initialize +-- memory data declarations, i.e. to be executed duing +-- simulation elaboration time. Handles the allocation +-- and initialization of memory for the memory data. +-- Default NoOfBitsPerSubWord is NoOfBitsPerWord. +-- ---------------------------------------------------------------------------- +IMPURE FUNCTION VitalDeclareMemory ( + CONSTANT NoOfWords : IN POSITIVE; + CONSTANT NoOfBitsPerWord : IN POSITIVE; + CONSTANT MemoryLoadFile : IN string := ""; + CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE +) RETURN VitalMemoryDataType IS + VARIABLE MemoryPtr : VitalMemoryDataType; +BEGIN + MemoryPtr := VitalDeclareMemory( + NoOfWords => NoOfWords, + NoOfBitsPerWord => NoOfBitsPerWord, + NoOfBitsPerSubWord => NoOfBitsPerWord, + MemoryLoadFile => MemoryLoadFile, + BinaryLoadFile => BinaryLoadFile + ); + RETURN MemoryPtr; +END; + +-- ---------------------------------------------------------------------------- +IMPURE FUNCTION VitalDeclareMemory ( + CONSTANT NoOfWords : IN POSITIVE; + CONSTANT NoOfBitsPerWord : IN POSITIVE; + CONSTANT NoOfBitsPerSubWord : IN POSITIVE; + CONSTANT MemoryLoadFile : IN string := ""; + CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE +) RETURN VitalMemoryDataType IS + VARIABLE MemoryPtr : VitalMemoryDataType; + VARIABLE BitsPerEnable : NATURAL + := ((NoOfBitsPerWord-1) + /NoOfBitsPerSubWord)+1; +BEGIN + PrintMemoryMessage(MsgVDM,ErrInitMem); + MemoryPtr := new VitalMemoryArrayRecType '( + NoOfWords => NoOfWords, + NoOfBitsPerWord => NoOfBitsPerWord, + NoOfBitsPerSubWord => NoOfBitsPerSubWord, + NoOfBitsPerEnable => BitsPerEnable, + MemoryArrayPtr => NULL + ); + MemoryPtr.MemoryArrayPtr + := new MemoryArrayType (0 to MemoryPtr.NoOfWords - 1); + FOR i IN 0 TO MemoryPtr.NoOfWords - 1 LOOP + MemoryPtr.MemoryArrayPtr(i) + := new MemoryWordType (MemoryPtr.NoOfBitsPerWord - 1 DOWNTO 0); + END LOOP; + IF (MemoryLoadFile /= "") THEN + LoadMemory (MemoryPtr, MemoryLoadFile, BinaryLoadFile); + END IF; + RETURN MemoryPtr; +END; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryTable +-- Parameters: DataOutBus - Output candidate zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- PrevControls - Previous data in for edge detection +-- PrevEnableBus - Previous enables for edge detection +-- PrevDataInBus - Previous data bus for edge detection +-- PrevAddressBus - Previous address bus for edge detection +-- PortFlag - Indicates port operating mode +-- PortFlagArray - Vector form of PortFlag for sub-word +-- Controls - Agregate of scalar control lines +-- EnableBus - Concatenation of vector control lines +-- DataInBus - Input value of data bus in +-- AddressBus - Input value of address bus in +-- AddressValue - Decoded value of the AddressBus +-- MemoryTable - Input memory action table +-- PortType - The type of port (currently not used) +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- MsgSeverity - Control level of message generation +-- Description: This procedure implements the majority of the memory +-- modeling functionality via lookup of the memory action +-- tables and performing the specified actions if matches +-- are found, or the default actions otherwise. The +-- overloadings are provided for the word and sub-word +-- (using the EnableBus and PortFlagArray arguments) addressing +-- cases. +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryTable ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PrevControls : INOUT std_logic_vector; + VARIABLE PrevDataInBus : INOUT std_logic_vector; + VARIABLE PrevAddressBus : INOUT std_logic_vector; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT Controls : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressBus : IN std_logic_vector; + VARIABLE AddressValue : INOUT VitalAddressValueType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType := UNDEF; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) IS + + VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) + := DataOutBus; + VARIABLE MemoryAction : VitalMemorySymbolType; + VARIABLE DataAction : VitalMemorySymbolType; + VARIABLE HighBit : NATURAL := MemoryData.NoOfBitsPerWord-1; + VARIABLE LowBit : NATURAL := 0; + VARIABLE Address : INTEGER := 0; + VARIABLE PortFlagTmp : VitalPortFlagType; + VARIABLE AddrFlag : VitalMemorySymbolType := 'g'; -- good addr + VARIABLE DataFlag : VitalMemorySymbolType := 'g'; -- good data + VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE); + VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE); + +BEGIN + + -- Optimize for case when all current inputs are same as previous + IF (PrevDataInBus = DataInBus + AND PrevAddressBus = AddressBus + AND PrevControls = Controls + AND PortFlag(0).MemoryCurrent = PortFlag(0).MemoryPrevious + AND PortFlag(0).DataCurrent = PortFlag(0).DataPrevious) THEN + PortFlag(0).OutputDisable := TRUE; + RETURN; + END IF; + + PortFlag(0).DataPrevious := PortFlag(0).DataCurrent; + PortFlag(0).MemoryPrevious := PortFlag(0).MemoryCurrent; + PortFlag(0).OutputDisable := FALSE; + PortFlagTmp := PortFlag(0); + + -- Convert address bus to integer value and table lookup flag + DecodeAddress( + Address => Address , + AddrFlag => AddrFlag , + MemoryData => MemoryData , + PrevAddressBus => PrevAddressBus , + AddressBus => AddressBus + ); + + -- Interpret data bus as a table lookup flag + DecodeData ( + DataFlag => DataFlag , + PrevDataInBus => PrevDataInBus , + DataInBus => DataInBus , + HighBit => HighBit , + LowBit => LowBit + ); + + -- Lookup memory and data actions + MemoryTableLookUp( + MemoryAction => MemoryAction , + DataAction => DataAction , + MemoryCorruptMask => MemCorruptMask , + DataCorruptMask => DatCorruptMask , + PrevControls => PrevControls , + Controls => Controls , + AddrFlag => AddrFlag , + DataFlag => DataFlag , + MemoryTable => MemoryTable , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + -- Handle data action before memory action + -- This allows reading previous memory contents + HandleDataAction( + DataOutBus => DataOutTmp , + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => DatCorruptMask , + DataInBus => DataInBus , + Address => Address , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => MemoryTable , + DataAction => DataAction , + CallerName => MsgVMT , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + HandleMemoryAction( + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => MemCorruptMask , + DataInBus => DataInBus , + Address => Address , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => MemoryTable , + MemoryAction => MemoryAction , + CallerName => MsgVMT , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + -- Set the output PortFlag(0) value + IF (DataAction = 'S') THEN + PortFlagTmp.OutputDisable := TRUE; + END IF; + IF (PortFlagTmp.DataCurrent = PortFlagTmp.DataPrevious + AND PortFlagTmp.DataCurrent = HIGHZ) THEN + PortFlagTmp.OutputDisable := TRUE; + END IF; + PortFlag(0) := PortFlagTmp; + + -- Set previous values for subsequent edge detection + PrevControls := Controls; + PrevDataInBus := DataInBus; + PrevAddressBus := AddressBus; + + -- Set the candidate zero delay return value + DataOutBus := DataOutTmp; + + -- Set the output AddressValue for VitalMemoryCrossPorts + AddressValue := Address; + +END VitalMemoryTable; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryTable ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PrevControls : INOUT std_logic_vector; + VARIABLE PrevEnableBus : INOUT std_logic_vector; + VARIABLE PrevDataInBus : INOUT std_logic_vector; + VARIABLE PrevAddressBus : INOUT std_logic_vector; + VARIABLE PortFlagArray : INOUT VitalPortFlagVectorType; + CONSTANT Controls : IN std_logic_vector; + CONSTANT EnableBus : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressBus : IN std_logic_vector; + VARIABLE AddressValue : INOUT VitalAddressValueType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType := UNDEF; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) IS + + VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord; + VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord; + VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable; + VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) + := DataOutBus; + VARIABLE MemoryAction : VitalMemorySymbolType; + VARIABLE DataAction : VitalMemorySymbolType; + VARIABLE HighBit : NATURAL := BitsPerSubWord-1; + VARIABLE LowBit : NATURAL := 0; + VARIABLE Address : INTEGER := 0; + VARIABLE PortFlagTmp : VitalPortFlagType; + VARIABLE AddrFlag : VitalMemorySymbolType := 'g'; -- good addr + VARIABLE DataFlag : VitalMemorySymbolType := 'g'; -- good data + VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE); + VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE); + +BEGIN + + -- Optimize for case when all current inputs are same as previous + IF (PrevDataInBus = DataInBus + AND PrevAddressBus = AddressBus + AND PrevControls = Controls) THEN + CheckFlags: + FOR i IN 0 TO BitsPerEnable-1 LOOP + IF (PortFlagArray(i).MemoryCurrent /= PortFlagArray(i).MemoryPrevious + OR PortFlagArray(i).DataCurrent /= PortFlagArray(i).DataPrevious) THEN + EXIT CheckFlags; + END IF; + IF (i = BitsPerEnable-1) THEN + FOR j IN 0 TO BitsPerEnable-1 LOOP + PortFlagArray(j).OutputDisable := TRUE; + END LOOP; + RETURN; + END IF; + END LOOP; + END IF; + + -- Convert address bus to integer value and table lookup flag + DecodeAddress( + Address => Address, + AddrFlag => AddrFlag, + MemoryData => MemoryData, + PrevAddressBus => PrevAddressBus, + AddressBus => AddressBus + ); + + -- Perform independent operations for each sub-word + FOR i IN 0 TO BitsPerEnable-1 LOOP + + -- Set the output PortFlag(i) value + PortFlagArray(i).DataPrevious := PortFlagArray(i).DataCurrent; + PortFlagArray(i).MemoryPrevious := PortFlagArray(i).MemoryCurrent; + PortFlagArray(i).OutputDisable := FALSE; + PortFlagTmp := PortFlagArray(i); + + -- Interpret data bus as a table lookup flag + DecodeData ( + DataFlag => DataFlag , + PrevDataInBus => PrevDataInBus , + DataInBus => DataInBus , + HighBit => HighBit , + LowBit => LowBit + ); + + -- Lookup memory and data actions + MemoryTableLookUp( + MemoryAction => MemoryAction , + DataAction => DataAction , + MemoryCorruptMask => MemCorruptMask , + DataCorruptMask => DatCorruptMask , + PrevControls => PrevControls , + PrevEnableBus => PrevEnableBus , + Controls => Controls , + EnableBus => EnableBus , + EnableIndex => i , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable , + AddrFlag => AddrFlag , + DataFlag => DataFlag , + MemoryTable => MemoryTable , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + -- Handle data action before memory action + -- This allows reading previous memory contents + HandleDataAction( + DataOutBus => DataOutTmp , + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => DatCorruptMask , + DataInBus => DataInBus , + Address => Address , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => MemoryTable , + DataAction => DataAction , + CallerName => MsgVMT , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + HandleMemoryAction( + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => MemCorruptMask , + DataInBus => DataInBus , + Address => Address , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => MemoryTable , + MemoryAction => MemoryAction , + CallerName => MsgVMT , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + -- Set the output PortFlag(i) value + IF (DataAction = 'S') THEN + PortFlagTmp.OutputDisable := TRUE; + END IF; + IF (PortFlagTmp.DataCurrent = PortFlagTmp.DataPrevious + AND PortFlagTmp.DataCurrent = HIGHZ) THEN + PortFlagTmp.OutputDisable := TRUE; + END IF; + PortFlagArray(i) := PortFlagTmp; + + IF (i < BitsPerEnable-1) THEN + -- Calculate HighBit and LowBit + LowBit := LowBit + BitsPerSubWord; + IF (LowBit > BitsPerWord) THEN + LowBit := BitsPerWord; + END IF; + HighBit := LowBit + BitsPerSubWord; + IF (HighBit > BitsPerWord) THEN + HighBit := BitsPerWord; + ELSE + HighBit := HighBit - 1; + END IF; + END IF; + + END LOOP; + + -- Set previous values for subsequent edge detection + PrevControls := Controls; + PrevEnableBus := EnableBus; + PrevDataInBus := DataInBus; + PrevAddressBus := AddressBus; + + -- Set the candidate zero delay return value + DataOutBus := DataOutTmp; + + -- Set the output AddressValue for VitalMemoryCrossPorts + AddressValue := Address; + +END VitalMemoryTable; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryCrossPorts +-- Parameters: DataOutBus - Output candidate zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- SamePortFlag - Operating mode for same port +-- SamePortAddressValue - Operating modes for cross ports +-- CrossPortAddressArray - Decoded AddressBus for cross ports +-- CrossPortMode - Write contention and crossport read control +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- Description: These procedures control the effect of memory operations +-- on a given port due to operations on other ports in a +-- multi-port memory. +-- This includes data write through when reading and writing +-- to the same address, as well as write contention when +-- there are multiple write to the same address. +-- If addresses do not match then data bus is unchanged. +-- The DataOutBus can be diabled with 'Z' value. +-- If the WritePortFlag is 'CORRUPT', that would mean +-- that the whole memory is corrupted. So, for corrupting +-- the Read port, the Addresses need not be compared. +-- +-- CrossPortMode Enum Description +-- 1. CpRead Allows Cross Port Read Only +-- No contention checking. +-- 2. WriteContention Allows for write contention checks +-- only between multiple write ports +-- 3. ReadWriteContention Allows contention between read and +-- write ports. The action is to corrupt +-- the memory and the output bus. +-- 4. CpReadAndWriteContention Is a combination of 1 & 2 +-- 5. CpReadAndReadContention Allows contention between read and +-- write ports. The action is to corrupt +-- the dataout bus only. The cp read is +-- performed if not contending. +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryCrossPorts ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE SamePortFlag : INOUT VitalPortFlagVectorType; + CONSTANT SamePortAddressValue : IN VitalAddressValueType; + CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType; + CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType; + CONSTANT CrossPortMode : IN VitalCrossPortModeType + := CpReadAndWriteContention; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + + VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord; + VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord; + VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable; + VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) := (OTHERS => 'Z'); + VARIABLE MemoryTmp : std_logic_vector(DataOutBus'RANGE); + VARIABLE CrossPorts : NATURAL := CrossPortAddressArray'LENGTH; + VARIABLE LowBit : NATURAL := 0; + VARIABLE HighBit : NATURAL := BitsPerSubWord-1; + VARIABLE Address : VitalAddressValueType := SamePortAddressValue; + VARIABLE AddressJ : VitalAddressValueType; + VARIABLE AddressK : VitalAddressValueType; + VARIABLE PortFlagI : VitalPortFlagType; + VARIABLE PortFlagIJ : VitalPortFlagType; + VARIABLE PortFlagIK : VitalPortFlagType; + VARIABLE DoCpRead : BOOLEAN := FALSE; + VARIABLE DoWrCont : BOOLEAN := FALSE; + VARIABLE DoCpCont : BOOLEAN := FALSE; + VARIABLE DoRdWrCont : BOOLEAN := FALSE; + VARIABLE CpWrCont : BOOLEAN := FALSE; + VARIABLE ModeWrCont : BOOLEAN := + (CrossPortMode=WriteContention) OR + (CrossPortMode=CpReadAndWriteContention); + VARIABLE ModeCpRead : BOOLEAN := + (CrossPortMode=CpRead) OR + (CrossPortMode=CpReadAndWriteContention); + VARIABLE ModeCpCont : BOOLEAN := (CrossPortMode=ReadWriteContention); + VARIABLE ModeRdWrCont : BOOLEAN := (CrossPortMode=CpReadAndReadContention); + +BEGIN + + -- Check for disabled port (i.e. OTHERS => 'Z') + IF (DataOutBus = DataOutTmp) THEN + RETURN; + ELSE + DataOutTmp := DataOutBus; + END IF; + + -- Check for error in address + IF (Address < 0) THEN + RETURN; + END IF; + + ReadMemory(MemoryData,MemoryTmp,Address); + + SubWordLoop: -- For each slice of the sub-word I + FOR i IN 0 TO BitsPerEnable-1 LOOP + PortFlagI := SamePortFlag(i); + + -- For each cross port J: check with same port address + FOR j IN 0 TO CrossPorts-1 LOOP + PortFlagIJ := CrossPortFlagArray(i+j*BitsPerEnable); + AddressJ := CrossPortAddressArray(j); + IF (AddressJ < 0) THEN + NEXT; + END IF; + DoWrCont := (Address = AddressJ) AND + (ModeWrCont = TRUE) AND + ((PortFlagI.MemoryCurrent = WRITE) OR + (PortFlagI.MemoryCurrent = CORRUPT)) AND + ((PortFlagIJ.MemoryCurrent = WRITE) OR + (PortFlagIJ.MemoryCurrent = CORRUPT)) ; + DoCpRead := (Address = AddressJ) AND + (ModeCpRead = TRUE) AND + ((PortFlagI.MemoryCurrent = READ) OR + (PortFlagI.OutputDisable = TRUE)) AND + ((PortFlagIJ.MemoryCurrent = WRITE) OR + (PortFlagIJ.MemoryCurrent = CORRUPT)) ; + DoCpCont := (Address = AddressJ) AND + (ModeCpCont = TRUE) AND + ((PortFlagI.MemoryCurrent = READ) OR + (PortFlagI.OutputDisable = TRUE)) AND + ((PortFlagIJ.MemoryCurrent = WRITE) OR + (PortFlagIJ.MemoryCurrent = CORRUPT)) ; + DoRdWrCont:= (Address = AddressJ) AND + (ModeRdWrCont = TRUE) AND + ((PortFlagI.MemoryCurrent = READ) OR + (PortFlagI.OutputDisable = TRUE)) AND + ((PortFlagIJ.MemoryCurrent = WRITE) OR + (PortFlagIJ.MemoryCurrent = CORRUPT)) ; + IF (DoWrCont OR DoCpCont) THEN + -- Corrupt dataout and memory + MemoryTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + SamePortFlag(i).MemoryCurrent := CORRUPT; + SamePortFlag(i).DataCurrent := CORRUPT; + SamePortFlag(i).OutputDisable := FALSE; + EXIT; + END IF; + IF (DoCpRead) THEN + -- Update dataout with memory + DataOutTmp(HighBit DOWNTO LowBit) := + MemoryTmp(HighBit DOWNTO LowBit); + SamePortFlag(i).MemoryCurrent := READ; + SamePortFlag(i).DataCurrent := READ; + SamePortFlag(i).OutputDisable := FALSE; + EXIT; + END IF; + IF (DoRdWrCont) THEN + -- Corrupt dataout only + DataOutTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + SamePortFlag(i).DataCurrent := CORRUPT; + SamePortFlag(i).OutputDisable := FALSE; + EXIT; + END IF; + END LOOP; + + IF (i < BitsPerEnable-1) THEN + -- Calculate HighBit and LowBit + LowBit := LowBit + BitsPerSubWord; + IF (LowBit > BitsPerWord) THEN + LowBit := BitsPerWord; + END IF; + HighBit := LowBit + BitsPerSubWord; + IF (HighBit > BitsPerWord) THEN + HighBit := BitsPerWord; + ELSE + HighBit := HighBit - 1; + END IF; + END IF; + + END LOOP; -- SubWordLoop + + DataOutBus := DataOutTmp; + + IF (DoWrCont) THEN + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMCP,ErrMcpWrCont,HeaderMsg,PortName); + END IF; + WriteMemory(MemoryData,MemoryTmp,Address); + END IF; + + IF (DoCpCont) THEN + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMCP,ErrMcpCpCont,HeaderMsg,PortName); + END IF; + WriteMemory(MemoryData,MemoryTmp,Address); + END IF; + + IF (DoCpRead) THEN + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMCP,ErrMcpCpRead,HeaderMsg,PortName); + END IF; + END IF; + + IF (DoRdWrCont) THEN + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMCP,ErrMcpRdWrCo,HeaderMsg,PortName); + END IF; + END IF; + +END VitalMemoryCrossPorts; + +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryCrossPorts ( + VARIABLE MemoryData : INOUT VitalMemoryDataType; + CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType; + CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) IS + + VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord; + VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord; + VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable; + VARIABLE MemoryTmp : std_logic_vector(BitsPerWord-1 DOWNTO 0); + VARIABLE CrossPorts : NATURAL := CrossPortAddressArray'LENGTH; + VARIABLE LowBit : NATURAL := 0; + VARIABLE HighBit : NATURAL := BitsPerSubWord-1; + VARIABLE AddressJ : VitalAddressValueType; + VARIABLE AddressK : VitalAddressValueType; + VARIABLE PortFlagIJ : VitalPortFlagType; + VARIABLE PortFlagIK : VitalPortFlagType; + VARIABLE CpWrCont : BOOLEAN := FALSE; + +BEGIN + + SubWordLoop: -- For each slice of the sub-word I + FOR i IN 0 TO BitsPerEnable-1 LOOP + + -- For each cross port J: check with each cross port K + FOR j IN 0 TO CrossPorts-1 LOOP + PortFlagIJ := CrossPortFlagArray(i+j*BitsPerEnable); + AddressJ := CrossPortAddressArray(j); + -- Check for error in address + IF (AddressJ < 0) THEN + NEXT; + END IF; + ReadMemory(MemoryData,MemoryTmp,AddressJ); + -- For each cross port K + FOR k IN 0 TO CrossPorts-1 LOOP + IF (k <= j) THEN + NEXT; + END IF; + PortFlagIK := CrossPortFlagArray(i+k*BitsPerEnable); + AddressK := CrossPortAddressArray(k); + -- Check for error in address + IF (AddressK < 0) THEN + NEXT; + END IF; + CpWrCont := ( (AddressJ = AddressK) AND + (PortFlagIJ.MemoryCurrent = WRITE) AND + (PortFlagIK.MemoryCurrent = WRITE) ) OR + ( (PortFlagIJ.MemoryCurrent = WRITE) AND + (PortFlagIK.MemoryCurrent = CORRUPT) ) OR + ( (PortFlagIJ.MemoryCurrent = CORRUPT) AND + (PortFlagIK.MemoryCurrent = WRITE) ) OR + ( (PortFlagIJ.MemoryCurrent = CORRUPT) AND + (PortFlagIK.MemoryCurrent = CORRUPT) ) ; + IF (CpWrCont) THEN + -- Corrupt memory only + MemoryTmp(HighBit DOWNTO LowBit) := (OTHERS => 'X'); + EXIT; + END IF; + END LOOP; -- FOR k IN 0 TO CrossPorts-1 LOOP + IF (CpWrCont = TRUE) THEN + IF (MsgOn) THEN + PrintMemoryMessage(MsgVMCP,ErrMcpCpWrCont,HeaderMsg); + END IF; + WriteMemory(MemoryData,MemoryTmp,AddressJ); + END IF; + END LOOP; -- FOR j IN 0 TO CrossPorts-1 LOOP + + IF (i < BitsPerEnable-1) THEN + -- Calculate HighBit and LowBit + LowBit := LowBit + BitsPerSubWord; + IF (LowBit > BitsPerWord) THEN + LowBit := BitsPerWord; + END IF; + HighBit := LowBit + BitsPerSubWord; + IF (HighBit > BitsPerWord) THEN + HighBit := BitsPerWord; + ELSE + HighBit := HighBit - 1; + END IF; + END IF; + END LOOP; -- SubWordLoop + +END VitalMemoryCrossPorts; + + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryViolation +-- Parameters: DataOutBus - Output zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- PortFlag - Indicates port operating mode +-- TimingDataArray - This is currently not used (comment out) +-- ViolationArray - Aggregation of violation variables +-- DataInBus - Input value of data bus in +-- AddressBus - Input value of address bus in +-- AddressValue - Decoded value of the AddressBus +-- ViolationTable - Input memory violation table +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- MsgSeverity - Control level of message generation +-- Description: This procedure is intended to implement all actions on the +-- memory contents and data out bus as a result of timing viols. +-- It uses the memory action table to perform various corruption +-- policies specified by the user. +-- ---------------------------------------------------------------------------- + +PROCEDURE VitalMemoryViolation ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressValue : IN VitalAddressValueType; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationFlagsArray : IN X01ArrayT; + CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) IS + + VARIABLE BitsPerWord : NATURAL := MemoryData.NoOfBitsPerWord; + VARIABLE BitsPerSubWord : NATURAL := MemoryData.NoOfBitsPerSubWord; + VARIABLE BitsPerEnable : NATURAL := MemoryData.NoOfBitsPerEnable; + VARIABLE DataOutTmp : std_logic_vector(DataOutBus'RANGE) + := DataOutBus; + VARIABLE MemoryAction : VitalMemorySymbolType; + VARIABLE DataAction : VitalMemorySymbolType; + -- VMT relies on the corrupt masks so HighBit/LowBit are full word + VARIABLE HighBit : NATURAL := BitsPerWord-1; + VARIABLE LowBit : NATURAL := 0; + VARIABLE PortFlagTmp : VitalPortFlagType; + VARIABLE VFlagArrayTmp : std_logic_vector + (0 TO ViolationFlagsArray'LENGTH-1); + VARIABLE MemCorruptMask : std_logic_vector (DataOutBus'RANGE); + VARIABLE DatCorruptMask : std_logic_vector (DataOutBus'RANGE); + +BEGIN + + -- Don't do anything if given an error address + IF (AddressValue < 0) THEN + RETURN; + END IF; + + FOR i IN ViolationFlagsArray'RANGE LOOP + VFlagArrayTmp(i) := ViolationFlagsArray(i); + END LOOP; + + -- Lookup memory and data actions + ViolationTableLookUp( + MemoryAction => MemoryAction , + DataAction => DataAction , + MemoryCorruptMask => MemCorruptMask , + DataCorruptMask => DatCorruptMask , + ViolationFlags => ViolationFlags , + ViolationFlagsArray => VFlagArrayTmp , + ViolationSizesArray => ViolationSizesArray , + ViolationTable => ViolationTable , + BitsPerWord => BitsPerWord , + BitsPerSubWord => BitsPerSubWord , + BitsPerEnable => BitsPerEnable , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + + -- Need to read incoming PF value (was not before) + PortFlagTmp := PortFlag(0); + + IF (PortType = READ OR PortType = RDNWR) THEN + -- Handle data action before memory action + -- This allows reading previous memory contents + HandleDataAction( + DataOutBus => DataOutTmp , + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => DatCorruptMask , + DataInBus => DataInBus , + Address => AddressValue , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => ViolationTable , + DataAction => DataAction , + CallerName => MsgVMV , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + END IF; + + IF (PortType = WRITE OR PortType = RDNWR) THEN + HandleMemoryAction( + MemoryData => MemoryData , + PortFlag => PortFlagTmp , + CorruptMask => MemCorruptMask , + DataInBus => DataInBus , + Address => AddressValue , + HighBit => HighBit , + LowBit => LowBit , + MemoryTable => ViolationTable , + MemoryAction => MemoryAction , + CallerName => MsgVMV , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn + ); + END IF; + + -- Check if we need to turn off PF.OutputDisable + IF (DataAction /= 'S') THEN + PortFlagTmp.OutputDisable := FALSE; + -- Set the output PortFlag(0) value + -- Note that all bits of PortFlag get PortFlagTmp + FOR i IN PortFlag'RANGE LOOP + PortFlag(i) := PortFlagTmp; + END LOOP; + END IF; + + -- Set the candidate zero delay return value + DataOutBus := DataOutTmp; + +END; + +PROCEDURE VitalMemoryViolation ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressValue : IN VitalAddressValueType; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) IS + + VARIABLE VFlagArrayTmp : X01ArrayT (0 TO 0); + +BEGIN + + VitalMemoryViolation ( + DataOutBus => DataOutBus , + MemoryData => MemoryData , + PortFlag => PortFlag , + DataInBus => DataInBus , + AddressValue => AddressValue , + ViolationFlags => ViolationFlags , + ViolationFlagsArray => VFlagArrayTmp , + ViolationSizesArray => ( 0 => 0 ) , + ViolationTable => ViolationTable , + PortType => PortType , + PortName => PortName , + HeaderMsg => HeaderMsg , + MsgOn => MsgOn , + MsgSeverity => MsgSeverity + ); + +END; + +END Vital_Memory ; diff --git a/libraries/vital2000/memory_p.vhdl b/libraries/vital2000/memory_p.vhdl new file mode 100644 index 000000000..83874f45e --- /dev/null +++ b/libraries/vital2000/memory_p.vhdl @@ -0,0 +1,1729 @@ +-- ---------------------------------------------------------------------------- +-- Title : Standard VITAL Memory Package +-- : +-- Library : Vital_Memory +-- : +-- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 +-- : Ekambaram Balaji, LSI Logic Corporation +-- : Jose De Castro, Consultant +-- : Prakash Bare, GDA Technologies +-- : William Yam, LSI Logic Corporation +-- : Dennis Brophy, Model Technology +-- : +-- Purpose : This packages defines standard types, constants, functions +-- : and procedures for use in developing ASIC memory models. +-- : +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Ver:|Auth:| Date:| Changes Made: +-- 0.1 | eb |071796| First prototye as part of VITAL memory proposal +-- 0.2 | jdc |012897| Initial prototyping with proposed MTM scheme +-- 0.3 | jdc |090297| Extensive updates for TAG review (functional) +-- 0.4 | eb |091597| Changed naming conventions for VitalMemoryTable +-- | | | Added interface of VitalMemoryCrossPorts() & +-- | | | VitalMemoryViolation(). +-- 0.5 | jdc |092997| Completed naming changes thoughout package body. +-- | | | Testing with simgle port test model looks ok. +-- 0.6 | jdc |121797| Major updates to the packages: +-- | | | - Implement VitalMemoryCrossPorts() +-- | | | - Use new VitalAddressValueType +-- | | | - Use new VitalCrossPortModeType enum +-- | | | - Overloading without SamePort args +-- | | | - Honor erroneous address values +-- | | | - Honor ports disabled with 'Z' +-- | | | - Implement implicit read 'M' table symbol +-- | | | - Cleanup buses to use (H DOWNTO L) +-- | | | - Message control via MsgOn,HeaderMsg,PortName +-- | | | - Tested with 1P1RW,2P2RW,4P2R2W,4P4RW cases +-- 0.7 | jdc |052698| Bug fixes to the packages: +-- | | | - Fix failure with negative Address values +-- | | | - Added debug messages for VMT table search +-- | | | - Remove 'S' for action column (only 's') +-- | | | - Remove 's' for response column (only 'S') +-- | | | - Remove 'X' for action and response columns +-- 0.8 | jdc |061298| Implemented VitalMemoryViolation() +-- | | | - Minimal functionality violation tables +-- | | | - Missing: +-- | | | - Cannot handle wide violation variables +-- | | | - Cannot handle sub-word cases +-- | | | Fixed IIC version of MemoryMatch +-- | | | Fixed 'M' vs 'm' switched on debug output +-- | | | TO BE DONE: +-- | | | - Implement 'd' corrupting a single bit +-- | | | - Implement 'D' corrupting a single bit +-- 0.9 |eb/sc|080498| Added UNDEF value for VitalPortFlagType +-- 0.10|eb/sc|080798| Added CORRUPT value for VitalPortFlagType +-- 0.11|eb/sc|081798| Added overloaded function interface for +-- | | | VitalDeclareMemory +-- 0.14| jdc |113198| Merging of memory functionality and version +-- | | | 1.4 9/17/98 of timing package from Prakash +-- 0.15| jdc |120198| Major development of VMV functionality +-- 0.16| jdc |120298| Complete VMV functionlality for initial testing +-- | | | - New ViolationTableCorruptMask() procedure +-- | | | - New MemoryTableCorruptMask() procedure +-- | | | - HandleMemoryAction(): +-- | | | - Removed DataOutBus bogus output +-- | | | - Replaced DataOutTmp with DataInTmp +-- | | | - Added CorruptMask input handling +-- | | | - Implemented 'd','D' using CorruptMask +-- | | | - CorruptMask on 'd','C','L','D','E' +-- | | | - CorruptMask ignored on 'c','l','e' +-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT +-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT +-- | | | - Changed 'c','l','d','e' to ignore HighBit, LowBit +-- | | | - Changed 'C','L','D','E' to use HighBit, LowBit +-- | | | - HandleDataAction(): +-- | | | - Added CorruptMask input handling +-- | | | - Implemented 'd','D' using CorruptMask +-- | | | - CorruptMask on 'd','C','L','D','E' +-- | | | - CorruptMask ignored on 'l','e' +-- | | | - Changed 'l','d','e' to set PortFlag to CORRUPT +-- | | | - Changed 'L','D','E' to set PortFlag to CORRUPT +-- | | | - Changed 'l','d','e' to ignore HighBit, LowBit +-- | | | - Changed 'L','D','E' to use HighBit, LowBit +-- | | | - MemoryTableLookUp(): +-- | | | - Added MsgOn table debug output +-- | | | - Uses new MemoryTableCorruptMask() +-- | | | - ViolationTableLookUp(): +-- | | | - Uses new ViolationTableCorruptMask() +-- 0.17| jdc |120898| - Added VitalMemoryViolationSymbolType, +-- | | | VitalMemoryViolationTableType data +-- | | | types but not used yet (need to discuss) +-- | | | - Added overload for VitalMemoryViolation() +-- | | | which does not have array flags +-- | | | - Bug fixes for VMV functionality: +-- | | | - ViolationTableLookUp() not handling '-' in +-- | | | scalar violation matching +-- | | | - VitalMemoryViolation() now normalizes +-- | | | VFlagArrayTmp'LEFT as LSB before calling +-- | | | ViolationTableLookUp() for proper scanning +-- | | | - ViolationTableCorruptMask() had to remove +-- | | | normalization of CorruptMaskTmp and +-- | | | ViolMaskTmp for proper MSB:LSB corruption +-- | | | - HandleMemoryAction(), HandleDataAction() +-- | | | - Removed 'D','E' since not being used +-- | | | - Use XOR instead of OR for corrupt masks +-- | | | - Now 'd' is sensitive to HighBit, LowBit +-- | | | - Fixed LowBit overflow in bit writeable case +-- | | | - MemoryTableCorruptMask() +-- | | | - ViolationTableCorruptMask() +-- | | | - VitalMemoryTable() +-- | | | - VitalMemoryCrossPorts() +-- | | | - Fixed VitalMemoryViolation() failing on +-- | | | error AddressValue from earlier VMT() +-- | | | - Minor cleanup of code formatting +-- 0.18| jdc |032599| - In VitalDeclareMemory() +-- | | | - Added BinaryLoadFile formal arg and +-- | | | modified LoadMemory() to handle bin +-- | | | - Added NOCHANGE to VitalPortFlagType +-- | | | - For VitalCrossPortModeType +-- | | | - Added CpContention enum +-- | | | - In HandleDataAction() +-- | | | - Set PortFlag := NOCHANGE for 'S' +-- | | | - In HandleMemoryAction() +-- | | | - Set PortFlag := NOCHANGE for 's' +-- | | | - In VitalMemoryTable() and +-- | | | VitalMemoryViolation() +-- | | | - Honor PortFlag = NOCHANGE returned +-- | | | from HandleMemoryAction() +-- | | | - In VitalMemoryCrossPorts() +-- | | | - Fixed Address = AddressJ for all +-- | | | conditions of DoWrCont & DoCpRead +-- | | | - Handle CpContention like WrContOnly +-- | | | under CpReadOnly conditions, with +-- | | | associated memory message changes +-- | | | - Handle PortFlag = NOCHANGE like +-- | | | PortFlag = READ for actions +-- | | | - Modeling change: +-- | | | - Need to init PortFlag every delta +-- | | | PortFlag_A := (OTHES => UNDEF); +-- | | | - Updated InternalTimingCheck code +-- 0.19| jdc |042599| - Fixes for bit-writeable cases +-- | | | - Check PortFlag after HandleDataAction +-- | | | in VitalMemoryViolation() +-- 0.20| jdc |042599| - Merge PortFlag changes from Prakash +-- | | | and Willian: +-- | | | VitalMemorySchedulePathDelay() +-- | | | VitalMemoryExpandPortFlag() +-- 0.21| jdc |072199| - Changed VitalCrossPortModeType enums, +-- | | | added new CpReadAndReadContention. +-- | | | - Fixed VitalMemoryCrossPorts() parameter +-- | | | SamePortFlag to INOUT so that it can +-- | | | set CORRUPT or READ value. +-- | | | - Fixed VitalMemoryTable() where PortFlag +-- | | | setting by HandleDataAction() is being +-- | | | ignored when HandleMemoryAction() sets +-- | | | PortFlagTmp to NOCHANGE. +-- | | | - Fixed VitalMemoryViolation() to set +-- | | | all bits of PortFlag when violating. +-- 0.22| jdc |072399| - Added HIGHZ to PortFlagType. HandleData +-- | | | checks whether the previous state is HIGHZ. +-- | | | If yes then portFlag should be NOCHANGE +-- | | | for VMPD to ignore IORetain corruption. +-- | | | The idea is that the first Z should be +-- | | | propagated but later ones should be ignored. +-- | | | +-- 0.23| jdc |100499| - Took code checked in by Dennis 09/28/99 +-- | | | - Changed VitalPortFlagType to record of +-- | | | new VitalPortStateType to hold current, +-- | | | previous values and separate disable. +-- | | | Also created VitalDefaultPortFlag const. +-- | | | Removed usage of PortFlag NOCHANGE +-- | | | - VitalMemoryTable() changes: +-- | | | Optimized return when all curr = prev +-- | | | AddressValue is now INOUT to optimize +-- | | | Transfer PF.MemoryCurrent to MemoryPrevious +-- | | | Transfer PF.DataCurrent to DataPrevious +-- | | | Reset PF.OutputDisable to FALSE +-- | | | Expects PortFlag init in declaration +-- | | | No need to init PortFlag every delta +-- | | | - VitalMemorySchedulePathDelay() changes: +-- | | | Initialize with VitalDefaultPortFlag +-- | | | Check PortFlag.OutputDisable +-- | | | - HandleMemoryAction() changes: +-- | | | Set value of PortFlag.MemoryCurrent +-- | | | Never set PortFlag.OutputDisable +-- | | | - HandleDataAction() changes: +-- | | | Set value of PortFlag.DataCurrent +-- | | | Set PortFlag.DataCurrent for HIGHZ +-- | | | - VitalMemoryCrossPorts() changes: +-- | | | Check/set value of PF.MemoryCurrent +-- | | | Check value of PF.OutputDisable +-- | | | - VitalMemoryViolation() changes: +-- | | | Fixed bug - not reading inout PF value +-- | | | Clean up setting of PortFlag +-- 0.24| jdc |100899| - Modified update of PF.OutputDisable +-- | | | to correctly accomodate 2P1W1R case: +-- | | | the read port should not exhibit +-- | | | IO retain corrupt when reading +-- | | | addr unrelated to addr being written. +-- 0.25| jdc |100999| - VitalMemoryViolation() change: +-- | | | Fixed bug with RDNWR mode incorrectly +-- | | | updating the PF.OutputDisable +-- 0.26| jdc |100999| - VitalMemoryCrossPorts() change: +-- | | | Fixed bugs with update of PF +-- 0.27| jdc |101499| - VitalMemoryCrossPorts() change: +-- | | | Added DoRdWrCont message (ErrMcpRdWrCo, +-- | | | Memory cross port read/write data only +-- | | | contention) +-- | | | - VitalMemoryTable() change: +-- | | | Set PF.OutputDisable := TRUE for the +-- | | | optimized cases. +-- 0.28| pb |112399| - Added 8 VMPD procedures for vector +-- | | | PathCondition support. Now the total +-- | | | number of overloadings for VMPD is 24. +-- | | | - Number of overloadings for SetupHold +-- | | | procedures increased to 5. Scalar violations +-- | | | are not supported anymore. Vector checkEnabled +-- | | | support is provided through the new overloading +-- 0.29| jdc |120999| - HandleMemoryAction() HandleDataAction() +-- | | | Reinstated 'D' and 'E' actions but +-- | | | with new PortFlagType +-- | | | - Updated file handling syntax, must compile +-- | | | with -93 syntax now. +-- 0.30| jdc |022300| - Formated for 80 column max width +-- ---------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.Vital_Timing.ALL; +USE IEEE.Vital_Primitives.ALL; + +LIBRARY STD; +USE STD.TEXTIO.ALL; + +PACKAGE Vital_Memory IS + +-- ---------------------------------------------------------------------------- +-- Timing Section +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- Types and constants for Memory timing procedures +-- ---------------------------------------------------------------------------- +TYPE VitalMemoryArcType IS (ParallelArc, CrossArc, SubwordArc); +TYPE OutputRetainBehaviorType IS (BitCorrupt, WordCorrupt); +TYPE VitalMemoryMsgFormatType IS (Vector, Scalar, VectorEnum); +TYPE X01ArrayT IS ARRAY (NATURAL RANGE <> ) OF X01; +TYPE X01ArrayPT IS ACCESS X01ArrayT; +TYPE VitalMemoryViolationType IS ACCESS X01ArrayT; +CONSTANT DefaultNumBitsPerSubword : INTEGER := -1; + + +-- Data type storing path delay and schedule information for output bits +TYPE VitalMemoryScheduleDataType IS RECORD + OutputData : std_ulogic; + NumBitsPerSubWord : INTEGER; + ScheduleTime : TIME; + ScheduleValue : std_ulogic; + LastOutputValue : std_ulogic; + PropDelay : TIME; + OutputRetainDelay : TIME; + InputAge : TIME; +END RECORD; + +TYPE VitalMemoryTimingDataType IS RECORD + NotFirstFlag : BOOLEAN; + RefLast : X01; + RefTime : TIME; + HoldEn : BOOLEAN; + TestLast : std_ulogic; + TestTime : TIME; + SetupEn : BOOLEAN; + TestLastA : VitalLogicArrayPT; + TestTimeA : VitalTimeArrayPT; + RefLastA : X01ArrayPT; + RefTimeA : VitalTimeArrayPT; + HoldEnA : VitalBoolArrayPT; + SetupEnA : VitalBoolArrayPT; +END RECORD; + +TYPE VitalPeriodDataArrayType IS ARRAY (NATURAL RANGE <>) OF + VitalPeriodDataType; + +-- Data type storing path delay and schedule information for output +-- vectors +TYPE VitalMemoryScheduleDataVectorType IS ARRAY (NATURAL RANGE <> ) OF + VitalMemoryScheduleDataType; + +-- VitalPortFlagType records runtime mode of port sub-word slices +-- TYPE VitalPortFlagType IS ( +-- UNDEF, +-- READ, +-- WRITE, +-- CORRUPT, +-- HIGHZ, +-- NOCHANGE +-- ); + +-- VitalPortFlagType records runtime mode of port sub-word slices +TYPE VitalPortStateType IS ( + UNDEF, + READ, + WRITE, + CORRUPT, + HIGHZ +); + +TYPE VitalPortFlagType IS RECORD + MemoryCurrent : VitalPortStateType; + MemoryPrevious : VitalPortStateType; + DataCurrent : VitalPortStateType; + DataPrevious : VitalPortStateType; + OutputDisable : BOOLEAN; +END RECORD; + +CONSTANT VitalDefaultPortFlag : VitalPortFlagType := ( + MemoryCurrent => READ, + MemoryPrevious => UNDEF, + DataCurrent => READ, + DataPrevious => UNDEF, + OutputDisable => FALSE +); + +-- VitalPortFlagVectorType to be same width i as enables of a port +-- or j multiples thereof, where j is the number of cross ports +TYPE VitalPortFlagVectorType IS + ARRAY (NATURAL RANGE <>) OF VitalPortFlagType; + +-- ---------------------------------------------------------------------------- +-- Functions : VitalMemory path delay procedures +-- - VitalMemoryInitPathDelay +-- - VitalMemoryAddPathDelay +-- - VitalMemorySchedulePathDelay +-- +-- Description: VitalMemoryInitPathDelay, VitalMemoryAddPathDelay and +-- VitalMemorySchedulePathDelay are Level 1 routines used +-- for selecting the propagation delay paths based on +-- path condition, transition type and delay values and +-- schedule a new output value. +-- +-- Following features are implemented in these procedures: +-- o condition dependent path selection +-- o Transition dependent delay selection +-- o shortest delay path selection from multiple +-- candidate paths +-- o Scheduling of the computed values on the specified +-- signal. +-- o output retain behavior if outputRetain flag is set +-- o output mapping to alternate strengths to model +-- pull-up, pull-down etc. +-- +-- +-- +-- Following is information on overloading of the procedures. +-- +-- VitalMemoryInitPathDelay is overloaded for ScheduleDataArray and +-- OutputDataArray +-- +-- ---------------------------------------------------------------------------- +-- ScheduleDataArray OutputDataArray +-- ---------------------------------------------------------------------------- +-- Scalar Scalar +-- Vector Vector +-- ---------------------------------------------------------------------------- +-- +-- +-- VitalMemoryAddPathDelay is overloaded for ScheduleDataArray, +-- PathDelayArray, InputSignal and delaytype. +-- +-- ---------------------------------------------------------------------------- +-- DelayType InputSignal ScheduleData PathDelay +-- Array Array +-- ---------------------------------------------------------------------------- +-- VitalDelayType Scalar Scalar Scalar +-- VitalDelayType Scalar Vector Vector +-- VitalDelayType Vector Scalar Vector +-- VitalDelayType Vector Vector Vector +-- VitalDelayType01 Scalar Scalar Scalar +-- VitalDelayType01 Scalar Vector Vector +-- VitalDelayType01 Vector Scalar Vector +-- VitalDelayType01 Vector Vector Vector +-- VitalDelayType01Z Scalar Scalar Scalar +-- VitalDelayType01Z Scalar Vector Vector +-- VitalDelayType01Z Vector Scalar Vector +-- VitalDelayType01Z Vector Vector Vector +-- VitalDelayType01XZ Scalar Scalar Scalar +-- VitalDelayType01XZ Scalar Vector Vector +-- VitalDelayType01XZ Vector Scalar Vector +-- VitalDelayType01XZ Vector Vector Vector +-- ---------------------------------------------------------------------------- +-- +-- +-- VitalMemorySchedulePathDelay is overloaded for ScheduleDataArray, +-- and OutSignal +-- +-- ---------------------------------------------------------------------------- +-- OutSignal ScheduleDataArray +-- ---------------------------------------------------------------------------- +-- Scalar Scalar +-- Vector Vector +-- ---------------------------------------------------------------------------- +-- +-- Procedure Declarations: +-- +-- +-- Function : VitalMemoryInitPathDelay +-- +-- Arguments: +-- +-- INOUT Type Description +-- +-- ScheduleDataArray/ VitalMemoryScheduleDataVectorType/ +-- ScheduleData VitalMemoryScheduleDataType +-- Internal data variable for +-- storing delay and schedule +-- information for each output bit +-- +-- +-- IN +-- +-- OutputDataArray/ STD_LOGIC_VECTOR/Array containing current output +-- OutputData STD_ULOGIC value +-- +-- +-- NumBitsPerSubWord INTEGER Number of bits per subword. +-- Default value of this argument +-- is DefaultNumBitsPerSubword +-- which is interpreted as no +-- subwords +-- +-- ---------------------------------------------------------------------------- +-- +-- +-- ScheduleDataArray - Vector +-- OutputDataArray - Vector +-- +PROCEDURE VitalMemoryInitPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + VARIABLE OutputDataArray : IN STD_LOGIC_VECTOR; + CONSTANT NumBitsPerSubWord : IN INTEGER := DefaultNumBitsPerSubword +); +-- +-- ScheduleDataArray - Scalar +-- OutputDataArray - Scalar +-- +PROCEDURE VitalMemoryInitPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + VARIABLE OutputData : IN STD_ULOGIC +); + +-- ---------------------------------------------------------------------------- +-- +-- Function : VitalMemoryAddPathDelay +-- +-- Arguments +-- +-- INOUT Type Description +-- +-- ScheduleDataArray/ VitalMemoryScheduleDataVectorType/ +-- ScheduleData VitalMemoryScheduleDataType +-- Internal data variable for +-- storing delay and schedule +-- information for each output bit +-- +-- InputChangeTimeArray/ VitaltimeArrayT/Time +-- InputChangeTime Holds the time since the last +-- input change +-- +-- IN +-- +-- InputSignal STD_LOGIC_VECTOR +-- STD_ULOGIC/ Array holding the input value +-- +-- OutputSignalName STRING The output signal name +-- +-- PathDelayArray/ VitalDelayArrayType01ZX, +-- PathDelay VitalDelayArrayType01Z, +-- VitalDelayArrayType01, +-- VitalDelayArrayType/ +-- VitalDelayType01ZX, +-- VitalDelayType01Z, +-- VitalDelayType01, +-- VitalDelayType Array of delay values +-- +-- ArcType VitalMemoryArcType +-- Indicates the Path type. This +-- can be SubwordArc, CrossArc or +-- ParallelArc +-- +-- PathCondition BOOLEAN If True, the transition in +-- the corresponding input signal +-- is considered while +-- caluculating the prop. delay +-- else the transition is ignored. +-- +-- OutputRetainFlag BOOLEAN If specified TRUE,output retain +-- (hold) behavior is implemented. +-- +-- ---------------------------------------------------------------------------- +-- +-- #1 +-- DelayType - VitalDelayType +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelay : IN VitalDelayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #2 +-- DelayType - VitalDelayType +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #3 +-- DelayType - VitalDelayType +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT +); + +-- #4 +-- DelayType - VitalDelayType +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #5 +-- DelayType - VitalDelayType +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #6 +-- DelayType - VitalDelayType +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT +); + +-- #7 +-- DelayType - VitalDelayType01 +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelay : IN VitalDelayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #8 +-- DelayType - VitalDelayType01 +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #9 +-- DelayType - VitalDelayType01 +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT +); + +-- #10 +-- DelayType - VitalDelayType01 +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #11 +-- DelayType - VitalDelayType01 +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE +); + +-- #12 +-- DelayType - VitalDelayType01 +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT +); + +-- #13 +-- DelayType - VitalDelayType01Z +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelay : IN VitalDelayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #14 +-- DelayType - VitalDelayType01Z +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #15 +-- DelayType - VitalDelayType01Z +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #16 +-- DelayType - VitalDelayType01Z +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- #17 +-- DelayType - VitalDelayType01Z +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- #18 +-- DelayType - VitalDelayType01Z +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01Z; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- #19 +-- DelayType - VitalDelayType01ZX +-- Input - Scalar +-- Output - Scalar +-- Delay - Scalar +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelay : IN VitalDelayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #20 +-- DelayType - VitalDelayType01ZX +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #21 +-- DelayType - VitalDelayType01ZX +-- Input - Scalar +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_ULOGIC; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTime : INOUT Time; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray: IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE +); + +-- #22 +-- DelayType - VitalDelayType01ZX +-- Input - Vector +-- Output - Scalar +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- #23 +-- DelayType - VitalDelayType01ZX +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Scalar + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathCondition : IN BOOLEAN := TRUE; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- #24 +-- DelayType - VitalDelayType01ZX +-- Input - Vector +-- Output - Vector +-- Delay - Vector +-- Condition - Vector + +PROCEDURE VitalMemoryAddPathDelay ( + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType; + SIGNAL InputSignal : IN STD_LOGIC_VECTOR; + CONSTANT OutputSignalName : IN STRING := ""; + VARIABLE InputChangeTimeArray : INOUT VitalTimeArrayT; + CONSTANT PathDelayArray : IN VitalDelayArrayType01ZX; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT PathConditionArray : IN VitalBoolArrayT; + CONSTANT OutputRetainFlag : IN BOOLEAN := FALSE; + CONSTANT OutputRetainBehavior : IN OutputRetainBehaviorType := BitCorrupt +); + +-- ---------------------------------------------------------------------------- +-- +-- Function : VitalMemorySchedulePathDelay +-- +-- Arguments: +-- +-- OUT Type Description +-- OutSignal STD_LOGIC_VECTOR/ The output signal for +-- STD_ULOGIC scheduling +-- +-- IN +-- OutputSignalName STRING The name of the output signal +-- +-- IN +-- PortFlag VitalPortFlagType Port flag variable from +-- functional procedures +-- +-- IN +-- OutputMap VitalOutputMapType For VitalPathDelay01Z, the +-- output can be mapped to +-- alternate strengths to model +-- tri-state devices, pull-ups +-- and pull-downs. +-- +-- INOUT +-- ScheduleDataArray/ VitalMemoryScheduleDataVectorType/ +-- ScheduleData VitalMemoryScheduleDataType +-- Internal data variable for +-- storing delay and schedule +-- information for each +-- output bit +-- +-- ---------------------------------------------------------------------------- +-- +-- ScheduleDataArray - Vector +-- OutputSignal - Vector +-- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT std_logic_vector; + CONSTANT OutputSignalName : IN STRING := ""; + CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType +); +-- +-- ScheduleDataArray - Vector +-- OutputSignal - Vector +-- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT std_logic_vector; + CONSTANT OutputSignalName : IN STRING := ""; + CONSTANT PortFlag : IN VitalPortFlagVectorType; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + VARIABLE ScheduleDataArray : INOUT VitalMemoryScheduleDataVectorType +); +-- +-- ScheduleDataArray - Scalar +-- OutputSignal - Scalar +-- +PROCEDURE VitalMemorySchedulePathDelay ( + SIGNAL OutSignal : OUT std_ulogic; + CONSTANT OutputSignalName : IN STRING := ""; + CONSTANT PortFlag : IN VitalPortFlagType := VitalDefaultPortFlag; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + VARIABLE ScheduleData : INOUT VitalMemoryScheduleDataType +); + +-- ---------------------------------------------------------------------------- +FUNCTION VitalMemoryTimingDataInit RETURN VitalMemoryTimingDataType; + +-- ---------------------------------------------------------------------------- +-- +-- Function Name: VitalMemorySetupHoldCheck +-- +-- Description: The VitalMemorySetupHoldCheck procedure detects a setup or a +-- hold violation on the input test signal with respect +-- to the corresponding input reference signal. The timing +-- constraints are specified through parameters +-- representing the high and low values for the setup and +-- hold values for the setup and hold times. This +-- procedure assumes non-negative values for setup and hold +-- timing constraints. +-- +-- It is assumed that negative timing constraints +-- are handled by internally delaying the test or +-- reference signals. Negative setup times result in +-- a delayed reference signal. Negative hold times +-- result in a delayed test signal. Furthermore, the +-- delays and constraints associated with these and +-- other signals may need to be appropriately +-- adjusted so that all constraint intervals overlap +-- the delayed reference signals and all constraint +-- values (with respect to the delayed signals) are +-- non-negative. +-- +-- This function is overloaded based on the input +-- TestSignal and reference signals. Parallel, Subword and +-- Cross Arc relationships between test and reference +-- signals are supported. +-- +-- TestSignal XXXXXXXXXXXX____________________________XXXXXXXXXXXXXXXXXXXXXX +-- : +-- : -->| error region |<-- +-- : +-- _______________________________ +-- RefSignal \______________________________ +-- : | | | +-- : | -->| |<-- thold +-- : -->| tsetup |<-- +-- +-- Arguments: +-- +-- IN Type Description +-- TestSignal std_logic_vector Value of test signal +-- TestSignalName STRING Name of test signal +-- TestDelay VitalDelayArrayType Model's internal delay associated +-- with TestSignal +-- RefSignal std_ulogic Value of reference signal +-- std_logic_vector +-- RefSignalName STRING Name of reference signal +-- RefDelay TIME Model's internal delay associated +-- VitalDelayArrayType with RefSignal +-- SetupHigh VitalDelayArrayType Absolute minimum time duration +-- before the transition of RefSignal +-- for which transitions of +-- TestSignal are allowed to proceed +-- to the "1" state without causing +-- a setup violation. +-- SetupLow VitalDelayArrayType Absolute minimum time duration +-- before the transition of RefSignal +-- for which transitions of +-- TestSignal are allowed to proceed +-- to the "0" state without causing +-- a setup violation. +-- HoldHigh VitalDelayArrayType Absolute minimum time duration +-- after the transition of RefSignal +-- for which transitions of +-- TestSignal are allowed to +-- proceed to the "1" state without +-- causing a hold violation. +-- HoldLow VitalDelayArrayType Absolute minimum time duration +-- after the transition of RefSignal +-- for which transitions of +-- TestSignal are allowed to +-- proceed to the "0" state without +-- causing a hold violation. +-- CheckEnabled BOOLEAN Check performed if TRUE. +-- RefTransition VitalEdgeSymbolType +-- Reference edge specified. Events +-- on the RefSignal which match the +-- edge spec. are used as reference +-- edges. +-- ArcType VitalMemoryArcType +-- NumBitsPerSubWord INTEGER +-- HeaderMsg STRING String that will accompany any +-- assertion messages produced. +-- XOn BOOLEAN If TRUE, Violation output +-- parameter is set to "X". +-- Otherwise, Violation is always +-- set to "0." +-- MsgOn BOOLEAN If TRUE, set and hold violation +-- message will be generated. +-- Otherwise, no messages are +-- generated, even upon violations. +-- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. +-- MsgFormat VitalMemoryMsgFormatType +-- Format of the Test/Reference +-- signals in violation messages. +-- +-- INOUT +-- TimingData VitalMemoryTimingDataType +-- VitalMemorySetupHoldCheck information +-- storage area. This is used +-- internally to detect reference +-- edges and record the time of the +-- last edge. +-- +-- OUT +-- Violation X01 This is the violation flag returned. +-- X01ArrayT Overloaded for array type. +-- +-- +-- ---------------------------------------------------------------------------- + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + 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 VitalDelayType; + CONSTANT SetupLow : IN VitalDelayType; + CONSTANT HoldHigh : IN VitalDelayType; + CONSTANT HoldLow : IN VitalDelayType; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArrayType; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArrayType; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN VitalBoolArrayT; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +--------------- following are not needed -------------------------- + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + +PROCEDURE VitalMemorySetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalMemoryTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + SIGNAL RefSignal : IN std_logic_vector; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN VitalDelayArrayType; + CONSTANT SetupHigh : IN VitalDelayArrayType; + CONSTANT SetupLow : IN VitalDelayArrayType; + CONSTANT HoldHigh : IN VitalDelayArrayType; + CONSTANT HoldLow : IN VitalDelayArrayType; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT ArcType : IN VitalMemoryArcType := CrossArc; + CONSTANT NumBitsPerSubWord : IN INTEGER := 1; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE +); + + +-- ---------------------------------------------------------------------------- +-- +-- Function Name: VitalPeriodPulseCheck +-- +-- Description: VitalPeriodPulseCheck checks for minimum and maximum +-- periodicity and pulse width for "1" and "0" values of +-- the input test signal. The timing constraint is +-- specified through parameters representing the minimal +-- period between successive rising and falling edges of +-- the input test signal and the minimum pulse widths +-- associated with high and low values. +-- +-- VitalPeriodCheck's accepts rising and falling edges +-- from 1 and 0 as well as transitions to and from 'X.' +-- +-- _______________ __________ +-- ____________| |_______| +-- +-- |<--- pw_hi --->| +-- |<-------- period ----->| +-- -->| pw_lo |<-- +-- +-- Arguments: +-- IN Type Description +-- TestSignal std_logic_vector Value of test signal +-- TestSignalName STRING Name of the test signal +-- TestDelay VitalDelayArrayType +-- Model's internal delay associated +-- with TestSignal +-- Period VitalDelayArrayType +-- Minimum period allowed between +-- consecutive rising ('P') or +-- falling ('F') transitions. +-- PulseWidthHigh VitalDelayArrayType +-- Minimum time allowed for a high +-- pulse ('1' or 'H') +-- PulseWidthLow VitalDelayArrayType +-- Minimum time allowed for a low +-- pulse ('0' or 'L') +-- CheckEnabled BOOLEAN Check performed if TRUE. +-- HeaderMsg STRING String that will accompany any +-- assertion messages produced. +-- XOn BOOLEAN If TRUE, Violation output parameter +-- is set to "X". Otherwise, Violation +-- is always set to "0." +-- MsgOn BOOLEAN If TRUE, period/pulse violation +-- message will be generated. +-- Otherwise, no messages are generated, +-- even though a violation is detected. +-- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. +-- MsgFormat VitalMemoryMsgFormatType +-- Format of the Test/Reference signals +-- in violation messages. +-- +-- INOUT +-- PeriodData VitalPeriodDataArrayType +-- VitalPeriodPulseCheck information +-- storage area. This is used +-- internally to detect reference edges +-- and record the pulse and period +-- times. +-- OUT +-- Violation X01 This is the violation flag returned. +-- X01ArrayT Overloaded for array type. +-- +-- ---------------------------------------------------------------------------- +PROCEDURE VitalMemoryPeriodPulseCheck ( + VARIABLE Violation : OUT X01ArrayT; + VARIABLE PeriodData : INOUT VitalPeriodDataArrayType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + CONSTANT Period : IN VitalDelayArrayType; + CONSTANT PulseWidthHigh : IN VitalDelayArrayType; + CONSTANT PulseWidthLow : IN VitalDelayArrayType; + 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; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType +); + +PROCEDURE VitalMemoryPeriodPulseCheck ( + VARIABLE Violation : OUT X01; + VARIABLE PeriodData : INOUT VitalPeriodDataArrayType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN VitalDelayArrayType; + CONSTANT Period : IN VitalDelayArrayType; + CONSTANT PulseWidthHigh : IN VitalDelayArrayType; + CONSTANT PulseWidthLow : IN VitalDelayArrayType; + 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; + CONSTANT MsgFormat : IN VitalMemoryMsgFormatType +); + +-- ---------------------------------------------------------------------------- +-- Functionality Section +-- ---------------------------------------------------------------------------- + +-- ---------------------------------------------------------------------------- +-- All Memory Types and Record definitions. +-- ---------------------------------------------------------------------------- +TYPE MemoryWordType IS ARRAY (NATURAL RANGE <>) OF UX01; +TYPE MemoryWordPtr IS ACCESS MemoryWordType; + +TYPE MemoryArrayType IS ARRAY (NATURAL RANGE <>) OF MemoryWordPtr; +TYPE MemoryArrayPtrType IS ACCESS MemoryArrayType; + +TYPE VitalMemoryArrayRecType IS +RECORD +NoOfWords : POSITIVE; +NoOfBitsPerWord : POSITIVE; +NoOfBitsPerSubWord : POSITIVE; +NoOfBitsPerEnable : POSITIVE; +MemoryArrayPtr : MemoryArrayPtrType; +END RECORD; + +TYPE VitalMemoryDataType IS ACCESS VitalMemoryArrayRecType; + +TYPE VitalTimingDataVectorType IS +ARRAY (NATURAL RANGE <>) OF VitalTimingDataType; + +TYPE VitalMemoryViolFlagSizeType IS ARRAY (NATURAL RANGE <>) OF INTEGER; + +-- ---------------------------------------------------------------------------- +-- Symbol Literals used for Memory Table Modeling +-- ---------------------------------------------------------------------------- + +-- Symbol literals from '/' to 'S' are closely related to MemoryTableMatch +-- lookup matching and the order cannot be arbitrarily changed. +-- The remaining symbol literals are interpreted directly and matchting is +-- handled in the MemoryMatch procedure itself. + +TYPE VitalMemorySymbolType IS ( + '/', -- 0 -> 1 + '\', -- 1 -> 0 + 'P', -- Union of '/' and '^' (any edge to 1) + 'N', -- Union of '\' and 'v' (any edge to 0) + 'r', -- 0 -> X + 'f', -- 1 -> X + 'p', -- Union of '/' and 'r' (any edge from 0) + 'n', -- Union of '\' and 'f' (any edge from 1) + 'R', -- Union of '^' and 'p' (any possible rising edge) + 'F', -- Union of 'v' and 'n' (any possible falling edge) + '^', -- X -> 1 + 'v', -- X -> 0 + 'E', -- Union of 'v' and '^' (any edge from X) + 'A', -- Union of 'r' and '^' (rising edge to or from 'X') + + 'D', -- Union of 'f' and 'v' (falling edge to or from 'X') + + '*', -- Union of 'R' and 'F' (any edge) + 'X', -- Unknown level + '0', -- low level + '1', -- high level + '-', -- don't care + 'B', -- 0 or 1 + 'Z', -- High Impedance + 'S', -- steady value + + 'g', -- Good address (no transition) + 'u', -- Unknown address (no transition) + 'i', -- Invalid address (no transition) + 'G', -- Good address (with transition) + 'U', -- Unknown address (with transition) + 'I', -- Invalid address (with transition) + + 'w', -- Write data to memory + 's', -- Retain previous memory contents + + 'c', -- Corrupt entire memory with 'X' + 'l', -- Corrupt a word in memory with 'X' + 'd', -- Corrupt a single bit in memory with 'X' + 'e', -- Corrupt a word with 'X' based on data in + 'C', -- Corrupt a sub-word entire memory with 'X' + 'L', -- Corrupt a sub-word in memory with 'X' + + -- The following entries are commented since their + -- interpretation overlap with existing definitions. + + -- 'D', -- Corrupt a single bit of a sub-word with 'X' + -- 'E', -- Corrupt a sub-word with 'X' based on datain + + 'M', -- Implicit read data from memory + 'm', -- Read data from memory + 't' -- Immediate assign/transfer data in + +); + +TYPE VitalMemoryTableType IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalMemorySymbolType; + +TYPE VitalMemoryViolationSymbolType IS ( + 'X', -- Unknown level + '0', -- low level + '-' -- don't care +); + +TYPE VitalMemoryViolationTableType IS + ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalMemoryViolationSymbolType; + +TYPE VitalPortType IS ( + UNDEF, + READ, + WRITE, + RDNWR +); + +TYPE VitalCrossPortModeType IS ( + CpRead, -- CpReadOnly, + WriteContention, -- WrContOnly, + ReadWriteContention, -- CpContention + CpReadAndWriteContention, -- WrContAndCpRead, + CpReadAndReadContention +); + +SUBTYPE VitalAddressValueType IS INTEGER; +TYPE VitalAddressValueVectorType IS + ARRAY (NATURAL RANGE <>) OF VitalAddressValueType; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalDeclareMemory +-- Parameters: NoOfWords - Number of words in the memory +-- NoOfBitsPerWord - Number of bits per word in memory +-- NoOfBitsPerSubWord - Number of bits per sub word +-- MemoryLoadFile - Name of data file to load +-- Description: This function is intended to be used to initialize +-- memory data declarations, i.e. to be executed duing +-- simulation elaboration time. Handles the allocation +-- and initialization of memory for the memory data. +-- Default NoOfBitsPerSubWord is NoOfBits. +-- ---------------------------------------------------------------------------- + +IMPURE FUNCTION VitalDeclareMemory ( + CONSTANT NoOfWords : IN POSITIVE; + CONSTANT NoOfBitsPerWord : IN POSITIVE; + CONSTANT NoOfBitsPerSubWord : IN POSITIVE; + CONSTANT MemoryLoadFile : IN string := ""; + CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE +) RETURN VitalMemoryDataType; + +IMPURE FUNCTION VitalDeclareMemory ( + CONSTANT NoOfWords : IN POSITIVE; + CONSTANT NoOfBitsPerWord : IN POSITIVE; + CONSTANT MemoryLoadFile : IN string := ""; + CONSTANT BinaryLoadFile : IN BOOLEAN := FALSE +) RETURN VitalMemoryDataType; + + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryTable +-- Parameters: DataOutBus - Output candidate zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- PrevControls - Previous data in for edge detection +-- PrevEnableBus - Previous enables for edge detection +-- PrevDataInBus - Previous data bus for edge detection +-- PrevAddressBus - Previous address bus for edge detection +-- PortFlag - Indicates port operating mode +-- PortFlagArray - Vector form of PortFlag for sub-word +-- Controls - Agregate of scalar control lines +-- EnableBus - Concatenation of vector control lines +-- DataInBus - Input value of data bus in +-- AddressBus - Input value of address bus in +-- AddressValue - Decoded value of the AddressBus +-- MemoryTable - Input memory action table +-- PortType - The type of port (currently not used) +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- MsgSeverity - Control level of message generation +-- Description: This procedure implements the majority of the memory +-- modeling functionality via lookup of the memory action +-- tables and performing the specified actions if matches +-- are found, or the default actions otherwise. The +-- overloadings are provided for the word and sub-word +-- (using the EnableBus and PortFlagArray arguments) addressing +-- cases. +-- ---------------------------------------------------------------------------- + +PROCEDURE VitalMemoryTable ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PrevControls : INOUT std_logic_vector; + VARIABLE PrevDataInBus : INOUT std_logic_vector; + VARIABLE PrevAddressBus : INOUT std_logic_vector; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT Controls : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressBus : IN std_logic_vector; + VARIABLE AddressValue : INOUT VitalAddressValueType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType := UNDEF; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +); + +PROCEDURE VitalMemoryTable ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PrevControls : INOUT std_logic_vector; + VARIABLE PrevEnableBus : INOUT std_logic_vector; + VARIABLE PrevDataInBus : INOUT std_logic_vector; + VARIABLE PrevAddressBus : INOUT std_logic_vector; + VARIABLE PortFlagArray : INOUT VitalPortFlagVectorType; + CONSTANT Controls : IN std_logic_vector; + CONSTANT EnableBus : IN std_logic_vector; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressBus : IN std_logic_vector; + VARIABLE AddressValue : INOUT VitalAddressValueType; + CONSTANT MemoryTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType := UNDEF; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +); + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryCrossPorts +-- Parameters: DataOutBus - Output candidate zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- SamePortFlag - Operating mode for same port +-- SamePortAddressValue - Decoded AddressBus for same port +-- CrossPortFlagArray - Operating modes for cross ports +-- CrossPortAddressArray - Decoded AddressBus for cross ports +-- CrossPortMode - Write contention and crossport read control +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- +-- Description: These procedures control the effect of memory operations +-- on a given port due to operations on other ports in a +-- multi-port memory. +-- This includes data write through when reading and writing +-- to the same address, as well as write contention when +-- there are multiple write to the same address. +-- If addresses do not match then data bus is unchanged. +-- The DataOutBus can be diabled with 'Z' value. +-- ---------------------------------------------------------------------------- + +PROCEDURE VitalMemoryCrossPorts ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE SamePortFlag : INOUT VitalPortFlagVectorType; + CONSTANT SamePortAddressValue : IN VitalAddressValueType; + CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType; + CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType; + CONSTANT CrossPortMode : IN VitalCrossPortModeType + := CpReadAndWriteContention; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) ; + +PROCEDURE VitalMemoryCrossPorts ( + VARIABLE MemoryData : INOUT VitalMemoryDataType; + CONSTANT CrossPortFlagArray : IN VitalPortFlagVectorType; + CONSTANT CrossPortAddressArray : IN VitalAddressValueVectorType; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE +) ; + +-- ---------------------------------------------------------------------------- +-- Procedure: VitalMemoryViolation +-- Parameters: DataOutBus - Output zero delay data bus out +-- MemoryData - Pointer to memory data structure +-- PortFlag - Indicates port operating mode +-- DataInBus - Input value of data bus in +-- AddressValue - Decoded value of the AddressBus +-- ViolationFlags - Aggregate of scalar violation vars +-- ViolationFlagsArray - Concatenation of vector violation vars +-- ViolationTable - Input memory violation table +-- PortType - The type of port (currently not used) +-- PortName - Port name string for messages +-- HeaderMsg - Header string for messages +-- MsgOn - Control the generation of messages +-- MsgSeverity - Control level of message generation +-- Description: This procedure is intended to implement all actions on the +-- memory contents and data out bus as a result of timing viols. +-- It uses the memory action table to perform various corruption +-- policies specified by the user. +-- ---------------------------------------------------------------------------- + +PROCEDURE VitalMemoryViolation ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressValue : IN VitalAddressValueType; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationFlagsArray : IN X01ArrayT; + CONSTANT ViolationSizesArray : IN VitalMemoryViolFlagSizeType; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) ; + +PROCEDURE VitalMemoryViolation ( + VARIABLE DataOutBus : INOUT std_logic_vector; + VARIABLE MemoryData : INOUT VitalMemoryDataType; + VARIABLE PortFlag : INOUT VitalPortFlagVectorType; + CONSTANT DataInBus : IN std_logic_vector; + CONSTANT AddressValue : IN VitalAddressValueType; + CONSTANT ViolationFlags : IN std_logic_vector; + CONSTANT ViolationTable : IN VitalMemoryTableType; + CONSTANT PortType : IN VitalPortType; + CONSTANT PortName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := ""; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING +) ; + +END Vital_Memory; diff --git a/libraries/vital2000/prmtvs_b.vhdl b/libraries/vital2000/prmtvs_b.vhdl new file mode 100644 index 000000000..c015e62d5 --- /dev/null +++ b/libraries/vital2000/prmtvs_b.vhdl @@ -0,0 +1,5622 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL_Primitives Package +-- : $Revision: 600 $ +-- : +-- 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 +-- ---------------------------------------------------------------------------- +-- v95.2 | ddl | 09/14/96 | #223 - single input prmtvs use on-detect +-- | | | instead of glitch-on-event behavior +-- v95.3 | ddl | 09/24/96 | #236 - VitalTruthTable DataIn should be of +-- | | | of class SIGNAL +-- v95.4 | ddl | 01/16/97 | #243 - index constraint error in nbit xor/xnor +-- v99.1 | dbb | 03/31/99 | Updated for VHDL 93 +-- ---------------------------------------------------------------------------- + +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 := -1 ns; -- IR#223 + 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 + ---------------------------------------------------------------------------- + IMPURE 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; + --------------------------------------------------------------------------- + IMPURE 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; + + IMPURE 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; + + IMPURE 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. + -- ------------------------------------------------------------------------ + IMPURE 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; + + IMPURE 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. + -- ------------------------------------------------------------------------ + IMPURE 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; + + IMPURE 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. + -- ------------------------------------------------------------------------ + IMPURE 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; + + IMPURE 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 + IMPURE 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 + IMPURE 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 ( ADataB_Schd, Data_Edge, Atpd_data_q ); + InvPath ( ADataI_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 ( ADataB_Schd, Data_Edge, Atpd_data_q ); + InvPath ( ADataI_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; + SIGNAL DataIn : IN std_logic_vector -- IR#236 + ) 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; + SIGNAL DataIn : IN std_logic_vector -- IR#236 + ) 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; + SIGNAL Data : IN std_logic_vector --IR236 4/2/98 + ) 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/vital2000/prmtvs_p.vhdl b/libraries/vital2000/prmtvs_p.vhdl new file mode 100644 index 000000000..764ac449a --- /dev/null +++ b/libraries/vital2000/prmtvs_p.vhdl @@ -0,0 +1,1413 @@ +-- ----------------------------------------------------------------------------- +-- Title : Standard VITAL_Primitives Package +-- : $Revision: 598 $ +-- : +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- 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. +-- : +-- Known Errors : +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the objects (types, subtypes, constants, functions, +-- : procedures ... etc.) that can be used by a user. The 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. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Acknowledgments: +-- This code was originally developed under the "VHDL Initiative Toward ASIC +-- Libraries" (VITAL), an industry sponsored initiative. Technical +-- Director: William Billowitch, VHDL Technology Group; U.S. Coordinator: +-- Steve Schultz; Steering Committee Members: Victor Berman, Cadence Design +-- Systems; Oz Levia, Synopsys Inc.; Ray Ryan, Ryan & Ryan; Herman van Beek, +-- Texas Instruments; Victor Martin, Hewlett-Packard Company. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/02/95 | Initial ballot draft 1995 +-- ---------------------------------------------------------------------------- +-- v95.3 | ddl | 09/24/96 | #236 - VitalTruthTable DataIn should be of +-- | | | of class SIGNAL (PROPOSED) +-- ---------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.Std_Logic_1164.ALL; +USE IEEE.VITAL_Timing.ALL; + +PACKAGE VITAL_Primitives IS + -- ------------------------------------------------------------------------ + -- Type and Subtype Declarations + -- ------------------------------------------------------------------------ + + -- For Truth and State Tables + SUBTYPE VitalTruthSymbolType IS VitalTableSymbolType RANGE 'X' TO 'Z'; + SUBTYPE VitalStateSymbolType IS VitalTableSymbolType RANGE '/' TO 'S'; + + TYPE VitalTruthTableType IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalTruthSymbolType; + TYPE VitalStateTableType IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalStateSymbolType; + + -- --------------------------------- + -- Default values used by primitives + -- --------------------------------- + CONSTANT VitalDefDelay01 : VitalDelayType01; -- Propagation delays + CONSTANT VitalDefDelay01Z : VitalDelayType01Z; + + -- ------------------------------------------------------------------------ + -- VITAL Primitives + -- + -- The primitives packages contains a collections of common gates, + -- including AND, OR, XOR, NAND, NOR, XNOR, BUF, INV, MUX and DECODER + -- functions. In addition, for sequential devices, a STATE TABLE construct + -- is provided. For complex functions a modeler may wish to use either + -- a collection of connected VITAL primitives, or a TRUTH TABLE construct. + -- + -- For each primitive a Function and Procedure is provided. The primitive + -- functions are provided to support behavioral modeling styles. The + -- primitive procedures are provided to support structural modeling styles. + -- + -- The procedures wait internally for an event on an input signal, compute + -- the new result, perform glitch handling, schedule transaction on the + -- output signals, and wait for future input events. All of the functional + -- (logic) input or output parameters of the primitive procedures are + -- signals. All the other parameters are constants. + -- + -- The procedure primitives are parameterized for separate path delays + -- from each input signal. All path delays default to 0 ns. + -- + -- The sequential primitive functions compute the defined function and + -- return a value of type std_ulogic or std_logic_vector. All parameters + -- of the primitive functions are constants of mode IN. + -- + -- The primitives are based on 1164 operators. The user may also elect to + -- express functions using the 1164 operators as well. These styles are + -- all equally acceptable methods for device modeling. + -- + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: N-input logic device function calls: + -- VitalAND VitalOR VitalXOR + -- VitalNAND VitalNOR VitalXNOR + -- + -- Description: The function calls return the evaluated logic function + -- corresponding to the function name. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector The input signals for the n-bit + -- wide logic functions. + -- ResultMap VitalResultMapType The output signal strength + -- result map to modify default + -- result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The evaluated logic function of + -- the n-bit wide primitives. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: N-input logic device concurrent procedure calls. + -- VitalAND VitalOR VitalXOR + -- VitalNAND VitalNOR VitalXNOR + -- + -- Description: The procedure calls return the evaluated logic function + -- corresponding to the function name as a parameter to the + -- procedure. Propagation delay form data to q is a + -- a parameter to the procedure. A vector of delay values + -- for inputs to output are provided. It is noted that + -- limitations in SDF make the back annotation of the delay + -- array difficult. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector The input signals for the n- + -- bit wide logic functions. + -- tpd_data_q VitalDelayArrayType01 The propagation delay from + -- the data inputs to the output + -- q. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The output signal of the + -- evaluated logic function. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalXOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalNAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalXNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + -- ------------------------------------------------------------------------- + -- + -- Sequential + -- Primitive + -- Function Name: 2,3 and 4 input logic device function calls. + -- + -- VitalAND2 VitalOR2 VitalXOR2 + -- VitalAND3 VitalOR3 VitalXOR3 + -- VitalAND4 VitalOR4 VitalXOR4 + -- + -- VitalNAND2 VitalNOR2 VitalXNOR2 + -- VitalNAND3 VitalNOR3 VitalXNOR3 + -- VitalNAND4 VitalNOR4 VitalXNOR4 + -- + -- Description: The function calls return the evaluated 2, 3 or 4 input + -- logic function corresponding to the function name. + -- + -- Arguments: + -- + -- IN Type Description + -- a, b, c, d std_ulogic 2 input devices have a and b as + -- inputs. 3 input devices have a, b + -- and c as inputs. 4 input devices + -- have a, b, c and d as inputs. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The result of the evaluated logic + -- function. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: 2, 3 and 4 input logic device concurrent procedure + -- calls. + -- + -- VitalAND2 VitalOR2 VitalXOR2 + -- VitalAND3 VitalOR3 VitalXOR3 + -- VitalAND4 VitalOR4 VitalXOR4 + -- + -- VitalNAND2 VitalNOR2 VitalXNOR2 + -- VitalNAND3 VitalNOR3 VitalXNOR3 + -- VitalNAND4 VitalNOR4 VitalXNOR4 + -- + -- Description: The procedure calls return the evaluated logic function + -- corresponding to the function name as a parameter to the + -- procedure. Propagation delays from a and b to q are + -- a parameter to the procedure. The default propagation + -- delay is 0 ns. + -- + -- Arguments: + -- + -- IN Type Description + -- a, b, c, d std_ulogic 2 input devices have a and b as + -- inputs. 3 input devices have a, b + -- and c as inputs. 4 input devices + -- have a, b, c and d as inputs. + -- tpd_a_q VitalDelayType01 The propagation delay from the a + -- input to output q for 2, 3 and 4 + -- input devices. + -- tpd_b_q VitalDelayType01 The propagation delay from the b + -- input to output q for 2, 3 and 4 + -- input devices. + -- tpd_c_q VitalDelayType01 The propagation delay from the c + -- input to output q for 3 and 4 input + -- devices. + -- tpd_d_q VitalDelayType01 The propagation delay from the d + -- input to output q for 4 input + -- devices. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The output signal of the evaluated + -- logic function. + -- + -- Returns + -- none + -- ------------------------------------------------------------------------- + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: Buffer logic device concurrent procedure calls. + -- + -- Description: Four buffer sequential primitive function calls are + -- provided. One is a simple buffer and the others + -- offer high and low enables and the four permits + -- propagation of Z as shown below: + -- + -- VitalBUF Standard non-inverting buffer + -- VitalBUFIF0 Non-inverting buffer with Enable low + -- VitalBUFIF1 Non-inverting buffer with Enable high + -- VitalIDENT Pass buffer capable of propagating Z + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input to the buffers + -- Enable std_ulogic Enable for the enable high and low + -- buffers. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple buffer. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low and + -- identity buffers. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The output signal of the evaluated + -- buffer function. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalBUF ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + FUNCTION VitalBUFIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + FUNCTION VitalBUFIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + FUNCTION VitalIDENT ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: Buffer device procedure calls. + -- + -- Description: Four buffer concurrent primitive procedure calls are + -- provided. One is a simple buffer and the others + -- offer high and low enables and the fourth permits + -- propagation of Z as shown below: + -- + -- VitalBUF Standard non-inverting buffer + -- VitalBUFIF0 Non-inverting buffer with Enable low + -- VitalBUFIF1 Non-inverting buffer with Enable high + -- VitalIDENT Pass buffer capable of propagating Z + -- + -- Arguments: + -- + -- IN Type Description + -- a std_ulogic Input signal to the buffers + -- Enable std_ulogic Enable signal for the enable high and + -- low buffers. + -- tpd_a_q VitalDelayType01 Propagation delay from input to + -- output for the simple buffer. + -- VitalDelayType01Z Propagation delay from input to + -- to output for the enable high and low + -- and identity buffers. + -- tpd_enable_q VitalDelayType01Z Propagation delay from enable to + -- output for the enable high and low + -- buffers. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple buffer. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low and + -- identity buffers. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output of the buffers. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalBUF ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + 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); + + + 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); + + PROCEDURE VitalIDENT ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalINV, VitalINVIF0, VitalINVIF1 + -- + -- Description: Inverter functions which return the inverted signal + -- value. Inverters with enable low and high are provided + -- which can drive high impedance when inactive. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input to the inverter + -- Enable std_ulogic Enable to the enable high and low + -- inverters. + -- ResultMap VitalResultMap The output signal strength result map + -- to modify default result mapping for + -- simple inverter. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low + -- inverters. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic Output of the inverter + -- + -- ------------------------------------------------------------------------- + + FUNCTION VitalINV ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalINVIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + FUNCTION VitalINVIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalINV, VitalINVIF0, VitalINVIF1 + -- + -- Description: The concurrent primitive procedure calls implement a + -- signal inversion function. The output is a parameter to + -- the procedure. The path delay information is passed as + -- a parameter to the call. + -- + -- Arguments: + -- + -- IN Type Description + -- a std_ulogic Input signal for the simple inverter + -- Data std_ulogic Input signal for the enable high and + -- low inverters. + -- Enable std_ulogic Enable signal for the enable high and + -- low inverters. + -- tpd_a_q VitalDelayType01 Propagation delay from input a to + -- output q for the simple inverter. + -- tpd_data_q VitalDelayType01 Propagation delay from input data to + -- output q for the enable high and low + -- inverters. + -- tpd_enable_q VitalDelayType01Z Propagation delay from input enable + -- to output q for the enable high and + -- low inverters. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple inverter. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low + -- inverters. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output signal of the inverter. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalINV ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + 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); + + 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); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalMUX, VitalMUX2, VitalMUX4, VitalMUX8 + -- + -- Description: The VitalMUX functions return the selected data bit + -- based on the value of dSelect. For MUX2, the function + -- returns data0 when dselect is 0 and returns data1 when + -- dselect is 1. When dselect is X, result is X for MUX2 + -- when data0 /= data1. X propagation is reduced when the + -- dselect signal is X and both data signals are identical. + -- When this is the case, the result returned is the value + -- of the data signals. + -- + -- For the N input device: + -- + -- N must equal 2**(bits of dSelect) + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector Input signal for the N-bit, 4-bit and + -- 8-bit mux. + -- Data1,Data0 std_ulogic Input signals for the 2-bit mux. + -- dSelect std_ulogic Select signal for 2-bit mux + -- std_logic_vector2 Select signal for 4-bit mux + -- std_logic_vector3 Select signal for 8-bit mux + -- std_logic_vector Select signal for N-Bit mux + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- all muxes. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The value of the selected bit is + -- returned. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalMUX ( + CONSTANT Data : IN std_logic_vector; + CONSTANT dSelect : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX2 ( + CONSTANT Data1, Data0 : IN std_ulogic; + CONSTANT dSelect : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX4 ( + CONSTANT Data : IN std_logic_vector4; + CONSTANT dSelect : IN std_logic_vector2; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX8 ( + CONSTANT Data : IN std_logic_vector8; + CONSTANT dSelect : IN std_logic_vector3; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalMUX, VitalMUX2, VitalMUX4, VitalMUX8 + -- + -- Description: The VitalMUX concurrent primitive procedures calls + -- return in the output q the value of the selected data + -- bit based on the value of dsel. For the two bit mux, + -- the data returned is either d0 or d1, the data input. + -- For 4, 8 and N-bit functions, data is the input and is + -- of type std_logic_vector. For the 2-bit mux, if d0 or + -- d1 are X, the output is X only when d0 do not equal d1. + -- When d0 and d1 are equal, the return value is this value + -- to reduce X propagation. + -- + -- Propagation delay information is passed as a parameter + -- to the procedure call for delays from data to output and + -- select to output. For 2-bit muxes, the propagation + -- delays from data are provided for d0 and d1 to output. + -- + -- + -- Arguments: + -- + -- IN Type Description + -- d1,d0 std_ulogic Input signals for the 2-bit mux. + -- Data std_logic_vector4 Input signals for the 4-bit mux. + -- std_logic_vector8 Input signals for the 8-bit mux. + -- std_logic_vector Input signals for the N-bit mux. + -- dsel std_ulogic Select signal for the 2-bit mux. + -- std_logic_vector2 Select signals for the 4-bit mux. + -- std_logic_vector3 Select signals for the 8-bit mux. + -- std_logic_vector Select signals for the N-bit mux. + -- tpd_d1_q VitalDelayType01 Propagation delay from input d1 to + -- output q for 2-bit mux. + -- tpd_d0_q VitalDelayType01 Propagation delay from input d0 to + -- output q for 2-bit mux. + -- tpd_data_q VitalDelayArrayType01 Propagation delay from input data + -- to output q for 4-bit, 8-bit and + -- N-bit muxes. + -- tpd_dsel_q VitalDelayType01 Propagation delay from input dsel + -- to output q for 2-bit mux. + -- VitalDelayArrayType01 Propagation delay from input dsel + -- to output q for 4-bit, 8-bit and + -- N-bit muxes. + -- ResultMap VitalResultMapType The output signal strength result + -- map to modify default result + -- mapping for all muxes. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The value of the selected signal. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 ); + + 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 ); + + 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 ); + + 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 ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalDECODER, VitalDECODER2, VitalDECODER4, + -- VitalDECODER8 + -- + -- Description: The VitalDECODER functions are the sequential primitive + -- calls for decoder logic. The functions are provided + -- for N, 2, 4 and 8-bit outputs. + -- + -- The N-bit decoder is (2**(bits of data)) wide. + -- + -- The VitalDECODER returns 0 if enable is 0. + -- The VitalDECODER returns the result bit set to 1 if + -- enable is 1. All other bits of returned result are + -- set to 0. + -- + -- The returned array is in descending order: + -- (n-1 downto 0). + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input signal for 2-bit decoder. + -- std_logic_vector2 Input signals for 4-bit decoder. + -- std_logic_vector3 Input signals for 8-bit decoder. + -- std_logic_vector Input signals for N-bit decoder. + -- Enable std_ulogic Enable input signal. The result is + -- output when enable is high. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- all output signals of the decoders. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_logic_vector2 The output of the 2-bit decoder. + -- std_logic_vector4 The output of the 4-bit decoder. + -- std_logic_vector8 The output of the 8-bit decoder. + -- std_logic_vector The output of the n-bit decoder. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalDECODER ( + CONSTANT Data : IN std_logic_vector; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector; + + FUNCTION VitalDECODER2 ( + CONSTANT Data : IN std_ulogic; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector2; + + FUNCTION VitalDECODER4 ( + CONSTANT Data : IN std_logic_vector2; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector4; + + FUNCTION VitalDECODER8 ( + CONSTANT Data : IN std_logic_vector3; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector8; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalDECODER, VitalDECODER2, VitalDECODER4, + -- VitalDECODER8 + -- + -- Description: The VitalDECODER procedures are the concurrent primitive + -- procedure calls for decoder functions. The procedures + -- are provided for N, 2, 4 and 8 outputs. + -- + -- The N-bit decoder is (2**(bits of data)) wide. + -- + -- The procedural form of the decoder is used for + -- distributed delay modeling. The delay information for + -- each path is passed as an argument to the procedure. + -- + -- Result is set to 0 if enable is 0. + -- The result bit represented by data is set to 1 if + -- enable is 1. All other bits of result are set to 0. + -- + -- The result array is in descending order: (n-1 downto 0). + -- + -- For the N-bit decoder, the delay path is a vector of + -- delays from inputs to outputs. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input signal for 2-bit decoder. + -- std_logic_vector2 Input signals for 4-bit decoder. + -- std_logic_vector3 Input signals for 8-bit decoder. + -- std_logic_vector Input signals for N-bit decoder. + -- enable std_ulogic Enable input signal. The result is + -- output when enable is high. + -- tpd_data_q VitalDelayType01 Propagation delay from input data + -- to output q for 2-bit decoder. + -- VitalDelayArrayType01 Propagation delay from input data + -- to output q for 4, 8 and n-bit + -- decoders. + -- tpd_enable_q VitalDelayType01 Propagation delay from input enable + -- to output q for 2, 4, 8 and n-bit + -- decoders. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_logic_vector2 Output signals for 2-bit decoder. + -- std_logic_vector4 Output signals for 4-bit decoder. + -- std_logic_vector8 Output signals for 8-bit decoder. + -- std_logic_vector Output signals for n-bit decoder. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 ); + 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 ); + + 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 ); + 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 ); + + -- ------------------------------------------------------------------------- + -- Function Name: VitalTruthTable + -- + -- Description: VitalTruthTable implements a truth table. Given + -- a set of inputs, a sequential search is performed + -- to match the input. If a match is found, the output + -- is set based on the contents of the CONSTANT TruthTable. + -- If there is no match, all X's are returned. There is + -- no limit to the size of the table. + -- + -- There is a procedure and function for VitalTruthTable. + -- For each of these, a single value output (std_logic) and + -- a multi-value output (std_logic_vector) are provided. + -- + -- The first dimension of the table is for number of + -- entries in the truth table and second dimension is for + -- the number of elements in a row. The number of inputs + -- in the row should be Data'LENGTH plus result'LENGTH. + -- + -- Elements is a row will be interpreted as + -- Input(NumInputs - 1),.., Input(0), + -- Result(NumOutputs - 1),.., Result(0) + -- + -- All inputs will be mapped to the X01 subtype + -- + -- If the value of Result is not in the range 'X' to 'Z' + -- then an error will be reported. Also, the Result is + -- always given either as a 0, 1, X or Z value. + -- + -- Arguments: + -- + -- IN Type Description + -- TruthTable The input constant which defines the + -- behavior in truth table form. + -- DataIn The inputs to the truth table used to + -- perform input match to select + -- output(s) to value(s) to drive. + -- + -- INOUT + -- none + -- + -- OUT + -- Result std_logic Concurrent procedure version scalar + -- output. + -- std_logic_vector Concurrent procedure version vector + -- output. + -- + -- Returns + -- Result std_logic Function version scalar output. + -- std_logic_vector Function version vector output. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic_vector; + + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic; + + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic_vector; + CONSTANT TruthTable : IN VitalTruthTableType; + SIGNAL DataIn : IN std_logic_vector -- IR#236 + ); + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic; + CONSTANT TruthTable : IN VitalTruthTableType; + SIGNAL DataIn : IN std_logic_vector -- IR#236 + ); + -- ------------------------------------------------------------------------- + -- + -- Function Name: VitalStateTable + -- + -- Description: VitalStateTable is a non-concurrent implementation of a + -- state machine (Moore Machine). It is used to model + -- sequential devices and devices with internal states. + -- + -- The procedure takes the value of the state table + -- data set and performs a sequential search of the + -- CONSTANT StateTable until a match is found. Once a + -- match is found, the result of that match is applied + -- to Result. If there is no match, all X's are returned. + -- The resultant output becomes the input for the next + -- state. + -- + -- The first dimension of the table is the number of + -- entries in the state table and second dimension is the + -- number of elements in a row of the table. The number of + -- inputs in the row should be DataIn'LENGTH. Result should + -- contain the current state (which will become the next + -- state) as well as the outputs + -- + -- Elements is a row of the table will be interpreted as + -- Input(NumInputs-1),.., Input(0), State(NumStates-1), + -- ..., State(0),Output(NumOutputs-1),.., Output(0) + -- + -- where State(numStates-1) DOWNTO State(0) represent the + -- present state and Output(NumOutputs - 1) DOWNTO + -- Outputs(NumOutputs - NumStates) represent the new + -- values of the state variables (i.e. the next state). + -- Also, Output(NumOutputs - NumStates - 1) + -- + -- This procedure returns the next state and the new + -- outputs when a match is made between the present state + -- and present inputs and the state table. A search is + -- made starting at the top of the state table and + -- terminates with the first match. If no match is found + -- then the next state and new outputs are set to all 'X's. + -- + -- (Asynchronous inputs (i.e. resets and clears) must be + -- handled by placing the corresponding entries at the top + -- of the table. ) + -- + -- All inputs will be mapped to the X01 subtype. + -- + -- NOTE: Edge transitions should not be used as values + -- for the state variables in the present state + -- portion of the state table. The only valid + -- values that can be used for the present state + -- portion of the state table are: + -- 'X', '0', '1', 'B', '-' + -- + -- Arguments: + -- + -- IN Type Description + -- StateTable VitalStateTableType The input constant which defines + -- the behavior in state table form. + -- DataIn std_logic_vector The current state inputs to the + -- state table used to perform input + -- matches and transition + -- calculations. + -- NumStates NATURAL Number of state variables + -- + -- INOUT + -- Result std_logic Output signal for scalar version of + -- the concurrent procedure call. + -- std_logic_vector Output signals for vector version + -- of the concurrent procedure call. + -- PreviousDataIn std_logic_vector The previous inputs and states used + -- in transition calculations and to + -- set outputs for steady state cases. + -- + -- OUT + -- none + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 + ); + + PROCEDURE VitalStateTable ( + VARIABLE Result : INOUT std_logic; + VARIABLE PreviousDataIn : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + CONSTANT DataIn : IN std_logic_vector + ); + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector; + CONSTANT NumStates : IN NATURAL + ); + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector + ); + + -- ------------------------------------------------------------------------- + -- + -- Function Name: VitalResolve + -- + -- Description: VitalResolve takes a vector of signals and resolves + -- them to a std_ulogic value. This procedure can be used + -- to resolve multiple drivers in a single model. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector Set of input signals which drive a + -- common signal. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output signal which is the resolved + -- value being driven by the collection of + -- input signals. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalResolve ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector); --IR236 4/2/98 + +END VITAL_Primitives; diff --git a/libraries/vital2000/timing_b.vhdl b/libraries/vital2000/timing_b.vhdl new file mode 100644 index 000000000..28bf52095 --- /dev/null +++ b/libraries/vital2000/timing_b.vhdl @@ -0,0 +1,2187 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL TIMING Package +-- : $Revision: 598 $ +-- Library : VITAL +-- : +-- Developers : IEEE DASC Timing Working Group (TWG), PAR 1076.4 +-- : +-- Purpose : This packages defines standard types, attributes, constants, +-- : functions and procedures for use in developing ASIC models. +-- : This file contains the Package Body. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/08/95 | Initial ballot draft 1995 +-- v95.1 | | 08/31/95 | #IR203 - Timing violations at time 0 +-- #IR204 - Output mapping prior to glitch detection +-- v98.0 |TAG | 03/27/98 | Initial ballot draft 1998 +-- | #IR225 - Negative Premptive Glitch +-- **Code_effected=ReportGlitch,VitalGlitch, +-- VitalPathDelay,VitalPathDelay01, +-- VitalPathDelay01z. +-- #IR105 - Skew timing check needed +-- **Code_effected=NONE, New code added!! +-- #IR245,IR246,IR251 ITC code to fix false boundry cases +-- **Code_effected=InternalTimingCheck. +-- #IR248 - Allows VPD to use a default timing delay +-- **Code_effected=VitalPathDelay, +-- VitalPathDelay01,VitalPathDelay01z, +-- VitalSelectPathDelay,VitalSelectPathDelay01, +-- VitalSelectPathDelay01z. +-- #IR250 - Corrects fastpath condition in VPD +-- **Code_effected=VitalPathDelay01, +-- VitalPathDelay01z, +-- #IR252 - Corrects cancelled timing check call if +-- condition expires. +-- **Code_effected=VitalSetupHoldCheck, +-- VitalRecoveryRemovalCheck. +-- v98.1 | jdc | 03/25/99 | Changed UseDefaultDelay to IgnoreDefaultDelay +-- and set default to FALSE in VitalPathDelay() +-- +-- ---------------------------------------------------------------------------- + +LIBRARY STD; +USE STD.TEXTIO.ALL; + +PACKAGE BODY VITAL_Timing IS + + -- -------------------------------------------------------------------- + -- Package Local Declarations + -- -------------------------------------------------------------------- + + TYPE CheckType IS ( SetupCheck, HoldCheck, RecoveryCheck, RemovalCheck, + PulseWidCheck, PeriodCheck ); + + TYPE CheckInfoType IS RECORD + Violation : BOOLEAN; + CheckKind : CheckType; + ObsTime : TIME; + ExpTime : TIME; + DetTime : TIME; + State : X01; + END RECORD; + + TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER; + TYPE HiLoStrType IS ARRAY (std_ulogic RANGE 'X' TO '1') OF STRING(1 TO 4); + + CONSTANT LogicCvtTable : LogicCvtTableType + := ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'); + CONSTANT HiLoStr : HiLoStrType := (" X ", " Low", "High" ); + + TYPE EdgeSymbolMatchType IS ARRAY (X01,X01,VitalEdgeSymbolType) OF BOOLEAN; + -- last value, present value, edge symbol + CONSTANT EdgeSymbolMatch : EdgeSymbolMatchType := ( + 'X'=>('X'=>( OTHERS => FALSE), + '0'=>('N'|'F'|'v'|'E'|'D'|'*' => TRUE, OTHERS => FALSE ), + '1'=>('P'|'R'|'^'|'E'|'A'|'*' => TRUE, OTHERS => FALSE ) ), + '0'=>('X'=>( 'r'|'p'|'R'|'A'|'*' => TRUE, OTHERS => FALSE ), + '0'=>( OTHERS => FALSE ), + '1'=>( '/'|'P'|'p'|'R'|'*' => TRUE, OTHERS => FALSE ) ), + '1'=>('X'=>( 'f'|'n'|'F'|'D'|'*' => TRUE, OTHERS => FALSE ), + '0'=>( '\'|'N'|'n'|'F'|'*' => TRUE, OTHERS => FALSE ), + '1'=>( OTHERS => FALSE ) ) ); + + + + + --------------------------------------------------------------------------- + -- Tables used to implement 'posedge' and 'negedge' in path delays + -- These are new tables for Skewcheck routines. IR105 + --------------------------------------------------------------------------- + + TYPE EdgeRable IS ARRAY(std_ulogic, std_ulogic) OF boolean; + + CONSTANT Posedge : EdgeRable := ( + -- ------------------------------------------------------------------------ + -- | U X 0 1 Z W L H - + -- ------------------------------------------------------------------------ + ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- U + ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- X + ( TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE , TRUE ), -- 0 + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- 1 + ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- Z + ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ), -- W + ( TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE , TRUE ), -- L + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- H + ( FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE ) -- - + + ); --IR105 + + + CONSTANT Negedge : EdgeRable := ( + -- ----------------------------------------------------------------------- + -- | U X 0 1 Z W L H - + -- ----------------------------------------------------------------------- + ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- U + ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- X + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- 0 + ( TRUE , TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE ), -- 1 + ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- Z + ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ), -- W + ( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- L + ( TRUE , TRUE , TRUE , FALSE, TRUE , TRUE , TRUE , FALSE, TRUE ), -- H + ( FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , FALSE, FALSE ) -- - + + ); --IR105 + + TYPE SkewType IS (Inphase, Outphase); --IR105 + + CONSTANT noTrigger : TIME := -1 ns; --IR105 + --------------------------------------------------------------------------- + -- End of Skew (IR105 additions) + --------------------------------------------------------------------------- + + + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + -- Misc Utilities Local Utilities + --------------------------------------------------------------------------- + ----------------------------------------------------------------------- + FUNCTION Minimum ( CONSTANT t1,t2 : IN TIME ) RETURN TIME IS + BEGIN + IF ( t1 < t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; + END Minimum; + ----------------------------------------------------------------------- + FUNCTION Maximum ( CONSTANT t1,t2 : IN TIME ) RETURN TIME IS + BEGIN + IF ( t1 > t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF; + END Maximum; + + -------------------------------------------------------------------- + -- Error Message Types and Tables + -------------------------------------------------------------------- + TYPE VitalErrorType IS ( + ErrVctLng , + ErrNoPath , + ErrNegPath , + ErrNegDel + ); + + TYPE VitalErrorSeverityType IS ARRAY (VitalErrorType) OF SEVERITY_LEVEL; + CONSTANT VitalErrorSeverity : VitalErrorSeverityType := ( + ErrVctLng => ERROR, + ErrNoPath => WARNING, + ErrNegPath => WARNING, + ErrNegDel => WARNING + ); + + CONSTANT MsgNoPath : STRING := + "No Delay Path Condition TRUE. 0-delay used. Output signal is: "; + CONSTANT MsgNegPath : STRING := + "Path Delay less than time since input. 0 delay used. Output signal is: "; + CONSTANT MsgNegDel : STRING := + "Negative delay. New output value not scheduled. Output signal is: "; + CONSTANT MsgVctLng : STRING := + "Vector (array) lengths not equal. "; + + CONSTANT MsgUnknown : STRING := + "Unknown error message."; + + FUNCTION VitalMessage ( + CONSTANT ErrorId : IN VitalErrorType + ) RETURN STRING IS + BEGIN + CASE ErrorId IS + WHEN ErrVctLng => RETURN MsgVctLng; + WHEN ErrNoPath => RETURN MsgNoPath; + WHEN ErrNegPath => RETURN MsgNegPath; + WHEN ErrNegDel => RETURN MsgNegDel; + WHEN OTHERS => RETURN MsgUnknown; + END CASE; + END; + + PROCEDURE VitalError ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalErrorType + ) IS + BEGIN + ASSERT FALSE + REPORT Routine & ": " & VitalMessage(ErrorId) + SEVERITY VitalErrorSeverity(ErrorId); + END; + + PROCEDURE VitalError ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalErrorType; + CONSTANT Info : IN STRING + ) IS + BEGIN + ASSERT FALSE + REPORT Routine & ": " & VitalMessage(ErrorId) & Info + SEVERITY VitalErrorSeverity(ErrorId); + END; + + PROCEDURE VitalError ( + CONSTANT Routine : IN STRING; + CONSTANT ErrorId : IN VitalErrorType; + CONSTANT Info : IN CHARACTER + ) IS + BEGIN + ASSERT FALSE + REPORT Routine & ": " & VitalMessage(ErrorId) & Info + SEVERITY VitalErrorSeverity(ErrorId); + END; + + --------------------------------------------------------------------------- + -- Time Delay Assignment Subprograms + --------------------------------------------------------------------------- + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType + ) RETURN VitalDelayType01Z IS + BEGIN + RETURN (OTHERS => Delay); + END VitalExtendToFillDelay; + + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01 + ) RETURN VitalDelayType01Z IS + VARIABLE Delay01Z : VitalDelayType01Z; + BEGIN + Delay01Z(tr01) := Delay(tr01); + Delay01Z(tr0z) := Delay(tr01); + Delay01Z(trz1) := Delay(tr01); + Delay01Z(tr10) := Delay(tr10); + Delay01Z(tr1z) := Delay(tr10); + Delay01Z(trz0) := Delay(tr10); + RETURN (Delay01Z); + END VitalExtendToFillDelay; + + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN VitalDelayType01Z IS + BEGIN + RETURN Delay; + END VitalExtendToFillDelay; + + --------------------------------------------------------------------------- + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType + ) RETURN TIME IS + BEGIN + RETURN delay; + END VitalCalcDelay; + + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01 + ) RETURN TIME IS + VARIABLE Result : TIME; + BEGIN + CASE Newval IS + WHEN '0' | 'L' => Result := Delay(tr10); + WHEN '1' | 'H' => Result := Delay(tr01); + WHEN 'Z' => + CASE Oldval IS + WHEN '0' | 'L' => Result := Delay(tr01); + WHEN '1' | 'H' => Result := Delay(tr10); + WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); + END CASE; + WHEN OTHERS => + CASE Oldval IS + WHEN '0' | 'L' => Result := Delay(tr01); + WHEN '1' | 'H' => Result := Delay(tr10); + WHEN 'Z' => Result := MINIMUM(Delay(tr10), Delay(tr01)); + WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); + END CASE; + END CASE; + RETURN Result; + END VitalCalcDelay; + + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN TIME IS + VARIABLE Result : TIME; + BEGIN + CASE Oldval IS + WHEN '0' | 'L' => + CASE Newval IS + WHEN '0' | 'L' => Result := Delay(tr10); + WHEN '1' | 'H' => Result := Delay(tr01); + WHEN 'Z' => Result := Delay(tr0z); + WHEN OTHERS => Result := MINIMUM(Delay(tr01), Delay(tr0z)); + END CASE; + WHEN '1' | 'H' => + CASE Newval IS + WHEN '0' | 'L' => Result := Delay(tr10); + WHEN '1' | 'H' => Result := Delay(tr01); + WHEN 'Z' => Result := Delay(tr1z); + WHEN OTHERS => Result := MINIMUM(Delay(tr10), Delay(tr1z)); + END CASE; + WHEN 'Z' => + CASE Newval IS + WHEN '0' | 'L' => Result := Delay(trz0); + WHEN '1' | 'H' => Result := Delay(trz1); + WHEN 'Z' => Result := MAXIMUM (Delay(tr0z), Delay(tr1z)); + WHEN OTHERS => Result := MINIMUM (Delay(trz1), Delay(trz0)); + END CASE; + WHEN 'U' | 'X' | 'W' | '-' => + CASE Newval IS + WHEN '0' | 'L' => Result := MAXIMUM(Delay(tr10), Delay(trz0)); + WHEN '1' | 'H' => Result := MAXIMUM(Delay(tr01), Delay(trz1)); + WHEN 'Z' => Result := MAXIMUM(Delay(tr1z), Delay(tr0z)); + WHEN OTHERS => Result := MAXIMUM(Delay(tr10), Delay(tr01)); + END CASE; + END CASE; + RETURN Result; + END VitalCalcDelay; + + --------------------------------------------------------------------------- + -- + -- VitalSelectPathDelay returns the path delay selected by the Paths array. + -- If no paths are selected, it returns either the appropriate default + -- delay or TIME'HIGH, depending upon the value of IgnoreDefaultDelay. + -- + + FUNCTION VitalSelectPathDelay ( + CONSTANT NewValue : IN std_logic; + CONSTANT OldValue : IN std_logic; + CONSTANT OutSignalName : IN string; + CONSTANT Paths : IN VitalPathArrayType; + CONSTANT DefaultDelay : IN VitalDelayType; + CONSTANT IgnoreDefaultDelay : IN BOOLEAN + ) RETURN TIME IS + + VARIABLE TmpDelay : TIME; + VARIABLE InputAge : TIME := TIME'HIGH; + VARIABLE PropDelay : TIME := TIME'HIGH; + BEGIN + -- for each delay path + FOR i IN Paths'RANGE LOOP + -- ignore the delay path if it is not enabled + NEXT WHEN NOT Paths(i).PathCondition; + -- ignore the delay path if a more recent input event has been seen + NEXT WHEN Paths(i).InputChangeTime > InputAge; + + -- This is the most recent input change (so far) + -- Get the transition dependent delay + TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); + + -- If other inputs changed at the same time, + -- then use the minimum of their propagation delays, + -- else use the propagation delay from this input. + IF Paths(i).InputChangeTime < InputAge THEN + PropDelay := TmpDelay; + ELSE -- Simultaneous inputs change + IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; + end if; + + InputAge := Paths(i).InputChangeTime; + END LOOP; + + -- If there were no paths (with an enabled condition), + -- use the default delay, if so indicated, otherwise return TIME'HIGH + IF (PropDelay = TIME'HIGH) THEN + IF (IgnoreDefaultDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + END IF; + + -- If the time since the most recent selected input event is + -- greater than the propagation delay from that input, + -- then use the default delay (won't happen if no paths are selected) + ELSIF (InputAge > PropDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + + -- Adjust the propagation delay by the time since the + -- the input event occurred (Usually 0 ns). + ELSE + PropDelay := PropDelay - InputAge; + END IF; + + RETURN PropDelay; + END; + + FUNCTION VitalSelectPathDelay ( + CONSTANT NewValue : IN std_logic; + CONSTANT OldValue : IN std_logic; + CONSTANT OutSignalName : IN string; + CONSTANT Paths : IN VitalPathArray01Type; + CONSTANT DefaultDelay : IN VitalDelayType01; + CONSTANT IgnoreDefaultDelay : IN BOOLEAN + ) RETURN TIME IS + + VARIABLE TmpDelay : TIME; + VARIABLE InputAge : TIME := TIME'HIGH; + VARIABLE PropDelay : TIME := TIME'HIGH; + BEGIN + -- for each delay path + FOR i IN Paths'RANGE LOOP + -- ignore the delay path if it is not enabled + NEXT WHEN NOT Paths(i).PathCondition; + -- ignore the delay path if a more recent input event has been seen + NEXT WHEN Paths(i).InputChangeTime > InputAge; + + -- This is the most recent input change (so far) + -- Get the transition dependent delay + TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); + + -- If other inputs changed at the same time, + -- then use the minimum of their propagation delays, + -- else use the propagation delay from this input. + IF Paths(i).InputChangeTime < InputAge THEN + PropDelay := TmpDelay; + ELSE -- Simultaneous inputs change + IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; + end if; + + InputAge := Paths(i).InputChangeTime; + END LOOP; + + -- If there were no paths (with an enabled condition), + -- use the default delay, if so indicated, otherwise return TIME'HIGH + IF (PropDelay = TIME'HIGH) THEN + IF (IgnoreDefaultDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + END IF; + + -- If the time since the most recent selected input event is + -- greater than the propagation delay from that input, + -- then use the default delay (won't happen if no paths are selected) + ELSIF (InputAge > PropDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + + -- Adjust the propagation delay by the time since the + -- the input event occurred (Usually 0 ns). + ELSE + PropDelay := PropDelay - InputAge; + END IF; + + RETURN PropDelay; + END; + + FUNCTION VitalSelectPathDelay ( + CONSTANT NewValue : IN std_logic; + CONSTANT OldValue : IN std_logic; + CONSTANT OutSignalName : IN string; + CONSTANT Paths : IN VitalPathArray01ZType; + CONSTANT DefaultDelay : IN VitalDelayType01Z; + CONSTANT IgnoreDefaultDelay : IN BOOLEAN + ) RETURN TIME IS + + VARIABLE TmpDelay : TIME; + VARIABLE InputAge : TIME := TIME'HIGH; + VARIABLE PropDelay : TIME := TIME'HIGH; + BEGIN + -- for each delay path + FOR i IN Paths'RANGE LOOP + -- ignore the delay path if it is not enabled + NEXT WHEN NOT Paths(i).PathCondition; + -- ignore the delay path if a more recent input event has been seen + NEXT WHEN Paths(i).InputChangeTime > InputAge; + + -- This is the most recent input change (so far) + -- Get the transition dependent delay + TmpDelay := VitalCalcDelay(NewValue, OldValue, Paths(i).PathDelay); + + -- If other inputs changed at the same time, + -- then use the minimum of their propagation delays, + -- else use the propagation delay from this input. + IF Paths(i).InputChangeTime < InputAge THEN + PropDelay := TmpDelay; + ELSE -- Simultaneous inputs change + IF TmpDelay < PropDelay THEN PropDelay := TmpDelay; END IF; + end if; + + InputAge := Paths(i).InputChangeTime; + END LOOP; + + -- If there were no paths (with an enabled condition), + -- use the default delay, if so indicated, otherwise return TIME'HIGH + IF (PropDelay = TIME'HIGH) THEN + IF (IgnoreDefaultDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + END IF; + + -- If the time since the most recent selected input event is + -- greater than the propagation delay from that input, + -- then use the default delay (won't happen if no paths are selected) + ELSIF (InputAge > PropDelay) THEN + PropDelay := VitalCalcDelay(NewValue, OldValue, DefaultDelay); + + -- Adjust the propagation delay by the time since the + -- the input event occurred (Usually 0 ns). + ELSE + PropDelay := PropDelay - InputAge; + END IF; + + RETURN PropDelay; + END; + + + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + -- Glitch Handlers + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + PROCEDURE ReportGlitch ( + CONSTANT GlitchRoutine : IN STRING; + CONSTANT OutSignalName : IN STRING; + CONSTANT PreemptedTime : IN TIME; + CONSTANT PreemptedValue : IN std_ulogic; + CONSTANT NewTime : IN TIME; + CONSTANT NewValue : IN std_ulogic; + CONSTANT Index : IN INTEGER := 0; + CONSTANT IsArraySignal : IN BOOLEAN := FALSE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + + VARIABLE StrPtr1, StrPtr2, StrPtr3, StrPtr4, StrPtr5 : LINE; + BEGIN + + Write (StrPtr1, PreemptedTime ); + Write (StrPtr2, NewTime); + Write (StrPtr3, LogicCvtTable(PreemptedValue)); + Write (StrPtr4, LogicCvtTable(NewValue)); + IF IsArraySignal THEN + Write (StrPtr5, STRING'( "(" ) ); + Write (StrPtr5, Index); + Write (StrPtr5, STRING'( ")" ) ); + ELSE + Write (StrPtr5, STRING'( " " ) ); + END IF; + + -- Issue Report only if Preempted value has not been + -- removed from event queue + ASSERT PreemptedTime > NewTime + REPORT GlitchRoutine & ": GLITCH Detected on port " & + OutSignalName & StrPtr5.ALL & + "; Preempted Future Value := " & StrPtr3.ALL & + " @ " & StrPtr1.ALL & + "; Newly Scheduled Value := " & StrPtr4.ALL & + " @ " & StrPtr2.ALL & + ";" + SEVERITY MsgSeverity; + + + ASSERT PreemptedTime <= NewTime + REPORT GlitchRoutine & ": GLITCH Detected on port " & + OutSignalName & StrPtr5.ALL & + "; Negative Preempted Value := " & StrPtr3.ALL & + " @ " & StrPtr1.ALL & + "; Newly Scheduled Value := " & StrPtr4.ALL & + " @ " & StrPtr2.ALL & + ";" + SEVERITY MsgSeverity; + + + DEALLOCATE(StrPtr1); + DEALLOCATE(StrPtr2); + DEALLOCATE(StrPtr3); + DEALLOCATE(StrPtr4); + DEALLOCATE(StrPtr5); + RETURN; + END ReportGlitch; + + --------------------------------------------------------------------------- + PROCEDURE VitalGlitch ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT NewValue : IN std_logic; + CONSTANT NewDelay : IN TIME := 0 ns; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 + CONSTANT MsgOn : IN BOOLEAN := FALSE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + --------------------------------------------------------------------------- + VARIABLE NewGlitch : BOOLEAN := TRUE; + VARIABLE dly : TIME := NewDelay; + VARIABLE NOW_TIME : TIME := NOW; + VARIABLE NegPreemptGlitch : BOOLEAN := FALSE; + + BEGIN + NegPreemptGlitch:=FALSE;--reset Preempt-Glitch + + -- If nothing to schedule, just return + IF NewDelay < 0 ns THEN + IF (NewValue /= GlitchData.SchedValue) THEN + VitalError ( "VitalGlitch", ErrNegDel, OutSignalName ); + END IF; + RETURN; + END IF; + + -- If simple signal assignment + -- perform the signal assignment + IF ( Mode = VitalInertial) THEN + OutSignal <= NewValue AFTER dly; + ELSIF ( Mode = VitalTransport ) THEN + OutSignal <= TRANSPORT NewValue AFTER dly; + ELSE + -- Glitch Processing --- + -- If nothing currently scheduled + IF GlitchData.SchedTime <= NOW THEN -- NOW >= last event + -- Note: NewValue is always /= OldValue when called from VPPD + IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF; + NewGlitch := FALSE; + GlitchData.GlitchTime := NOW+dly; + + -- New value earlier than the earliest previous value scheduled + -- (negative preemptive) + ELSIF (NOW+dly <= GlitchData.GlitchTime) + AND (NOW+dly <= GlitchData.SchedTime) THEN + + -- Glitch is negative preemptive - check if same value and + -- NegPreempt is on IR225 + IF (GlitchData.SchedValue /= NewValue) AND (NegPreemptOn) AND + (NOW > 0 NS) THEN + NewGlitch := TRUE; + NegPreemptGlitch :=TRUE; -- Set preempt Glitch condition + ELSE + NewGlitch := FALSE; -- No new glitch, save time for + -- possible future glitch + END IF; + GlitchData.GlitchTime := NOW+dly; + + -- Transaction currently scheduled - if glitch already happened + ELSIF GlitchData.GlitchTime <= NOW THEN + IF (GlitchData.SchedValue = NewValue) THEN + dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); + END IF; + NewGlitch := FALSE; + + -- Transaction currently scheduled (no glitch if same value) + ELSIF (GlitchData.SchedValue = NewValue) + AND (GlitchData.SchedTime = GlitchData.GlitchTime) THEN + -- revise scheduled output time if new delay is sooner + dly := Minimum( GlitchData.SchedTime-NOW, NewDelay ); + -- No new glitch, save time for possable future glitch + NewGlitch := FALSE; + GlitchData.GlitchTime := NOW+dly; + + -- Transaction currently scheduled represents a glitch + ELSE + NewGlitch := TRUE; -- A new glitch has been detected + END IF; + + IF NewGlitch THEN + -- If messages requested, report the glitch + IF MsgOn THEN + IF NegPreemptGlitch THEN --IR225 + ReportGlitch ("VitalGlitch-Neg", OutSignalName, + GlitchData.GlitchTime, GlitchData.SchedValue, + (dly + NOW), NewValue, + MsgSeverity=>MsgSeverity ); + ELSE + ReportGlitch ("VitalGlitch", OutSignalName, + GlitchData.GlitchTime, GlitchData.SchedValue, + (dly + NOW), NewValue, + MsgSeverity=>MsgSeverity ); + END IF; + END IF; + + -- If 'X' generation is requested, schedule the new value + -- preceeded by a glitch pulse. + -- Otherwise just schedule the new value (inertial mode). + IF XOn THEN + IF (Mode = OnDetect) THEN + OutSignal <= 'X'; + ELSE + OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW; + END IF; + + IF NegPreemptGlitch THEN -- IR225 + OutSignal <= TRANSPORT NewValue AFTER GlitchData.SchedTime-NOW; + ELSE + OutSignal <= TRANSPORT NewValue AFTER dly; + END IF; + ELSE + OutSignal <= NewValue AFTER dly; -- no glitch regular prop delay + END IF; + + -- If there no new glitch was detected, just schedule the new value. + ELSE + OutSignal <= NewValue AFTER dly; + END IF; + END IF; + + -- Record the new value and time depending on glitch type just scheduled. + IF NOT NegPreemptGlitch THEN -- 5/2/96 for "x-pulse" IR225 + GlitchData.SchedValue := NewValue; + GlitchData.SchedTime := NOW+dly; -- pulse timing. + ELSE + GlitchData.SchedValue := 'X'; + -- leave GlitchData.SchedTime to old value since glitch is negative + END IF; + RETURN; + END; + + --------------------------------------------------------------------------- + PROCEDURE VitalPathDelay ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArrayType; + CONSTANT DefaultDelay : IN VitalDelayType := VitalZeroDelay; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE --IR248 3/14/98 + ) IS + + VARIABLE PropDelay : TIME; + + BEGIN + -- Check if the new value to be scheduled is different than the + -- previously scheduled value + IF (GlitchData.SchedTime <= NOW) AND + (GlitchData.SchedValue = OutTemp) + THEN RETURN; + END IF; + + -- Evaluate propagation delay paths + PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, + OutSignalName, Paths, DefaultDelay, + IgnoreDefaultDelay); + + GlitchData.LastValue := OutTemp; + + -- Schedule the output transactions - including glitch handling + VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, + PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); + + END VitalPathDelay; + + --------------------------------------------------------------------------- + + PROCEDURE VitalPathDelay01 ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArray01Type; + CONSTANT DefaultDelay : IN VitalDelayType01 := VitalZeroDelay01; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 + CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 + + + ) IS + + VARIABLE PropDelay : TIME; + BEGIN + + -- Check if the new value to be scheduled is different than the + -- previously scheduled value + IF (GlitchData.SchedTime <= NOW) AND + (GlitchData.SchedValue = OutTemp) + THEN RETURN; + -- Check if the new value to be Scheduled is the same as the + -- previously scheduled output transactions. If this condition + -- exists and the new scheduled time is < the current GlitchData. + -- schedTime then a fast path condition exists (IR250). If the + -- modeler wants this condition rejected by setting the + -- RejectFastPath actual to true then exit out. + ELSIF (GlitchData.SchedValue=OutTemp) AND (RejectFastPath) + THEN RETURN; + END IF; + + -- Evaluate propagation delay paths + PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, + OutSignalName, Paths, DefaultDelay, + IgnoreDefaultDelay); + + GlitchData.LastValue := OutTemp; + + + VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, + PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); + END VitalPathDelay01; + + --------------------------------------------------------------------------- + PROCEDURE VitalPathDelay01Z ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArray01ZType; + CONSTANT DefaultDelay : IN VitalDelayType01Z := VitalZeroDelay01Z; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 + CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 + ) IS + + VARIABLE PropDelay : TIME; + + BEGIN + -- Check if the new value to be scheduled is different than the + -- previously scheduled value + IF (GlitchData.SchedTime <= NOW) AND + (GlitchData.SchedValue = OutTemp) + THEN RETURN; + -- Check if the new value to be Scheduled is the same as the + -- previously scheduled output transactions. If this condition + -- exists and the new scheduled time is < the current GlitchData. + -- schedTime then a fast path condition exists (IR250). If the + -- modeler wants this condition rejected by setting the + -- RejectFastPath actual to true then exit out. + ELSIF (GlitchData.SchedValue=OutTemp) AND (RejectFastPath) + THEN RETURN; + END IF; + + -- Evaluate propagation delay paths + PropDelay := VitalSelectPathDelay (OutTemp, GlitchData.LastValue, + OutSignalName, Paths, DefaultDelay, + IgnoreDefaultDelay); + + GlitchData.LastValue := OutTemp; + + + -- Schedule the output transactions - including glitch handling + VitalGlitch (OutSignal, GlitchData, OutSignalName, OutTemp, + PropDelay, Mode, XOn, NegPreemptOn, MsgOn, MsgSeverity ); + END VitalPathDelay01Z; + + + ---------------------------------------------------------------------------- + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType + ) IS + BEGIN + OutSig <= TRANSPORT InSig AFTER twire; + END VitalWireDelay; + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01 + ) IS + VARIABLE Delay : TIME; + BEGIN + Delay := VitalCalcDelay( InSig, InSig'LAST_VALUE, twire ); + OutSig <= TRANSPORT InSig AFTER Delay; + END VitalWireDelay; + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01Z + ) IS + VARIABLE Delay : TIME; + BEGIN + Delay := VitalCalcDelay( InSig, InSig'LAST_VALUE, twire ); + OutSig <= TRANSPORT InSig AFTER Delay; + END VitalWireDelay; + + ---------------------------------------------------------------------------- + PROCEDURE VitalSignalDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT dly : IN TIME + ) IS + BEGIN + OutSig <= TRANSPORT InSig AFTER dly; + END; + + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + -- Setup and Hold Time Check Routine + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + PROCEDURE ReportViolation ( + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT CheckInfo : IN CheckInfoType; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + VARIABLE Message : LINE; + BEGIN + IF NOT CheckInfo.Violation THEN RETURN; END IF; + + Write ( Message, HeaderMsg ); + Case CheckInfo.CheckKind IS + WHEN SetupCheck => Write ( Message, STRING'(" SETUP ") ); + WHEN HoldCheck => Write ( Message, STRING'(" HOLD ") ); + WHEN RecoveryCheck => Write ( Message, STRING'(" RECOVERY ") ); + WHEN RemovalCheck => Write ( Message, STRING'(" REMOVAL ") ); + WHEN PulseWidCheck => Write ( Message, STRING'(" PULSE WIDTH ")); + WHEN PeriodCheck => Write ( Message, STRING'(" PERIOD ") ); + END CASE; + Write ( Message, HiLoStr(CheckInfo.State) ); + Write ( Message, STRING'(" VIOLATION ON ") ); + Write ( Message, TestSignalName ); + IF (RefSignalName'LENGTH > 0) THEN + Write ( Message, STRING'(" WITH RESPECT TO ") ); + Write ( Message, RefSignalName ); + END IF; + Write ( Message, ';' & LF ); + Write ( Message, STRING'(" Expected := ") ); + Write ( Message, CheckInfo.ExpTime); + Write ( Message, STRING'("; Observed := ") ); + Write ( Message, CheckInfo.ObsTime); + Write ( Message, STRING'("; At : ") ); + Write ( Message, CheckInfo.DetTime); + + ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity; + + DEALLOCATE (Message); + END ReportViolation; + + + --------------------------------------------------------------------------- + -- Procedure : InternalTimingCheck + --------------------------------------------------------------------------- + PROCEDURE InternalTimingCheck ( + CONSTANT TestSignal : IN std_ulogic; + CONSTANT RefSignal : IN std_ulogic; + CONSTANT TestDelay : IN TIME := 0 ns; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + VARIABLE RefTime : IN TIME; + VARIABLE RefEdge : IN BOOLEAN; + VARIABLE TestTime : IN TIME; + VARIABLE TestEvent : IN BOOLEAN; + VARIABLE SetupEn : INOUT BOOLEAN; + VARIABLE HoldEn : INOUT BOOLEAN; + VARIABLE CheckInfo : INOUT CheckInfoType; + CONSTANT MsgOn : IN BOOLEAN + ) IS + VARIABLE bias : TIME; + VARIABLE actualObsTime : TIME; + VARIABLE BC : TIME; + VARIABLE Message:LINE; + BEGIN + -- Check SETUP constraint + IF RefEdge THEN + IF SetupEn THEN + CheckInfo.ObsTime := RefTime - TestTime; + CheckInfo.State := To_X01(TestSignal); + CASE CheckInfo.State IS + WHEN '0' => CheckInfo.ExpTime := SetupLow; + -- start of new code IR245-246 + BC := HoldHigh; + -- end of new code IR245-246 + WHEN '1' => CheckInfo.ExpTime := SetupHigh; + -- start of new code IR245-246 + BC := HoldLow; + -- end of new code IR245-246 + WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); + -- start of new code IR245-246 + BC := Maximum(HoldHigh,HoldLow); + -- end of new code IR245-246 + END CASE; + -- added the second condition for IR 245-246 + CheckInfo.Violation := ( (CheckInfo.ObsTime < CheckInfo.ExpTime) + AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))) ); + -- start of new code IR245-246 + IF(CheckInfo.ExpTime = 0 ns) THEN + CheckInfo.CheckKind := HoldCheck; + ELSE + CheckInfo.CheckKind := SetupCheck; + END IF; + -- end of new code IR245-246 + SetupEn := FALSE; + ELSE + CheckInfo.Violation := FALSE; + END IF; + + -- Check HOLD constraint + ELSIF TestEvent THEN + IF HoldEn THEN + CheckInfo.ObsTime := TestTime - RefTime; + CheckInfo.State := To_X01(TestSignal); + CASE CheckInfo.State IS + WHEN '0' => CheckInfo.ExpTime := HoldHigh; + + -- new code for unnamed IR + CheckInfo.State := '1'; + + -- start of new code IR245-246 + BC := SetupLow; + -- end of new code IR245-246 + WHEN '1' => CheckInfo.ExpTime := HoldLow; + + -- new code for unnamed IR + CheckInfo.State := '0'; + + -- start of new code IR245-246 + BC := SetupHigh; + -- end of new code IR245-246 + WHEN 'X' => CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); + -- start of new code IR245-246 + BC := Maximum(SetupHigh,SetupLow); + -- end of new code IR245-246 + END CASE; + -- added the second condition for IR 245-246 + CheckInfo.Violation := ( (CheckInfo.ObsTime < CheckInfo.ExpTime) + AND ( NOT ((CheckInfo.ObsTime = BC) and (BC = 0 ns))) ); + + -- start of new code IR245-246 + IF(CheckInfo.ExpTime = 0 ns) THEN + CheckInfo.CheckKind := SetupCheck; + ELSE + CheckInfo.CheckKind := HoldCheck; + END IF; + -- end of new code IR245-246 + HoldEn := NOT CheckInfo.Violation; + ELSE + CheckInfo.Violation := FALSE; + END IF; + ELSE + CheckInfo.Violation := FALSE; + END IF; + + -- Adjust report values to account for internal model delays + -- Note: TestDelay, RefDelay, TestTime, RefTime are non-negative + -- Note: bias may be negative or positive + IF MsgOn AND CheckInfo.Violation THEN + -- modified the code for correct reporting of violation in case of + -- order of signals being reversed because of internal delays + -- new variable + actualObsTime := (TestTime-TestDelay)-(RefTime-RefDelay); + bias := TestDelay - RefDelay; + IF (actualObsTime < 0 ns) THEN -- It should be a setup check + IF ( CheckInfo.CheckKind = HoldCheck) then + CheckInfo.CheckKind := SetupCheck; + CASE CheckInfo.State IS + WHEN '0' => CheckInfo.ExpTime := SetupLow; + WHEN '1' => CheckInfo.ExpTime := SetupHigh; + WHEN 'X' => CheckInfo.ExpTime := Maximum(SetupHigh,SetupLow); + END CASE; + END IF; + + CheckInfo.ObsTime := -actualObsTime; + CheckInfo.ExpTime := CheckInfo.ExpTime + bias; + CheckInfo.DetTime := RefTime - RefDelay; + ELSE -- It should be a hold check + IF ( CheckInfo.CheckKind = SetupCheck) then + CheckInfo.CheckKind := HoldCheck; + CASE CheckInfo.State IS + WHEN '0' => CheckInfo.ExpTime := HoldHigh; + CheckInfo.State := '1'; + WHEN '1' => CheckInfo.ExpTime := HoldLow; + CheckInfo.State := '0'; + WHEN 'X' => CheckInfo.ExpTime := Maximum(HoldHigh,HoldLow); + END CASE; + END IF; + + CheckInfo.ObsTime := actualObsTime; + CheckInfo.ExpTime := CheckInfo.ExpTime - bias; + CheckInfo.DetTime := TestTime - TestDelay; + END IF; + + END IF; + END InternalTimingCheck; + + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + FUNCTION VitalTimingDataInit + RETURN VitalTimingDataType IS + BEGIN + RETURN (FALSE,'X', 0 ns, FALSE, 'X', 0 ns, FALSE, NULL, NULL, NULL, NULL); + END; + + --------------------------------------------------------------------------- + -- Procedure : VitalSetupHoldCheck + --------------------------------------------------------------------------- + PROCEDURE VitalSetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_ulogic; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + ) IS + + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge, TestEvent : BOOLEAN; + VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; + BEGIN + + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLast := To_X01(TestSignal); + TimingData.RefLast := To_X01(RefSignal); + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), + RefTransition); + TimingData.RefLast := To_X01(RefSignal); + IF RefEdge THEN + TimingData.RefTime := NOW; + TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef; --IR252 3/23/98 + TimingData.HoldEn := EnableHoldOnRef; --IR252 3/23/98 + END IF; + + -- Detect test (data) changes and record the time of the last change + TestEvent := TimingData.TestLast /= To_X01Z(TestSignal); + TimingData.TestLast := To_X01Z(TestSignal); + IF TestEvent THEN + TimingData.TestTime := NOW; + TimingData.SetupEn := EnableSetupOnTest; --IR252 3/23/98 + TimingData.HoldEn := TimingData.HoldEn AND EnableHoldOnTest; --IR252 3/23/98 + END IF; + + -- Perform timing checks (if enabled) + Violation := '0'; + IF (CheckEnabled) THEN + InternalTimingCheck ( + TestSignal => TestSignal, + RefSignal => RefSignal, + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHigh, + SetupLow => SetupLow, + HoldHigh => HoldHigh, + HoldLow => HoldLow, + RefTime => TimingData.RefTime, + RefEdge => RefEdge, + TestTime => TimingData.TestTime, + TestEvent => TestEvent, + SetupEn => TimingData.SetupEn, + HoldEn => TimingData.HoldEn, + CheckInfo => CheckInfo, + MsgOn => MsgOn ); + + -- Report any detected violations and set return violation flag + IF CheckInfo.Violation THEN + IF (MsgOn) THEN + ReportViolation (TestSignalName, RefSignalName, + HeaderMsg, CheckInfo, MsgSeverity ); + END IF; + IF (XOn) THEN Violation := 'X'; END IF; + END IF; + END IF; + + END VitalSetupHoldCheck; + + --------------------------------------------------------------------------- + PROCEDURE VitalSetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + + ) IS + + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge : BOOLEAN; + VARIABLE TestEvent : VitalBoolArrayT(TestSignal'RANGE); + VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; + VARIABLE ChangedAllAtOnce : BOOLEAN := TRUE; + VARIABLE StrPtr1 : LINE; + + BEGIN + -- Initialization of working area. + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLastA := NEW std_logic_vector(TestSignal'RANGE); + TimingData.TestTimeA := NEW VitalTimeArrayT(TestSignal'RANGE); + TimingData.HoldEnA := NEW VitalBoolArrayT(TestSignal'RANGE); + TimingData.SetupEnA := NEW VitalBoolArrayT(TestSignal'RANGE); + FOR i IN TestSignal'RANGE LOOP + TimingData.TestLastA(i) := To_X01(TestSignal(i)); + END LOOP; + TimingData.RefLast := To_X01(RefSignal); + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), + RefTransition); + TimingData.RefLast := To_X01(RefSignal); + IF RefEdge THEN + TimingData.RefTime := NOW; + TimingData.SetupEn := TimingData.SetupEn AND EnableSetupOnRef; --IR252 3/23/98 + TimingData.HoldEnA.all := (TestSignal'RANGE => EnableHoldOnRef); --IR252 3/23/98 + END IF; + + -- Detect test (data) changes and record the time of the last change + FOR i IN TestSignal'RANGE LOOP + TestEvent(i) := TimingData.TestLastA(i) /= To_X01Z(TestSignal(i)); + TimingData.TestLastA(i) := To_X01Z(TestSignal(i)); + IF TestEvent(i) THEN + TimingData.TestTimeA(i) := NOW; + TimingData.SetupEnA(i) := EnableSetupOnTest; --IR252 3/23/98 + TimingData.HoldEnA(i) := TimingData.HoldEn AND EnableHoldOnTest; --IR252 3/23/98 + TimingData.TestTime := NOW; --IR252 3/23/98 + END IF; + END LOOP; + + -- Check to see if the Bus subelements changed all at the same time. + -- If so, then we can reduce the volume of error messages since we no + -- longer have to report every subelement individually + FOR i IN TestSignal'RANGE LOOP + IF TimingData.TestTimeA(i) /= TimingData.TestTime THEN + ChangedAllAtOnce := FALSE; + EXIT; + END IF; + END LOOP; + + -- Perform timing checks (if enabled) + Violation := '0'; + IF (CheckEnabled) THEN + FOR i IN TestSignal'RANGE LOOP + InternalTimingCheck ( + TestSignal => TestSignal(i), + RefSignal => RefSignal, + TestDelay => TestDly, + RefDelay => RefDly, + SetupHigh => SetupHigh, + SetupLow => SetupLow, + HoldHigh => HoldHigh, + HoldLow => HoldLow, + RefTime => TimingData.RefTime, + RefEdge => RefEdge, + TestTime => TimingData.TestTimeA(i), + TestEvent => TestEvent(i), + SetupEn => TimingData.SetupEnA(i), + HoldEn => TimingData.HoldEnA(i), + CheckInfo => CheckInfo, + MsgOn => MsgOn ); + + -- Report any detected violations and set return violation flag + IF CheckInfo.Violation THEN + IF (MsgOn) THEN + IF ( ChangedAllAtOnce AND (i = TestSignal'LEFT) ) THEN + ReportViolation (TestSignalName&"(...)", RefSignalName, + HeaderMsg, CheckInfo, MsgSeverity ); + ELSIF (NOT ChangedAllAtOnce) THEN + Write (StrPtr1, i); + ReportViolation (TestSignalName & "(" & StrPtr1.ALL & ")", + RefSignalName, + HeaderMsg, CheckInfo, MsgSeverity ); + DEALLOCATE (StrPtr1); + END IF; + END IF; + IF (XOn) THEN + Violation := 'X'; + END IF; + END IF; + END LOOP; + END IF; + + DEALLOCATE (StrPtr1); + + END VitalSetupHoldCheck; + + --------------------------------------------------------------------------- + -- Function : VitalRecoveryRemovalCheck + --------------------------------------------------------------------------- + PROCEDURE VitalRecoveryRemovalCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_ulogic; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT Recovery : IN TIME := 0 ns; + CONSTANT Removal : IN TIME := 0 ns; + CONSTANT ActiveLow : IN BOOLEAN := TRUE; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableRecOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRecOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRemOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRemOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + ) IS + VARIABLE CheckInfo : CheckInfoType; + VARIABLE RefEdge, TestEvent : BOOLEAN; + VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); + VARIABLE RefDly : TIME := Maximum(0 ns, RefDelay); + VARIABLE bias : TIME; + BEGIN + + IF (TimingData.NotFirstFlag = FALSE) THEN + TimingData.TestLast := To_X01(TestSignal); + TimingData.RefLast := To_X01(RefSignal); + TimingData.NotFirstFlag := TRUE; + END IF; + + -- Detect reference edges and record the time of the last edge + RefEdge := EdgeSymbolMatch(TimingData.RefLast, To_X01(RefSignal), + RefTransition); + TimingData.RefLast := To_X01(RefSignal); + IF RefEdge THEN + TimingData.RefTime := NOW; + TimingData.SetupEn := TimingData.SetupEn AND EnableRecOnRef; --IR252 3/23/98 + TimingData.HoldEn := EnableRemOnRef; --IR252 3/23/98 + END IF; + + -- Detect test (data) changes and record the time of the last change + TestEvent := TimingData.TestLast /= To_X01Z(TestSignal); + TimingData.TestLast := To_X01Z(TestSignal); + IF TestEvent THEN + TimingData.TestTime := NOW; + TimingData.SetupEn := EnableRecOnTest; --IR252 3/23/98 + TimingData.HoldEn := TimingData.HoldEn AND EnableRemOnTest; --IR252 3/23/98 + END IF; + + -- Perform timing checks (if enabled) + Violation := '0'; + IF (CheckEnabled) THEN + + IF ActiveLow THEN + InternalTimingCheck ( + TestSignal, RefSignal, TestDly, RefDly, + Recovery, 0 ns, 0 ns, Removal, + TimingData.RefTime, RefEdge, + TimingData.TestTime, TestEvent, + TimingData.SetupEn, TimingData.HoldEn, + CheckInfo, MsgOn ); + ELSE + InternalTimingCheck ( + TestSignal, RefSignal, TestDly, RefDly, + 0 ns, Recovery, Removal, 0 ns, + TimingData.RefTime, RefEdge, + TimingData.TestTime, TestEvent, + TimingData.SetupEn, TimingData.HoldEn, + CheckInfo, MsgOn ); + END IF; + + + -- Report any detected violations and set return violation flag + IF CheckInfo.Violation THEN + IF CheckInfo.CheckKind = SetupCheck THEN + CheckInfo.CheckKind := RecoveryCheck; + ELSE + CheckInfo.CheckKind := RemovalCheck; + END IF; + IF (MsgOn) THEN + ReportViolation (TestSignalName, RefSignalName, + HeaderMsg, CheckInfo, MsgSeverity ); + END IF; + IF (XOn) THEN Violation := 'X'; END IF; + END IF; + END IF; + + END VitalRecoveryRemovalCheck; + + --------------------------------------------------------------------------- + PROCEDURE VitalPeriodPulseCheck ( + VARIABLE Violation : OUT X01; + VARIABLE PeriodData : INOUT VitalPeriodDataType; + SIGNAL TestSignal : IN std_ulogic; + CONSTANT TestSignalName : IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + CONSTANT Period : IN TIME := 0 ns; + CONSTANT PulseWidthHigh : IN TIME := 0 ns; + CONSTANT PulseWidthLow : IN TIME := 0 ns; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING + ) IS + + VARIABLE TestDly : TIME := Maximum(0 ns, TestDelay); + VARIABLE CheckInfo : CheckInfoType; + VARIABLE PeriodObs : TIME; + VARIABLE PulseTest, PeriodTest : BOOLEAN; + VARIABLE TestValue : X01 := To_X01(TestSignal); + BEGIN + + IF (PeriodData.NotFirstFlag = FALSE) THEN + PeriodData.Rise := + -maximum(Period, maximum(PulseWidthHigh, PulseWidthLow)); + PeriodData.Fall := + -maximum(Period, maximum(PulseWidthHigh, PulseWidthLow)); + PeriodData.Last := To_X01(TestSignal); + PeriodData.NotFirstFlag := TRUE; + END IF; + + -- Initialize for no violation + -- No violation possible if no test signal change + Violation := '0'; + IF (PeriodData.Last = TestValue) THEN + RETURN; + END IF; + + -- record starting pulse times + IF EdgeSymbolMatch(PeriodData.Last, TestValue, 'P') THEN + -- Compute period times, then record the High Rise Time + PeriodObs := NOW - PeriodData.Rise; + PeriodData.Rise := NOW; + PeriodTest := TRUE; + ELSIF EdgeSymbolMatch(PeriodData.Last, TestValue, 'N') THEN + -- Compute period times, then record the Low Fall Time + PeriodObs := NOW - PeriodData.Fall; + PeriodData.Fall := NOW; + PeriodTest := TRUE; + ELSE + PeriodTest := FALSE; + END IF; + + -- do checks on pulse ends + IF EdgeSymbolMatch(PeriodData.Last, TestValue, 'p') THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData.Fall; + CheckInfo.ExpTime := PulseWidthLow; + PulseTest := TRUE; + ELSIF EdgeSymbolMatch(PeriodData.Last, TestValue, 'n') THEN + -- Compute pulse times + CheckInfo.ObsTime := NOW - PeriodData.Rise; + CheckInfo.ExpTime := PulseWidthHigh; + PulseTest := TRUE; + ELSE + PulseTest := FALSE; + END IF; + + IF PulseTest AND CheckEnabled THEN + -- Verify Pulse Width [ignore 1st edge] + IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN + IF (XOn) THEN Violation := 'X'; END IF; + IF (MsgOn) THEN + CheckInfo.Violation := TRUE; + CheckInfo.CheckKind := PulseWidCheck; + CheckInfo.DetTime := NOW - TestDly; + CheckInfo.State := PeriodData.Last; + ReportViolation (TestSignalName, "", + HeaderMsg, CheckInfo, MsgSeverity ); + END IF; -- MsgOn + END IF; + END IF; + + IF PeriodTest AND CheckEnabled THEN + -- Verify the Period [ignore 1st edge] + CheckInfo.ObsTime := PeriodObs; + CheckInfo.ExpTime := Period; + IF ( CheckInfo.ObsTime < CheckInfo.ExpTime ) THEN + IF (XOn) THEN Violation := 'X'; END IF; + IF (MsgOn) THEN + CheckInfo.Violation := TRUE; + CheckInfo.CheckKind := PeriodCheck; + CheckInfo.DetTime := NOW - TestDly; + CheckInfo.State := TestValue; + ReportViolation (TestSignalName, "", + HeaderMsg, CheckInfo, MsgSeverity ); + END IF; -- MsgOn + END IF; + END IF; + + PeriodData.Last := TestValue; + + END VitalPeriodPulseCheck; + + + + PROCEDURE ReportSkewViolation ( + CONSTANT Signal1Name : IN STRING := ""; + CONSTANT Signal2Name : IN STRING := ""; + CONSTANT ExpectedTime : IN TIME; + CONSTANT OccuranceTime : IN TIME; + CONSTANT HeaderMsg : IN STRING; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT SkewPhase : IN SkewType; + CONSTANT ViolationFlag : IN BOOLEAN := TRUE + ) IS + VARIABLE Message : LINE; + BEGIN + Write ( Message, HeaderMsg ); + IF (ViolationFlag /= TRUE) THEN + Write ( Message, STRING'(" POSSIBLE") ); + END IF; + IF (SkewPhase = Inphase) THEN + Write ( Message, STRING'(" IN PHASE ") ); + ELSE + Write ( Message, STRING'(" OUT OF PHASE ") ); + END IF; + Write ( Message, STRING'("SKEW VIOLATION ON ") ); + Write ( Message, Signal2Name ); + IF (Signal1Name'LENGTH > 0) THEN + Write ( Message, STRING'(" WITH RESPECT TO ") ); + Write ( Message, Signal1Name ); + END IF; + Write ( Message, ';' & LF ); + Write ( Message, STRING'(" At : ") ); + Write ( Message, OccuranceTime); + Write ( Message, STRING'("; Skew Limit : ") ); + Write ( Message, ExpectedTime); + + ASSERT FALSE REPORT Message.ALL SEVERITY MsgSeverity; + + DEALLOCATE (Message); + END ReportSkewViolation; + + + PROCEDURE VitalInPhaseSkewCheck ( + VARIABLE Violation : OUT X01; + VARIABLE SkewData : INOUT VitalSkewDataType; + SIGNAL Signal1 : IN std_ulogic; + CONSTANT Signal1Name : IN STRING := ""; + CONSTANT Signal1Delay : IN TIME := 0 ns; + SIGNAL Signal2 : IN std_ulogic; + CONSTANT Signal2Name : IN STRING := ""; + CONSTANT Signal2Delay : IN TIME := 0 ns; + CONSTANT SkewS1S2RiseRise : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1RiseRise : IN TIME := TIME'HIGH; + CONSTANT SkewS1S2FallFall : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1FallFall : IN TIME := TIME'HIGH; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT HeaderMsg : IN STRING := ""; + SIGNAL Trigger : INOUT std_ulogic + ) IS + VARIABLE ReportType : VitalSkewExpectedType := none; + VARIABLE ExpectedType : VitalSkewExpectedType := none; + VARIABLE ReportTime : TIME; + VARIABLE TriggerDelay : TIME; + VARIABLE ViolationCertain : Boolean := TRUE; + BEGIN + Violation := '0'; + ReportType := none; + TriggerDelay := noTrigger; + + IF (CheckEnabled) THEN + IF (SkewData.ExpectedType /= none) THEN + IF (trigger'Event) THEN + CASE SkewData.ExpectedType IS + WHEN s1r => ReportType := s1r; + ReportTime := NOW - Signal1Delay; + WHEN s1f => ReportType := s1f; + ReportTime := NOW - Signal1Delay; + WHEN s2r => ReportType := s2r; + ReportTime := NOW - Signal2Delay; + WHEN s2f => ReportType := s2f; + ReportTime := NOW - Signal2Delay; + WHEN OTHERS => + END CASE; + SkewData.ExpectedType := none; + ELSIF ( Signal1'Event OR Signal2'Event ) THEN + IF ( Signal1 /= 'X' AND Signal2 /= 'X' ) THEN + TriggerDelay := 0 ns; + ExpectedType := none; + END IF; + END IF; + END IF; + + IF (Signal1'EVENT and Signal2'EVENT) THEN + IF (Signal1 = Signal2) THEN + IF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - Signal2Delay) >= + SkewS1S2RiseRise) THEN + ReportType := s2r; + ReportTime := NOW - Signal1Delay + + SkewS1S2RiseRise; + ELSIF ((Signal2Delay -Signal1Delay) >= + SkewS2S1RiseRise) THEN + ReportType := s1r; + ReportTime := NOW - Signal2Delay + + SkewS2S1RiseRise; + END IF; + ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - Signal2Delay) >= + SkewS1S2FallFall) THEN + ReportType := s2f; + ReportTime := NOW - Signal1Delay + + SkewS1S2FallFall; + ELSIF ((Signal2Delay - Signal1Delay) >= + SkewS2S1FallFall) THEN + ReportType := s1f; + ReportTime := NOW - Signal2Delay + + SkewS2S1FallFall; + END IF; + END IF; + ELSIF (Posedge(Signal1'LAST_VALUE , Signal1)) THEN + IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > + SkewS2S1FallFall)) THEN + ReportType := s1f; + ReportTime := NOW - Signal2Delay + + SkewS2S1FallFall; + ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > + SkewS1S2RiseRise)) THEN + ReportType := s2r; + ReportTime := NOW - Signal1Delay + + SkewS1S2RiseRise; + ELSIF (Signal2Delay > Signal1Delay) THEN + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2RiseRise + + Signal2Delay - Signal1Delay; + ELSIF (Signal1Delay > Signal2Delay) THEN + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1RiseRise + + Signal1Delay - Signal2Delay; + ELSIF (SkewS1S2RiseRise < SkewS2S1RiseRise) THEN + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2RiseRise; + ELSE + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1RiseRise; + END IF; + ELSIF (Negedge(Signal1'LAST_VALUE , Signal1)) THEN + IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > + SkewS2S1RiseRise)) THEN + ReportType := s1r; + ReportTime := NOW - Signal2Delay + + SkewS2S1RiseRise; + ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > + SkewS1S2FallFall)) THEN + ReportType := s2f; + ReportTime := NOW - Signal1Delay + + SkewS1S2FallFall; + ELSIF (Signal2Delay > Signal1Delay) THEN + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2FallFall + + Signal2Delay - Signal1Delay; + ELSIF (Signal1Delay > Signal2Delay) THEN + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1FallFall + + Signal1Delay - Signal2Delay; + ELSIF (SkewS1S2FallFall < SkewS2S1FallFall) THEN + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2FallFall; + ELSE + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1FallFall; + END IF; + END IF; + ELSIF (Signal1'EVENT) THEN + IF ( Signal1 /= Signal2) THEN + IF ( Posedge( Signal1'LAST_VALUE, Signal1)) THEN + IF (SkewS1S2RiseRise > (Signal1Delay - + Signal2Delay)) THEN + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2RiseRise + + Signal2Delay - + Signal1Delay; + ELSE + ReportType := s2r; + ReportTime := NOW + SkewS1S2RiseRise - + Signal1Delay; + END IF; + ELSIF ( Negedge( Signal1'LAST_VALUE, Signal1)) THEN + IF (SkewS1S2FallFall > (Signal1Delay - + Signal2Delay)) THEN + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2FallFall + + Signal2Delay - + Signal1Delay; + ELSE + ReportType := s2f; + ReportTime := NOW + SkewS1S2FallFall - + Signal1Delay; + END IF; + END IF; + ELSE + IF ( Posedge( Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - SkewS1S2RiseRise) > + (Signal2'LAST_EVENT + Signal2Delay)) THEN + IF ((SkewData.Signal2Old2 - Signal2Delay) > + (NOW - Signal1Delay + + SkewS1S2RiseRise)) THEN + ViolationCertain := FALSE; + ReportType := s2r; + ReportTime := NOW + SkewS1S2RiseRise - + Signal1Delay; + END IF; + END IF; + ELSIF ( Negedge( Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - SkewS1S2FallFall) > + (Signal2'LAST_EVENT + Signal2Delay)) THEN + IF (( SkewData.Signal2Old2 - Signal2Delay) > + (NOW - Signal1Delay + + SkewS1S2FallFall )) THEN + ViolationCertain := FALSE; + ReportType := s2f; + ReportTime := NOW + SkewS1S2FallFall - + Signal1Delay; + END IF; + END IF; + END IF; + END IF; + ELSIF (Signal2'EVENT) THEN + IF (Signal1 /= Signal2) THEN + IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN + IF ( SkewS2S1RiseRise > (Signal2Delay - + Signal1Delay)) THEN + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1RiseRise + + Signal1Delay - + Signal2Delay; + ELSE + ReportType := s2r; + ReportTime := NOW + SkewS2S1RiseRise - + Signal2Delay; + END IF; + ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN + IF ( SkewS2S1FallFall > (Signal2Delay - + Signal1Delay)) THEN + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1FallFall + + Signal1Delay - + Signal2Delay; + ELSE + ReportType := s1f; + ReportTime := NOW + SkewS2S1FallFall - + Signal2Delay; + END IF; + END IF; + ELSE + IF (Posedge(Signal2'LAST_VALUE, Signal2)) THEN + IF ((Signal2Delay - SkewS2S1RiseRise) > + (Signal1'LAST_EVENT + Signal1Delay)) THEN + IF (( SkewData.Signal1Old2 - Signal1Delay) > + (NOW - Signal2Delay + + SkewS2S1RiseRise )) THEN + ViolationCertain := FALSE; + ReportType := s1r; + ReportTime := NOW + SkewS2S1RiseRise - + Signal2Delay; + END IF; + END IF; + ELSIF (Negedge(Signal2'LAST_VALUE, Signal2)) THEN + IF ((Signal2Delay - SkewS2S1FallFall) > + (Signal1'LAST_EVENT + Signal1Delay)) THEN + IF (( SkewData.Signal1Old2 - Signal1Delay) > + (NOW - Signal2Delay + + SkewS2S1FallFall )) THEN + ViolationCertain := FALSE; + ReportType := s1f; + ReportTime := NOW + SkewS2S1FallFall - + Signal2Delay; + END IF; + END IF; + END IF; + END IF; + END IF; + + IF (ReportType /= none) THEN + IF (MsgOn) THEN + CASE ReportType IS + WHEN s1r => + ReportSkewViolation( + Signal2Name, + Signal1Name, + SkewS2S1RiseRise, + ReportTime, + HeaderMsg, + MsgSeverity, + Inphase, + ViolationCertain); + WHEN s1f => + ReportSkewViolation( + Signal2Name, + Signal1Name, + SkewS2S1FallFall, + ReportTime, + HeaderMsg, + MsgSeverity, + Inphase, + ViolationCertain); + WHEN s2r => + ReportSkewViolation( + Signal1Name, + Signal2Name, + SkewS1S2RiseRise, + ReportTime, + HeaderMsg, + MsgSeverity, + Inphase, + ViolationCertain); + WHEN s2f => + ReportSkewViolation( + Signal1Name, + Signal2Name, + SkewS1S2FallFall, + ReportTime, + HeaderMsg, + MsgSeverity, + Inphase, + ViolationCertain); + WHEN OTHERS => + END CASE; + END IF; + IF (XOn) THEN + Violation := 'X'; + END IF; + SkewData.ExpectedType := none; + END IF; + IF (TriggerDelay /= noTrigger) THEN + IF (TriggerDelay = 0 ns) THEN + trigger <= TRANSPORT trigger AFTER 0 ns; + ELSE + trigger <= TRANSPORT not (trigger) AFTER + TriggerDelay; + END IF; + END IF; + END IF; + IF (Signal1'EVENT and SkewData.Signal1Old1 /= NOW) THEN + SkewData.Signal1Old2 := SkewData.Signal1Old1; + SkewData.Signal1Old1 := NOW; + END IF; + IF (Signal2'EVENT and SkewData.Signal2Old1 /= NOW) THEN + SkewData.Signal2Old2 := SkewData.Signal2Old1; + SkewData.Signal2Old1 := NOW; + END IF; + END VitalInPhaseSkewCheck; + + PROCEDURE VitalOutPhaseSkewCheck ( + VARIABLE Violation : OUT X01; + VARIABLE SkewData : INOUT VitalSkewDataType; + SIGNAL Signal1 : IN std_ulogic; + CONSTANT Signal1Name : IN STRING := ""; + CONSTANT Signal1Delay : IN TIME := 0 ns; + SIGNAL Signal2 : IN std_ulogic; + CONSTANT Signal2Name : IN STRING := ""; + CONSTANT Signal2Delay : IN TIME := 0 ns; + CONSTANT SkewS1S2RiseFall : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1RiseFall : IN TIME := TIME'HIGH; + CONSTANT SkewS1S2FallRise : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1FallRise : IN TIME := TIME'HIGH; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT HeaderMsg : IN STRING := ""; + SIGNAL Trigger : INOUT std_ulogic + ) IS + VARIABLE ReportType : VitalSkewExpectedType := none; + VARIABLE ExpectedType : VitalSkewExpectedType := none; + VARIABLE ReportTime : TIME; + VARIABLE TriggerDelay : TIME; + VARIABLE ViolationCertain : Boolean := TRUE; + BEGIN + Violation := '0'; + TriggerDelay := noTrigger; + IF (CheckEnabled) THEN + IF (SkewData.ExpectedType /= none) THEN + IF (trigger'Event) THEN + CASE SkewData.ExpectedType IS + WHEN s1r => ReportType := s1r; + ReportTime := NOW - Signal1Delay; + WHEN s1f => ReportType := s1f; + ReportTime := NOW - Signal1Delay; + WHEN s2r => ReportType := s2r; + ReportTime := NOW - Signal2Delay; + WHEN s2f => ReportType := s2f; + ReportTime := NOW - Signal2Delay; + WHEN OTHERS => + END CASE; + SkewData.ExpectedType := none; + ELSIF (Signal1'Event OR Signal2'Event ) THEN + IF (Signal1 /= 'X' AND Signal2 /= 'X' ) THEN + TriggerDelay := 0 ns; + SkewData.ExpectedType := none; + END IF; + END IF; + END IF; + + IF (Signal1'EVENT and Signal2'EVENT) THEN + IF (Signal1 /= Signal2) THEN + IF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - Signal2Delay) >= + SkewS1S2RiseFall) THEN + ReportType := s2f; + ReportTime := NOW - Signal1Delay + + SkewS1S2RiseFall; + ELSIF ((Signal2Delay - Signal1Delay) >= + SkewS2S1FallRise) THEN + ReportType := s1r; + ReportTime := NOW - Signal2Delay + + SkewS2S1FallRise; + END IF; + ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - Signal2Delay) >= + SkewS1S2FallRise) THEN + ReportType := s2r; + ReportTime := NOW - Signal1Delay + + SkewS1S2FallRise; + ELSIF ((Signal2Delay - Signal1Delay) >= + SkewS2S1RiseFall) THEN + ReportType := s1f; + ReportTime := NOW - Signal2Delay + + SkewS2S1RiseFall; + END IF; + END IF; + ELSIF (Posedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > + SkewS2S1RiseFall)) THEN + ReportType := s1f; + ReportTime := NOW - Signal2Delay + + SkewS2S1RiseFall; + ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > + SkewS1S2RiseFall)) THEN + ReportType := s2f; + ReportTime := NOW - Signal1Delay + + SkewS1S2RiseFall; + ELSIF (Signal1Delay > Signal2Delay) THEN + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1RiseFall + + Signal1Delay - Signal2Delay; + ELSIF (Signal2Delay > Signal1Delay) THEN + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2RiseFall + + Signal2Delay - Signal1Delay; + ELSIF (SkewS2S1RiseFall < SkewS1S2RiseFall) THEN + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1RiseFall; + ELSE + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2RiseFall; + END IF; + ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay >= Signal2Delay) and (Signal2Delay > + SkewS2S1FallRise)) THEN + ReportType := s1r; + ReportTime := NOW - Signal2Delay + + SkewS2S1FallRise; + ELSIF ((Signal2Delay >= Signal1Delay) and (Signal1Delay > + SkewS1S2FallRise)) THEN + ReportType := s2r; + ReportTime := NOW - Signal1Delay + + SkewS1S2FallRise; + ELSIF (Signal1Delay > Signal2Delay) THEN + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1FallRise + + Signal1Delay - Signal2Delay; + ELSIF (Signal2Delay > Signal1Delay) THEN + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2FallRise + + Signal2Delay - Signal1Delay; + ELSIF (SkewS2S1FallRise < SkewS1S2FallRise) THEN + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1FallRise; + ELSE + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2FallRise; + END IF; + END IF; + ELSIF (Signal1'EVENT) THEN + IF (Signal1 = Signal2) THEN + IF (Posedge(Signal1'LAST_VALUE,Signal1)) THEN + IF (SkewS1S2RiseFall > (Signal1Delay - + Signal2Delay)) THEN + SkewData.ExpectedType := s2f; + TriggerDelay := SkewS1S2RiseFall + + Signal2Delay - Signal1Delay; + ELSE + ReportType := s2f; + ReportTime := NOW - Signal1Delay + + SkewS1S2RiseFall; + END IF; + ELSIF ( Negedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ( SkewS1S2FallRise > (Signal1Delay - + Signal2Delay)) THEN + SkewData.ExpectedType := s2r; + TriggerDelay := SkewS1S2FallRise + + Signal2Delay - Signal1Delay; + ELSE + ReportType := s2r; + ReportTime := NOW - Signal1Delay + + SkewS1S2FallRise; + END IF; + END IF; + ELSE + IF (Posedge( Signal1'LAST_VALUE, Signal1 )) THEN + IF ((Signal1Delay - SkewS1S2RiseFall) > + (Signal2'LAST_EVENT + Signal2Delay)) THEN + IF (( SkewData.Signal2Old2 - Signal2Delay) > + (NOW - Signal1Delay + + SkewS1S2RiseFall )) THEN + ViolationCertain := FALSE; + ReportType := s2f; + ReportTime := NOW + SkewS1S2RiseFall - + Signal1Delay; + END IF; + END IF; + ELSIF (Negedge(Signal1'LAST_VALUE, Signal1)) THEN + IF ((Signal1Delay - SkewS1S2FallRise) > + (Signal2'LAST_EVENT + Signal2Delay)) THEN + IF (( SkewData.Signal2Old2 - Signal2Delay) > + (NOW - Signal1Delay + + SkewS1S2FallRise )) THEN + ViolationCertain := FALSE; + ReportType := s2r; + ReportTime := NOW + SkewS1S2FallRise - + Signal1Delay; + END IF; + END IF; + END IF; + END IF; + ELSIF (Signal2'EVENT) THEN + IF (Signal1 = Signal2) THEN + IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN + IF (SkewS2S1RiseFall > (Signal2Delay - + Signal1Delay)) THEN + SkewData.ExpectedType := s1f; + TriggerDelay := SkewS2S1RiseFall + Signal1Delay - + Signal2Delay ; + ELSE + ReportType := s1f; + ReportTime := NOW + SkewS2S1RiseFall - + Signal2Delay; + END IF; + ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN + IF (SkewS2S1FallRise > (Signal2Delay - + Signal1Delay)) THEN + SkewData.ExpectedType := s1r; + TriggerDelay := SkewS2S1FallRise + Signal1Delay - + Signal2Delay; + ELSE + ReportType := s1r; + ReportTime := NOW + SkewS2S1FallRise - + Signal2Delay; + END IF; + END IF; + ELSE + IF (Posedge(Signal2'LAST_VALUE,Signal2)) THEN + IF ((Signal2Delay - SkewS2S1RiseFall) > + (Signal1'LAST_EVENT + Signal1Delay)) THEN + IF (( SkewData.Signal1Old2 - Signal1Delay) > + (NOW - Signal2Delay + + SkewS2S1RiseFall )) THEN + ViolationCertain := FALSE; + ReportType := s1f; + ReportTime := NOW + SkewS2S1RiseFall - + Signal2Delay; + END IF; + END IF; + ELSIF (Negedge(Signal2'LAST_VALUE,Signal2)) THEN + IF ((Signal2Delay - SkewS2S1FallRise) > + (Signal1'LAST_EVENT + Signal1Delay)) THEN + IF (( SkewData.Signal1Old2 - Signal1Delay) > + (NOW - Signal2Delay + + SkewS2S1FallRise )) THEN + ViolationCertain := FALSE; + ReportType := s1r; + ReportTime := NOW + SkewS2S1FallRise - + Signal2Delay; + END IF; + END IF; + END IF; + END IF; + END IF; + + IF (ReportType /= none) THEN + IF (MsgOn) THEN + CASE ReportType IS + WHEN s1r => + ReportSkewViolation( + Signal2Name, + Signal1Name, + SkewS2S1FallRise, + ReportTime, + HeaderMsg, + MsgSeverity, + Outphase, + ViolationCertain); + WHEN s1f => + ReportSkewViolation( + Signal2Name, + Signal1Name, + SkewS2S1RiseFall, + ReportTime, + HeaderMsg, + MsgSeverity, + Outphase, + ViolationCertain); + WHEN s2r => + ReportSkewViolation( + Signal1Name, + Signal2Name, + SkewS1S2FallRise, + ReportTime, + HeaderMsg, + MsgSeverity, + Outphase, + ViolationCertain); + WHEN s2f => + ReportSkewViolation( + Signal1Name, + Signal2Name, + SkewS1S2RiseFall, + ReportTime, + HeaderMsg, + MsgSeverity, + Outphase, + ViolationCertain); + WHEN OTHERS => + END CASE; + END IF; + IF (XOn) THEN + Violation := 'X'; + END IF; + ReportType := none; + END IF; + IF (TriggerDelay /= noTrigger) THEN + IF (TriggerDelay = 0 ns) THEN + trigger <= TRANSPORT trigger AFTER 0 ns; + ELSE + trigger <= TRANSPORT not (trigger) AFTER + TriggerDelay; + END IF; + END IF; + END IF; + IF (Signal1'EVENT and SkewData.Signal1Old1 /= NOW) THEN + SkewData.Signal1Old2 := SkewData.Signal1Old1; + SkewData.Signal1Old1 := NOW; + END IF; + IF (Signal2'EVENT and SkewData.Signal2Old1 /= NOW) THEN + SkewData.Signal2Old2 := SkewData.Signal2Old1; + SkewData.Signal2Old1 := NOW; + END IF; + END VitalOutPhaseSkewCheck; + +END VITAL_Timing; diff --git a/libraries/vital2000/timing_p.vhdl b/libraries/vital2000/timing_p.vhdl new file mode 100644 index 000000000..e18c8c24a --- /dev/null +++ b/libraries/vital2000/timing_p.vhdl @@ -0,0 +1,1202 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL TIMING Package +-- : $Revision: 598 $ +-- : +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- 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. +-- : +-- Known Errors : +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the objects (types, subtypes, constants, functions, +-- : procedures ... etc.) that can be used by a user. The 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. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Acknowledgments: +-- This code was originally developed under the "VHDL Initiative Toward ASIC +-- Libraries" (VITAL), an industry sponsored initiative. Technical +-- Director: William Billowitch, VHDL Technology Group; U.S. Coordinator: +-- Steve Schultz; Steering Committee Members: Victor Berman, Cadence Design +-- Systems; Oz Levia, Synopsys Inc.; Ray Ryan, Ryan & Ryan; Herman van Beek, +-- Texas Instruments; Victor Martin, Hewlett-Packard Company. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/02/95 | Initial ballot draft 1995 +-- v95.1 | | 08/31/95 | #203 - Timing violations at time 0 +-- #204 - Output mapping prior to glitch detection +-- v98.0 |TAG | 03/27/98 | Initial ballot draft 1998 +-- | #IR225 - Negative Premptive Glitch +-- **Pkg_effected=VitalPathDelay, +-- VitalPathDelay01,VitalPathDelay01z. +-- #IR105 - Skew timing check needed +-- **Pkg_effected=NONE, New code added!! +-- #IR248 - Allows VPD to use a default timing +-- delay +-- **Pkg_effected=VitalPathDelay, +-- VitalPathDelay01,VitalPathDelay01z, +-- #IR250 - Corrects fastpath condition in VPD +-- **Pkg_effected=VitalPathDelay01, +-- VitalPathDelay01z, +-- #IR252 - Corrects cancelled timing check call if +-- condition expires. +-- **Pkg_effected=VitalSetupHoldCheck, +-- VitalRecoveryRemovalCheck. +-- #IR105 - Skew timing check +-- **Pkg_effected=NONE, New code added +-- v98.1 | jdc | 03/25/99 | Changed UseDefaultDelay to IgnoreDefaultDelay +-- and set default to FALSE in VitalPathDelay() +-- v00.7 | dbb | 07/18/00 | Removed "maximum" from VitalPeriodPulse() +-- comments + + +LIBRARY IEEE; +USE IEEE.Std_Logic_1164.ALL; + +PACKAGE VITAL_Timing IS + TYPE VitalTransitionType IS ( tr01, tr10, tr0z, trz1, tr1z, trz0, + tr0X, trx1, tr1x, trx0, trxz, trzx); + + SUBTYPE VitalDelayType IS TIME; + TYPE VitalDelayType01 IS ARRAY (VitalTransitionType RANGE tr01 to tr10) + OF TIME; + TYPE VitalDelayType01Z IS ARRAY (VitalTransitionType RANGE tr01 to trz0) + OF TIME; + TYPE VitalDelayType01ZX IS ARRAY (VitalTransitionType RANGE tr01 to trzx) + OF TIME; + + TYPE VitalDelayArrayType IS ARRAY (NATURAL RANGE <>) OF VitalDelayType; + TYPE VitalDelayArrayType01 IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01; + TYPE VitalDelayArrayType01Z IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01Z; + TYPE VitalDelayArrayType01ZX IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01ZX; + -- ---------------------------------------------------------------------- + -- ********************************************************************** + -- ---------------------------------------------------------------------- + + CONSTANT VitalZeroDelay : VitalDelayType := 0 ns; + CONSTANT VitalZeroDelay01 : VitalDelayType01 := ( 0 ns, 0 ns ); + CONSTANT VitalZeroDelay01Z : VitalDelayType01Z := ( OTHERS => 0 ns ); + CONSTANT VitalZeroDelay01ZX : VitalDelayType01ZX := ( OTHERS => 0 ns ); + + --------------------------------------------------------------------------- + -- examples of usage: + --------------------------------------------------------------------------- + -- tpd_CLK_Q : VitalDelayType := 5 ns; + -- tpd_CLK_Q : VitalDelayType01 := (tr01 => 2 ns, tr10 => 3 ns); + -- tpd_CLK_Q : VitalDelayType01Z := ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns ); + -- tpd_CLK_Q : VitalDelayArrayType(0 to 1) + -- := (0 => 5 ns, 1 => 6 ns); + -- tpd_CLK_Q : VitalDelayArrayType01(0 to 1) + -- := (0 => (tr01 => 2 ns, tr10 => 3 ns), + -- 1 => (tr01 => 2 ns, tr10 => 3 ns)); + -- tpd_CLK_Q : VitalDelayArrayType01Z(0 to 1) + -- := (0 => ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns ), + -- 1 => ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns )); + --------------------------------------------------------------------------- + + -- TRUE if the model is LEVEL0 | LEVEL1 compliant + ATTRIBUTE VITAL_Level0 : BOOLEAN; + ATTRIBUTE VITAL_Level1 : BOOLEAN; + + SUBTYPE std_logic_vector2 IS std_logic_vector(1 DOWNTO 0); + SUBTYPE std_logic_vector3 IS std_logic_vector(2 DOWNTO 0); + SUBTYPE std_logic_vector4 IS std_logic_vector(3 DOWNTO 0); + SUBTYPE std_logic_vector8 IS std_logic_vector(7 DOWNTO 0); + + -- Types for strength mapping of outputs + TYPE VitalOutputMapType IS ARRAY ( std_ulogic ) OF std_ulogic; + TYPE VitalResultMapType IS ARRAY ( UX01 ) OF std_ulogic; + TYPE VitalResultZMapType IS ARRAY ( UX01Z ) OF std_ulogic; + CONSTANT VitalDefaultOutputMap : VitalOutputMapType + := "UX01ZWLH-"; + CONSTANT VitalDefaultResultMap : VitalResultMapType + := ( 'U', 'X', '0', '1' ); + CONSTANT VitalDefaultResultZMap : VitalResultZMapType + := ( 'U', 'X', '0', '1', 'Z' ); + + -- Types for fields of VitalTimingDataType + TYPE VitalTimeArrayT IS ARRAY (INTEGER RANGE <>) OF TIME; + TYPE VitalTimeArrayPT IS ACCESS VitalTimeArrayT; + TYPE VitalBoolArrayT IS ARRAY (INTEGER RANGE <>) OF BOOLEAN; + TYPE VitalBoolArrayPT IS ACCESS VitalBoolArrayT; + TYPE VitalLogicArrayPT IS ACCESS std_logic_vector; + + TYPE VitalTimingDataType IS RECORD + NotFirstFlag : BOOLEAN; + RefLast : X01; + RefTime : TIME; + HoldEn : BOOLEAN; + TestLast : std_ulogic; + TestTime : TIME; + SetupEn : BOOLEAN; + TestLastA : VitalLogicArrayPT; + TestTimeA : VitalTimeArrayPT; + HoldEnA : VitalBoolArrayPT; + SetupEnA : VitalBoolArrayPT; + END RECORD; + + FUNCTION VitalTimingDataInit RETURN VitalTimingDataType; + + -- type for internal data of VitalPeriodPulseCheck + TYPE VitalPeriodDataType IS RECORD + Last : X01; + Rise : TIME; + Fall : TIME; + NotFirstFlag : BOOLEAN; + END RECORD; + CONSTANT VitalPeriodDataInit : VitalPeriodDataType + := ('X', 0 ns, 0 ns, FALSE ); + + -- Type for specifying the kind of Glitch handling to use + TYPE VitalGlitchKindType IS (OnEvent, + OnDetect, + VitalInertial, + VitalTransport); + + TYPE VitalGlitchDataType IS + RECORD + SchedTime : TIME; + GlitchTime : TIME; + SchedValue : std_ulogic; + LastValue : std_ulogic; + END RECORD; + TYPE VitalGlitchDataArrayType IS ARRAY (NATURAL RANGE <>) + OF VitalGlitchDataType; + + -- PathTypes: for handling simple PathDelay info + TYPE VitalPathType IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType; -- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + TYPE VitalPath01Type IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType01; -- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + TYPE VitalPath01ZType IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType01Z;-- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + + -- For representing multiple paths to an output + TYPE VitalPathArrayType IS ARRAY (NATURAL RANGE <> ) OF VitalPathType; + TYPE VitalPathArray01Type IS ARRAY (NATURAL RANGE <> ) OF VitalPath01Type; + TYPE VitalPathArray01ZType IS ARRAY (NATURAL RANGE <> ) OF VitalPath01ZType; + + TYPE VitalTableSymbolType IS ( + '/', -- 0 -> 1 + '\', -- 1 -> 0 + 'P', -- Union of '/' and '^' (any edge to 1) + 'N', -- Union of '\' and 'v' (any edge to 0) + 'r', -- 0 -> X + 'f', -- 1 -> X + 'p', -- Union of '/' and 'r' (any edge from 0) + 'n', -- Union of '\' and 'f' (any edge from 1) + 'R', -- Union of '^' and 'p' (any possible rising edge) + 'F', -- Union of 'v' and 'n' (any possible falling edge) + '^', -- X -> 1 + 'v', -- X -> 0 + 'E', -- Union of 'v' and '^' (any edge from X) + 'A', -- Union of 'r' and '^' (rising edge to or from 'X') + 'D', -- Union of 'f' and 'v' (falling edge to or from 'X') + '*', -- Union of 'R' and 'F' (any edge) + 'X', -- Unknown level + '0', -- low level + '1', -- high level + '-', -- don't care + 'B', -- 0 or 1 + 'Z', -- High Impedance + 'S' -- steady value + ); + + SUBTYPE VitalEdgeSymbolType IS VitalTableSymbolType RANGE '/' TO '*'; + + + + + -- Addition of Vital Skew Type Information + -- March 14, 1998 + + --------------------------------------------------------------------------- + -- Procedures and Type Definitions for Defining Skews + --------------------------------------------------------------------------- + + TYPE VitalSkewExpectedType IS (none, s1r, s1f, s2r, s2f); + + TYPE VitalSkewDataType IS RECORD + ExpectedType : VitalSkewExpectedType; + Signal1Old1 : TIME; + Signal2Old1 : TIME; + Signal1Old2 : TIME; + Signal2Old2 : TIME; + END RECORD; + + CONSTANT VitalSkewDataInit : VitalSkewDataType := ( none, 0 ns, 0 ns, 0 ns, 0 ns ); + + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalExtendToFillDelay + -- + -- Description: A six element array of delay values of type + -- VitalDelayType01Z is returned when a 1, 2 or 6 + -- element array is given. This function will convert + -- VitalDelayType and VitalDelayType01 delay values into + -- a VitalDelayType01Z type following these rules: + -- + -- When a VitalDelayType is passed, all six transition + -- values are assigned the input value. When a + -- VitalDelayType01 is passed, the 01 transitions are + -- assigned to the 01, 0Z and Z1 transitions and the 10 + -- transitions are assigned to 10, 1Z and Z0 transition + -- values. When a VitalDelayType01Z is passed, the values + -- are kept as is. + -- + -- The function is overloaded based on input type. + -- + -- There is no function to fill a 12 value delay + -- type. + -- + -- Arguments: + -- + -- IN Type Description + -- Delay A one, two or six delay value Vital- + -- DelayType is passed and a six delay, + -- VitalDelayType01Z, item is returned. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- VitalDelayType01Z + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType + ) RETURN VitalDelayType01Z; + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01 + ) RETURN VitalDelayType01Z; + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN VitalDelayType01Z; + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalCalcDelay + -- + -- Description: This function accepts a 1, 2 or 6 value delay and + -- chooses the correct delay time to delay the NewVal + -- signal. This function is overloaded based on the + -- delay type passed. The function returns a single value + -- of time. + -- + -- This function is provided for Level 0 models in order + -- to calculate the delay which should be applied + -- for the passed signal. The delay selection is performed + -- using the OldVal and the NewVal to determine the + -- transition to select. The default value of OldVal is X. + -- + -- This function cannot be used in a Level 1 model since + -- the VitalPathDelay routines perform the delay path + -- selection and output driving function. + -- + -- Arguments: + -- + -- IN Type Description + -- NewVal New value of the signal to be + -- assigned + -- OldVal Previous value of the signal. + -- Default value is 'X' + -- Delay The delay structure from which to + -- select the appropriate delay. The + -- function overload is based on the + -- type of delay passed. In the case of + -- the single delay, VitalDelayType, no + -- selection is performed, since there + -- is only one value to choose from. + -- For the other cases, the transition + -- from the old value to the new value + -- decide the value returned. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- Time The time value selected from the + -- Delay INPUT is returned. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType + ) RETURN TIME; + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01 + ) RETURN TIME; + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN TIME; + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalPathDelay + -- + -- Description: VitalPathDelay is the Level 1 routine used to select + -- the propagation delay path and schedule a new output + -- value. + -- + -- For single and dual delay values, VitalDelayType and + -- VitalDelayType01 are used. The output value is + -- scheduled with a calculated delay without strength + -- modification. + -- + -- For the six delay value, VitalDelayType01Z, the output + -- value is scheduled with a calculated delay. The drive + -- strength can be modified to handle weak signal strengths + -- to model tri-state devices, pull-ups and pull-downs as + -- an example. + -- + -- The correspondence between the delay type and the + -- path delay function is as follows: + -- + -- Delay Type Path Type + -- + -- VitalDelayType VitalPathDelay + -- VitalDelayType01 VitalPathDelay01 + -- VitalDelayType01Z VitalPathDelay01Z + -- + -- For each of these routines, the following capabilities + -- is provided: + -- + -- o Transition dependent path delay selection + -- o User controlled glitch detection with the ability + -- to generate "X" on output and report the violation + -- o Control of the severity level for message generation + -- o Scheduling of the computed values on the specified + -- signal. + -- + -- Selection of the appropriate path delay begins with the + -- candidate paths. The candidate paths are selected by + -- identifying the paths for which the PathCondition is + -- true. If there is a single candidate path, then that + -- delay is selected. If there is more than one candidate + -- path, then the shortest delay is selected using + -- transition dependent delay selection. If there is no + -- candidate paths, then the delay specified by the + -- DefaultDelay parameter to the path delay is used. + -- + -- Once the delay is known, the output signal is then + -- scheduled with that delay. In the case of + -- VitalPathDelay01Z, an additional result mapping of + -- the output value is performed before scheduling. The + -- result mapping is performed after transition dependent + -- delay selection but before scheduling the final output. + -- + -- In order to perform glitch detection, the user is + -- obligated to provide a variable of VitalGlitchDataType + -- for the propagation delay functions to use. The user + -- cannot modify or use this information. + -- + -- Arguments: + -- + -- IN Type Description + -- OutSignalName string The name of the output signal + -- OutTemp std_logic The new output value to be driven + -- Paths VitalPathArrayType A list of paths of VitalPathArray + -- VitalPathArrayType01 type. The VitalPathDelay routine + -- VitalPathArrayType01Z is overloaded based on the type + -- of constant passed in. With + -- VitalPathArrayType01Z, the + -- resulting output strengths can be + -- mapped. + -- DefaultDelay VitalDelayType The default delay can be changed + -- VitalDelayType01 from zero-delay to another set + -- VitalDelayType01Z of values. + -- + -- IgnoreDefaultDelay BOOLEAN If TRUE, the default delay will + -- be used when no paths are + -- selected. If false, no event + -- will be scheduled if no paths are + -- selected. + -- + -- Mode VitalGlitchKindType The value of this constant + -- selects the type of glitch + -- detection. + -- OnEvent Glitch on transition event + -- | OnDetect Glitch immediate on detection + -- | VitalInertial No glitch, use INERTIAL + -- assignment + -- | VitalTransport No glitch, use TRANSPORT + -- assignment + -- XOn BOOLEAN Control for generation of 'X' on + -- glitch. When TRUE, 'X's are + -- scheduled for glitches, otherwise + -- no are generated. + -- MsgOn BOOLEAN Control for message generation on + -- glitch detect. When TRUE, + -- glitches are reported, otherwise + -- they are not reported. + -- MsgSeverity SEVERITY_LEVEL The level at which the message, + -- or assertion, will be reported. + -- IgnoreDefaultDelay BOOLEAN Tells the VPD whether to use the + -- default delay value in the absense + -- of a valid delay for input conditions 3/14/98 MG + -- + -- OutputMap VitalOutputMapType For VitalPathDelay01Z, the output + -- can be mapped to alternate + -- strengths to model tri-state + -- devices, pull-ups and pull-downs. + -- + -- INOUT + -- GlitchData VitalGlitchDataType The internal data storage + -- variable required to detect + -- glitches. + -- + -- OUT + -- OutSignal std_logic The output signal to be driven + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalPathDelay ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArrayType; + CONSTANT DefaultDelay : IN VitalDelayType := VitalZeroDelay; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE --IR248 3/14/98 + ); + PROCEDURE VitalPathDelay01 ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArray01Type; + CONSTANT DefaultDelay : IN VitalDelayType01 := VitalZeroDelay01; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 + CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 + ); + PROCEDURE VitalPathDelay01Z ( + SIGNAL OutSignal : OUT std_logic; + VARIABLE GlitchData : INOUT VitalGlitchDataType; + CONSTANT OutSignalName : IN string; + CONSTANT OutTemp : IN std_logic; + CONSTANT Paths : IN VitalPathArray01ZType; + CONSTANT DefaultDelay : IN VitalDelayType01Z := VitalZeroDelay01Z; + CONSTANT Mode : IN VitalGlitchKindType := OnEvent; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT OutputMap : IN VitalOutputMapType := VitalDefaultOutputMap; + CONSTANT NegPreemptOn : IN BOOLEAN := FALSE; --IR225 3/14/98 + CONSTANT IgnoreDefaultDelay : IN BOOLEAN := FALSE; --IR248 3/14/98 + CONSTANT RejectFastPath : IN BOOLEAN := FALSE --IR250 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalWireDelay + -- + -- Description: VitalWireDelay is used to delay an input signal. + -- The delay is selected from the input parameter passed. + -- The function is useful for back annotation of actual + -- net delays. + -- + -- The function is overloaded to permit passing a delay + -- value for twire for VitalDelayType, VitalDelayType01 + -- and VitalDelayType01Z. twire is a generic which can + -- be back annotated and must be constructed to follow + -- the SDF to generic mapping rules. + -- + -- Arguments: + -- + -- IN Type Description + -- InSig std_ulogic The input signal (port) to be + -- delayed. + -- twire VitalDelayType The delay value for which the input + -- VitalDelayType01 signal should be delayed. For Vital- + -- VitalDelayType01Z DelayType, the value is single value + -- passed. For VitalDelayType01 and + -- VitalDelayType01Z, the appropriate + -- delay value is selected by VitalCalc- + -- Delay. + -- + -- INOUT + -- none + -- + -- OUT + -- OutSig std_ulogic The internal delayed signal + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType + ); + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01 + ); + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01Z + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalSignalDelay + -- + -- Description: The VitalSignalDelay procedure is called in a signal + -- delay block in the architecture to delay the + -- appropriate test or reference signal in order to + -- accommodate negative constraint checks. + -- + -- The amount of delay is of type TIME and is a constant. + -- + -- Arguments: + -- + -- IN Type Description + -- InSig std_ulogic The signal to be delayed. + -- dly TIME The amount of time the signal is + -- delayed. + -- + -- INOUT + -- none + -- + -- OUT + -- OutSig std_ulogic The delayed signal + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalSignalDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT dly : IN TIME + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalSetupHoldCheck + -- + -- Description: The VitalSetupHoldCheck procedure detects a setup or a + -- hold violation on the input test signal with respect + -- to the corresponding input reference signal. The timing + -- constraints are specified through parameters + -- representing the high and low values for the setup and + -- hold values for the setup and hold times. This + -- procedure assumes non-negative values for setup and hold + -- timing constraints. + -- + -- It is assumed that negative timing constraints + -- are handled by internally delaying the test or + -- reference signals. Negative setup times result in + -- a delayed reference signal. Negative hold times + -- result in a delayed test signal. Furthermore, the + -- delays and constraints associated with these and + -- other signals may need to be appropriately + -- adjusted so that all constraint intervals overlap + -- the delayed reference signals and all constraint + -- values (with respect to the delayed signals) are + -- non-negative. + -- + -- This function is overloaded based on the input + -- TestSignal. A vector and scalar form are provided. + -- + -- TestSignal XXXXXXXXXXXX____________________________XXXXXXXXXXXXXXXXXXXXXX + -- : + -- : -->| error region |<-- + -- : + -- _______________________________ + -- RefSignal \______________________________ + -- : | | | + -- : | -->| |<-- thold + -- : -->| tsetup |<-- + -- + -- Arguments: + -- + -- IN Type Description + -- TestSignal std_ulogic Value of test signal + -- std_logic_vector + -- TestSignalName STRING Name of test signal + -- TestDelay TIME Model's internal delay associated + -- with TestSignal + -- RefSignal std_ulogic Value of reference signal + -- RefSignalName STRING Name of reference signal + -- RefDelay TIME Model's internal delay associated + -- with RefSignal + -- SetupHigh TIME Absolute minimum time duration before + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "1" state without + -- causing a setup violation. + -- SetupLow TIME Absolute minimum time duration before + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "0" state without + -- causing a setup violation. + -- HoldHigh TIME Absolute minimum time duration after + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "1" state without + -- causing a hold violation. + -- HoldLow TIME Absolute minimum time duration after + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "0" state without + -- causing a hold violation. + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- RefTransition VitalEdgeSymbolType + -- Reference edge specified. Events on + -- the RefSignal which match the edge + -- spec. are used as reference edges. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0". + -- MsgOn BOOLEAN If TRUE, set and hold violation + -- message will be generated. + -- Otherwise, no messages are generated, + -- even upon violations. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- EnableSetupOnTest BOOLEAN If FALSE at the time that the + -- TestSignal signal changes, + -- no setup check will be performed. + -- EnableSetupOnRef BOOLEAN If FALSE at the time that the + -- RefSignal signal changes, + -- no setup check will be performed. + -- EnableHoldOnRef BOOLEAN If FALSE at the time that the + -- RefSignal signal changes, + -- no hold check will be performed. + -- EnableHoldOnTest BOOLEAN If FALSE at the time that the + -- TestSignal signal changes, + -- no hold check will be performed. + -- + -- INOUT + -- TimingData VitalTimingDataType + -- VitalSetupHoldCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the time of the last edge. + -- + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalSetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_ulogic; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + ); + + PROCEDURE VitalSetupHoldCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_logic_vector; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT SetupHigh : IN TIME := 0 ns; + CONSTANT SetupLow : IN TIME := 0 ns; + CONSTANT HoldHigh : IN TIME := 0 ns; + CONSTANT HoldLow : IN TIME := 0 ns; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableSetupOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableSetupOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableHoldOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + ); + + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalRecoveryRemovalCheck + -- + -- Description: The VitalRecoveryRemovalCheck detects the presence of + -- a recovery or removal violation on the input test + -- signal with respect to the corresponding input reference + -- signal. It assumes non-negative values of setup and + -- hold timing constraints. The timing constraint is + -- specified through parameters representing the recovery + -- and removal times associated with a reference edge of + -- the reference signal. A flag indicates whether a test + -- signal is asserted when it is high or when it is low. + -- + -- It is assumed that negative timing constraints + -- are handled by internally delaying the test or + -- reference signals. Negative recovery times result in + -- a delayed reference signal. Negative removal times + -- result in a delayed test signal. Furthermore, the + -- delays and constraints associated with these and + -- other signals may need to be appropriately + -- adjusted so that all constraint intervals overlap + -- the delayed reference signals and all constraint + -- values (with respect to the delayed signals) are + -- non-negative. + -- + -- Arguments: + -- + -- IN Type Description + -- TestSignal std_ulogic Value of TestSignal. The routine is + -- TestSignalName STRING Name of TestSignal + -- TestDelay TIME Model internal delay associated with + -- the TestSignal + -- RefSignal std_ulogic Value of RefSignal + -- RefSignalName STRING Name of RefSignal + -- RefDelay TIME Model internal delay associated with + -- the RefSignal + -- Recovery TIME A change to an unasserted value on + -- the asynchronous TestSignal must + -- precede reference edge (on RefSignal) + -- by at least this time. + -- Removal TIME An asserted condition must be present + -- on the asynchronous TestSignal for at + -- least the removal time following a + -- reference edge on RefSignal. + -- ActiveLow BOOLEAN A flag which indicates if TestSignal + -- is asserted when it is low - "0." + -- FALSE indicate that TestSignal is + -- asserted when it has a value "1." + -- CheckEnabled BOOLEAN The check in enabled when the value + -- is TRUE, otherwise the constraints + -- are not checked. + -- RefTransition VitalEdgeSymbolType + -- Reference edge specifier. Events on + -- RefSignal will match the edge + -- specified. + -- HeaderMsg STRING A header message that will accompany + -- any assertion message. + -- XOn BOOLEAN When TRUE, the output Violation is + -- set to "X." When FALSE, it is always + -- "0." + -- MsgOn BOOLEAN When TRUE, violation messages are + -- output. When FALSE, no messages are + -- generated. + -- MsgSeverity SEVERITY_LEVEL Severity level of the asserted + -- message. + -- EnableRecOnTest BOOLEAN If FALSE at the time that the + -- TestSignal signal changes, + -- no recovery check will be performed. + -- EnableRecOnRef BOOLEAN If FALSE at the time that the + -- RefSignal signal changes, + -- no recovery check will be performed. + -- EnableRemOnRef BOOLEAN If FALSE at the time that the + -- RefSignal signal changes, + -- no removal check will be performed. + -- EnableRemOnTest BOOLEAN If FALSE at the time that the + -- TestSignal signal changes, + -- no removal check will be performed. + -- + -- INOUT + -- TimingData VitalTimingDataType + -- VitalRecoveryRemovalCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the time of the last edge. + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalRecoveryRemovalCheck ( + VARIABLE Violation : OUT X01; + VARIABLE TimingData : INOUT VitalTimingDataType; + SIGNAL TestSignal : IN std_ulogic; + CONSTANT TestSignalName: IN STRING := ""; + CONSTANT TestDelay : IN TIME := 0 ns; + SIGNAL RefSignal : IN std_ulogic; + CONSTANT RefSignalName : IN STRING := ""; + CONSTANT RefDelay : IN TIME := 0 ns; + CONSTANT Recovery : IN TIME := 0 ns; + CONSTANT Removal : IN TIME := 0 ns; + CONSTANT ActiveLow : IN BOOLEAN := TRUE; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT RefTransition : IN VitalEdgeSymbolType; + CONSTANT HeaderMsg : IN STRING := " "; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT EnableRecOnTest : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRecOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRemOnRef : IN BOOLEAN := TRUE; --IR252 3/23/98 + CONSTANT EnableRemOnTest : IN BOOLEAN := TRUE --IR252 3/23/98 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalPeriodPulseCheck + -- + -- Description: VitalPeriodPulseCheck checks for minimum + -- periodicity and pulse width for "1" and "0" values of + -- the input test signal. The timing constraint is + -- specified through parameters representing the minimal + -- period between successive rising and falling edges of + -- the input test signal and the minimum pulse widths + -- associated with high and low values. + -- + -- VitalPeriodCheck's accepts rising and falling edges + -- from 1 and 0 as well as transitions to and from 'X.' + -- + -- _______________ __________ + -- ____________| |_______| + -- + -- |<--- pw_hi --->| + -- |<-------- period ----->| + -- -->| pw_lo |<-- + -- + -- Arguments: + -- IN Type Description + -- TestSignal std_ulogic Value of test signal + -- TestSignalName STRING Name of the test signal + -- TestDelay TIME Model's internal delay associated + -- with TestSignal + -- Period TIME Minimum period allowed between + -- consecutive rising ('P') or + -- falling ('F') transitions. + -- PulseWidthHigh TIME Minimum time allowed for a high + -- pulse ('1' or 'H') + -- PulseWidthLow TIME Minimum time allowed for a low + -- pulse ('0' or 'L') + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0". + -- XOnChecks is a global that allows for + -- only timing checks to be turned on. + -- MsgOn BOOLEAN If TRUE, period/pulse violation + -- message will be generated. + -- Otherwise, no messages are generated, + -- even though a violation is detected. + -- MsgOnChecks allows for only timing + -- check messages to be turned on. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- + -- INOUT + -- PeriodData VitalPeriodDataType + -- VitalPeriodPulseCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the pulse and period + -- times. + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------ + 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 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalInPhaseSkewCheck + -- + -- Description: The VitalInPhaseSkewCheck procedure detects an in-phase + -- skew violation between input signals Signal1 and Signal2. + -- This is a timer based skew check in which a + -- violation is detected if Signal1 and Signal2 are in + -- different logic states longer than the specified skew + -- interval. + -- + -- The timing constraints are specified through parameters + -- representing the skew values for the different states + -- of Signal1 and Signal2. + -- + -- + -- Signal2 XXXXXXXXXXXX___________________________XXXXXXXXXXXXXXXXXXXXXX + -- : + -- : -->| |<-- + -- : Signal2 should go low in this region + -- : + -- + -- ____________ + -- Signal1 \_________________________________________________ + -- : | | + -- : |<-------- tskew -------->| + -- + -- Arguments: + -- + -- IN Type Description + -- Signal1 std_ulogic Value of first signal + -- Signal1Name STRING Name of first signal + -- Signal1Delay TIME Model's internal delay associated + -- with Signal1 + -- Signal2 std_ulogic Value of second signal + -- Signal2Name STRING Name of second signal + -- Signal2Delay TIME Model's internal delay associated + -- with Signal2 + -- SkewS1S2RiseRise TIME Absolute maximum time duration for + -- which Signal2 can remain at "0" + -- after Signal1 goes to the "1" state, + -- without causing a skew violation. + -- SkewS2S1RiseRise TIME Absolute maximum time duration for + -- which Signal1 can remain at "0" + -- after Signal2 goes to the "1" state, + -- without causing a skew violation. + -- SkewS1S2FallFall TIME Absolute maximum time duration for + -- which Signal2 can remain at "1" + -- after Signal1 goes to the "0" state, + -- without causing a skew violation. + -- SkewS2S1FallFall TIME Absolute maximum time duration for + -- which Signal1 can remain at "1" + -- after Signal2 goes to the "0" state, + -- without causing a skew violation. + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0." + -- MsgOn BOOLEAN If TRUE, skew timing violation + -- messages will be generated. + -- Otherwise, no messages are generated, + -- even upon violations. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- + -- INOUT + -- SkewData VitalSkewDataType + -- VitalInPhaseSkewCheck information + -- storage area. This is used + -- internally to detect signal edges + -- and record the time of the last edge. + -- + -- + -- Trigger std_ulogic This signal is used to trigger the + -- process in which the timing check + -- occurs upon expiry of the skew + -- interval. + -- + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + + PROCEDURE VitalInPhaseSkewCheck ( + VARIABLE Violation : OUT X01; + VARIABLE SkewData : INOUT VitalSkewDataType; + SIGNAL Signal1 : IN std_ulogic; + CONSTANT Signal1Name : IN STRING := ""; + CONSTANT Signal1Delay : IN TIME := 0 ns; + SIGNAL Signal2 : IN std_ulogic; + CONSTANT Signal2Name : IN STRING := ""; + CONSTANT Signal2Delay : IN TIME := 0 ns; + CONSTANT SkewS1S2RiseRise : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1RiseRise : IN TIME := TIME'HIGH; + CONSTANT SkewS1S2FallFall : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1FallFall : IN TIME := TIME'HIGH; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT HeaderMsg : IN STRING := ""; + SIGNAL Trigger : INOUT std_ulogic + ); + + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalOutPhaseSkewCheck + -- + -- Description: The VitalOutPhaseSkewCheck procedure detects an + -- out-of-phase skew violation between input signals Signal1 + -- and Signal2. This is a timer based skew check in + -- which a violation is detected if Signal1 and Signal2 are + -- in the same logic state longer than the specified skew + -- interval. + -- + -- The timing constraints are specified through parameters + -- representing the skew values for the different states + -- of Signal1 and Signal2. + -- + -- + -- Signal2 XXXXXXXXXXXX___________________________XXXXXXXXXXXXXXXXXXXXXX + -- : + -- : -->| |<-- + -- : Signal2 should go high in this region + -- : + -- + -- ____________ + -- Signal1 \_________________________________________________ + -- : | | + -- : |<-------- tskew -------->| + -- + -- Arguments: + -- + -- IN Type Description + -- Signal1 std_ulogic Value of first signal + -- Signal1Name STRING Name of first signal + -- Signal1Delay TIME Model's internal delay associated + -- with Signal1 + -- Signal2 std_ulogic Value of second signal + -- Signal2Name STRING Name of second signal + -- Signal2Delay TIME Model's internal delay associated + -- with Signal2 + -- SkewS1S2RiseFall TIME Absolute maximum time duration for + -- which Signal2 can remain at "1" + -- after Signal1 goes to the "1" state, + -- without causing a skew violation. + -- SkewS2S1RiseFall TIME Absolute maximum time duration for + -- which Signal1 can remain at "1" + -- after Signal2 goes to the "1" state, + -- without causing a skew violation. + -- SkewS1S2FallRise TIME Absolute maximum time duration for + -- which Signal2 can remain at "0" + -- after Signal1 goes to the "0" state, + -- without causing a skew violation. + -- SkewS2S1FallRise TIME Absolute maximum time duration for + -- which Signal1 can remain at "0" + -- after Signal2 goes to the "0" state, + -- without causing a skew violation. + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0." + -- MsgOn BOOLEAN If TRUE, skew timing violation + -- messages will be generated. + -- Otherwise, no messages are generated, + -- even upon violations. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- + -- INOUT + -- SkewData VitalSkewDataType + -- VitalInPhaseSkewCheck information + -- storage area. This is used + -- internally to detect signal edges + -- and record the time of the last edge. + -- + -- Trigger std_ulogic This signal is used to trigger the + -- process in which the timing check + -- occurs upon expiry of the skew + -- interval. + -- + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalOutPhaseSkewCheck ( + VARIABLE Violation : OUT X01; + VARIABLE SkewData : INOUT VitalSkewDataType; + SIGNAL Signal1 : IN std_ulogic; + CONSTANT Signal1Name : IN STRING := ""; + CONSTANT Signal1Delay : IN TIME := 0 ns; + SIGNAL Signal2 : IN std_ulogic; + CONSTANT Signal2Name : IN STRING := ""; + CONSTANT Signal2Delay : IN TIME := 0 ns; + CONSTANT SkewS1S2RiseFall : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1RiseFall : IN TIME := TIME'HIGH; + CONSTANT SkewS1S2FallRise : IN TIME := TIME'HIGH; + CONSTANT SkewS2S1FallRise : IN TIME := TIME'HIGH; + CONSTANT CheckEnabled : IN BOOLEAN := TRUE; + CONSTANT XOn : IN BOOLEAN := TRUE; + CONSTANT MsgOn : IN BOOLEAN := TRUE; + CONSTANT MsgSeverity : IN SEVERITY_LEVEL := WARNING; + CONSTANT HeaderMsg : IN STRING := ""; + SIGNAL Trigger : INOUT std_ulogic + ); + + +END VITAL_Timing; diff --git a/libraries/vital95/vital_primitives.vhdl b/libraries/vital95/vital_primitives.vhdl new file mode 100644 index 000000000..d0da36ba0 --- /dev/null +++ b/libraries/vital95/vital_primitives.vhdl @@ -0,0 +1,1410 @@ +-- ----------------------------------------------------------------------------- +-- Title : Standard VITAL_Primitives Package +-- : $Revision: 597 $ +-- : +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- 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. +-- : +-- Known Errors : +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the objects (types, subtypes, constants, functions, +-- : procedures ... etc.) that can be used by a user. The 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. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Acknowledgments: +-- This code was originally developed under the "VHDL Initiative Toward ASIC +-- Libraries" (VITAL), an industry sponsored initiative. Technical +-- Director: William Billowitch, VHDL Technology Group; U.S. Coordinator: +-- Steve Schultz; Steering Committee Members: Victor Berman, Cadence Design +-- Systems; Oz Levia, Synopsys Inc.; Ray Ryan, Ryan & Ryan; Herman van Beek, +-- Texas Instruments; Victor Martin, Hewlett-Packard Company. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/02/95 | Initial ballot draft 1995 +-- ---------------------------------------------------------------------------- +-- +LIBRARY IEEE; +USE IEEE.Std_Logic_1164.ALL; +USE IEEE.VITAL_Timing.ALL; + +PACKAGE VITAL_Primitives IS + -- ------------------------------------------------------------------------ + -- Type and Subtype Declarations + -- ------------------------------------------------------------------------ + + -- For Truth and State Tables + SUBTYPE VitalTruthSymbolType IS VitalTableSymbolType RANGE 'X' TO 'Z'; + SUBTYPE VitalStateSymbolType IS VitalTableSymbolType RANGE '/' TO 'S'; + + TYPE VitalTruthTableType IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalTruthSymbolType; + TYPE VitalStateTableType IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) + OF VitalStateSymbolType; + + -- --------------------------------- + -- Default values used by primitives + -- --------------------------------- + CONSTANT VitalDefDelay01 : VitalDelayType01; -- Propagation delays + CONSTANT VitalDefDelay01Z : VitalDelayType01Z; + + -- ------------------------------------------------------------------------ + -- VITAL Primitives + -- + -- The primitives packages contains a collections of common gates, + -- including AND, OR, XOR, NAND, NOR, XNOR, BUF, INV, MUX and DECODER + -- functions. In addition, for sequential devices, a STATE TABLE construct + -- is provided. For complex functions a modeler may wish to use either + -- a collection of connected VITAL primitives, or a TRUTH TABLE construct. + -- + -- For each primitive a Function and Procedure is provided. The primitive + -- functions are provided to support behavioral modeling styles. The + -- primitive procedures are provided to support structural modeling styles. + -- + -- The procedures wait internally for an event on an input signal, compute + -- the new result, perform glitch handling, schedule transaction on the + -- output signals, and wait for future input events. All of the functional + -- (logic) input or output parameters of the primitive procedures are + -- signals. All the other parameters are constants. + -- + -- The procedure primitives are parameterized for separate path delays + -- from each input signal. All path delays default to 0 ns. + -- + -- The sequential primitive functions compute the defined function and + -- return a value of type std_ulogic or std_logic_vector. All parameters + -- of the primitive functions are constants of mode IN. + -- + -- The primitives are based on 1164 operators. The user may also elect to + -- express functions using the 1164 operators as well. These styles are + -- all equally acceptable methods for device modeling. + -- + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: N-input logic device function calls: + -- VitalAND VitalOR VitalXOR + -- VitalNAND VitalNOR VitalXNOR + -- + -- Description: The function calls return the evaluated logic function + -- corresponding to the function name. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector The input signals for the n-bit + -- wide logic functions. + -- ResultMap VitalResultMapType The output signal strength + -- result map to modify default + -- result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The evaluated logic function of + -- the n-bit wide primitives. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR ( + CONSTANT Data : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: N-input logic device concurrent procedure calls. + -- VitalAND VitalOR VitalXOR + -- VitalNAND VitalNOR VitalXNOR + -- + -- Description: The procedure calls return the evaluated logic function + -- corresponding to the function name as a parameter to the + -- procedure. Propagation delay form data to q is a + -- a parameter to the procedure. A vector of delay values + -- for inputs to output are provided. It is noted that + -- limitations in SDF make the back annotation of the delay + -- array difficult. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector The input signals for the n- + -- bit wide logic functions. + -- tpd_data_q VitalDelayArrayType01 The propagation delay from + -- the data inputs to the output + -- q. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The output signal of the + -- evaluated logic function. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalXOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalNAND ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + PROCEDURE VitalXNOR ( + SIGNAL q : OUT std_ulogic; + SIGNAL Data : IN std_logic_vector; + CONSTANT tpd_data_q : IN VitalDelayArrayType01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + -- ------------------------------------------------------------------------- + -- + -- Sequential + -- Primitive + -- Function Name: 2,3 and 4 input logic device function calls. + -- + -- VitalAND2 VitalOR2 VitalXOR2 + -- VitalAND3 VitalOR3 VitalXOR3 + -- VitalAND4 VitalOR4 VitalXOR4 + -- + -- VitalNAND2 VitalNOR2 VitalXNOR2 + -- VitalNAND3 VitalNOR3 VitalXNOR3 + -- VitalNAND4 VitalNOR4 VitalXNOR4 + -- + -- Description: The function calls return the evaluated 2, 3 or 4 input + -- logic function corresponding to the function name. + -- + -- Arguments: + -- + -- IN Type Description + -- a, b, c, d std_ulogic 2 input devices have a and b as + -- inputs. 3 input devices have a, b + -- and c as inputs. 4 input devices + -- have a, b, c and d as inputs. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The result of the evaluated logic + -- function. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR2 ( + CONSTANT a, b : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR3 ( + CONSTANT a, b, c : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNAND4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalXNOR4 ( + CONSTANT a, b, c, d : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: 2, 3 and 4 input logic device concurrent procedure + -- calls. + -- + -- VitalAND2 VitalOR2 VitalXOR2 + -- VitalAND3 VitalOR3 VitalXOR3 + -- VitalAND4 VitalOR4 VitalXOR4 + -- + -- VitalNAND2 VitalNOR2 VitalXNOR2 + -- VitalNAND3 VitalNOR3 VitalXNOR3 + -- VitalNAND4 VitalNOR4 VitalXNOR4 + -- + -- Description: The procedure calls return the evaluated logic function + -- corresponding to the function name as a parameter to the + -- procedure. Propagation delays from a and b to q are + -- a parameter to the procedure. The default propagation + -- delay is 0 ns. + -- + -- Arguments: + -- + -- IN Type Description + -- a, b, c, d std_ulogic 2 input devices have a and b as + -- inputs. 3 input devices have a, b + -- and c as inputs. 4 input devices + -- have a, b, c and d as inputs. + -- tpd_a_q VitalDelayType01 The propagation delay from the a + -- input to output q for 2, 3 and 4 + -- input devices. + -- tpd_b_q VitalDelayType01 The propagation delay from the b + -- input to output q for 2, 3 and 4 + -- input devices. + -- tpd_c_q VitalDelayType01 The propagation delay from the c + -- input to output q for 3 and 4 input + -- devices. + -- tpd_d_q VitalDelayType01 The propagation delay from the d + -- input to output q for 4 input + -- devices. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The output signal of the evaluated + -- logic function. + -- + -- Returns + -- none + -- ------------------------------------------------------------------------- + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: Buffer logic device concurrent procedure calls. + -- + -- Description: Four buffer sequential primitive function calls are + -- provided. One is a simple buffer and the others + -- offer high and low enables and the four permits + -- propagation of Z as shown below: + -- + -- VitalBUF Standard non-inverting buffer + -- VitalBUFIF0 Non-inverting buffer with Enable low + -- VitalBUFIF1 Non-inverting buffer with Enable high + -- VitalIDENT Pass buffer capable of propagating Z + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input to the buffers + -- Enable std_ulogic Enable for the enable high and low + -- buffers. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple buffer. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low and + -- identity buffers. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The output signal of the evaluated + -- buffer function. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalBUF ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + FUNCTION VitalBUFIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + FUNCTION VitalBUFIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + FUNCTION VitalIDENT ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: Buffer device procedure calls. + -- + -- Description: Four buffer concurrent primitive procedure calls are + -- provided. One is a simple buffer and the others + -- offer high and low enables and the fourth permits + -- propagation of Z as shown below: + -- + -- VitalBUF Standard non-inverting buffer + -- VitalBUFIF0 Non-inverting buffer with Enable low + -- VitalBUFIF1 Non-inverting buffer with Enable high + -- VitalIDENT Pass buffer capable of propagating Z + -- + -- Arguments: + -- + -- IN Type Description + -- a std_ulogic Input signal to the buffers + -- Enable std_ulogic Enable signal for the enable high and + -- low buffers. + -- tpd_a_q VitalDelayType01 Propagation delay from input to + -- output for the simple buffer. + -- VitalDelayType01Z Propagation delay from input to + -- to output for the enable high and low + -- and identity buffers. + -- tpd_enable_q VitalDelayType01Z Propagation delay from enable to + -- output for the enable high and low + -- buffers. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple buffer. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low and + -- identity buffers. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output of the buffers. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalBUF ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + + 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); + + + 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); + + PROCEDURE VitalIDENT ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01Z := VitalDefDelay01Z; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalINV, VitalINVIF0, VitalINVIF1 + -- + -- Description: Inverter functions which return the inverted signal + -- value. Inverters with enable low and high are provided + -- which can drive high impedance when inactive. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input to the inverter + -- Enable std_ulogic Enable to the enable high and low + -- inverters. + -- ResultMap VitalResultMap The output signal strength result map + -- to modify default result mapping for + -- simple inverter. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low + -- inverters. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic Output of the inverter + -- + -- ------------------------------------------------------------------------- + + FUNCTION VitalINV ( + CONSTANT Data : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalINVIF0 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + FUNCTION VitalINVIF1 ( + CONSTANT Data, Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultZMapType + := VitalDefaultResultZMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalINV, VitalINVIF0, VitalINVIF1 + -- + -- Description: The concurrent primitive procedure calls implement a + -- signal inversion function. The output is a parameter to + -- the procedure. The path delay information is passed as + -- a parameter to the call. + -- + -- Arguments: + -- + -- IN Type Description + -- a std_ulogic Input signal for the simple inverter + -- Data std_ulogic Input signal for the enable high and + -- low inverters. + -- Enable std_ulogic Enable signal for the enable high and + -- low inverters. + -- tpd_a_q VitalDelayType01 Propagation delay from input a to + -- output q for the simple inverter. + -- tpd_data_q VitalDelayType01 Propagation delay from input data to + -- output q for the enable high and low + -- inverters. + -- tpd_enable_q VitalDelayType01Z Propagation delay from input enable + -- to output q for the enable high and + -- low inverters. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- simple inverter. + -- VitalResultZMapType The output signal strength result map + -- to modify default result mapping + -- which has high impedance capability + -- for the enable high, enable low + -- inverters. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output signal of the inverter. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalINV ( + SIGNAL q : OUT std_ulogic; + SIGNAL a : IN std_ulogic; + CONSTANT tpd_a_q : IN VitalDelayType01 := VitalDefDelay01; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap ); + 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); + + 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); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalMUX, VitalMUX2, VitalMUX4, VitalMUX8 + -- + -- Description: The VitalMUX functions return the selected data bit + -- based on the value of dSelect. For MUX2, the function + -- returns data0 when dselect is 0 and returns data1 when + -- dselect is 1. When dselect is X, result is X for MUX2 + -- when data0 /= data1. X propagation is reduced when the + -- dselect signal is X and both data signals are identical. + -- When this is the case, the result returned is the value + -- of the data signals. + -- + -- For the N input device: + -- + -- N must equal 2**(bits of dSelect) + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector Input signal for the N-bit, 4-bit and + -- 8-bit mux. + -- Data1,Data0 std_ulogic Input signals for the 2-bit mux. + -- dSelect std_ulogic Select signal for 2-bit mux + -- std_logic_vector2 Select signal for 4-bit mux + -- std_logic_vector3 Select signal for 8-bit mux + -- std_logic_vector Select signal for N-Bit mux + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- all muxes. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_ulogic The value of the selected bit is + -- returned. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalMUX ( + CONSTANT Data : IN std_logic_vector; + CONSTANT dSelect : IN std_logic_vector; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX2 ( + CONSTANT Data1, Data0 : IN std_ulogic; + CONSTANT dSelect : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX4 ( + CONSTANT Data : IN std_logic_vector4; + CONSTANT dSelect : IN std_logic_vector2; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + FUNCTION VitalMUX8 ( + CONSTANT Data : IN std_logic_vector8; + CONSTANT dSelect : IN std_logic_vector3; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_ulogic; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalMUX, VitalMUX2, VitalMUX4, VitalMUX8 + -- + -- Description: The VitalMUX concurrent primitive procedures calls + -- return in the output q the value of the selected data + -- bit based on the value of dsel. For the two bit mux, + -- the data returned is either d0 or d1, the data input. + -- For 4, 8 and N-bit functions, data is the input and is + -- of type std_logic_vector. For the 2-bit mux, if d0 or + -- d1 are X, the output is X only when d0 do not equal d1. + -- When d0 and d1 are equal, the return value is this value + -- to reduce X propagation. + -- + -- Propagation delay information is passed as a parameter + -- to the procedure call for delays from data to output and + -- select to output. For 2-bit muxes, the propagation + -- delays from data are provided for d0 and d1 to output. + -- + -- + -- Arguments: + -- + -- IN Type Description + -- d1,d0 std_ulogic Input signals for the 2-bit mux. + -- Data std_logic_vector4 Input signals for the 4-bit mux. + -- std_logic_vector8 Input signals for the 8-bit mux. + -- std_logic_vector Input signals for the N-bit mux. + -- dsel std_ulogic Select signal for the 2-bit mux. + -- std_logic_vector2 Select signals for the 4-bit mux. + -- std_logic_vector3 Select signals for the 8-bit mux. + -- std_logic_vector Select signals for the N-bit mux. + -- tpd_d1_q VitalDelayType01 Propagation delay from input d1 to + -- output q for 2-bit mux. + -- tpd_d0_q VitalDelayType01 Propagation delay from input d0 to + -- output q for 2-bit mux. + -- tpd_data_q VitalDelayArrayType01 Propagation delay from input data + -- to output q for 4-bit, 8-bit and + -- N-bit muxes. + -- tpd_dsel_q VitalDelayType01 Propagation delay from input dsel + -- to output q for 2-bit mux. + -- VitalDelayArrayType01 Propagation delay from input dsel + -- to output q for 4-bit, 8-bit and + -- N-bit muxes. + -- ResultMap VitalResultMapType The output signal strength result + -- map to modify default result + -- mapping for all muxes. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic The value of the selected signal. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 ); + + 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 ); + + 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 ); + + 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 ); + + -- ------------------------------------------------------------------------ + -- + -- Sequential + -- Primitive + -- Function Name: VitalDECODER, VitalDECODER2, VitalDECODER4, + -- VitalDECODER8 + -- + -- Description: The VitalDECODER functions are the sequential primitive + -- calls for decoder logic. The functions are provided + -- for N, 2, 4 and 8-bit outputs. + -- + -- The N-bit decoder is (2**(bits of data)) wide. + -- + -- The VitalDECODER returns 0 if enable is 0. + -- The VitalDECODER returns the result bit set to 1 if + -- enable is 1. All other bits of returned result are + -- set to 0. + -- + -- The returned array is in descending order: + -- (n-1 downto 0). + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input signal for 2-bit decoder. + -- std_logic_vector2 Input signals for 4-bit decoder. + -- std_logic_vector3 Input signals for 8-bit decoder. + -- std_logic_vector Input signals for N-bit decoder. + -- Enable std_ulogic Enable input signal. The result is + -- output when enable is high. + -- ResultMap VitalResultMapType The output signal strength result map + -- to modify default result mapping for + -- all output signals of the decoders. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- std_logic_vector2 The output of the 2-bit decoder. + -- std_logic_vector4 The output of the 4-bit decoder. + -- std_logic_vector8 The output of the 8-bit decoder. + -- std_logic_vector The output of the n-bit decoder. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalDECODER ( + CONSTANT Data : IN std_logic_vector; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector; + + FUNCTION VitalDECODER2 ( + CONSTANT Data : IN std_ulogic; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector2; + + FUNCTION VitalDECODER4 ( + CONSTANT Data : IN std_logic_vector2; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector4; + + FUNCTION VitalDECODER8 ( + CONSTANT Data : IN std_logic_vector3; + CONSTANT Enable : IN std_ulogic; + CONSTANT ResultMap : IN VitalResultMapType + := VitalDefaultResultMap + ) RETURN std_logic_vector8; + + -- ------------------------------------------------------------------------- + -- + -- Concurrent + -- Primitive + -- Procedure Name: VitalDECODER, VitalDECODER2, VitalDECODER4, + -- VitalDECODER8 + -- + -- Description: The VitalDECODER procedures are the concurrent primitive + -- procedure calls for decoder functions. The procedures + -- are provided for N, 2, 4 and 8 outputs. + -- + -- The N-bit decoder is (2**(bits of data)) wide. + -- + -- The procedural form of the decoder is used for + -- distributed delay modeling. The delay information for + -- each path is passed as an argument to the procedure. + -- + -- Result is set to 0 if enable is 0. + -- The result bit represented by data is set to 1 if + -- enable is 1. All other bits of result are set to 0. + -- + -- The result array is in descending order: (n-1 downto 0). + -- + -- For the N-bit decoder, the delay path is a vector of + -- delays from inputs to outputs. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_ulogic Input signal for 2-bit decoder. + -- std_logic_vector2 Input signals for 4-bit decoder. + -- std_logic_vector3 Input signals for 8-bit decoder. + -- std_logic_vector Input signals for N-bit decoder. + -- enable std_ulogic Enable input signal. The result is + -- output when enable is high. + -- tpd_data_q VitalDelayType01 Propagation delay from input data + -- to output q for 2-bit decoder. + -- VitalDelayArrayType01 Propagation delay from input data + -- to output q for 4, 8 and n-bit + -- decoders. + -- tpd_enable_q VitalDelayType01 Propagation delay from input enable + -- to output q for 2, 4, 8 and n-bit + -- decoders. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_logic_vector2 Output signals for 2-bit decoder. + -- std_logic_vector4 Output signals for 4-bit decoder. + -- std_logic_vector8 Output signals for 8-bit decoder. + -- std_logic_vector Output signals for n-bit decoder. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 ); + 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 ); + + 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 ); + 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 ); + + -- ------------------------------------------------------------------------- + -- Function Name: VitalTruthTable + -- + -- Description: VitalTruthTable implements a truth table. Given + -- a set of inputs, a sequential search is performed + -- to match the input. If a match is found, the output + -- is set based on the contents of the CONSTANT TruthTable. + -- If there is no match, all X's are returned. There is + -- no limit to the size of the table. + -- + -- There is a procedure and function for VitalTruthTable. + -- For each of these, a single value output (std_logic) and + -- a multi-value output (std_logic_vector) are provided. + -- + -- The first dimension of the table is for number of + -- entries in the truth table and second dimension is for + -- the number of elements in a row. The number of inputs + -- in the row should be Data'LENGTH plus result'LENGTH. + -- + -- Elements is a row will be interpreted as + -- Input(NumInputs - 1),.., Input(0), + -- Result(NumOutputs - 1),.., Result(0) + -- + -- All inputs will be mapped to the X01 subtype + -- + -- If the value of Result is not in the range 'X' to 'Z' + -- then an error will be reported. Also, the Result is + -- always given either as a 0, 1, X or Z value. + -- + -- Arguments: + -- + -- IN Type Description + -- TruthTable The input constant which defines the + -- behavior in truth table form. + -- DataIn The inputs to the truth table used to + -- perform input match to select + -- output(s) to value(s) to drive. + -- + -- INOUT + -- none + -- + -- OUT + -- Result std_logic Concurrent procedure version scalar + -- output. + -- std_logic_vector Concurrent procedure version vector + -- output. + -- + -- Returns + -- Result std_logic Function version scalar output. + -- std_logic_vector Function version vector output. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic_vector; + + FUNCTION VitalTruthTable ( + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ) RETURN std_logic; + + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic_vector; + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ); + PROCEDURE VitalTruthTable ( + SIGNAL Result : OUT std_logic; + CONSTANT TruthTable : IN VitalTruthTableType; + CONSTANT DataIn : IN std_logic_vector + ); + -- ------------------------------------------------------------------------- + -- + -- Function Name: VitalStateTable + -- + -- Description: VitalStateTable is a non-concurrent implementation of a + -- state machine (Moore Machine). It is used to model + -- sequential devices and devices with internal states. + -- + -- The procedure takes the value of the state table + -- data set and performs a sequential search of the + -- CONSTANT StateTable until a match is found. Once a + -- match is found, the result of that match is applied + -- to Result. If there is no match, all X's are returned. + -- The resultant output becomes the input for the next + -- state. + -- + -- The first dimension of the table is the number of + -- entries in the state table and second dimension is the + -- number of elements in a row of the table. The number of + -- inputs in the row should be DataIn'LENGTH. Result should + -- contain the current state (which will become the next + -- state) as well as the outputs + -- + -- Elements is a row of the table will be interpreted as + -- Input(NumInputs-1),.., Input(0), State(NumStates-1), + -- ..., State(0),Output(NumOutputs-1),.., Output(0) + -- + -- where State(numStates-1) DOWNTO State(0) represent the + -- present state and Output(NumOutputs - 1) DOWNTO + -- Outputs(NumOutputs - NumStates) represent the new + -- values of the state variables (i.e. the next state). + -- Also, Output(NumOutputs - NumStates - 1) + -- + -- This procedure returns the next state and the new + -- outputs when a match is made between the present state + -- and present inputs and the state table. A search is + -- made starting at the top of the state table and + -- terminates with the first match. If no match is found + -- then the next state and new outputs are set to all 'X's. + -- + -- (Asynchronous inputs (i.e. resets and clears) must be + -- handled by placing the corresponding entries at the top + -- of the table. ) + -- + -- All inputs will be mapped to the X01 subtype. + -- + -- NOTE: Edge transitions should not be used as values + -- for the state variables in the present state + -- portion of the state table. The only valid + -- values that can be used for the present state + -- portion of the state table are: + -- 'X', '0', '1', 'B', '-' + -- + -- Arguments: + -- + -- IN Type Description + -- StateTable VitalStateTableType The input constant which defines + -- the behavior in state table form. + -- DataIn std_logic_vector The current state inputs to the + -- state table used to perform input + -- matches and transition + -- calculations. + -- NumStates NATURAL Number of state variables + -- + -- INOUT + -- Result std_logic Output signal for scalar version of + -- the concurrent procedure call. + -- std_logic_vector Output signals for vector version + -- of the concurrent procedure call. + -- PreviousDataIn std_logic_vector The previous inputs and states used + -- in transition calculations and to + -- set outputs for steady state cases. + -- + -- OUT + -- none + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 + ); + + PROCEDURE VitalStateTable ( + VARIABLE Result : INOUT std_logic; + VARIABLE PreviousDataIn : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + CONSTANT DataIn : IN std_logic_vector + ); + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic_vector; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector; + CONSTANT NumStates : IN NATURAL + ); + + PROCEDURE VitalStateTable ( + SIGNAL Result : INOUT std_logic; + CONSTANT StateTable : IN VitalStateTableType; + SIGNAL DataIn : IN std_logic_vector + ); + + -- ------------------------------------------------------------------------- + -- + -- Function Name: VitalResolve + -- + -- Description: VitalResolve takes a vector of signals and resolves + -- them to a std_ulogic value. This procedure can be used + -- to resolve multiple drivers in a single model. + -- + -- Arguments: + -- + -- IN Type Description + -- Data std_logic_vector Set of input signals which drive a + -- common signal. + -- + -- INOUT + -- none + -- + -- OUT + -- q std_ulogic Output signal which is the resolved + -- value being driven by the collection of + -- input signals. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalResolve ( + SIGNAL q : OUT std_ulogic; + CONSTANT Data : IN std_logic_vector); + +END VITAL_Primitives; diff --git a/libraries/vital95/vital_primitives_body.vhdl b/libraries/vital95/vital_primitives_body.vhdl new file mode 100644 index 000000000..25e834189 --- /dev/null +++ b/libraries/vital95/vital_primitives_body.vhdl @@ -0,0 +1,5614 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL_Primitives Package +-- : $Revision: 597 $ +-- : +-- 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.vhdl b/libraries/vital95/vital_timing.vhdl new file mode 100644 index 000000000..1fe5a9e24 --- /dev/null +++ b/libraries/vital95/vital_timing.vhdl @@ -0,0 +1,880 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL TIMING Package +-- : $Revision: 597 $ +-- : +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- 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. +-- : +-- Known Errors : +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the objects (types, subtypes, constants, functions, +-- : procedures ... etc.) that can be used by a user. The 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. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Acknowledgments: +-- This code was originally developed under the "VHDL Initiative Toward ASIC +-- Libraries" (VITAL), an industry sponsored initiative. Technical +-- Director: William Billowitch, VHDL Technology Group; U.S. Coordinator: +-- Steve Schultz; Steering Committee Members: Victor Berman, Cadence Design +-- Systems; Oz Levia, Synopsys Inc.; Ray Ryan, Ryan & Ryan; Herman van Beek, +-- Texas Instruments; Victor Martin, Hewlett-Packard Company. +-- ---------------------------------------------------------------------------- +-- +-- ---------------------------------------------------------------------------- +-- Modification History : +-- ---------------------------------------------------------------------------- +-- Version No:|Auth:| Mod.Date:| Changes Made: +-- v95.0 A | | 06/02/95 | Initial ballot draft 1995 +-- v95.1 | | 08/31/95 | #203 - Timing violations at time 0 +-- #204 - Output mapping prior to glitch detection +-- ---------------------------------------------------------------------------- +LIBRARY IEEE; +USE IEEE.Std_Logic_1164.ALL; + +PACKAGE VITAL_Timing IS + TYPE VitalTransitionType IS ( tr01, tr10, tr0z, trz1, tr1z, trz0, + tr0X, trx1, tr1x, trx0, trxz, trzx); + + SUBTYPE VitalDelayType IS TIME; + TYPE VitalDelayType01 IS ARRAY (VitalTransitionType RANGE tr01 to tr10) + OF TIME; + TYPE VitalDelayType01Z IS ARRAY (VitalTransitionType RANGE tr01 to trz0) + OF TIME; + TYPE VitalDelayType01ZX IS ARRAY (VitalTransitionType RANGE tr01 to trzx) + OF TIME; + + TYPE VitalDelayArrayType IS ARRAY (NATURAL RANGE <>) OF VitalDelayType; + TYPE VitalDelayArrayType01 IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01; + TYPE VitalDelayArrayType01Z IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01Z; + TYPE VitalDelayArrayType01ZX IS ARRAY (NATURAL RANGE <>) OF VitalDelayType01ZX; + -- ---------------------------------------------------------------------- + -- ********************************************************************** + -- ---------------------------------------------------------------------- + + CONSTANT VitalZeroDelay : VitalDelayType := 0 ns; + CONSTANT VitalZeroDelay01 : VitalDelayType01 := ( 0 ns, 0 ns ); + CONSTANT VitalZeroDelay01Z : VitalDelayType01Z := ( OTHERS => 0 ns ); + CONSTANT VitalZeroDelay01ZX : VitalDelayType01ZX := ( OTHERS => 0 ns ); + + --------------------------------------------------------------------------- + -- examples of usage: + --------------------------------------------------------------------------- + -- tpd_CLK_Q : VitalDelayType := 5 ns; + -- tpd_CLK_Q : VitalDelayType01 := (tr01 => 2 ns, tr10 => 3 ns); + -- tpd_CLK_Q : VitalDelayType01Z := ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns ); + -- tpd_CLK_Q : VitalDelayArrayType(0 to 1) + -- := (0 => 5 ns, 1 => 6 ns); + -- tpd_CLK_Q : VitalDelayArrayType01(0 to 1) + -- := (0 => (tr01 => 2 ns, tr10 => 3 ns), + -- 1 => (tr01 => 2 ns, tr10 => 3 ns)); + -- tpd_CLK_Q : VitalDelayArrayType01Z(0 to 1) + -- := (0 => ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns ), + -- 1 => ( 1 ns, 2 ns, 3 ns, 4 ns, 5 ns, 6 ns )); + --------------------------------------------------------------------------- + + -- TRUE if the model is LEVEL0 | LEVEL1 compliant + ATTRIBUTE VITAL_Level0 : BOOLEAN; + ATTRIBUTE VITAL_Level1 : BOOLEAN; + + SUBTYPE std_logic_vector2 IS std_logic_vector(1 DOWNTO 0); + SUBTYPE std_logic_vector3 IS std_logic_vector(2 DOWNTO 0); + SUBTYPE std_logic_vector4 IS std_logic_vector(3 DOWNTO 0); + SUBTYPE std_logic_vector8 IS std_logic_vector(7 DOWNTO 0); + + -- Types for strength mapping of outputs + TYPE VitalOutputMapType IS ARRAY ( std_ulogic ) OF std_ulogic; + TYPE VitalResultMapType IS ARRAY ( UX01 ) OF std_ulogic; + TYPE VitalResultZMapType IS ARRAY ( UX01Z ) OF std_ulogic; + CONSTANT VitalDefaultOutputMap : VitalOutputMapType + := "UX01ZWLH-"; + CONSTANT VitalDefaultResultMap : VitalResultMapType + := ( 'U', 'X', '0', '1' ); + CONSTANT VitalDefaultResultZMap : VitalResultZMapType + := ( 'U', 'X', '0', '1', 'Z' ); + + -- Types for fields of VitalTimingDataType + TYPE VitalTimeArrayT IS ARRAY (INTEGER RANGE <>) OF TIME; + TYPE VitalTimeArrayPT IS ACCESS VitalTimeArrayT; + TYPE VitalBoolArrayT IS ARRAY (INTEGER RANGE <>) OF BOOLEAN; + TYPE VitalBoolArrayPT IS ACCESS VitalBoolArrayT; + TYPE VitalLogicArrayPT IS ACCESS std_logic_vector; + + TYPE VitalTimingDataType IS RECORD + NotFirstFlag : BOOLEAN; + RefLast : X01; + RefTime : TIME; + HoldEn : BOOLEAN; + TestLast : std_ulogic; + TestTime : TIME; + SetupEn : BOOLEAN; + TestLastA : VitalLogicArrayPT; + TestTimeA : VitalTimeArrayPT; + HoldEnA : VitalBoolArrayPT; + SetupEnA : VitalBoolArrayPT; + END RECORD; + + FUNCTION VitalTimingDataInit RETURN VitalTimingDataType; + + -- type for internal data of VitalPeriodPulseCheck + TYPE VitalPeriodDataType IS RECORD + Last : X01; + Rise : TIME; + Fall : TIME; + NotFirstFlag : BOOLEAN; + END RECORD; + CONSTANT VitalPeriodDataInit : VitalPeriodDataType + := ('X', 0 ns, 0 ns, FALSE ); + + -- Type for specifying the kind of Glitch handling to use + TYPE VitalGlitchKindType IS (OnEvent, + OnDetect, + VitalInertial, + VitalTransport); + + TYPE VitalGlitchDataType IS + RECORD + SchedTime : TIME; + GlitchTime : TIME; + SchedValue : std_ulogic; + LastValue : std_ulogic; + END RECORD; + TYPE VitalGlitchDataArrayType IS ARRAY (NATURAL RANGE <>) + OF VitalGlitchDataType; + + -- PathTypes: for handling simple PathDelay info + TYPE VitalPathType IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType; -- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + TYPE VitalPath01Type IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType01; -- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + TYPE VitalPath01ZType IS RECORD + InputChangeTime : TIME; -- timestamp for path input signal + PathDelay : VitalDelayType01Z;-- delay for this path + PathCondition : BOOLEAN; -- path sensitize condition + END RECORD; + + -- For representing multiple paths to an output + TYPE VitalPathArrayType IS ARRAY (NATURAL RANGE <> ) OF VitalPathType; + TYPE VitalPathArray01Type IS ARRAY (NATURAL RANGE <> ) OF VitalPath01Type; + TYPE VitalPathArray01ZType IS ARRAY (NATURAL RANGE <> ) OF VitalPath01ZType; + + TYPE VitalTableSymbolType IS ( + '/', -- 0 -> 1 + '\', -- 1 -> 0 + 'P', -- Union of '/' and '^' (any edge to 1) + 'N', -- Union of '\' and 'v' (any edge to 0) + 'r', -- 0 -> X + 'f', -- 1 -> X + 'p', -- Union of '/' and 'r' (any edge from 0) + 'n', -- Union of '\' and 'f' (any edge from 1) + 'R', -- Union of '^' and 'p' (any possible rising edge) + 'F', -- Union of 'v' and 'n' (any possible falling edge) + '^', -- X -> 1 + 'v', -- X -> 0 + 'E', -- Union of 'v' and '^' (any edge from X) + 'A', -- Union of 'r' and '^' (rising edge to or from 'X') + 'D', -- Union of 'f' and 'v' (falling edge to or from 'X') + '*', -- Union of 'R' and 'F' (any edge) + 'X', -- Unknown level + '0', -- low level + '1', -- high level + '-', -- don't care + 'B', -- 0 or 1 + 'Z', -- High Impedance + 'S' -- steady value + ); + + SUBTYPE VitalEdgeSymbolType IS VitalTableSymbolType RANGE '/' TO '*'; + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalExtendToFillDelay + -- + -- Description: A six element array of delay values of type + -- VitalDelayType01Z is returned when a 1, 2 or 6 + -- element array is given. This function will convert + -- VitalDelayType and VitalDelayType01 delay values into + -- a VitalDelayType01Z type following these rules: + -- + -- When a VitalDelayType is passed, all six transition + -- values are assigned the input value. When a + -- VitalDelayType01 is passed, the 01 transitions are + -- assigned to the 01, 0Z and Z1 transitions and the 10 + -- transitions are assigned to 10, 1Z and Z0 transition + -- values. When a VitalDelayType01Z is passed, the values + -- are kept as is. + -- + -- The function is overloaded based on input type. + -- + -- There is no function to fill a 12 value delay + -- type. + -- + -- Arguments: + -- + -- IN Type Description + -- Delay A one, two or six delay value Vital- + -- DelayType is passed and a six delay, + -- VitalDelayType01Z, item is returned. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- VitalDelayType01Z + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType + ) RETURN VitalDelayType01Z; + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01 + ) RETURN VitalDelayType01Z; + FUNCTION VitalExtendToFillDelay ( + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN VitalDelayType01Z; + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalCalcDelay + -- + -- Description: This function accepts a 1, 2 or 6 value delay and + -- chooses the correct delay time to delay the NewVal + -- signal. This function is overloaded based on the + -- delay type passed. The function returns a single value + -- of time. + -- + -- This function is provided for Level 0 models in order + -- to calculate the delay which should be applied + -- for the passed signal. The delay selection is performed + -- using the OldVal and the NewVal to determine the + -- transition to select. The default value of OldVal is X. + -- + -- This function cannot be used in a Level 1 model since + -- the VitalPathDelay routines perform the delay path + -- selection and output driving function. + -- + -- Arguments: + -- + -- IN Type Description + -- NewVal New value of the signal to be + -- assigned + -- OldVal Previous value of the signal. + -- Default value is 'X' + -- Delay The delay structure from which to + -- select the appropriate delay. The + -- function overload is based on the + -- type of delay passed. In the case of + -- the single delay, VitalDelayType, no + -- selection is performed, since there + -- is only one value to choose from. + -- For the other cases, the transition + -- from the old value to the new value + -- decide the value returned. + -- + -- INOUT + -- none + -- + -- OUT + -- none + -- + -- Returns + -- Time The time value selected from the + -- Delay INPUT is returned. + -- + -- ------------------------------------------------------------------------- + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType + ) RETURN TIME; + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01 + ) RETURN TIME; + FUNCTION VitalCalcDelay ( + CONSTANT NewVal : IN std_ulogic := 'X'; + CONSTANT OldVal : IN std_ulogic := 'X'; + CONSTANT Delay : IN VitalDelayType01Z + ) RETURN TIME; + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalPathDelay + -- + -- Description: VitalPathDelay is the Level 1 routine used to select + -- the propagation delay path and schedule a new output + -- value. + -- + -- For single and dual delay values, VitalDelayType and + -- VitalDelayType01 are used. The output value is + -- scheduled with a calculated delay without strength + -- modification. + -- + -- For the six delay value, VitalDelayType01Z, the output + -- value is scheduled with a calculated delay. The drive + -- strength can be modified to handle weak signal strengths + -- to model tri-state devices, pull-ups and pull-downs as + -- an example. + -- + -- The correspondence between the delay type and the + -- path delay function is as follows: + -- + -- Delay Type Path Type + -- + -- VitalDelayType VitalPathDelay + -- VitalDelayType01 VitalPathDelay01 + -- VitalDelayType01Z VitalPathDelay01Z + -- + -- For each of these routines, the following capabilities + -- is provided: + -- + -- o Transition dependent path delay selection + -- o User controlled glitch detection with the ability + -- to generate "X" on output and report the violation + -- o Control of the severity level for message generation + -- o Scheduling of the computed values on the specified + -- signal. + -- + -- Selection of the appropriate path delay begins with the + -- candidate paths. The candidate paths are selected by + -- identifying the paths for which the PathCondition is + -- true. If there is a single candidate path, then that + -- delay is selected. If there is more than one candidate + -- path, then the shortest delay is selected using + -- transition dependent delay selection. If there is no + -- candidate paths, then the delay specified by the + -- DefaultDelay parameter to the path delay is used. + -- + -- Once the delay is known, the output signal is then + -- scheduled with that delay. In the case of + -- VitalPathDelay01Z, an additional result mapping of + -- the output value is performed before scheduling. The + -- result mapping is performed after transition dependent + -- delay selection but before scheduling the final output. + -- + -- In order to perform glitch detection, the user is + -- obligated to provide a variable of VitalGlitchDataType + -- for the propagation delay functions to use. The user + -- cannot modify or use this information. + -- + -- Arguments: + -- + -- IN Type Description + -- OutSignalName string The name of the output signal + -- OutTemp std_logic The new output value to be driven + -- Paths VitalPathArrayType A list of paths of VitalPathArray + -- VitalPathArrayType01 type. The VitalPathDelay routine + -- VitalPathArrayType01Z is overloaded based on the type + -- of constant passed in. With + -- VitalPathArrayType01Z, the + -- resulting output strengths can be + -- mapped. + -- DefaultDelay VitalDelayType The default delay can be changed + -- VitalDelayType01 from zero-delay to another set of + -- VitalDelayType01Z values. + -- Mode VitalGlitchKindType The value of this constant + -- selects the type of glitch + -- detection. + -- OnEvent Glitch on transition event + -- | OnDetect Glitch immediate on detection + -- | VitalInertial No glitch, use INERTIAL + -- assignment + -- | VitalTransport No glitch, use TRANSPORT + -- assignment + -- XOn BOOLEAN Control for generation of 'X' on + -- glitch. When TRUE, 'X's are + -- scheduled for glitches, otherwise + -- no are generated. + -- MsgOn BOOLEAN Control for message generation on + -- glitch detect. When TRUE, + -- glitches are reported, otherwise + -- they are not reported. + -- MsgSeverity SEVERITY_LEVEL The level at which the message, + -- or assertion, will be reported. + -- OutputMap VitalOutputMapType For VitalPathDelay01Z, the output + -- can be mapped to alternate + -- strengths to model tri-state + -- devices, pull-ups and pull-downs. + -- + -- INOUT + -- GlitchData VitalGlitchDataType The internal data storage + -- variable required to detect + -- glitches. + -- + -- OUT + -- OutSignal std_logic The output signal to be driven + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 + ); + 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 + ); + 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 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalWireDelay + -- + -- Description: VitalWireDelay is used to delay an input signal. + -- The delay is selected from the input parameter passed. + -- The function is useful for back annotation of actual + -- net delays. + -- + -- The function is overloaded to permit passing a delay + -- value for twire for VitalDelayType, VitalDelayType01 + -- and VitalDelayType01Z. twire is a generic which can + -- be back annotated and must be constructed to follow + -- the SDF to generic mapping rules. + -- + -- Arguments: + -- + -- IN Type Description + -- InSig std_ulogic The input signal (port) to be + -- delayed. + -- twire VitalDelayType The delay value for which the input + -- VitalDelayType01 signal should be delayed. For Vital- + -- VitalDelayType01Z DelayType, the value is single value + -- passed. For VitalDelayType01 and + -- VitalDelayType01Z, the appropriate + -- delay value is selected by VitalCalc- + -- Delay. + -- + -- INOUT + -- none + -- + -- OUT + -- OutSig std_ulogic The internal delayed signal + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType + ); + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01 + ); + + PROCEDURE VitalWireDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT twire : IN VitalDelayType01Z + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalSignalDelay + -- + -- Description: The VitalSignalDelay procedure is called in a signal + -- delay block in the architecture to delay the + -- appropriate test or reference signal in order to + -- accommodate negative constraint checks. + -- + -- The amount of delay is of type TIME and is a constant. + -- + -- Arguments: + -- + -- IN Type Description + -- InSig std_ulogic The signal to be delayed. + -- dly TIME The amount of time the signal is + -- delayed. + -- + -- INOUT + -- none + -- + -- OUT + -- OutSig std_ulogic The delayed signal + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + PROCEDURE VitalSignalDelay ( + SIGNAL OutSig : OUT std_ulogic; + SIGNAL InSig : IN std_ulogic; + CONSTANT dly : IN TIME + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalSetupHoldCheck + -- + -- Description: The VitalSetupHoldCheck procedure detects a setup or a + -- hold violation on the input test signal with respect + -- to the corresponding input reference signal. The timing + -- constraints are specified through parameters + -- representing the high and low values for the setup and + -- hold values for the setup and hold times. This + -- procedure assumes non-negative values for setup and hold + -- timing constraints. + -- + -- It is assumed that negative timing constraints + -- are handled by internally delaying the test or + -- reference signals. Negative setup times result in + -- a delayed reference signal. Negative hold times + -- result in a delayed test signal. Furthermore, the + -- delays and constraints associated with these and + -- other signals may need to be appropriately + -- adjusted so that all constraint intervals overlap + -- the delayed reference signals and all constraint + -- values (with respect to the delayed signals) are + -- non-negative. + -- + -- This function is overloaded based on the input + -- TestSignal. A vector and scalar form are provided. + -- + -- TestSignal XXXXXXXXXXXX____________________________XXXXXXXXXXXXXXXXXXXXXX + -- : + -- : -->| error region |<-- + -- : + -- _______________________________ + -- RefSignal \______________________________ + -- : | | | + -- : | -->| |<-- thold + -- : -->| tsetup |<-- + -- + -- Arguments: + -- + -- IN Type Description + -- TestSignal std_ulogic Value of test signal + -- std_logic_vector + -- TestSignalName STRING Name of test signal + -- TestDelay TIME Model's internal delay associated + -- with TestSignal + -- RefSignal std_ulogic Value of reference signal + -- RefSignalName STRING Name of reference signal + -- RefDelay TIME Model's internal delay associated + -- with RefSignal + -- SetupHigh TIME Absolute minimum time duration before + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "1" state without + -- causing a setup violation. + -- SetupLow TIME Absolute minimum time duration before + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "0" state without + -- causing a setup violation. + -- HoldHigh TIME Absolute minimum time duration after + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "1" state without + -- causing a hold violation. + -- HoldLow TIME Absolute minimum time duration after + -- the transition of RefSignal for which + -- transitions of TestSignal are allowed + -- to proceed to the "0" state without + -- causing a hold violation. + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- RefTransition VitalEdgeSymbolType + -- Reference edge specified. Events on + -- the RefSignal which match the edge + -- spec. are used as reference edges. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0." + -- MsgOn BOOLEAN If TRUE, set and hold violation + -- message will be generated. + -- Otherwise, no messages are generated, + -- even upon violations. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- + -- INOUT + -- TimingData VitalTimingDataType + -- VitalSetupHoldCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the time of the last edge. + -- + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 + ); + + 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 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalRecoveryRemovalCheck + -- + -- Description: The VitalRecoveryRemovalCheck detects the presence of + -- a recovery or removal violation on the input test + -- signal with respect to the corresponding input reference + -- signal. It assumes non-negative values of setup and + -- hold timing constraints. The timing constraint is + -- specified through parameters representing the recovery + -- and removal times associated with a reference edge of + -- the reference signal. A flag indicates whether a test + -- signal is asserted when it is high or when it is low. + -- + -- It is assumed that negative timing constraints + -- are handled by internally delaying the test or + -- reference signals. Negative recovery times result in + -- a delayed reference signal. Negative removal times + -- result in a delayed test signal. Furthermore, the + -- delays and constraints associated with these and + -- other signals may need to be appropriately + -- adjusted so that all constraint intervals overlap + -- the delayed reference signals and all constraint + -- values (with respect to the delayed signals) are + -- non-negative. + -- + -- Arguments: + -- + -- IN Type Description + -- TestSignal std_ulogic Value of TestSignal. The routine is + -- TestSignalName STRING Name of TestSignal + -- TestDelay TIME Model internal delay associated with + -- the TestSignal + -- RefSignal std_ulogic Value of RefSignal + -- RefSignalName STRING Name of RefSignal + -- RefDelay TIME Model internal delay associated with + -- the RefSignal + -- Recovery TIME A change to an unasserted value on + -- the asynchronous TestSignal must + -- precede reference edge (on RefSignal) + -- by at least this time. + -- Removal TIME An asserted condition must be present + -- on the asynchronous TestSignal for at + -- least the removal time following a + -- reference edge on RefSignal. + -- ActiveLow BOOLEAN A flag which indicates if TestSignal + -- is asserted when it is low - "0." + -- FALSE indicate that TestSignal is + -- asserted when it has a value "1." + -- CheckEnabled BOOLEAN The check in enabled when the value + -- is TRUE, otherwise the constraints + -- are not checked. + -- RefTransition VitalEdgeSymbolType + -- Reference edge specifier. Events on + -- RefSignal will match the edge + -- specified. + -- HeaderMsg STRING A header message that will accompany + -- any assertion message. + -- XOn BOOLEAN When TRUE, the output Violation is + -- set to "X." When FALSE, it is always + -- "0." + -- MsgOn BOOLEAN When TRUE, violation messages are + -- output. When FALSE, no messages are + -- generated. + -- MsgSeverity SEVERITY_LEVEL Severity level of the asserted + -- message. + -- + -- INOUT + -- TimingData VitalTimingDataType + -- VitalRecoveryRemovalCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the time of the last edge. + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------- + 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 + ); + + -- ------------------------------------------------------------------------ + -- + -- Function Name: VitalPeriodPulseCheck + -- + -- Description: VitalPeriodPulseCheck checks for minimum and maximum + -- periodicity and pulse width for "1" and "0" values of + -- the input test signal. The timing constraint is + -- specified through parameters representing the minimal + -- period between successive rising and falling edges of + -- the input test signal and the minimum pulse widths + -- associated with high and low values. + -- + -- VitalPeriodCheck's accepts rising and falling edges + -- from 1 and 0 as well as transitions to and from 'X.' + -- + -- _______________ __________ + -- ____________| |_______| + -- + -- |<--- pw_hi --->| + -- |<-------- period ----->| + -- -->| pw_lo |<-- + -- + -- Arguments: + -- IN Type Description + -- TestSignal std_ulogic Value of test signal + -- TestSignalName STRING Name of the test signal + -- TestDelay TIME Model's internal delay associated + -- with TestSignal + -- Period TIME Minimum period allowed between + -- consecutive rising ('P') or + -- falling ('F') transitions. + -- PulseWidthHigh TIME Minimum time allowed for a high + -- pulse ('1' or 'H') + -- PulseWidthLow TIME Minimum time allowed for a low + -- pulse ('0' or 'L') + -- CheckEnabled BOOLEAN Check performed if TRUE. + -- HeaderMsg STRING String that will accompany any + -- assertion messages produced. + -- XOn BOOLEAN If TRUE, Violation output parameter + -- is set to "X". Otherwise, Violation + -- is always set to "0." + -- MsgOn BOOLEAN If TRUE, period/pulse violation + -- message will be generated. + -- Otherwise, no messages are generated, + -- even though a violation is detected. + -- MsgSeverity SEVERITY_LEVEL Severity level for the assertion. + -- + -- INOUT + -- PeriodData VitalPeriodDataType + -- VitalPeriodPulseCheck information + -- storage area. This is used + -- internally to detect reference edges + -- and record the pulse and period + -- times. + -- OUT + -- Violation X01 This is the violation flag returned. + -- + -- Returns + -- none + -- + -- ------------------------------------------------------------------------ + 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 + ); + +END VITAL_Timing; diff --git a/libraries/vital95/vital_timing_body.vhdl b/libraries/vital95/vital_timing_body.vhdl new file mode 100644 index 000000000..09eb75565 --- /dev/null +++ b/libraries/vital95/vital_timing_body.vhdl @@ -0,0 +1,1275 @@ +------------------------------------------------------------------------------- +-- Title : Standard VITAL TIMING Package +-- : $Revision: 597 $ +-- 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