Design Entities und Configurations
Entity
Beispiele
Beispiel für eine Testbench, die keine Ein- oder Ausgänge besitzt.
ENTITY testbench IS END testbench ;
Entity für einen 2-Bit-Volladdierer.
- X , Y und Cin sind Eingänge vom Typ Bit.
- Cout und Sum sind Ausgänge vom Typ Bit.
ENTITY fulladder IS PORT (X,Y,Cin : IN Bit; Cout, Sum : OUT Bit); END fulladder ;
Entity mit mehreren Features:
- Definition eines Parameters m .
- b1 und b2 sind Eingänge (Bits), b3 ist ein Ausgangsvektor der Breite m .
- Definition des Typs byte als Bitvektor.
- Einbinden der Objekte aus dem Package timing_library . Definition und Initialisierung einer konstanten Setup-Zeit.
Definition der Prozedur init mit Signalübergabe. Um delay verzögerte Belegung von b4 mit lauter Einsen.
Anweisungen innerhalb der Entity:
- Ist die zu überprüfende Bedingung nicht erfüllt, erfolgt eine Fehlermeldung. Sicherheitsstufe ist Error .
- Aufruf einer passiven Prozedur (keine Signalzuweisungen in der Entity erlaubt!) mit b4 und delay als Übergabewerte.
ENTITY big_example IS GENERIC (m : Positive); PORT (b1,b2 : IN Bit; b3: OUT Bit_Vector(1 to m)); TYPE byte IS ARRAY (1 TO 8) OF Bit; USE work.timing_library.all; CONSTANT setuptime : Time := 12 ns; PROCEDURE init ( SIGNAL b4: OUT byte) IS BEGIN b4 <= ( OTHERS => '1') AFTER delay; END init; BEGIN ASSERT b4' DELAYED'STABLE (5 ns) REPORT "Error occured!" SEVERITY Error; passive_procedure(b2,delay); END big_example ;
Architecture
Beispiele
Beispiel für eine leere Architecture der Entity box .
ARCHITECTURE arch OF box IS BEGIN END arch ;
Beispiel für eine Architecture der Entity fulladder . A und B sind die benötigten internen Zwischensignale.
Im architecture-body stehen mehrere nebenläufige Anweisungen, die die Funktion des Volladdierers beschreiben.
ARCHITECTURE rtl OF fulladder IS SIGNAL A,B: Bit ; BEGIN A <= X XOR Y ; B <= A AND Cin ; Sum <= A XOR Cin ; Cout <= B OR (X AND Y) ; END rtl ;
Beispiel für zwei verschiedene Architectures für die Entity entity1 . rtl1 : Definition der benötigten Konstante delay und des Zwischensignals S .
Zwei nebenläfige Signalzuweisungen mit Zeitverzögerungen und dem Aufruf der Funktion czbit .
ARCHITECTURE rtl1 OF entity1 IS CONSTANT delay: Time :=5 ns; SIGNAL S: Bit; BEGIN S2 <= czbit(S) AFTER 3 ns ; S <= S1 AFTER delay ; END rtl1 ;
rtl2 : Definition und Initialisierung des Zwischensignals S .
Definition der Procedure proc mit Signalübergabe von A und B .
Bedingte Signalzuweisung an B .
Drei nebenläufige Anweisungen mit Namen P1 , P2 und P3 .
- P1 ist ein Prozeduraufruf.
- P2 ist eine Signalzuweiung durch Aufruf einer Funktion.
- P3 ist ein Prozeß, in dem die Variable V deklariert und dieser der Wert von S zugewiesen wird.
ARCHITECTURE rtl2 OF entity1 IS SIGNAL S: Bit :='1' ; PROCEDURE proc( SIGNAL A: IN Bit SIGNAL B: INOUT Bit) IS BEGIN B <= NOT B WHEN A ='1' ELSE B ; END proc ; BEGIN P1: proc(S1,S); P2: S2 <= czbit(S) AFTER 2 ns ; P3: PROCESS (S) VARIABLE V :Bit ; BEGIN V := S ; END PROCESS P3; END rtl2 ;
Configuration
Beispiele
Beispiel für eine Default-Configuration einer Testbench, die für die Architecture arch_of_testbench das entsprechende analysierte Objekt verwendet.
CONFIGURATION cfg OF testbench IS FOR arch_of_testbench END FOR ; END cfg ;
Die Bibliotheken vendor und mylib werden bekanntgemacht.
Für die Entity example wird alles aus der Bibliothek mylib bekanntgemacht und in ihrer Architecture structural werden für die Instanz ALU mit dem Label ALU1 die Entity alu_ver_2 mit der Architecture beh aus der Bibliothek mylib , für die Instanzen von MUX unter den Labeln mux1 , mux2 und mux3 die Entity mux12345 mit der Architecture rtl aus der Bibliothek vendor und für alle Instanzen von add die Defaults verwendet.
LIBRARY vendor, mylib ; CONFIGURATION cfg_of_ex OF example IS USE mylib.ALL ; FOR structural FOR ALU1: ALU USE ENTITY mylib.alu_ver_2(beh); END FOR ; FOR mux1, mux2, mux3: MUX USE ENTITY vendor.mux12345(rtl); END FOR ; FOR ALL : add END FOR ; END FOR ; END cfg_of_ex ;
Unterprogramme und Packages
Unterprogrammdeklaration
Anmerkung
Reine (pure) Funktionen liefern bei mehreren Aufrufen mit den gleichen actual parameters die gleichen Rückgabewerte. Unreine (impure) Funktionen können bei mehreren Aufrufen mit den gleichen actual parameters unterschiedliche Rückgabewerte liefern. Dies ist z.B. der Fall wenn die unreine Funktion Files ausliest, deren Inhalt sich während der Simulatin ändern.
Beispiele
Einfache Deklaration der Prozedur thank_you ohne Übergabewerte
PROCEDURE thank_you ;
Declaration of the procedure test with the transfer value A .
PROCEDURE test( A : Bit ) ;
Deklaration der Funktion convert mit B als Übergabewert und fuzzy_bit als Ergebnistyp.
FUNCTION convert( B : Bit ) RETURN fuzzy_bit ;
Deklaration der Prozedur regist mit Übergabe der Signal D , CK und Q .
PROCEDURE regist( SIGNAL D : IN Bit; SIGNAL CK : IN Bit; SIGNAL Q : OUT Bit ) ;
Deklaration der Prozedur p mit Übergabe der Variablen COL und der Konstanten C .
PROCEDURE p( VARIABLE COL : INOUT color; CONSTANT C : IN choice ) ;
Der Body eines Unterprogramms
Anmerkungen
- Die Deklaration eines Unterprogrammes ist optional. Die Unterprogrammdefinition kann als Deklaration angesehen werden.
- In Unterprogrammen sind Deklarationen von shared variables verboten.
- Ein “fremdes Unterprogramm” ist ein Unterprogramm, das mit dem Attribut FOREIGN versehen ist. Der Wert des Attributes (ein String) kann z.B. implementierungsspezifische Angaben zur Anbindung eines externen Programms enthalten (siehe Beispiel unten).
- Eine reine Funktion darf keine Referenz zu einem explizit deklarierten Fileobjekt beinhalten.
- Eine reine Funktion darf nicht Elternteil einer unreinen Funktion sein.
Beispiele
Definition der Prozedur thank_you .
Ist die Bedingung false nicht erfüllt, wird die Meldung “Thank You !” ausgegeben, da die Sicherheitsstufe note ist.
PROCEDURE thank_you IS BEGIN ASSERT false REPORT "Thank You !" SEVERITY note ; END thank_you ;
Definition der Funktion convert mit Übergabewert B und Ergebnistyp fuzzy_bit .
In der If-Schleife wird der Variable v abhängig vom Wert von B der Wert High oder Low zugewiesen.
Als Rückgabewert wird v übergeben.
FUNCTION convert(B : Bit ) RETURN fuzzy_bit IS VARIABLE v : fuzzy_bit ; BEGIN IF B = '1' THEN v := High ; ELSE v := Low ; END IF ; RETURN v ; END convert ;
Definition der Prozedur regist mit den Übergabewerten der Signale D , CK und Q .
In der Endlosschleife (LOOP) wird ein Register deklariert, das mit der positiven Taktflanke den Wert vom Eingang D am Ausgang Q mit einer Verzögerung von 1 ns übernimmt.
PROCEDURE regist( SIGNAL D : IN Bit ; SIGNAL CK : IN Bit ; SIGNAL Q : OUT Bit ) IS BEGIN LOOP WAIT ON CK ; IF CK = '1' THEN Q <= D AFTER 1 ns ; END IF ; END LOOP ; END regist ;
Definition der Prozedur p mit den Übergabewerten der Variable COL und der Konstante C .
Es wird der Untertyp primary_color aus dem Typ color deklariert, mit dem Bereich (aus dem Aufzälungstyp color ) von yellow bis red . Es werden die Variablen X , Y und Z deklariert.
PROCEDURE p( VARIABLE COL : INOUT color ; CONSTANT C : IN choice ) IS SUBTYPE primary_color IS color RANGE yellow TO red ; VARIABLE X, Y, Z : primary_color ; BEGIN ... ... END p ;
Die extern vorliegende Funktion exfunc wird deklariert.
Das Attribut FOREIGN für exfunc wird mit (Simulator-)programmspezifischen Daten belegt.
FUNCTION exfunc RETURN INTEGER ; ATTRIBUTE FOREIGN OF exfunc FUNCTION IS "C:modellib.so.0.1 ELAB:mod_lab";
Überladen
Überladen von Unterprogrammen
Verschiedene Unterprogramme mit gleichem Namen, aber mit unterschiedlichem Verhalten, werden wie gewöhnlich deklariert. Dies gilt gleichermaßen für Prozeduren und Funktionen. Nach folgenden Kritierien muß genau eine Prozedur oder Funktion gewählt werden können (Auflösung von Überladungen):
- Zahl der Argumente
- Typen der Argumente
- Namen der Argumente (bei Argumentübergabe durch explizite Namensnennung “named association”, s.Bsp.)
- Typ des Rückgabewertes
Besitzen bei einem Funktionsaufruf mehrere Varianten Gültigkeit, so verbirgt die lokale Variante (z.B. im Deklarationsteil der Architektur) die hierarchisch höher deklarierte Variante (z.B. aus einem Package). Mit vollständiger hierarchischer Angabe des Unterprogrammnamens kann trotzdem auf jede gewünschte Variante zugegriffen werden (Qualified Expression).
Überladen von Operatoren
Operatoren unterscheiden sich von einfachen Funktionen in zwei Punkten:
- Der Name bzw. das Symbol von Operatoren gilt nicht als “normaler” Bezeichner, sondern ist eine Zeichenkette (String) und steht deshalb bei der Deklaration in Anführungsstrichen.
- Die Operanden stehen beim üblichen Aufruf eines Operators vor bzw. nach dem Operator (bei unären Operatoren nur danach) und nicht in nachgestellten runden Klammern. Operatoren können aber auch in der Syntax normaler Funtionsaufrufe angesprochen werden (s.Bsp.).
Die Handhabung von Operatoren als String ist bei der Deklaration von überladenen Operatoren zu beachten. Ansonsten entspricht diese dem Überladen von Funktionen und Prozeduren.
Beispiele
In den Beispielen werden nur die Deklarationen und die Aufrufe der überladenen Unterprogramme gezeigt. Zu jeder Deklaration muß natürlich eine Definition des Unterprogrammes geschrieben werden.
Es werden zwei Prozeduren write deklariert, wobei der Übergabewert value einmal als Integer und einmal als String deklariert wird.
Beim Aufruf der Prozeduren wird durch den Typ des jeweiligen zweiten Übergabewertes bestimmt, welche Prozedur zu verwenden ist.
PROCEDURE write ( F : INOUT Text ; value : Integer ) ; PROCEDURE write ( F : INOUT Text ; value : String ) ; write (sys_error, "Unexpected output"); write (sys_output, 12) ;
Es werden zwei Prozeduren check deklariert. Sie unterscheiden sich einerseits im Namen des ersten Übergabewertes und andererseits in der Reihenfolge der Definition der zwei Signale C und D .
Bei den ersten beiden Prozedur-Aufrufen wird durch den Namen des ersten Übergabewertes bestimmt, welche Prozedur zu verwenden ist. Sind die Typen Data und Clock identisch, ist der dritte Aufruf nicht eindeutig und damit verboten.
PROCEDURE check ( setup : Time ; SIGNAL D : Data ; SIGNAL C : Clock ) ; PROCEDURE check ( hold : Time ; SIGNAL C : Clock ; SIGNAL D : Data ) ; check ( setup => 10 ns, D => D_Bus, C => Clk_1 ) ; check ( hold => 5 ns, D => D_Bus, C => Clk_2 ) ; check ( 15 ns, D_Bus, Clk ) ;
Nach der Definition des Typs mvl werden die Standardoperatoren AND , OR und NOT überladen. Als übergabe- und Ergebniswerte wird hier jeweils der Typ mvl verwendet.
Die Signalzuweisungen an Q , R und S zeigen die Verwendung der überladenen Operatoren. Interessant ist der zweite Aufruf, bei dem der Operator explizit als Funktion aufgerufen wird und die Operanden als Übergabewerte dienen.
TYPE mvl IS ( '0', '1', 'Z', 'X' ) ; FUNCTION "AND" (L, R : mvl) RETURN mvl; FUNCTION "OR" ( L, R : mvl ) RETURN mvl ; FUNCTION "NOT" ( R : mvl ) RETURN mvl ; SIGNAL Q, R, S : mvl ; Q <= 'X' OR '1' ; R <= " OR "( '0', 'Z' ) ; S <= ( Q AND R ) OR NOT S ;
Auflösungsfunktion
Definition
Eine Resolution Function (Auflösungsfunktion) bestimmt den Wert eines Signals, wenn an dieses Signal gleichzeitig durch mehr als eine Quelle Zuweisungen erfolgen.
Notwendig wird dies z.B., wenn folgende nebenläufige Zuweisungen an das unresolved Signal Z existieren:
Z <= A;
Z <= B;
Exisitert für Z keine Resolution Function, so ist nicht geklärt, welchen Wert Z erhält, wenn A='0' und B='1' gilt. Die Verbindung zwischen Signal und einer Resolution Function wird in der Signaldeklaration hergestellt. Es ist auch möglich, einen Subtype zu deklarieren, der einen Typ mit einer Resolution Function verbindet.
Beispiel
Es wird eine Resolution Function deklariert, die mehrfache Signalzuweisungen nach dem Prinzip des wired_or auflöst.
Die Konstante floatvalue wird als Bit deklariert und mit '0' initialisiert. Treibt keine Quelle ein Signal ( inputs'Length = 0) wird der Wert von floatvalue , also '0' übergeben.
Treibt einer der Eingänge eine '1', so wird der Wert '1' zurückgegeben, ansonsten '0'.
FUNCTION wired_or ( inputs : Bit_vector ) RETURN Bit IS CONSTANT floatvalue : Bit := '0' ; BEGIN IF inputs'Length = 0 THEN RETURN floatvalue ; ELSE FOR i IN inputs'Range LOOP IF inputs(i) = '1' THEN RETURN '1' ; END IF ; END LOOP ; RETURN '0' ; END IF ; END ;
Packagedeklaration
Beispiele
Deklaration des Packages pck , in dem die Integer-Konstante CINT deklariert wird.
PACKAGE pck IS CONSTANT CINT : integer; END pck;
Deklaration des Packages tristate , in dem der Aufzählungstyp Tri deklariert und drei Funktionen ( BitVal , TriVal , Resolve ) mit entsprechenden Übergabewerten und Ergebnistypen deklariert werden. Weiterhin wird ein Typ TriVector als Vektor des Typs Tri und der maximalen Länge ( NATURAL RANGE <> ) deklariert.
PACKAGE tristate IS TYPE Tri IS ('0', '1', 'Z', 'E'); FUNCTION BitVal (Value : Tri) RETURN Bit; FUNCTION TriVal (Value : Bit) RETURN Tri; TYPE TriVector IS ARRAY ( NATURAL RANGE <>) OF Tri; FUNCTION Resolve (Sources : TriVector) RETURN Tri; END tristate;
Es werden die Objekte der Bibliothek parts eingebunden.
Das Signal S wird als guarded signal (BUS) deklariert und mit dem Wert 1 initialisiert. Der/Die Treiber für das Signal S wird/werden nicht sofort nach Deaktivierung von S getrennt, sondern erst 2 ns später.
Es werden die zwei Components latch und clock mit entsprechenden Ein- und Ausgängen deklariert. Die Component latch beinhaltet dabei noch einen Generic N .
PACKAGE pck_2 IS USE work.parts.all; SIGNAL S : resol_bit BUS := '1'; DISCONNECT S AFTER 2 ns; COMPONENT latch GENERIC (C : Natural); PORT (A : IN Bit; B : OUT Bit_vector (1 TO C)); END COMPONENT ; COMPONENT clock PORT (CK : OUT Bit); END COMPONENT ; END pck_2;
Der Body eines Packages
Beispiele
Die Objekte der Bibliothek pck_0 werden eingebunden. Im Package Body wird die Konstante cint , die schon im Package-Kopf deklariert sein muß, nochmals als Integer deklariert und mit dem Ergebniswert aus dem Funktionsaufruf f(6) initialisiert. (deferred constant)
USE work.pck_0.all; PACKAGE BODY pck IS CONSTANT cint : integer := f(6); END pck ;
Definition des Package Bodys pck_1 , in dem die zwei Funktionen G und F deklariert werden.
In der Funktion G wird als Ergebnis der Wert der Gleichung A XOR B als Bit zurückgegeben.
In der Funktion F wird eine Variable V als Bit deklariert, der der Wert aus S1 NAND S2 übergeben wird. Als Ergebniswert liefert die Funktion F den Bit-Wert, der sich aus dem Funktionsaufruf G(V, S2) ergibt.
PACKAGE BODY pck_1 IS FUNCTION G ( A, B : Bit ) RETURN Bit IS BEGIN RETURN NOT ( A XOR B ); END ; FUNCTION F ( S1, S2 : Bit ) RETURN Bit IS VARIABLE V : Bit; BEGIN V := S1 NAND S2; RETURN G(V, S2); END ; END pck_1 ;
Definition des Package Bodys tristate , in dem die zwei Funktionen BitVal und TriVal deklariert werden.
In der Funktion BitVal wird eine Konstante Bits deklariert und mit dem Wert “0100” initialiasiert. Als Ergebnis wird hier der Wert des Bits an der Stelle Tri'Pos ( Value ) von Bits zurügegeben.
In der Funktion TriVal wird eine Variable V vom Typ Tri deklariert und mit dem Wert Z initialisiert.
In der LOOP-Schleife wird in Abhängigkeit vom jeweiligen Wert von Source(i) und V entweder der Wert von Source(i) an V übergeben oder E als Ergebniswert zurückgegeben. Für ersteren Fall wird anschließend V als Ergebniswert zurückgegeben.
PACKAGE BODY tristate IS FUNCTION BitVal ( Value : Tri ) RETURN Bit IS CONSTANT Bits : Bit_Vector := "0100"; BEGIN RETURN Bits(Tri'Pos(Value)) END ; FUNCTION TriVal ( Value : Bit ) RETURN Tri IS VARIABLE V : Tri := 'Z'; BEGIN FOR i IN Sources'Range LOOP IF Sources(i) /= 'Z' THEN IF V = 'Z' THEN V := Sources(i); ELSE RETURN 'E'; END IF ; END IF ; END LOOP ; RETURN V ; END ; END tristate ;
Konformitätsregeln
Definition
Falls die Sprach-Regeln eine Mehrfach-Spezifikation eines Unterprogrammes benötigen oder erlauben, so sind folgende Variationen erlaubt:
- Eine numerische Variable kann nur genau dann durch eine andere numerische Variable ersetzt werden, wenn beide den gleichen Wert besitzen.
- Ein einfacher Name kann nur genau dann durch einen selektierten Namen, innerhalb dessen der einfache Namen den Selektor darstellt, ersetzt werden, wenn in beiden Spezifikationen der Sinn des einfachen Namens durch die selbe Deklaration festgelegt wird.
Zwei Spezifikationen von einem Unterprogramm sind konform , wenn, abgesehen von Kommentaren und den oben erwähnten Variation, beide Spezifikationen aus der selben Abfolge von lexikalischen Elementen gebildet werden und korrespondierende lexikalische Elemente die selbe Bedeutung haben. Die Spezifikation einer unreinen Funktion ist niemals konform zu der einer reinen Funktion.
Beispiele
Die Spezifikationen der Prozedur p sind nicht konform, da diese nicht aus der selben Abfolge von lexikalischen Elementen gebildet werden.
PROCEDURE p ( x, y : integer ); PROCEDURE p (x : integer ; y : integer); PROCEDURE p ( x, y : IN integer );
Typen
Skalare Typen
Beispiele
Es werden unterschiedliche Typen deklariert.
- Die Typen Bit und switch_level sind als Aufzählungstypen über Characters deklariert und können nur die Werte 0 oder 1 bzw. X annehmen. Diese 0 und 1 sind von den Integerwerten 0 und 1 zu unterscheiden. Diese beiden Zeichen sind dann überladen.
- Die Typen states und colors sind als Aufzählungstypen über selbstsprechende Elementennamen deklariert.
TYPE Bit IS ( '0', '1' ) ; TYPE switch_level IS ( '0', '1', 'X' ) ; TYPE states IS (out, sleeping, working); TYPE colors IS ( red, green, blue );
- Integertypen werden durch die Angabe von ganzen Zahlen bei der Bereichsangabe (RANGE) erzwungen.
- Der Bereich kann aufsteigend (TO) oder abfallend (DOWNTO) deklariert werden.
- Reelle Typen werden durch reelle Bereichsangaben erzwungen.
- Subtypes können durch die Angabe des Basistyps und des ausgewählten Bereiches deklariert werden.
TYPE byte_length_integer IS RANGE 0 TO 255 ; TYPE word_index IS RANGE 31 DOWNTO 0 ; TYPE my_real IS RANGE 0.0 TO 9.99 ; SUBTYPE high_bit_low IS byte_length_integer RANGE 0 TO 127 ;
Bei physikalischen Typen wird zuerst ein Real-Typ definiert. Anschließend wird die Basiseinheit und die daraus abgeleiteten Einheiten deklariert.
Als Beipiele sind hier die Definitionen der Längeneinheiten ( distance ) und der Zeiteinheiten ( time ) gezeigt.
Die physikalische Einheit time ist ein vordefinierter Typ.
TYPE distance IS RANGE 0 TO 1E16 UNITS -- Basiseinheit : A -- Angström -- Metrische Einheiten : nm = 10 A ; -- Nanometer um = 1000 nm ; -- Mikrometer mm = 1000 um ; -- Millimeter cm = 10 mm ; -- Centimeter m = 1000 mm ; -- Meter km = 1000 m ; -- Kilometer END UNITS ; TYPE time IS RANGE -1E18 TO 1E18 UNITS fs ; --Femtosekunde ps = 1000 fs ; -- Picosecond ns = 1000 ps ; -- Nanosecond us = 1000 ns ; -- Microsecond ms = 1000 us ; -- Millisecond sec = 1000 ms ; -- Second min = 60 sec ; -- Minute END UNITS
Zusammengesetzte Typen
Beispiele
mt_word wird als Bitvektor der Breite 32 deklariert, wobei die Indizes von links nach rechts ansteigen.
TYPE my_word IS ARRAY ( 0 TO 31 ) OF bit ;
data_in wird als Vektor des Typs five_level_logic und der Breite 8 deklariert, wobei die Indizes von links nach rechts abfallen.
TYPE data_in IS ARRAY ( 7 DOWNTO 0 ) OF five_level_logic
memory wird als Vektor des Typs my_word und beliebiger Breite (<>) deklariert. Die Richtung und die maximal mögliche Breite wird durch den Typ integer festgelegt.
TYPE memory IS ARRAY (integer RANGE <>) OF my_word ;
t wird als Vektor des Typs element und der Breite 1+( max - min ) vom Typ positiv deklariert.
TYPE t IS ARRAY (positive RANGE min TO max) OF element;
date wird als Record deklariert, welches aus den Elementen day , month und year besteht.
TYPE date IS RECORD day : integer RANGE 1 TO 31; month : month_name; year : integer RANGE 0 TO 2100; END RECORD ;
Zeiger-Typen
Definitionen
access_type_definition
access subtype_indication
Durch die Deklaration eines Access Type wird ein Zeigertyp deklariert, der für eine spätere Deklaration einer Zeigervariablen verwendet werden kann.
incomplete_type_declaration
type identifier
Durch eine unvollständige Typ-Deklaration wird eine Modellierung von rekursiven Strukturen möglich. Die vollständige Typ-Deklaration muß noch im gleichen Deklarationsbereich erfolgen.
Examples
Es werden die Zeigertypen address und buffer_ptr deklariert. Zieltypen sind memory und buffer .
TYPE address IS ACCESS memory ; TYPE buffer_ptr IS ACCESS buffer ;
Es wird eine rekursive Struktur aufgebaut. Zunächst wird der Typ cell unvollständig deklariert. Daraufhin wird der Zeigertyp link auf den Typ cell deklariert.
Anschließend wird der Typ cell vollständig als Record deklariert. Die Elemente succ und pred werden als Zeigertypen deklariert. Dadurch kann eine verkettete Liste aufgebaut werden, bei der jedes Element einen Zeiger auf seinen Vorgänger und auf seinen Nachfolger enthält.
TYPE cell ; TYPE link IS ACCESS cell ; TYPE cell IS RECORD value : integer ; succ : link ; pred : link ; END RECORD ;
Datei-Typen
Beispiele
Es werden die zwei Filetypen string_file und natural_file deklariert. Sie sollen Elemente des Typs string und natural enthalten.
TYPE string_file IS FILE OF string TYPE natural_file IS FILE OF natural
Es wird ein Filetyp ft mit Elementen vom Typ tm deklariert.
In der Procedure read soll aus einem File der nächste Wert ausgelesen werden.
In der Procedure write soll an ein File ein Wert angehängt werden.
Die Function endfile überprüft, ob das Ende eines Files erreicht ist.
TYPE ft IS FILE OF tm ; PROCEDURE read ( f : IN ft ; value : OUT tm ; length : OUT natural ) ; PROCEDURE write ( f : OUT ft ; value : IN tm ) ; FUNCTION endfile ( f : IN ft ) RETURN boolean ;
Deklarationen
Type Declaration
Beispiele
Es werden zwei Integertypen A und B deklariert, die beide einen Bereich von 1 bis 10 umfassen.
TYPE A IS RANGE 1 TO 10 ; TYPE B IS RANGE 1 TO 10 ;
Der physikalische Typ capacitance wird als Real-Typ mit einem Bereich von 0 bis 1E16 deklariert. Anschließend werden eine Basiseinheit und abgeleitete Einheiten deklariert.
TYPE capacitance IS RANGE 0 TO 1E16 UNITS fF ; -- Femtofarad pF = 1000 fF ; -- Picofarad nF = 1000 pF ; -- Nanofarad uF = 1000 nF ; -- Microfarad END UNITS ;
Es wird eine rekursive Struktur aufgebaut. Zunächst wird der Typ cell unvollständig deklariert. Daraufhin wird der Zeigertyp link auf den Typ cell deklariert.
Anschließend wird der Typ cell vollständig als Record deklariert. Die Elemente succ und pred werden als Zeigertypen deklariert. Dadurch kann eine verkettete Liste aufgebaut werden, bei der jedes Element einen Zeiger auf seinen Vorgänger und auf seinen Nachfolger enthält.
TYPE cell ; TYPE link IS ACCESS cell ; TYPE cell IS RECORD value : integer ; succ : link ; pred : link ; END RECORD ;
Die sind Beispiele für standardmäßig vordefinierte Typen. boolean , bit und character sind Aufzählungstypen. string und bit_vector sind Felder mit jeweils beliebiger Breite (RANGE <>), wobei die maximale Breite durch den entsprechenden Typ ( positiv , natural ) vorgegeben ist.
TYPE boolean IS ( false, true ) ; TYPE bit IS ( '0', '1' ) ; TYPE string IS ARRAY (positive RANGE <>) OF character ; TYPE bit_vector IS ARRAY (natural RANGE <>) OF bit ;
Untertypendeklaration
Beispiele
Dies sind standardmäßig vordefinierte Subtypes. natural ist ein integer -Typ, beschränkt auf den Bereich von 0 bis zum maximalen integer -Wert. positiv ist ebenfalls ein integer -Typ, beschränkt auf den Bereich von 1 bis zum maximalen integer -Wert.
SUBTYPE natural IS integer RANGE 0 TO integer'high ; SUBTYPE positive IS integer RANGE 1 TO integer'high ;
Dies sind allgemeine Beispiele, wie Subtypes durch range-constraints aus Basic-Types gebildet werden.
Bei den integer - und real Subtypes werden die Bereiche mit Hilfe des Schlüsselworts RANGE deklariert.
Bei character -, string - und enumaration Subtypes werden die Bereiche durch explizite Angabe eines bestimmten Ausschnitts deklariert.
SUBTYPE primary_color IS color RANGE yellow TO blue ; SUBTYPE same_color IS primary_color ; SUBTYPE address_integer IS integer RANGE 0 TO 127 ; SUBTYPE human_size IS real RANGE 0.50 TO 2.50 ; SUBTYPE byte IS bit_vector (7 DOWNTO 0); SUBTYPE name IS string ( 1 TO 31 ); SUBTYPE color_10 IS colors (1 TO 10);
Die zwei Subtypes sbit und xbit werden als Untertypen von zbit deklariert, wobei beiden eine Auflösungsfunktion zugewiesen wird. Die Resolution Function sorgt bei Mehrfachzuweisungen an ein Signal für eine eindeutige Wertzuweisung.
SUBTYPE sbit IS wiredX zbit ; SUBTYPE xbit IS wiredX zbit RANGE 'X' TO '1' ;
Konstantendeklaration
Beispiele
Die Konstante cte ist vom Typ integer und besitzt den Wert 5. Die Konstanten Vdd und Vcc sind vom Typ bit und besitzten den Wert '1'. Die Konstante minimum_setup_time ist vom physikalischen Typ time und besitzt den Wert 5 ns.
CONSTANT cte : integer := 5 ; CONSTANT Vdd, Vcc : bit := '1' ; CONSTANT minimum_setup_time : time := 5 ns ;
- Die Konstante name beinhaltet den String “ Dupond ”.
- Der Bitvektor address besitzt den konstanten Wert “00110110”.
- Die Konstante mask ist als Subtype von bit_vector mit dem Wert “0101” deklariert.
- Die Konstante bittab ist als Subtype von bit_vector mit dem Wert “000111Z1Z” deklariert.
- Die Konstante tab ist als Subtype von table_type deklariert, wobei den einzelnen Elementen die konstanten Werte 2, 3, 4, -2 und 0 zugwiesen werden.
CONSTANT name : string := "Dupond" ; CONSTANT address : bit_vector := "00110110" ; CONSTANT mask : bit_vector( 1 TO 3 ) := "0101" ; CONSTANT bittab : bit_vector( 1 TO 9 ) := ( 1 TO 3 => '0', 7 | 9 => 'Z', OTHERS => '1' ) ; CONSTANT tab : table_type( 0 TO 4 ) := ( 2, 3, 4, -2, 0 ) ;
Eine unvollständige Konstantendeklaration,wie hier für deferred , darf nur in der Package-Daklaration stehen. Die vollständige Konstantendeklaration muß in dem Package Body enthalten sein. Bei Veränderung des Konstantenwertes muß nur der PACKAGE BODY neu übersetzt werden und keine der auf das Package aufbauenden Design-Einheiten.
PACKAGE P IS CONSTANT deferred : integer ; END P; PACKAGE BODY P IS CONSTANT deferred : integer := 200 ; END P ;
Signaldeklaration
Weitere Definitionen
Die mit REGISTER oder BUS deklarierten Signale sind (kontrollierte Signale) 'guarded signals'.
'Guarded signals' müssen (aufgelöste Signale) 'resolved signals' sein.
Kontrollierte Signalzuweisungen haben für 'guarded signals' folgende Bedeutung:
IF guard_expression THEN sig_name <= sig_waveform ; ELSE sig_name <= NULL ; END IF ;
Die Zuweisung von NULL an das Signal sig_name bedeutet, daß der Treiber dieser Signalzuweisung abgeschaltet wird. Für das 'resolved signal' hat das zur Folge:
- Wurden nicht alle Treiber abgeschaltet, so wird das resultierende Signal nur anhand der nicht abgeschalteten Treiber ermittelt,
- wurden alle Treiber abgeschaltet, so wird im Falle der Signaldeklaration REGISTER der zuletzt vorhandene Signalwert beibehalten,
- wurden alle Treiber abgeschaltet, so wird im Falle der Signaldeklaration BUS der in der 'resolution function' angegebene Defaultwert angenommen.
Das Abschalten des Signaltreibers erfolgt unmittelbar, d.h. ohne Verzögerung, nachdem die guard_expression den Wert false angenommen hat, es sei denn, es wurde für das Signal im Anschluß an dessen Deklaration als kontrolliertes Signal eine explizite Verzögerungszeit durch die DISCONNECTION Anweisung vereinbart. Ein ausführliches Beispiel dazu ist unter Disconnection Spezifikation zu finden.
Beispiele
Die Signale clk_1 und clk_2 vom physikalischen Typ time werden deklariert.
SIGNAL clk_1, clk_2 : time ;
- Das Signal address vom Typ bit8 wird deklariert und mit dem Wert “00110110” initialisiert.
- Das Signal bittab wird vom Typ bit_vector deklariert und mit dem Wert “000111Z1Z” initialisiert.
- Das Signal tab wird vom Typ table_type deklariert und mit den Werten 2, 3, 4, -2 und 0 initialisiert.
SIGNAL address : bit8 := "00110110" ; SIGNAL bittab : bit_vector(1 TO 9) := ( 1 TO 3 => '0', 7 | 9 => 'Z', OTHERS => '1' ) ; SIGNAL tab : table_type( 0 TO 4 ) := ( 2, 3, 4, -2, 0 ) ;
Das Signal address_bus wird als guarded signal (BUS) vom Typ resolved_bit_vector und dem Initialisierungswert “10011001” deklariert.
SIGNAL address_bus : resolved_bit_vector BUS := "10011001";
Das Signal resolved_s wird als guarded signal (REGISTER) vom Typ zbit deklariert. Zusätzlich wird dem Signal eine Auflösungsfunktion resolution_function zugewiesen.
SIGNAL resolved_s : resolution_function zbit REGISTER ;
Variablendeklaration
Anmerkungen
Shared variables dürfen nur im Deklarationsbereichen von Entities, Architekturen, Packages, Package Bodies und Blöcken verwendet werden. In Prozessen und Unterprogrammen dürfen keine shared variables deklariert werden.
Auf eine shared variable können mehrere Prozesse zugreifen. Greifen mehrere Prozesse während eines Simulationszyklusses auf eine shared variable zu, ist die Reihenfolge der Zugriffe nicht vorgeschrieben. D.h. welche Werte innerhalb des Zimulationszyklusses gelesen werden oder welcher Wert am Schluß vorliegt ist nicht deterministisch. Siehe Beispiel unten.
Beispiele
Die Variable count vom Typ positive wird deklariert.
VARIABLE count : positive ;
Die Variablen index und memory werden als Subtypes von den Typen integer und bit_matrix deklariert.
VARIABLE index : integer RANGE 0 TO 99 := 0 ; VARIABLE memory : bit_matrix ( 0 TO 7, 0 TO 1023 ) ;
- address_bus wird als Variable vom Typ bit8 deklariert und mit “00110110” initialisiert.
- integer_address wird als Variable vom Typ integer deklariert und mit (2**nb_bit-1) initialisiert.
- Die Variable bittab wird als subtype vom Typ bit_vector deklariert und mit “000111Z1Z” initialisiert.
- Die Variable tab wird als subtype vom Typ table_type deklariert und mit den Werten 2, 3, 4, -2 und 0 initialisiert.
VARIABLE address_bus : bit8 := "00110110" ; VARIABLE integer_address : integer := 2**nb_bit - 1 ; VARIABLE bittab : bit_vector (1 TO 9) := ( 1 TO 3 => '0', 7 | 9 => 'Z', OTHERS => '1' ) ; VARIABLE tab : table_type( 0 TO 4 ) := ( 2, 3, 4, -2, 0 ) ;
Beispiel für den Nichtdeterminismus von shared variables :
In der Architektur wird eine shared variable deklariert, die anschließend von zwei Prozessen manipuliert wird.
Es ist nicht festgelegt, ob
- zuerst p1 counter um eins erhöht (counter = 1) und dann p2 counter um eins erniedrigt (counter = 0)
- zuerst p2 versucht counter um eins zu erniedrigen, was zu einem Fehler aufgrund der Verletzung des Untertypen führen würde.
ARCHITECTURE beh OF sv_example IS SHARED VARIABLE counter : integer RANGE 0 TO 1 := 0 ; BEGIN p1: PROCESS BEGIN counter := counter + 1 ; wait ; END PROCESS p1; p2: PROCESS BEGIN counter := counter - 1; wait ; END PROCESS p2 ; END ARCHITECTURE beh;
Filedeklarationen
Anmerkungen
Filedeklaration der Versionen VHDL'87 und VHDL'93 sind inkompatibel!
Der Standard legt nicht fest, was passieren soll, wenn mehrere logisch files ein und das selbe physikalische File lesen bzw. schreiben wollen.
Beispiele
VHDL'87
simulation_output wird als (virtuelles) Ausgabe-File vom Typ my_file_type mit dem physikalischen Pfad und Namen /home/usr2/sim.res deklariert.
FILE simulation_output : my_file_type IS OUT "/home/usr2/sim.res" ;
rom_content wird als (virtuelles) Eingabe-File vom Typ rom_file_type mit dem physikalischen Namen “rom2048.txt” deklariert.
FILE rom_content : rom_file_type IS IN "rom2048.txt" ;
input und output sind vordefinierte Files vom Typ text mit den physikalischen Namen std_input und std_output.
FILE input : text IS IN "std_input"; FILE output : text IS OUT "std_output";
sim_output wird als (virtuelles) Ausgabe-File (mode IN ist default) vom Typ my_file_type mit dem physikalischen Pfad und Namen /home/usr3/sim.trc deklariert.
FILE sim_output : my_file_type IS OUT "/home/usr3/sim.trc" ;
VHDL'93
nowhere wird als (virtuelles) File vom Typ my_file_type deklariert, aber nicht explizit geöffnet.
FILE nowhere : my_file_type ;
simulation_input wird als (virtuelles) File vom Typ my_file_type mit dem physikalischen Pfad und Namen /home/usr2/sim.in deklariert. Während der Elaboration wird implizit FILE_OPEN(simulation_input,“/home/usr2/sim.res”) mit dem Default READ-MODE aufgerufen.
FILE simulation_input : my_file_type IS "/home/usr2/sim.res" ;
simulation_output wird als (virtuelles) Ausgabe-File vom Typ my_file_type mit dem physikalischen Pfad und Namen /home/usr2/sim.res deklariert.
FILE simulation_output : my_file_type OPEN WRITE_MODE IS "/home/usr2/sim.res" ;
Schnittstellendeklaration
- Interface-Declarations definieren Schnittstellenobjekte von einem genau festgelegten Typ.
- Schnittstellenobjekte sind (Schnittstellen-) Konstanten, (Schnittstellen-) Signale, (Schnittstellen-) Variablen und (Schnittstellen-) Dateien.
interface_signal_declaration
[ signal ] identifier_list : [ mode ] subtype_indication [ bus ] [ := static _expression ]
– subtype_indication darf kein Datei- oder Pointertyp sein.
interface_file_declaration
file identifier_list : subtype_indication
– subtype_indication muß einen Untertyp eines Deteityps bezeichnen.
mode
- in – Ports können nicht geschrieben werden; Standardmode
- out – Ports können nicht gelesen werden
- inout – Ports können gelesen und geschrieben werden
- buffer – Ports können gelesen und nur von einer Quelle geschrieben werden
- linkage – Ports können gelesen und geschrieben werden, aber nur als “actuals”.
Alias-Deklaration
Ergänzungen
Alle benamten Dinge bis auf Labels, Schleifenparameter und Generate-Parameter kann mit einem Alias versehen werden. Ein Alias für ein Objekt (Konstanten, Variablen, Signale, File) nennt man object alias. Alle anderen nennt man nonobject alias.
Das Alias eines überladbaren Objekts ist selbst wieder überladbar.
Für object aliases gelten folgende Regeln:
- Signaturen sind nicht erlaubt.
- Der Name in einer Aliasdeklaration muß ein statischer Name (See Name) sein. Wird der Untertyp in der Aliasdeklaration angegeben, muß dieser mit dem Typ des angegeben Namen übereinstimmen. Mehrdimensionale Arrays als Untertyp sind verboten. Folgende Regeln gelten:
- Wenn die Untertypenangabe fehlt oder vorhanden ist und einen unbeschränkten Feldtyp bezeichnet:
- Wenn das Alias einen Feldausschnitt bezeichnet, dann wird der Untertyp des Objekts als solchiger Typ des Feldausschnitt betrachtet.
- Ansonsten besitzt das (neue) Objekt den Typ welcher durch das (alte) Objekt vorgegeben ist.
- Wenn eine vorhandene Untertypenangabe einen beschränkten Feldtyp bezeichnet, dann besitzt das Objekt diesen angegeben Untertyp. Der angegebene Untertyp muß passende Einzelelemente bezüglich des Typen des (alten) Objekts haben.
- Wenn eine vorhandene Untertypenangabe einen skalaren Typ bezeichnet, dann besitzt das Objekt diesen angegeben Untertyp. Desweitern müssen altes und neues Objekt die selben Wertegrenzen und Richtungsdefinition besitzen.
- Das gleiche gilt für Referenzen von Attributen, bei denen der Prefix des Attributname ein Alias bezeichnet.
- Eine Referenz eines object alias ist automatisch eine Referenz auf das eigentliche Objekt (gilt auch für Feldausschnitte).
Für nonobject aliases gelten folgende Regeln:
- Untertypenangaben sind nicht erlaubt.
- Bezeichnet der Name ein Unterprogramm (auch Operatoren) oder einen Wert eines Aufzählungstyp, so ist eine Signatur erforderlich. Die Signatur muß dabei mit der Parameter und Rückgabetypen Kombination (See Überladen) genau eines der Unterprogramme oder des Aufzählungswertes übereinstimmen.
- Bezeichnet der Name einen Aufzählungstypen, so werden durch die Aliasdeklarationen für jedes Element des ursprünglichen Aufzählungstyps eine Aliasdeklaration impliziert (alias_designator = Aufzählungselementnamen; name = urzprünglicher Aufzählungstyp.Aufzählungselementnamen).
- Gleiches gilt bei einem Alias für einen physikalischen Typ.
- Bezeichnet der Name einen Typ, dann impliziert die Aliasdeklaration weitere Aliasdeklarationionen für damit verbundene Operatoren und gegebenenfalls für entsprechende Werte und Einheiten. Jede implizite Operator-Aliasdeklaration hat eine Signatur, die genau eines der Parameter und Rückgabetypen Kombination (2.3) des Operators entspricht.
Beispiele
Die Konstante tc ist durch die Alias-Deklaration nun auch über den Namen delay ansprechbar.
CONSTANT tc : time := 2.5 ns ; ALIAS delay : time IS tc ;
Durch das Alias kann die Variable vector nun über den Namen reverse_vector angesprochen werden, wobei hier die Indizes von 8 bis 1 gehen.
VARIABLE vector : bit_vector(0 TO 7); ALIAS reverse_vector : bit_vector ( vector'length DOWNTO 1 ) IS vector ;
Hier wird die Variable real_number unterschiedlich aliased.
Mit sign ist das MSB von real_number ansprechbar.
Mit mantissa werden die Elemente 8 bis 31 von real_number angesprochen, wobei die Indizes hier von 0 bis 23 gehen.
Mit exponent werden die Elemente 1 bis 7 von real_number angesprochen, wobei die Indizes hier ebenfalls von 1 bis 7 gehen.
VARIABLE real_number : bit_vector ( 0 TO 31 ) ; ALIAS sign : bit IS real_number(0) ; ALIAS mantissa : bit_vector( 0 TO 23 ) IS real_number( 8 TO 31 ) ; ALIAS exponent : bit_vector( 1 TO 7 ) IS real_number( 1 TO 7 ) ;
Der vordefinierte Typ BIT aus dem automatisch verfügbaren Package STANDARD und der Bibliothek STD wird mit dem Alias std_bit versehen.
Damit werden automatisch weitere Alias-deklarationen für die Werte des Aufzählungstyps und die vordefinierten Operatoren impliziert.
ALIAS std_bit IS STD.STANDARD.BIT ; -- ALIAS `0' IS STD.STANDARD .'0' -- [ RETURN STD.STANDARD.BIT ] ; -- ALIAS `1' IS STD.STANDARD .'1' ; -- [ RETURN STD.STANDARD.BIT ] ; -- ALIAS "and" IS STD.STANDARD ."and" ; --[ STD.STANDARD.BIT , STD.STANDARD.BIT -- RETURN STD.STANDARD.BIT ] ; -- ALIAS "or" IS STD.STANDARD ."or" ; --[ STD.STANDARD.BIT , STD.STANDARD.BIT -- RETURN STD.STANDARD.BIT ] ; -- ···
Attributdeklaration
Mit Attributen können Eigenschaften von Objekten (z.B. Signalen) abgefragt werden. Damit kann in vielen Fällen eine elegantere und kürzere VHDL-Beschreibung gestaltet werden. Die wichtigsten sind bereits vordefinierte Attribute.
Für eigene Attribute muß eine entsprechende Funktion geschrieben werden, die dann zu jeder Zeit den Wert des Attributes liefert. Weiteres unter Attribut Spezifikation.
Beispiele
capacitance_value wird als Attribut vom Typ capacitance deklariert.
ATTRIBUTE capacitance_value : capacitance ;
Das hier deklarierte Attribute pin_number ist vom Subtype pin_natural .
SUBTYPE pin_natural IS natural RANGE 1 TO 24 ; ATTRIBUTE pin_number : pin_natural ;
Es werden zwei verschiedene Attribute deklariert.
location ist vom Typ coordinate , einem Record.
pin_no ist vom Typ positive , einem Subtype von integer .
TYPE coordinate IS RECORD x, y : integer ; END RECORD ; TYPE positive IS integer RANGE 1 TO integer'high ; ATTRIBUTE location : coordinate ; ATTRIBUTE pin_no : positive ;
Mit vordefinierten Attributen kann die Schleifenanweisung auch anders formuliert werden :
FOR i IN a1'LOW TO a1'HIGH FOR i IN a1'RIGHT TO a1'LEFT FOR i IN a1'REVERSE_RANGE FOR i IN a1'RANGE
SIGNAL a1: bit_vector(3 DOWNTO 0) ; ... PROCESS (a) BEGIN z<= "0000"; FOR i in 0 TO 3 LOOP IF (a = i) THEN z(i) <= '1' ; END IF ; END LOOP ; END PROCESS ; ...
Komponentendeklaration
Beispiele
Es wird die Component gen_clock deklariert, die nur den Ausgang clk als Schnittstelle nach außen besitzt.
COMPONENT gen_clock PORT ( clk : OUT tri_bit ) ; END COMPONENT ;
Die hier deklarierte Component adder_8_bit besitzt die Eingänge a , b und cin sowie die Ausgänge sum und cout .
COMPONENT adder_8_bit PORT (a, b : IN bit_vector(1 TO 8); cin : IN bit ; sum : OUT bit_vector(1 TO 8); cout: OUT bit ) ; END COMPONENT ;
Die hier deklarierte Component adder_n_bit ist über den Generic n parametrisiert.
Die Breite der Eingangsvektoren a und b sowie des Ausgangsvektors sum ergibt sich aus dem Wert des Generics n .
COMPONENT adder_n_bit GENERIC ( n : positive ) ; PORT (a, b : IN bit_vector(1 TO n); cin : IN bit ; sum : OUT bit_vector(1 TO n); cout: OUT bit ) ; END COMPONENT ;
Gruppentemplatedeklaration
Beispiele
Gruppen dieses Typs bestehen aus zwei Signalen
GROUP pin2pin IS ( SIGNAL , SIGNAL ) ;
Gruppen dieses Typs bestehen aus einer beliebigen Anzahl von Signalen
GROUP pin_set IS ( SIGNAL <>) ;
Gruppen dieses Typs bestehen aus einer beliebigen Anzahl von Dateien.
GROUP file_groups IS ( FILE <>) ;
Gruppen dieses Typs bestehen aus einer beliebigen Anzahl von Gruppen.
GROUP gog IS ( GROUP <>) ;
Gruppendeklaration
Beispiele
Gruppen vom Typ pin2pin werden deklariert.
GROUP pinpair1 : pin2pin (clk, q1) ;
GROUP pinpair2 : pin2pin (clk, q2) ;
Gruppe der beiden vorher definierten Gruppen.
GROUP clocked : gog (pinpair1, pinpair2);
- Der Gruppentyp path wird deklariert.
- Die Gruppe a_to_s wird deklariert.
- Das Attribut propagation_delay wird deklariert.
- Das Attribut propagation_delay wird der Gruppe a_to_s verbunden und mit dem Wert 250 ns belegt.
GROUP path IS ( SIGNAL , SIGNAL ) ; GROUP a_to_s : path (a,s) ; ATTRIBUTE propagation_delay : time ; ATTRIBUTE propagation_delay OF a_to_s : GROUP IS 250 ns ;
- Der Signalgruppemtyp pin_set wird deklariert.
- Der Gruppengruppentyp paths wird deklariert.
- Die Signalsgruppen sources und targets werden deklariert.
- Die Gruppengruppe ins_to_outs wird deklariert.
- Das Attribut propagation_delay wird deklariert.
- Das Attribut propagation_delay wird der Gruppe ins_to_outs verbunden und mit dem Wert delay belegt.
GROUP pin_set IS ( SIGNAL <>) ; GROUP paths IS ( GROUPS <>) ; GROUP sources : pin_set (inp1, inp2) ; GROUP targets : pin_set (outp1, outp2) ; GROUP ins_to_outs : paths (sources, targets) ; ATTRIBUTE propagation_delay : time ; ATTRIBUTE propagation_delay OF ins_to_outs : GROUP IS delay ;
Spezifikation
Attribut Spezifikation
Beispiele
Values for the attribute pin_number are determined. For the signal cin the attribute value is 10 and for the signal cout it is 5 .
ATTRIBUTE pin_number OF cin : SIGNAL IS 10 ; ATTRIBUTE pin_number OF cout : SIGNAL IS 5 ;
Der Wert des Attributes instance_location beträgt für das Label adder_1 (10,15) und für alle anderen Labels (25,65) .
ATTRIBUTE instance_location OF adder_1 : LABEL IS ( 10, 15 ) ; ATTRIBUTE instance_location OF OTHERS : LABEL IS ( 25, 65 ) ;
- Das Attribut author der Entity add_entity wird mit dem String Martin belegt.
- Das Attribut is_generic der Component cmos_nand wird mit dem Wert false belegt.
- Das Attribut creation_date der Architecture add_arc wird mit dem Record (14,Aug,95) belegt.
- Das Attribut safety der Procedure arithm_conv wird mit dem Wert bug belegt.
- Das Attribut confidentiality des Package cmos_pkg wird mit dem Wert restrictive belegt.
ATTRIBUTE author OF add_entity : ENTITY IS "Martin" ; ATTRIBUTE is_generic OF cmos_nand : COMPONENT IS false ; ATTRIBUTE creation_date OF add_arc : ARCHITECTURE IS (11, aug, 95) ; ATTRIBUTE safety OF arithm_conv : PROCEDURE IS bug ; ATTRIBUTE confidentiality OF cmos_pkg : PACKAGE IS restrictive ;
Mit vordefinierten Attributen kann die Schleifenanweisung auch anders formuliert werden :
FOR i IN a1'LOW TO a1'HIGH FOR i IN a1'RIGHT TO a1'LEFT FOR i IN a1'REVERSE_RANGE FOR i IN a1'RANGE
SIGNAL a1: bit_vector(3 DOWNTO 0) ; ... PROCESS (a) BEGIN z<= "0000" : FOR i in 0 TO 3 LOOP IF (a = i) THEN z(i) <= '1' ; END IF ; END LOOP ; END PROCESS ; ...
Konfiguration Spezifikation
Anmerkungen
In der generic map aspect muß ein actual ein Ausdruck oder das reservierte Wort OPEN sein.
In der port map aspect muß ein actual ein signal, ein Ausdruck oder das reservierte Wort OPEN sein. (In VHDL'87 durften Eingänge nur mit Signalen belegt werden; in VHDL'93 dürfen globale statische Werte auf Eingänge gelegt werden.)
Beispiele
Für die Components add_comp der Labels c1 , c2 und c3 soll die Verhaltensbeschreibung add_1 aus der Default-Bibliothek ( work ) verwendet werden.
In den restlichen Labels ( OTHERS ) soll für die Components add_comp die Beschreibung add_configuration aus der Default-Bibliothek ( work ) verwendet werden.
FOR c1, c2, c3 : add_comp USE ENTITY work.add_1( behaviour ) ; FOR OTHERS : add_comp USE CONFIGURATION work.add_configuration;
Alle verwendeten Components register_comp sollen nicht verbunden werden.
FOR ALL : register_comp USE OPEN ;
Für die Components nand2_comp der Labels c(1) bis c(5) soll die Entity nand mit dem Generic N=2 und der entsprechenden Ein-/Ausgangsverknüpfung ( PORT MAP ) verwendet werden.
Für die Component nand2_comp des Labels c(6) soll die Configuration nand2_configuration aus der Bibliothek my_lib mit der entsprechenden Ein-/Ausgangsverknüpfung ( PORT MAP ) verwendet werden.
FOR c( 1 TO 5 ) : nand2_comp USE ENTITY nand( arc ) GENERIC MAP ( N => 2 ) PORT MAP ( I(1) => a, I(2) => b, O => s ) ; FOR c(6) : nand2_comp USE CONFIGURATION my_lib.nand2_configuration PORT MAP ( a, b, s ) ;
Disconnection Spezifikation
Beispiele
a wird als Guarded Signal vom Typ REGISTER deklariert. Wird während der Simulation ein Treiber für das Signal a deaktiviert, so geschieht das um 1 ns zeitverzögert.
SIGNAL a : resolved_type REGISTER ; DISCONNECT a : resolved_type AFTER 1 ns;
sig1 , sig2 und sig3 werden als Guarded Signals vom Typ REGISTER deklariert. Die Treiber für sig1 werden während der Simulation um 5 ns und die der anderen Signale um 8 ns verzögert abgeschaltet.
SIGNAL sig1, sig2, sig3 : resolved_bit REGISTER ; DISCONNECT sig1 : resolved_bit AFTER 5 ns ; DISCONNECT OTHERS : resolved_bit AFTER 8 ns ;
bus_a und bus_b werden als Guarded Signals vom Typ bus deklariert. Die Treiber für beide Signale werden während der Simulation um 6 ns ( delay + 1 ns) verzögert abgeschaltet.
CONSTANT delay : time := 5 ns ; SIGNAL bus_a, bus_b : resolved_zbit_vector32 BUS ; DISCONNECT ALL : resolved_zbit_vector32 AFTER delay + 1 ns ;
Im PACKAGE fourval wird eine vierwertige Logik mvl4 und ein entsprechender Vektor definiert.
Es wird die Funktion resolved deklariert. Daraufhin kann ein 'resolved signal' als SUBTYPE abgeleitet werden.
Im PACKAGE BODY wird die Funktion resolved beschrieben.
- Wechselt das Eingangssignal choice auf 1 , so wird der Signaltreiber des ersten Blocks aktiv und gibt das erste Eingangssignal nach 20 ns an den Ausgang weiter.
- Wechselt choice auf 2 , so wird durch den zweiten Block das zweite Eingangssignal nach 18 ns ebenfalls auf den Ausgang gelegt. Da der erste Signaltreiber aber erst nach 25 ns abschaltet, sind für 7 ns zwei Treiber aktiv.
- Das resultierende Signal wird durch die 'resolution function' des Ausgangssignals ermittlelt.
- Wechselt choice auf einen Wert ungleich 1 oder 2 , so schaltet der zuletzt aktive Treiber nach 25 ns ab und das Ausgangssignal wechselt in den Defaultwert (in diesem Fall 'Z'), da es als bus deklariert ist.
- Bei einer Deklaration als REGISTER würde der letzte Signalwert erhalten bleiben.
PACKAGE fourval IS TYPE mvl4 IS ('X','0','1','Z') ; TYPE mvl4_vector IS ARRAY (natural RANGE <>) OF mvl4 ; FUNCTION resolved (a: mvl4_vector) RETURN mvl4 ; SUBTYPE mvl4_r IS resolved mvl4 ; END fourval ; PACKAGE BODY fourval IS FUNCTION resolved (a: mvl4_vector) RETURN mvl4 IS VARIABLE result : mvl4 := 'Z' ; -- Defaultwert: 'Z' BEGIN ... RETURN result ; END resolved ; END fourval ; USE work.fourval.ALL ; ENTITY mux_2_1 IS PORT (in_signals : IN mvl4_vector (1 TO 2) ; choice : IN integer ; out_signal : OUT mvl4_r BUS ) ; END mux_2_1 ; ARCHITECTURE with_guards OF mux_2_1 IS DISCONNECT out_signal : mvl4_r AFTER 25 ns ; BEGIN choice_1 : BLOCK (choice = 1) BEGIN out_signal <= GUARDED in_signals(1) AFTER 20 ns ; END BLOCK ; choice_2 : BLOCK (choice = 2) BEGIN out_signal <= GUARDED in_signals(2) AFTER 18 ns ; END BLOCK ; END with_guards ;
Namen
Name
Einfache Namen
Definition
Über einen einfachen Namen können verschiedene Objekte im VHDl-Code angesprochen und manipuliert werden.
Auswählende Namen
Beispiele
Es wird das Element opcode des Records instruction angesprochen.
instruction.opcode
Es werden alle Elemente ( ALL ) angesprochen, auf die der Zeiger ptr zeigt.
ptr. ALL
Es wird die Design-Einheit SN74LS221 aus der Bibliothek ttl angesprochen.
ttl.SN74LS221
Angesprochen werden alle Design-Einheiten aus der Bibliothek cmos .
cmos. ALL
Es wird die Entity voltage aus dem Package measurements angesprochen.
measurements.voltage
Angesprochen werden alle Entities aus dem Package standard .
standard. ALL
Es wird die Entity data angesprochen, die in dem Prozeß p definiert ist.
p.data
Indizierte Namen
Beispiele
Es wird das 5'te Element des Arrays register_array angesprochen.
register_array(5)
Es wird das Element mit den Inidzes (1024,7) des zweidimensionalen Arrays memory_cell angesprochen.
memory_cell( 1024, 7 )
Bereichsnamen
Beispiel
Es werden verschieden Slices angesprochen.
- Der erste Slice spricht den Bereich 0 bis 7 von r15 an.
- Der zweite Slice spricht den Bereich 24 bis 1 von data an.
- Der dritte Slice ist ungültig, weil die Indizierungsrichtung in Deklaration und Slice entgegengesetzt ist.
SIGNAL r15 : bit_vector( 0 TO 31 ) ; CONSTANT data : bit_vector(31 DOWNTO 0); r15( 0 TO 7 ) ; data( 24 DOWNTO 1 ) ; data( 24 TO 25 ) ;
Attributnamen
Beispiele
Angesprochen wird das linke Element der ersten Dimension des ein- oder mehrdimensionalen Arrays register .
register'left(1)
Das Attribut fanout liefert die Anzahl der von output getriebenen Signale.
output'fanout
Es wird das um 5 ns verzögerte Signal clk angesprochen.
clk'delayed( 5 ns )
Mit vordefinierten Attributen kann die Schleifenanweisung auch anders formuliert werden :
FOR i IN a1'LOW TO a1'HIGH FOR i IN a1'RIGHT TO a1'LEFT FOR i IN a1'REVERSE_RANGE FOR i IN a1'RANGE
SIGNAL a1: bit_vector(3 DOWNTO 0) ; ... PROCESS (a) BEGIN z<= "0000" : FOR i in 0 TO 3 LOOP IF (a = i) THEN z(i) <= '1' ; END IF ; END LOOP ; END PROCESS ; ...
Ausdrücke
Ausdruck
Definitionen
expression
Jeder Ausdruck entspricht einer Gleichung, die eine Vorschrift zur Berechnung eines Wertes bildet.
Logische Operatoren
Definition
Die logischen Operatoren AND , OR , NAND , NOR , XOR, XNOR und NOT sind für die vordefinierten Datentypen bit und boolean definiert. Sie können auch auf eindimensionale Feld-Typen ( Array ), deren Elemente vom Typ bit oder boolean sind, angewendet werden. Bei Anwendung der Operatoren AND , OR , NAND , NOR , XOR und XNOR ist im letzteren Fall folgendes zu beachten :
- Die beiden Felder müssen die gleiche Feldlänge haben.
- Die Operation wird mit den betreffenden Elementen beider Felder ausgeführt.
- Das Ergebnis ist ein Feld, das die gleiche Feldtiefe besitzt wie der linke Operand.
Entsprechendes gilt für den Operator NOT , wobei allerdings die Operation mit jedem einzelnen Element des Feldes durchgeführt wird. Alle binären logischen Operatoren besitzen die niedrigste Priorität. Der unäre Operator NOT hat höchste Priorität.
Wahrheitstafel
Das Symbol T steht für true (Typ boolean ), '1' (Typ bit ).
Das Symbol F steht für false (Typ boolean ), '0' (Typ bit ).
Relationale Operatoren
Definition
- Vergleichsoperatoren dienen zum Vergleichen der Operanden bezüglich der Gleichheit, Ungleichheit und Größenverhältnisse.
- Die Operanden müssen stets vom gleichen Typ sein.
- Das Ergebnis der Operation ist vom vordefinierten Typ boolean .
Anmerkungen
Bei einem Vergleich von diskreten Feldern werden die “linken” Werte verglichen! Vektoren z.B. werden also nach links ausgerichtet und verglichen. (“110” < “1000” ergibt also false, da nur die ersten drei Stellen ausschlaggebend sind)
Übersicht
Operator | Operation | Typ der Operanden | Typ des Ergebnisses |
---|---|---|---|
= | Gleichheit | beliebig | boolean |
/= | Ungleichheit | beliebig | boolean |
< <= > >= | Vergleich | jeder skalare Typ oder ein Feldtyp | boolean |
Shift Operatoren
Definition
Die Shift Operatoren sind vordefiniert für beliebige eindimensionale Felder mit den Elemententypen BIT oder BOOLEAN .
Die Operatoren sind folgendermaßen definiert, wobei L der linke Operand und R der rechte Operand ist:
- L sll R : Shifte L um R Positionen nach links (R≥0) bzw. rechts (R<0). Die vordersten (R≥0) bzw. hintersten (R<0) Werte “fallen weg” und der Wert T'LEFT wird nachgeschoben. T ist dabei der Typ der Elemente des Feldes.
- L srl R : Shifte L um R Positionen nach rechts (R≥0) bzw. links (R<0). Die hintersten (R≥0) bzw. vordersten (R<0) Werte “fallen weg” und der Wert T'LEFT wird nachgeschoben. T ist dabei der Typ der Elemente des Feldes.
- L sla R : Shifte L um R Positionen nach links (R≥0) bzw. rechts (R<0). Die vordersten (R≥0) bzw. hintersten (R<0) Werte “fallen weg” und der Wert L'RIGHT (R≥0) bzw. L'LEFT (R<0) wird nachgeschoben. Der letzte (R≥0) bzw. erste (R<0) Wert von L wird also nachgeschoben.
- L sra R : Shifte L um R Positionen nach rechts (R≥0) bzw. links (R<0). Die hintersten (R≥0) bzw. vordersten (R<0) Werte “fallen weg” und der Wert L'LEFT (R≥0) bzw. L'RIGHT (R<0) wird nachgeschoben. Der erste (R≥0) bzw. letzte (R<0) Wert von L wird also nachgeschoben.
- L rol R : Rotiere L um R Positionen nach links (R≥0) bzw. rechts (R<0). Die vordersten (R≥0) bzw. hintersten (R<0) Werte werden hinten (R≥0) bzw. vorne (R<0) nachgeschoben.
- L ror R : Rotiere L um R Positionen nach rechts (R≥0) bzw. links (R<0). Die hintersten (R≥0) bzw. vordersten (R<0) Werte werden vorne (R≥0) bzw. hinten (R<0) nachgeschoben.
Übersicht
Operator | Operation | Typ des linken Operanden | Typ des rechten Operanden | Typ des Ergebnisses |
---|---|---|---|---|
sll | Shift Left Logical | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
srl | Shift Right Logical | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
sla | Shift Left Arithmetic | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
sra | Shift Right Arithmetic | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
rol | Rotate Left Logical | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
ror | Rotate Right Logical | Beliebiges eindimensionales Feld mit Elementen des Typs BIT oder BOOLEAN | INTEGER | Typ des linken Operanden |
Addierende Operatoren
Definition
Die Additionsoperatoren + und - sind in ihrer bekannten Bedeutung für jeden numerischen Typ vordefiniert.
Der Verkettungsoperator (Concatination) & ist für beliebige eindimensionale Feldtypen vordefiniert.
Übersicht
Operator | Operation | Typ des linken Operanden | Typ des rechten Operanden | Typ des Ergebnisses |
---|---|---|---|---|
+ | Addition | beliebiger numerischer Typ | gleicher Typ | gleicher Typ |
- | Subtraktion | beliebiger numerischer Typ | gleicher Typ | gleicher Typ |
& | Verkettung (Concatination) | beliebiger Feldtyp | gleicher Feldtyp | gleicher Feldtyp |
beliebiger Feldtyp | Elementtyp | gleicher Feldtyp | ||
Elementtyp | beliebiger Feldtyp | gleicher Feldtyp | ||
Elementtyp | Elementtyp | beliebiger Feldtyp |
Ergänzung
Die Vorzeichen + und - sind für jeden numerischen Typ vordefiniert.
Nach den Prioritätsregeln für Ausdrücke darf ein Vorzeichenoperand nicht Multiplikationsoperatoren, dem Exponentialoperator ** oder den Operatoren ABS und NOT folgen.
Z. B. sind folgende Ausdrücke syntaktisch falsch :
- A / +B
- A ** -B
Erlaubt sind jedoch Ausdrücke der folgenden Form :
- A / (+B)
- A ** (-B)
Multiplizierende Operatoren
Definition
Die Multiplikationsoperatoren * und / sind in ihrer bekannten Bedeutung für jeden Integer- und Fließkommatyp vordefiniert.
Die Operatoren MOD und REM sind für beliebige Integer-Typen vordefiniert.
Das Ergebnis jeder Operation ist vom gleichen Typ wie die (typgleichen) Operanden.
Übersicht 1
Operator | Operation | Typ des linken Operanden | Typ des rechten Operanden | Typ des Ergebnisse |
---|---|---|---|---|
* | Multiplikation | beliebiger Integer-Typ | gleicher Typ | gleicher Typ |
beliebiger Fließkomma-Typ | gleicher Typ | gleicher Typ | ||
/ | Division | beliebiger Integer-Typ | gleicher Typ | gleicher Typ |
beliebiger Fließkomma-Typ | gleicher Typ | gleicher Typ | ||
MOD | Modulo | beliebiger Integer-Typ | gleicher Typ | gleicher Typ |
REM | Rest | beliebiger Integer-Typ | gleicher Typ | gleicher Typ |
Ergänzungen
Die Operatoren * und / sind für jeden beliebigen physikalischen Typ vordefiniert.
Übersicht 2
Operator | Operation | Typ des linken Operanden | Typ des rechten Operanden | Typ des Ergebnisse |
---|---|---|---|---|
* | Multiplikation | beliebiger physikalischer Typ | integer | gleicher Typ wie linker Operand |
beliebiger physikalischer Typ | real | gleicher Typ wie linker Operand | ||
integer | beliebiger physikalischer Typ | gleicher Typ wie rechter Operand | ||
real | beliebiger physikalischer Typ | gleicher Typ wie rechter Operand | ||
/ | Division | beliebiger physikalischer Typ | integer | gleicher Typ wie linker Operand |
beliebiger physikalischer Typ | real | gleicher Typ wie linker Operand | ||
beliebiger physikalischer Typ | gleicher Typ | universal integer |
Verschiedene Operatoren
Definition
Der unäre Operator ABS ist für jeden numerischen Typ vordefiniert.
Der Potenzoperator ** ist für jeden Integer-und Fließkommatyp vordefiniert. Der rechte Operand, der Exponent, ist stets vom vordefinierten Typ integer .
Der Operator ABS
Operator | Operation | Typ des Operanden | Typ des Ergebnisses |
---|---|---|---|
ABS | absoluter Wert | beliebiger numerischer Typ | gleicher Typ |
Der Operator **
Operator | Operation | Typ des linken Operators | Typ des rechten Operators | Typ des Ergebnisses |
---|---|---|---|---|
** | Potenz | beliebiger Integer-Typ | integer | gleicher Typ wie linker Operand |
beliebiger Fließkomma-Typ | integer | gleicher Typ wie linker Operand |
Anmerkung
Das Potenzieren mit negativen Exponenten ist nur möglich, wenn der linke Operand ein Fließkomma-Typ ist.
Buchstabensymbole (Literal)
Beispiele
Ein Literal vom Typ universal_real (abstrakter Typ).
3.14159_26536
Ein Literal vom Typ universal_integer (abstrakter Typ).
5280
Ein Literal von einem physikalischen Typ.
10.7 ns
Ein Literal vom Typ bit_string .
O"4777"
Ein Literal vom Typ string .
"54LS281"
Ein String -Literal, das ein leeres Feld darstellt.
""
Aggregate
Beispiele
Dieses Aggregat besitzt die Breite 4.
(a_bit, b_bit, c_bit, d_bit)
Mit diesem Aggregat kann man den einzelnen Elementen eines Feldes unterschiedliche Werte zuweisen.
(7=>'1', 5 downto 1 => '1', 6 => b_bit, others => '0')
Mit diesem Aggregat kann man allen einzelnen Elementen eines zweidimensionalen Feldes den Wert 0 zuweisen.
(others => (others => '0'));
Funktionsaufruf
Beispiele
Durch diesen Funktionsaufruf erhält exnor_out den Rückgabewert der Funktion exnor .
exnor_out <= exnor(in1, in2);
x2 erhält den Rückgabewert der Funktion exnor . Die Übergabeparameter a und b besitzen dabei die Werte der angegebenen Vektorbereiche.
x2 <= exnor ( a => in1(2 downto 0), b => in2(2 downto 0) );
i erhält die Summe der Rückgabewerte der beiden Funktionen bit_to_integer und count_ones .
i <= bit_to_integer(bit_a => in(8)) + count_ones(in2);
Qualified Expression
Beispiel
Durch die qualifizierten Ausdrücke wird der Typ des jeweiligen Return-Wertes explizit ausgewählt und damit auch die passende '='-Funktion.
w <= (a=b) = (c=d); x <= (a=b) = mvl4'(c=d); y <= (a=b) = bit'(c=d); z <= (a=b) = boolean'(c=d);
Durch den qualifizierten Ausdruck wird aus zwei Einzelbittypen ein Vektor mit dem (Unter-) Typ vec_type gebildet, dessen Wert in der case-Anweisung überprüft wird
CASE vec_type'(A & B) is when "00" => VALUE <= 0; when "01" => VALUE <= 1; when "10" => VALUE <= 2; when "11" => VALUE <= 3; when others => VALUE <= 9; end case;
Typenkonvertierung
Beispiele
Die float_varibale wird durch Abrunden bzw. Aufrunden in den Typ integer umgewandelt
integer(float_varibale)
Die integer_variable wird in den Typ real umgewandelt.
real(integer_variable)
Allocator
Beispiele
Es wird Speicher für den Typ node allokiert. Bei der ersten Variante wird der Default-Wert des Typs node zur Initialisierung verwendet, bei den anderen die in den Klammern angegebenen Werte.
NEW node NEW node'( 15 ns, NULL ) NEW node'( delay => 5 ns, next => stack )
Durch die Initialisierung mit “01100010” wird die Breite des allokierten Objektes auf 8 festgelegt.
NEW bit_vector'( "01100010" )
Hier wird die Größe des allokierten Speicherbereichs durch die Festlegung der Stringbreite (10) begrenzt.
NEW string( 1 TO 10 )
Statischer Ausdruck
Definition
Es gibt zwei Kategorien von statischen Ausdrücken.
Ein Ausdruck ist genau dann lokal statisch , wenn jeder Operator in diesem Ausdruck ein implizit definierter Operator ist, die Operanden sowie die Ergebnisse skalar sind und jedes Primary in diesem Ausdruck ein local static Primary ist; als local static Primaries gelten:
- Werte jeglichen Typs außer dem Typ TIME .
- Konstanten, die explizit durch eine Konstantendeklaration deklariert und mit einem lokal statischen Ausdruck initialisiert sind. (NICHT verschobene (deferred) Konstanten).
- Ein Alias dessen Name-Part ein lokal statisches Primitiv ist.
- Funktionsaufrufe, deren Namen einen vordefinierten Operator darstellen und deren aktuelle Parameter jeweils lokal statische Ausdrücke sind.
- Vordefinierte Attribute welche einen Wert liefern (außer `PATH_NAME ) und dessen Prefix entweder einen lokal statischen Untertyp besitzen oder ein Objektname eines lokal statischen Untertyp sind.
- Vordefinierte Attribute, außer ` LAST_EVENT , ` LAST_ACTIVE , ` LAST_VALUE , ` DRIVING und ` DIRIVNG_VALUE , von lokal statischen Untertypen, die einen Funktionsaufruf darstellen, in dem die aktuellen Parameter jeweils lokal statische Ausdrücke sind.
- Benutzerdefinierte Attribute, deren Werte durch lokal statische Ausdrücke definiert werden.
- Qualifizierte Ausdrücke, deren Ergebnisse lokal statische Untertypen sind und deren Operanden lokal statische Ausdrücke sind.
- Eine Typenkonversion dessen Ausdruck lokal statisch ist.
- Lokale statische Ausdrücke, die in Klammern gefaßt sind.
Ein Ausdruck ist genau dann global statisch (nicht dynamisch elaboriert), wenn jeder Operator in diesem Ausdruck eine reine Funtion ist und jedes Primary in diesem Ausdruck ein global static Primary ist; als global static Primaries gelten:
- Werte vom Typ TIME .
- Lokal statische Primaries
- Generische Konstanten
- Generische Parameter
- Konstanten, inklusive verschobene (deferred) Konstanten.
- Aliases, dessen Name ein global statisches Primary ist.
- Feld-Aggregate von global statischen Untertypen, deren Elemente nur aus global statischen Ausdrücken bestehen und deren Elemente nur global statische Bereiche (ranges) haben.
- Record-Aggregate, dessen Elemente alle global statische Ausdrücke sind.
- Funktionsaufrufe, deren Namen eine reine Funktion darstellen und deren aktuelle Parameter jeweils global statische Ausdrücke sind.
- Vordefinierte Attribute, welchen einen Wert darstellen und dessen Prefix entweder ein global statischer Untertyp ist oder ein Objekt oder Funktionsaufruf, die von einem global statischen Untertyp sind.
- Vordefinierte Attribute, welche eine Funktion außer `EVENT, `ACTIVE, `LAST_EVENT, `LAST_ACTIVE, `LAST_VALUE, `DRIVING oder `DRIVING_VALUE darstellen, dessen Prefix entweder ein global statischer Untertyp ist oder ein Objekt oder Funktionsaufruf, die von einem global statischen Untertyp sind, und dessen tatsächlichen Parameter (falls vorhanden) global statische Ausdrücke sind.
- Benutzerdefinierte Attribute, deren Werte durch global statische Ausdrücke definiert werden.
- Qualifizierte Ausdrücke, dessen Operand ein global statischer Ausdruck ist.
- Typenkonvertierung, dessen Ausdruck eine global statischer Ausdruck ist.
- Ein Zeiger der ersten Form (See Allocator) dessen Untertypekennzeichnung einen global statischen Untertypen bezeichnet.
- Ein Zeiger der zweiten Form, dessen qualifizierter Ausdruck ein global statischer Ausdruck ist.
- Global statische Ausdrücke, die in Klammern gefaßt sind.
- Ein Unterelement oder ein Feldausschnitt eines global statischen Primary, vorrausgesetzt, daß jeder Indexausdruck global statisch Ausdrücke sind und jeder diskrete Bereich des entsprechenden Feldausschnitts global statische diskrete Bereiche sind.
Anmerkungen
An Stellen wo nur “statisch” steht, kann lokal oder global statisch eingesetzt werden.
Die Regeln für lokal und global statische Ausdrücke implizieren, daß eine Konstante oder auch ein Generic mit einem nichtstatischen Ausdruck initialisiert werden können; die Konstante selber kann aber trotzdem lokal oder global statisch sein. Nur für Schnittstellenbkonstanten, Variablen und Signaldeklarationen gilt, daß ein vorhandener Initialisierungsausdruck lokal oder global statisch sein muß.
Universeller Ausdruck
Definition
Ein universeller Ausdruck ist ein Ausdruck, der als Ergebnis entweder den Typ universal integer oder universal real liefert.
Übersicht
Operator | Operation | Typ des linken Operanden | Typ des rechten Operanden | Typ des Ergebnisses |
---|---|---|---|---|
* | Multiplikation | universal_real | universal_integer | universal_real |
universal_integer | universal_real | universal_real | ||
/ | Division | universal_real | universal_integer | universal_real |
Sequentielle Anweisungen
Wait
Anmerkungen
Die WAIT-Anweisung darf nicht innerhalb einer Funktion oder einer Prozedur verwendet werden, die selbst innerhalb einer Funktion aufgerufen wird.
Die WAIT-Anweisung darf nicht von einem Prozess, der eine 'sensitivity list' besitzt, aufgerufen werden.
Im allgemeinen ist die WAIT-Anweisung sensitiv auf die benutzten Signale, außer es wird explizit eine Sensitivityliste angegeben (Wie dies bei der WAIT ON Anweisung der Fall ist; siehe letztes Beispiel).
In einem postponed process kann die Bedingung innerhalb einer WAIT Anweisung schon wieder unwahr sein, wenn der Prozeß dann tatsaechlich weiter abgearbeitet wird (eben erst im letzten Delat Zyklus).
Beispiele
Der Prozess wird auf Dauer unterbrochen.
WAIT ;
Der Prozess wird für 5 ns unterbrochen.
WAIT FOR 5 ns ;
Der Prozess wird solange unterbrochen, bis sich der Wert eines der beiden Signale ändert.
WAIT ON sig_1, sig_2 ;
Der Prozess wird solange unterbrochen, bis ein Ereignis an clock auftritt und der Wert von clock gleich 1 ist.
WAIT UNTIL clock = '1' ;
Der Prozess wird solange unterbrochen, bis der Wert von data gleich good ist oder 25 ns vergangen sind.
WAIT UNTIL data = good FOR 25 ns ;
Hier wird zunächst auf eine Änderung einer der Signale sig_1, sig_2, sig_3 gewartet; besitzt clock den Wert 1, wird der Prozeß reaktiviert. Die maximale Unterbrechungsdauer ist 25 ns.
WAIT ON sig_1, sig_2, sig_3 UNTIL clock = '1' FOR 25 ns ;
Assertion
Anmerkungen
Der REPORT Ausdruck muß vom Typ string sein.
Wird der REPORT Part weggelassen, so wird der vorgegebene Ausdruck “Assertion violation” verwendet.
Der SEVERITY Ausdruck muß vom Typ severity_level sein. Mögliche Werte sind: note, warning, error, failure.
Wird der SEVERITY Part weggelassen, wird der vorgegebene Ausdruck error verwendet.
Beispiele
Es wird überprüft, ob signal_reset ungleich 1 ist.
ASSERT signal_reset = '1' ;
Wenn variable_reset ungleich 1 ist, wird die Meldung “Reset ist aktiv !” ausgegeben.
ASSERT variable_reset = '1' REPORT "Reset is active !" ;
Wenn die zu überprüfende Bedingung nicht erfüllt ist wird eine Fehlermeldung ausgegeben und entsprechend der Severity-Stufe Aktionen durchgeführt.
ASSERT reset = '1' OR set = '1' REPORT "Reset and Set" & "simultaneously active !" SEVERITY failure ;
Wenn data ungleich 0 ist, wird nur eine Fehlermeldung ( SEVERITY note) mit dem aktuellen Wert von data ausgegeben.
ASSERT data = 0 REPORT "Datum ist gleich " & integer_to_string( data ) & " !" SEVERITY note ;
Diese Assertion führt automatisch (wegen false) zum Ende der Simualtion (Severitylevel=failure), wenn sie ausgeführt wird.
ASSERT false REPORT "End of simulation!" SEVERITY failure ;
Report
Anmerkungen
Der REPORT Ausdruck muß vom Typ string sein.
Der SEVERITY Ausdruck muß vom Typ severity_level sein. Mögliche Werte sind: note, warning, error, failure.
Wird der SEVERITY Part weggelassen, wird der vorgegebene Ausdruck note verwendet.
Beispiele
Dieser Report führt zum Ende der Simualtion (Severitylevel=failure), wenn sie ausgeführt wird.
REPORT "End of simulaion!" SEVERITY failure ;
Dieser Report meldet das Betreten eines Prozesses.
REPORT "Entering process clkdiv" ;
Signalzuweisung ... <= ..."
Ergänzungen
Das Schlüßelwort unaffected darf nur in nebenläufigen Signalzuweisungen auftauchen.
Voreingestellter Verzögerungsmechanismus ist inertial .
Beim transport Verzögerungsmechanismus werden alle Pulse durchgelassen
Beim inertial Verzögerungsmechanismus werden nur Pulse durchgelassen, die breiter als eine vorgegeben Grenze sind. Diese Grenze wird durch den Wert nach reject oder den ersten Zeitwert in der Waveform bestimmt.
Der Wert hinter reject darf nicht größer als der erste Zeitwert der Waveform sein.
Beispiele
Der Wert von B wird nach 5 ns dem Signal A zugewiesen.
Im ersten Fall wird das InertialVerzögerungsmodell verwendet, im zweiten Fall das Transportverzögerungsmodell.
A <= B AFTER 5 ns; A <= TRANSPORT B AFTER 5 ns;
Dem Signal data wird eine Waveform zugewiesen, nach der data nach 1 ns den Wert 2 , nach 3 ns den Wert 4 und nach 8 ns den Wert 10 erhält.
data <= 2 AFTER 1 ns, 4 AFTER 3 ns, 10 AFTER 8 ns;
Dem Signal A wird jeweils mit dem Inertialverzögerungsmodell das Ergebnis der Funktion my_function zugewiesen.
Dies geschieht bei der ersten Variante nach 5 ns, bei der zweiten und dritten Variante nach einer Zeit, die durch die Konstante delay festgelegt wird. Bei der dritten Variante wird 2 ns nach der vorhergehenden Zuweisung der Wert 0 an A übergeben.
A <= my_function(data, 4) AFTER 5 ns; A <= my_function(data, 4) AFTER delay; A <= my_function(data, 4) AFTER delay, 0 AFTER delay + 2 ns;
Diese Zuweisungen sind alle equivalent. Der Wert von input wird mit 6 ns Verzögerung an output weitergegeben. Pulse kleiner 6 ns werden unterdrückt.
ouptut <= input AFTER 6 ns; output <= INERTIAL input AFTER 6 ns; output <= REJECT 6 ns INERTIAL input AFTER 6 ns;
Hier ist die Pulsbreite anders als der erste Zeitwert der Waveform. So werden alle Signale mit einer Pulsbreite kleiner 3 ns unterdrückt.
output1 <= REJECT 3 ns INERTIAL input1 AFTER 6 ns; output2 <= REJECT 3 ns INERTIAL input2 AFTER 6 ns, NOT input2 AFTER 12 ns;
Die Signalzuweisungen an output1 und output2 sind equivalent den Zuweisungen an output3 und output4 .
Keine Signalpulse werden unterdrückt.
output1 <= TRANSPORT input1 AFTER 6 ns; output2 <= TRANSPORT input2 AFTER 6 ns, NOT input2 AFTER 12 ns; output3 <= REJECT 0 ns INERTIAL input1 AFTER 6 ns; output4 <= REJECT 0 ns INERTIAL input2 AFTER 6 ns NOT input2 AFTER 12 ns;
In VHDL'87 mußte die obere Form der Signalzuweisungen gewählt werden. Die beiden Zuweisungsvarianten equivalent.
-- VHDL'87 sig2 <= input AFTER 3 ns; output <= TRANSPORT sig2 AFTER 9 ns; -- VHDL'93 output <= REJECT 3 ns INERTIAL input AFTER 12 ns;
Variablenzuweisung ... := ..."
Beispiele
var erhält den Wert 0 .
var := 0;
a erhält den aktuellen Wert von b .
a := b;
a erhält als neuen Wert das Ergebnis der Funktion my_function .
a := my_function ( data, 4 );
str_a wird ein String zugewiesen, der aus drei verknuepften Teilen besteht.
str_a := "Mein Name ist " & get_name & ", und Ihrer ?";
var_int erhält als Wert das Ergebnis der rechten Gleichung.
var_int := my_function( data, 4 ) + 4 * a_function(var_int) - 2 ** data;
Prozeduraufruf
Beispiele
Die Prozedur a_proc wird aufgerufen; sie besitzt keine Übergabeparameter.
a_proc ;
Die Prozedur my_proc wird mit den Übergabeparametern sig_1 , sig_2 , var_3 aufgerufen.
my_proc( sig_1, sig_2, var_3 ) ;
Die Prozedur another_proc wird mit den Übergabe- parametern var_1 , var_2 , q aufgerufen.
another_proc( var_1, var_2, q => const_3 ) ;
Die Prozedur register_proc wird mit den explizit über Namen zugewiesenen Übergabeparametern ck , d , q aufgerufen.
register_proc( ck => clock, d => reg_in, q => reg_out ) ;
IF
Beispiele
Besitzt a den Wert 1 , so wird b der Wert 0 zugewiesen.
IF a = '1' THEN b := '0' ; END IF ;
Ist der Wert von a größer als 0 , erhält b den Wert von a , ansonsten den Wert von ABS ( a + 1 ).
IF a > 0 THEN b := a ; ELSE b := ABS ( a + 1 ) ; END IF ;
Dies ist ein Beispiel für eine komplette IF - ELSIF -Schleife. Die Bedingungen werden nacheinander überprüft. Bei der ersten Übereinstimmung werden die zugehörigen Aktionen ausgeführt und danach die IF -Schleife verlassen.
IF val >= 5 AND val < 10 THEN int := 7 ; ELSIF val < 5 THEN int := val + func( val + 2 ) ; ELSIF val < 15 THEN int := func( val ) ; ELSE int := 0 ; END IF ;
CASE
Beispiele
Der Wert des Bits a wird überprüft. Ist er 0 , wird s der Wert 0000 nach 2 ns zugewiesen, ansonsten der Wert 1111 , ebenfalls nach 2 ns.
CASE a IS WHEN '0' => s <= "0000" AFTER 2 ns ; WHEN '1' => s <= "1111" AFTER 2 ns ; END CASE ;
Der Wert des Integers int_value wird überprüft. Ist er 0 , wird int der Wert 5 zugewiesen, ist er 1 , 2 oder 8 , bekommt int den Wert von int_value , ist er zwischen 3 und 7 bekommt int den Wert int_value + 5 , ist er 9 , dann wird keine Aktion ausgeführt. Für alle anderen Werte von int_value wird int der Wert 0 zugewiesen.
CASE int_value IS WHEN 0 => int := 5 ; WHEN 1 | 2 | 8 => int := int_value ; WHEN 3 TO 7 => int := int_value+5; WHEN 9 => NULL ; WHEN OTHERS => int := 0 ; END CASE ;
Abhängig vom Wert des Ausdrucks two_bit '( a_enable & b_enable ) wird s der entsprechchende Wert nach einer bestimmten Zeitverzögerung zugewiesen.
CASE two_bit'( a_enable & b_enable ) IS WHEN "00" => s <= zero AFTER 1 ns ; WHEN "10" => s <= a AFTER 1 ns ; WHEN "01" => s <= b AFTER 2 ns ; WHEN "11" => s <= one AFTER 1 ns ; END CASE ;
LOOP
Beispiele
Dies ist eine Endlosschleife, in der bei Erfüllen der Bedingung clock='1' dem Signal q der Wert von d nach 1 ns zugewiesen wird.
LOOP WAIT UNTIL clock = '1' ; q <= d AFTER 1 ns ; END LOOP ;
Diese mit einem Label versehene Schleife wird sechs mal durchlaufen, wobei der Wert von var jeweils um 5 erhöht wird.
lbl : FOR i IN 0 TO 5 LOOP var := var + 5 ; END LOOP ;
Die While-Schleife wird durchlaufen, solange value > 0 gilt. Die Anweisungen innerhalb der Schleife werden für den Fall value = 3 übersprungen.
WHILE value > 0 LOOP NEXT WHEN value = 3 ; tab( value ) := value REM 2 ; value := value / 2 ; END LOOP ;
Dies sind zwei Beispiele für verkettete FOR -Schleifen, die zur Berechnung der Werte der Elemente eines zweidimensionalen Feldes benötigt werden.
In der zweiten Variante besitzen die FOR -Schleifen jeweils ein eigenes Label. Mit der EXIT -Anweisung wird die innere Schleife verlassen, wenn i = j gilt.
FOR i IN 10 DOWNTO 2 LOOP FOR j IN 0 TO i LOOP table( i, j ) := i + j - 7 ; END LOOP ; END LOOP ;
lbl_1 : FOR i IN 10 DOWNTO 2 LOOP lbl_2 : FOR j IN 0 TO i LOOP EXIT lbl_2 WHEN i = j ; table ( i, j ) := i + j - 7 ; END LOOP lbl_2 ; END LOOP lbl_1 ;
NEXT
Beispiele
In beiden Beispielen werden die Anweisungen nach der NEXT -Anweisung ignoriert, wenn value = 3 gilt.
In der ersten Variante wird dies durch eine bedingte NEXT -Anweisung erreicht, während in der zweiten Variante eine unbedingte NEXT -Anweisung in eine IF -Schleife eingebaut worden ist.
WHILE value > 0 LOOP NEXT WHEN value = 3 ; tab( value ) := value REM 2 ; value := value / 2 ; END LOOP ;
WHILE value > 0 LOOP IF value = 3 THEN NEXT ; END IF ; tab( value ) := value REM 2 ; value := value / 2 ; END LOOP ;
Dies sind zwei Beispiele für verkettete FOR -Schleifen, die zur Berechnung der Werte der Elemente eines zweidimensionalen Feldes benötigt werden.
In der ersten Variante werden für i = j die nachfolgenden Anweisungen der inneren Schleife übergangen.
In der zweiten Variante wird für i = j mit dem nächsten Durchlauf der äußeren Schleife weitergemacht.
lbl_1 : FOR i IN 10 DOWNTO 2 LOOP lbl_2 : FOR j IN 0 TO i LOOP NEXT lbl_2 WHEN i = j ; table ( i, j ) := i + j - 7 ; END LOOP lbl_2 ; END LOOP lbl_1 ;
lbl_1 : FOR i IN 10 DOWNTO 2 LOOP lbl_2 : FOR j IN 0 TO i LOOP NEXT lbl_1 WHEN i = j ; table ( i, j ) := i + j - 7 ; END LOOP lbl_2 ; END LOOP lbl_1 ;
EXIT
Beispiele
In beiden Beispielen werden die Schleifen mit der EXIT -Anweisung verlassen, wenn value = 0 gilt.
In der ersten Variante wird dies durch eine bedingte EXIT -Anweisung erreicht, während in der zweiten Variante eine unbedingte EXIT -Anweisung in eine IF -Schleife ein-gebaut worden ist.
LOOP EXIT WHEN value = 0 ; tab( value ) := value REM 2 ; value := value / 2 ; END LOOP ;
LOOP IF value = 0 THEN EXIT ; END IF ; tab( value ) := value REM 2 ; value := value / 2 ; END LOOP ;
Dies sind zwei Beispiele für verkettete FOR -Schleifen, die zur Berechnung der Werte der Elemente eines zweidimensionalen Feldes benötigt werden.
In der ersten Variante wird für i = j die innere Schleife verlassen. In der zweiten Variante wird für i = j die äußere Schleife verlassen.
lbl_1 : FOR i IN 10 DOWNTO 2 LOOP lbl_2 : FOR j IN 0 TO i LOOP EXIT lbl_2 WHEN i = j ; table ( i, j ) := i + j - 7 ; END LOOP lbl_2 ; END LOOP lbl_1 ;
lbl_1 : FOR i IN 10 DOWNTO 2 LOOP lbl_2 : FOR j IN 0 TO i LOOP EXIT lbl_1 WHEN i = j ; table ( i, j ) := i + j - 7 ; END LOOP lbl_2 ; END LOOP lbl_1 ;
RETURN
Anmerkung
Ein Funktionskörper muß eine RETURN -Anweisung beinhalten.
Nach der BNF Definition des Prozeßes wird auch hier jede sequentielle Anweisung zugelassen, allerdings wird eine RETURN Anweisung in Prozessen nicht von Tools unterstützt.
Beispiele
Es wird kein Wert zurückgegeben.
RETURN ;
Rückgabewert ist der von value .
RETURN value ;
Rückgabewert ist das Ergebnis der Funktion my_function .
RETURN my_function( data, 5 pF ) ;
Rückgabewert ist die Summe a + b + 5 ns .
RETURN a + b + 5 ns ;
Rückgabewert ist ein verknüpfter String.
RETURN "author name : " & name ;
NULL
Beispiel
Durch die NULL -Anweisung wird explizit erwirkt, daß keine Aktion ausgeführt wird.
NULL ;
Nebenläufige Anweisungen
Block
Beispiele
Dieser einfache Block besitzt einen Label und im Anweisungsteil eine verzögerte Signalzuweisung.
b : BLOCK BEGIN s <= '1' AFTER 2 ns ; END BLOCK b ;
Diese Block besitzt zusätzlich einen Header, in dem das Signal int deklariert wird.
c : BLOCK SIGNAL int : bit_vector( 1 TO 3 ) := "010" ; BEGIN s <= int AFTER 5 ns ; END BLOCK c ;
In diesem Block wird eine kontrollierte Signalzuweisung verwendet. Ist die Bedingung clock = '1' nicht erfüllt, so wird die Signalzuweisung nicht ausgeführt.
latch : BLOCK ( clock = '1' ) BEGIN latch_output <= GUARDED latch_input AFTER 1 ns ; END BLOCK latch ;
Dieser Block besitzt eigenständige Ein-/Ausgänge, die über die PORT MAP mit den übergeordneten Signalen verbunden werden.
lbl : BLOCK PORT ( a, b : INOUT bit ) ; PORT MAP ( a => s1, b => s2 ) ; BEGIN b <= a AFTER 1 ns ; a <= b AFTER 1 ns ; END BLOCK lbl ;
Prozeß
Anmerkungen
Alternativ zur Sensitivity-List nach dem Schlüsselwort PROCESS kann am Ende des Prozesses folgende Wait Anweisung stehen: WAIT ON sensitivity_list ;
Ein Prozeß darf nur eine Sensitivity-List ODER eine bzw. mehrere explizite WAIT-Anweisungen enthalten.
Eine PROCESS -Anweisung innerhalb eines ENTITY -Anweisungsteiles muß eine passive PROCESS -Anweisung sein.
Ein Prozeß mit dem Schlüsselwort POSTPONED wird als “Postponed Process” bezeichnet. Dieser wird immer (soweit nur ein postponed process existiert) im letzten Delta Zyklus eines Simulationszykluses abgearbeitet. Dies schließt ein, daß also gegebenenfalls nur Signalzuweisungen mit Verzögerungen erlaubt sind (Ansonsten könnten noch weitere Prozesse in nachfolgenden Delta Zyklen abgearbeitet werden).
Beispiele
Dieser Prozeß beschreibt ein FlipFlop.
Durch die WAIT -Anweisung und die Überprüfung der Bedingung clock = '1' wird die positive Takflanke detektiert. 2 ns nach der Taktflanke liegt am Ausgang q der Wert vom Eingang d an.
PROCESS BEGIN IF ( clock = '1' ) THEN q <= d AFTER 2 ns ; END IF ; WAIT ON clock ; END PROCESS ;
Dieser benamte Prozeß beschreibt ebenfalls ein FlipFlop.
Durch die Sensitivity-List und die Überprüfung der Bedingung clock = '1' wird die positive Takflanke detektiert. 1 ns nach der Taktflanke liegt am Ausgang q der Wert vom Eingang d an.
reg : PROCESS ( clock ) BEGIN IF clock = '1' THEN q <= d AFTER 1 ns ; END IF ; END PROCESS reg ;
Dies ist ein Beispiel für einen passiven Prozeß.
Mit der positiven Takflanke wird nur die Bedingung reset = '1' überprüft und gegebenenfalls eine Warnung ausgegeben.
passive : PROCESS BEGIN WAIT ON clock ; IF clock = '1' THEN ASSERT reset = '1' ; REPORT "reset is active!" ; SEVERITY warning ; END IF ; END PROCESS passive ;
Dieser Prozeß beinhaltet zwei WAIT - Anweisungen.
Die erste WAIT -Anweisung bewirkt eine Unterbrechung, bis sig_2 = 0 ist, während die zweite WAIT -Anweisung ein Warten auf eine Veränderung einer der beiden Signal sig_1 oder sig_2 bewirkt.
PROCESS VARIABLE v1, v2 : integer := 1 ; BEGIN sig_1 <= v1 AFTER 1 ns ; WAIT UNTIL sig_2 = 0 ; v2 := v2 * 2 ; v1 := v2 + 4 ; sig_1 <= v1 AFTER 1 ns ; WAIT ON sig_1, sig_2 ; FOR i IN 1 TO 3 LOOP v1 := v1 + v2 ; END LOOP ; END PROCESS ;
Ein postponed process, der ein Signalwert übeprüfen soll, wird definiert.
POSTPONED PROCESS (testsig) BEGIN ASSERT testsig=expected_value REPORT "testsig differs from" & "expected value!" SEVERITY error ; END POSTPONED PROCESS ;
Nebenläufiger Prozeduraufruf
Anmerkungen
Für jeden nebenläufigen Prozeduraufruf gibt es einen equivalenten Prozeß.
Der equivalente Prozeß eines nebenläufigen Prozedurausrufs mit dem Schlüßelwort POSTPONED ist ein postponed process.
Ein nebenläufiger Prozeduraufruf innerhalb eines ENTITY -Anweisungsteiles muß ein passiver nebenläufiger Prozeduraufruf sein.
Beispiele
Prozeduraufruf ohne Übergabeparamter.
a_proc ;
Benamter Prozeduraufruf mit über Position verbundenen Übergabeparametern.
lab : my_proc( sig_1, sig_2, sig_3 ) ;
Prozeduraufruf mit über explizite Zuweisung verbundenen Übergabeparametern.
register_proc( ck => clock, d => reg_in, q => reg_out ) ;
Prozeduraufruf mit Übergabeparametern, die über Position oder explizite Zuweisung verbunden werden.
another_proc( sig_1, sig_2, q => sig_3);
Dieses Beispiel verdeutlicht, daß ein nebenläufiger Prozeduraufruf gleich einem Prozeß ist, der als Anweisungsteil nur den Aufruf der Prozedur enthält.
check_timing( tplh, tphl, clk, d, q ) ; -- concurrent procedure call PROCESS -- corresponding process BEGIN check_timing( tplh, tphl, clk, d, q); WAIT ON clk, d, q ; END PROCESS ;
Nebenläufige Assertion
Anmerkungen
Für jede nebenläufige Assertion gibt es einen equivalenten (passiven) Prozeß.
Der equivalente (passive) Prozeß einer nebenläufigen Assertion mit dem Schlüßelwort POSTPONED ist ein postponed process.
Besitzt eine nebenläufige Assertion eine statische Bedingung, so wird die Assertion nur ein einziges mal zu Begin der Simulation ausgeführt.
Beispiele
Dies sind unterschiedliche Beispiele für Assertions.
Es wird immer eine Bedingung überprüft ( ASSERT ) und gegebenfalls bei Nichterfüllung eine Meldung ( REPORT ) ausgegeben. Der SeverityLevel bestimmt, welche Aktionen ausgeführt werden, wenn die zu überprüfende Bedingung nicht erfüllt wird.
ASSERT reset = '1' ;
ASSERT reset = '1' REPORT "Reset ist aktiv !" ;
lbl : ASSERT reset = '1' REPORT "Reset ist aktiv !" SEVERITY warning ;
latch_check : ASSERT reset = '1' OR set = '1' REPORT "Reset und Set sind" & "gleichzeitig aktiv !" SEVERITY failure ;
lbl : ASSERT data = 0 REPORT "Datum ist gleich " & integer_to_string ( data ) & " !" SEVERITY note ;
Nebenläufige Signalzuweisung "... <= ..."
Ergänzungen
Zu einer bedingten Signalzuweisung existiert eine äquivalente Prozessanweisung, wie dies i.a. für alle nebenläufige Zuweisungen gilt.
Der equivalente Prozeß einer nebenläufigen Signalzuweisung mit dem Schlüßelwort POSTPONED ist ein postponed process.
Hat die bedingte Signalzuweisung die Form
target <= options waveform_1 WHEN condition_1 ELSE waveform_2 WHEN condition_2 ELSE . . . waveform_n-1 WHEN condition_n-1 ELSE waveform_n ;
dann hat die Signalzuweisung in der zugehörigen Prozessanweisung die Form
IF condition_1 THEN target <= wave_transform_1 ; ELSIF condition_2 THEN target <= wave_transform_2 ; . . . ELSIF condition_n-1 THEN target <= wave_transform_n-1 ; ELSE target <= wave_transform_n ; END IF ;
Ist die (bedingte) Waveform eine einfache Waveform, so hat die Signalzuweisung in der zugehörigen Prozessanweisung die Form
target <= wave_transform ;
Die Prozeßanweisung der wave_transform einer waveform der Form
waveform_element1, waveform_element1, ..., waveform_elementN
besitzt die Form
target <= [delay_mechanism] waveform_element1, waveform_element1, ..., waveform_elementN ;
Die Prozeßanweisung einer wave_transform einer waveform der Form
unaffected
besitzt die Form
null ;
null ist hier eine null-Anweisung, keine null-Transaktion!
Die Charakteristika der Waveformen und die in der Signalzuweisung enthaltenen Bedingungen müssen so formuliert sein, daß die IF-Anweisung in der zugehörigen Prozessanweisung eine erlaubte Anweisung ist.
Zu einer auswählenden Signalzuweisung existiert eine äquivalente Prozessanweisung. Hat die auswählende Signalzuweisung die Form
WITH expression SELECT target <= options waveform_1 WHEN choice_list_1 , waveform_2 WHEN choice_list_2 , . . . waveform_n-1 WHEN choice_list_n-1 , waveform_n WHEN choice_list_n ;
dann hat die Signalzuweisung in der zugehörigen Prozessanweisung die Form
CASE expression IS WHEN choice_list_1 => target <= wave_transform_1 ; WHEN choice_list_2 => target <= wave_transform_2 ; . . . WHEN choice_list_n-1 => target <= wave_transform_n-1 ; WHEN choice_list_n => target <= wave_transform_n ; END CASE ;
Zu wave_transform siehe vorhergehenden Punkt zur bedingten Signalzuweisung.
Die Charakteristika des Auswahlausdruckes, der Waveformen und die in der Signalzuweisung enthaltene Auswahlbedingungen müssen so formuliert sein, daß die CASE -Anweisung in der zugehörigen Prozessanweisung eine erlaubte Anweisung ist.
Falls die Option GUARDED in der Signalzuweisung enthalten ist, liegt eine sog. kontrollierte Zuweisung vor. Ist hierbei das Zielobjekt (target) ebenfalls kontrolliert, dann lautet der Anweisungsteil der zugehörigen Prozessanweisung wie folgt :
IF guard THEN signal_transform ELSE disconnection_statements END IF ;
Ist das Zielobjekt (target) nicht kontrolliert, so lautet der Anweisungsteil der zugehörigen Prozessanweisung wie folgt :
IF guard THEN signal_transform END IF ;
Zuletzt kann der Fall eintreten, daß die Signalzuweisung und das Zielobjekt nicht kontrolliert sind. Dann hat der Anweisungsteil der zugehörigen Prozessanweisung folgendes einfaches Aussehen :
signal_transform
Es ist nicht erlaubt, eine Signalzuweisung als nicht kontrolliert, das entsprechende Zielobjekt jedoch als kontrolliert zu behandeln !
Beispiele
Der Wert von b wird nach 5 ns dem Signal a zugewiesen. Im ersten Fall wird das Inertialverzögerungsmodell verwendet, im zweiten Fall das Transportverzögerungsmodell.
a <= b AFTER 5 ns ;
lbl : a <= TRANSPORT b AFTER 5 ns ;
Die kontrollierte Signalzuweisung wird nur ausgeführt, wenn die entsprechende Bedingung in der Blockdeklaration erfüllt ist.
c : data_bus <= GUARDED reg_output AFTER 3 ns ;
Gilt sel=0 , wird a nach 5 ns der Wert 1 zugewiesen; gilt sel=1 , wird a nach 3 ns der Wert 0 und nach 5 ns der Wert 1 zugewiesen; ansonsten erhält a den Wert X nach 2 ns.
a <= '1' AFTER 5 ns WHEN sel = 0 ELSE '0' AFTER 3 ns, '1' AFTER 5 ns WHEN sel = 1 ELSE 'X' AFTER 2 ns ;
Bei dieser Wertzuweisung an das Signal sig wird der Wert von muxval berücksichtigt.
Gilt muxval=0 erhält sig den Wert 001 usw. Es wird bei dieser Zuweisung unabhängig vom Wert von muxval das Verzögerungsmodell TRANSPORT verwendet.
lmux : WITH muxval SELECT sig <= TRANSPORT "001" AFTER 2 ns WHEN 0 , "110" AFTER 5 ns WHEN 1 , "000" AFTER 5 ns WHEN 2 , "111" AFTER 5 ns WHEN 3 , "XXX" WHEN OTHERS ;
S wird nur dann mit einem Wert getrieben, wenn der Wert sich vom aktuellen unterscheidet; ansonsten passiert nichts.
S <= UNAFFECTED WHEN input = S' DRIVING_VALUE ELSE input AFTER delay ;
Komponenteninstantiierung
Anmerkungen
Im 87'er Standard von VHDL war nur eine Komponenteninstanziierung möglich. Im 93'er Standard ist es nun möglich, eine Entity direkt zu instanziieren oder auch eine Konfiguration einzubinden.
Bei der Komponenteninstanziierung muß die entsprechende Komponente vorher deklariert worden sein.
Bei der Instanz einer Entity oder Konfiguration muß diese jeweils schon als übersetztes Objekt in einer (für den Compiler sichtbaren) Bibliothek vorhanden sein.
Beispiele
my_component wird in die aktuelle Architecture ohne Port-Map eingebunden.
c_1 : my_component ;
Die Component add_n wird mit dem Generic-Wert 8 instantiiert. Das Signal s8 wird dabei mit den Ports Vss , a8 , b8 , sum und sig mit dem Port cout der instantiierten Component verbunden.
c : add_n GENERIC MAP (8) PORT MAP ( Vss, a8, b8, sum => s8, cout => sig ) ;
Die Entity my_entity wird direkt instanziiert. Die Signale I1 und I2 der Entity my_entity werden mit den lokalen Signalen S1 und S2 verbunden.
u_myent: ENTITY work.my_entity(beh) PORT MAP (I1 => S1 , I2 => S2 ) ;
Die Konfiguration my_cfg wird instanziiert. Die Signale I1 und I2 der in der Konfiguration angegeben Entity werden mit den lokalen Signalen S1 und S2 verbunden.
u_config: CONFIGURATION work.my_cfg PORT MAP (I1 => S1 , I2 => S2 ) ;
ram_comp wird instantiiiert und automatisch die Generics nb_data und nb_addr vorbelegt. Die Signale werden namentlich einander zugewiesen, wobei der port ready nicht angeschlossen wird.
the_ram : ram_comp GENERIC MAP ( nb_data => 8, nb_addr => 5 ) PORT MAP ( cs => cs, rw => rw, d => data, a => address, ready => OPEN ) ;
Dies ist ein Beispiel, das die Zusammenhänge erklären soll.
- ← Komponenten-Deklaration
- ← Komponenten-Instantiierung mit Verknüpfung der Ports
- ← Deklaration der Configuration (Für comp soll die Architecture y der Entity x verwendet werden.)
- ← Deklaration der Entity (check_timing ist eine passive Prozedur!)
- ← Deklaration der Architecture
COMPONENT comp PORT (a , b : INOUT bit); c : comp PORT MAP ( a => s1, b => s2 ) ; FOR c : comp USE ENTITY x(y) ; PORT MAP ( p1 => a, p2 => b ) ; ... ENTITY x IS PORT ( p1, p2 : INOUT bit ) CONSTANT delay : time := 1 ms ; BEGIN check_timing( p1, p2, 2 * delay ) ; END x ; ARCHITECTURE y OF x IS SIGNAL p3 : bit ; BEGIN p3 <= p1 AFTER delay ; p2 <= p3 AFTER delay ; b : BLOCK ... BEGIN ... END BLOCK ; END y ;
Hier der zu dem oberen gleichwertige Code:
- ← Komponenten-Block
- ← lokale Ports
- ← Portverknüpfung
- ← Entity-Block
- ← formale Ports
- ← Portverknüpfung
- ← Vereinbarung in der Entity
- ← Vereinbarung in der Architecture
- ← Entity-Anweisung
- ← 2 Architecture-Anweisungen
- ← interne Blockhierarchie
c : BLOCK PORT ( a, b : INOUT bit ) ; PORT MAP ( a => s1, b => s2 ) ; BEGIN x : BLOCK PORT ( p1, p2 : INOUT bit ) ; PORT MAP ( p1 => a, p2 => b ) ; CONSTANT delay : time := 1 ms ; SIGNAL p3 : bit ; BEGIN check_timing(p1, p2, 2 * delay) ; p3 <= p1 AFTER delay ; p2 <= p3 AFTER delay ; b : BLOCK ... BEGIN ... END BLOCK ; END BLOCK x ; END BLOCK c ;
Generateanweisung
Anmerkungen
In VHDL'87 war kein deklarativer Bereich zugelassen.
Beispiele
Diese Generate-Anweisung erzeugt eine parallele Kette aus den beiden Komponenten comp_1 und comp_2 mit der Länge 5.
lbl_1 : FOR i IN 1 TO 5 GENERATE c1 : comp_1 PORT MAP ( ck => clock, d => a(i), q => a(i+1) ) ; c2 : comp_2 PORT MAP ( ck => clock, d => a(i) ) ; END GENERATE ;
Wenn das Generic n größer 0 ist, so werden die Signalzuweisungen wirksam und die Komponente my_comp instantiiert.
lbl_2 : IF n > 0 GENERATE sig_1 <= '1' AFTER 5 ns ; sig_2 <= sig_1 AFTER 2 ns ; c : my_comp PORT MAP (a, b, c) ; END GENERATE ;
Beispiel für eine verkettete Generate-Anweisung.
Innerhalb der äußeren Anweisung werden abhängig von der Zählervariablen i verschiedene Komponenten instantiiert.
cadd : FOR i IN 1 TO n GENERATE cb : IF i = 1 GENERATE add_b : add_begin PORT MAP ( ... ) ; END GENERATE ; cm : IF i > 1 AND i < n GENERATE add_m : add_middle PORT MAP ( ... ) ; END GENERATE ; ce : IF i = n GENERATE add_e : add_end PORT MAP ( ... ) ; END GENERATE ; END GENERATE cadd ;
Beispiel für die weitreichende Einsatzmöglichkeit der Generate-Anweisung.
Die verketteten Generate-Anweisungen unter Label l2 wurden wegen der Übersichtlichkeit unter Label l6 mit einer veränderten IF -Bedingung dupliziert.
Die Generate-Anweisung unter Label l8 kann auch innerhalb der der Generate-Anweisung unter Label l3 angeführtwerden.
b : BLOCK BEGIN l1 : cell PORT MAP ( top, bottom, a(0), b(0) ) ; l2 : FOR i IN 1 TO 3 GENERATE l3 : FOR j IN 1 TO 3 GENERATE l4 : IF i + j > 4 GENERATE l5 : cell PORT MAP ( a(i-1), b(j-1), a(i),b(j)); END GENERATE ; END GENERATE ; END GENERATE ; l6 : FOR i IN 1 TO 3 GENERATE l7 : FOR j IN 1 TO 3 GENERATE l8 : IF i + j < 4 GENERATE l9 : cell PORT MAP ( a(i+1), b(j+1), a(i), b(j)); END GENERATE ; END GENERATE ; END GENERATE ; END BLOCK b ;
Verschiedenes
Sichtbarkeits- und Gültigkeitsbereiche
Deklarationsbereich
Deklarative Bereiche sind Teile des Beschreibungstextes. Einzelne, deklarative Bereiche sind:
- Entity-Deklarationen, zusammen mit den korrospondierenden Architekturkörpern
- Konfigurationsdeklarationen
- Unterprogrammdeklarationen, zusammen mit dem korrospondierenden Unterprogrammkörper
- Packagedeklarationen, zusammen mit dem korrospondierenden Packagekörper (wenn vorhanden)
- Recorddeklarationen
- Komponentendeklarationen
- Blockanweisungen
- Prozeßanweisungen
- Loopanweisungen
- Blockkonfigurationen
- Komponentenkonfigurationen
Gültigkeitsbereich einer Deklaration
Der Gültigkeitsbereich einer Deklaration erstreckt sich vom Anfang der Deklaration bis zum Ende des deklarative Bereiches, in dem die Deklaration erfolgt; dieser Bereich wird unmittelbarer Bereich genannt.
Für folgende Deklarationen erstreckt sich der Gültigkeitsbereich über den entsprechenden deklarativen Bereich hinaus:
- Deklarationen, die unmittelbar innerhalb einer Packagedeklaration erfolgen
- Elementendeklarationen innerhalb einer Recordtypendeklaration
- Deklarationen formaler Parameter innerhalb von Unterprogrammdeklarationen (Unterprogrammspezifikation, falls keine Unterprogrammdeklaration vorhanden)
- Deklarationen lokaler Generics innerhalb von Komponentendeklarationen
- Deklarationen lokaler Ports innerhalb von Komponentendeklarationen
- Deklarationen formaler Generics innerhalb von Entitydeklarationen
- Deklarationen formaler Ports innerhalb von Entitydeklarationen
Allgemein erstreckt sich der Gültigkeitsbereich auch auf die entsprechende Konfiguration, Deklaration und auf die in dieser enthaltenen Konfigurationen und Deklarationen (Hierarchie).
Sichtbarkeit
Elemente werden entweder über Selektion sichtbar gemacht oder sind direkt sichtbar. Die Sichtbarkeitsregeln definieren den Bereich, in dem auf ein deklariertes Objekt (Identifier!) zugegriffen werden kann. Auch kann nur eine Deklaration für die Verwendung des Objekts gültig sein (Overloading)., Eine Deklaration wird über eine Selektion an folgenden Stellen sichtbar gemacht:
- Für ein Primary Unit in einer Bibliothek: An der Stelle des Suffix in einem selektierten Namen, dessen Prefix eine Bibliothek kennzeichnet.
- Für eine Architektur, die mit einer Entity verknüpft ist: An der Stelle einer Blockspezifikation innerhalb einer Blockkonfiguration eines externen Blocks, dessen Schnittstelle durch die aktuelle Entity definiert ist.
- Für eine Deklaration innerhalb einer Packagedeklaration: An der Stelle des Suffix in einem selektierten Namen, dessen Prefix ein Package kennzeichnet.
- Für eine Elementendeklaration einer gegebenen Recorddeklaration: An der Stelle des Suffix in einem selektierten Namen, dessen Prefix passend für diesen Typ ist; ebenso an der Stelle einer Auswahl in einer Zuweisung über Namen innerhalb eines Aggregats dieses Typs.
- Für ein vordefiniertes Attribut, welches zu einem Bereich einer Definition paßt: An der Stelle des Designators in einem Attributnamen, dessen Prefix einem gegebenen Bereich zugeordnet ist.
- Für ein benutzerdefiniertes Attribut: An der Stelle des Designators in einem Attributnamen, dessen Prefix eine Entity bezeichnet.
- Für eine formale Parameterdeklaration innerhalb einer gegebenen Unterprogrammdeklaration: An der Stelle des formalen Designators in einer Namenszuweisungsliste innerhalb des Unterprogrammaufrufs.
- Für eine lokale Genericdeklaration einer gegebenen Komponentendeklaration: An der Stelle des formalen Designators in einer Generic-Namenszuweisungsliste der korrespondierenden Komponentenistantiierung; gleichfalls an der Stelle des aktuellen Designators in einer Generic-Namenszuweisungsliste der korrespondierenden Einbindung.
- Für eine lokale Portdeklaration einer gegebenen Komponentendeklaration: An der Stelle des formalen Designators in einer Port-Namenszuweisungsliste der korrespondierenden Komponeteninstantiierung; gleichfalls an der Stelle des aktuellen Designators in einer Port-Namenszuweisungsliste der korresponmdierenden Einbindung.
- Für eine lokale Genericdeklaration einer gegebenen Entitydeklaration: An der Stelle des formalen Designators in einer Generic-Namenszuweisungsliste der korrespondierenden Einbindung.
- Für eine formale Portdeklaration einer gegebenen Entitydeklaration: An der Stelle des formalen Designators in einer Port-Namenszuweisungsliste der korrespondierenden Einbindung.
- Für eine formale Generic- oder Portdeklaration einer gegebenen Blockanweisung: An der Stelle des formalen Designators im formalen Teil einer Namenszuweisung der entsprechenden Generic- oder Portabbildung.
Letztlich wird jede Deklaration, die innerhalb des Deklarationsbereiches eines beliebigen Konstrukts (außer eines Records) steht, als Suffix eines expanded name sichtbar, wobei das Prefix obiges Konstrukt markiert.
z.B. in einer Konfiguration :
USE ENTITY WORK.tv(SAT1) Prefix.Suffix
wie 1.
Rom cell(0) <= ROMBIB.rom_package.constant(0) date.month <= "April" date <= (Year => 1997, Day => 9, Month => "April") ; ASSERT ack`STABLE(setup_time) REPORT "setup time violation by Ack" SEVERITY WARNING ATTRIBUTE author OF tb_i2c : ENTITY IS "Martin Padeffke" FUNCTION ksc_fans(Number) RETURN INTEGER ; ARCHITECTURE einschaltquoten OF tv IS BEGIN ... pot_viewers <= ksc_fans(football_fans) + ... END einschaltquoten ; UUT : bus_monitor GENERIC MAP ( setup_time => setup, clock_period => clk_period , ... ) ; PORT MAP ( bus => scd, takt => scl, ...) ;
wie 8. wie 9. wie 8. bzw. wie 9.
Direkte Sichtbarkeit
Eine beliebige Deklaration ist in ihrem unmittelbaren Gültigkeitsbereich direkt sichtbar (Ausnahme: versteckte Deklaration) : Deklarationen eines Packages können über Use Anweisungen direkt sichtbar gemacht werden.
Eine Deklaration heißt hidden , wenn sie durch eine lokale Deklaration überdeckt wird - wie im Beispiel.
Ausnahme: Overloading - mehrere Deklarationen mit gleichem Identifier existieren nebeneinander und aus dem Zusammenhang des Aufrufs wird die passende ausgewählt (Auflösung von Überladungen).
Das Signal b wird in Block lbl_1 und in Block lbl_2 deklariert. Wird b ohne weitere Kennzeichnung angesprochen, so ist das 'innere' Signal gemeint. Ansonsten ist dies explizit durch Voranstellen des entsprechenden Labels zu kennzeichnen.
lbl_1 : BLOCK SIGNAL a, b : bit ; BEGIN lbl_2 : BLOCK SIGNAL b : bit ; BEGIN a <= b AFTER 5 ns ; -- Equivalent: <- lbl_1.a <= lbl_2.b AFTER 5 ns b <= lbl_1.b AFTER 10 ns ; -- Equivalent: <- lbl_2.b <= lbl_1.b AFTER 10 ns END BLOCK lbl_2 ; b <= a AFTER 15 ns ; -- Equivalent: <- lbl_1.b <= lbl_1.a AFTER 15 ns END BLOCK lbl_1 ;
Use Anweisungen
Anmerkung
Die USE -Anweisung kann auch als Kontext-Anweisung vor jedem Bibliothekenbaustein, d. h. entity, architecture, package, package body und configuration, gestellt werden.
Beispiele
Alle Packages aus der Default-Biblitohek work werden eingebunden.
USE work. ALL ;
Alle Elemente des Package my_package aus der Bibliothek work werden eingebunden.
USE work.my_package. ALL ;
Die Funktion my_function aus dem Package my_package in der Biblitohek work wird eingebunden.
USE work.my_package.my_function ;
Aus den Packages pkg_1 und pkg_3 werden alle Elemente eingebunden; vom Package pkg_2 wird nur die Prozedur proc_1 eingebunden.
USE lib_1.pkg_1. ALL , lib_1.pkg_2.proc_1, lib_2.pkg_3. ALL ;
Auflösung von Überladungen
Das Überladen ist für Unterprogramme, Operatoren und Werte von Aufzählungstypen definiert.
Unter Überladung versteht man die gleichzeitige Sichtbarkeit von mehreren gleichnamigen Unterprogrammen, Operatoren bzw. von Objektwerten, die zu unterschiedlichen Aufzählungstypen gehören können. Mit Hilfe der Überladung gelingt es beispielsweise, den Anwendungsbereich einer Funktion zu vergrößern. Die verschiedenen Varianten eines Unterprogramms oder eines Operators unterscheiden sich nur in Anzahl und Typ ihrer Argumente und Ergebnisse. VHDL-Programme erkennen aus dem Kontext heraus (d.h. aus der Argumentanzahl und deren Typen), welche der sichtbaren Varianten anzuwenden ist. Ist diese Entscheidung nicht eindeutig, d.h. sollten sich mehrere sichtbare Alternativen als “passend” für die zu erfüllende Aufgabe erweisen, erfolgt die Ausgabe einer Fehlermeldung.
Durch das Konzept der Überladung werden VHDL-Modelle übersichtlicher, da nicht für jede Variante einer beestimmten Funktionalität ein neuer Bezeichner vergeben werden muß.
Design Units und deren Analyse
Anmerkung
Die LIBRARY -Anweisung ist als Kontext-Anweisung vor jedem Bibliothekenbaustein, d. h. entity, architecture, package, package body und configuration anführbar.
Beispiele
Verschiedene Bibliotheken werden bekanntgemacht.
LIBRARY my_library ;
LIBRARY my_library_1, my_library_2 ;
Nach Bekanntmachung der Bibliotheken std und work werden alle Elemente aus dem Package standard der Bibliothek std eingebunden.
LIBRARY std, work ; USE std.standard. ALL ;
Elaboration und Simulation
Die Elaboration ist für Deklarationen, Entwurfshierarchien sowie Anweisungen (einschließlich nebenläufiger Anweisungen) definiert. Ein Konstrukt wird erst durch den Vorgang der Elaboration wirksam. Vor Beendigung der Elaboration ist das betreffende Konstrukt nicht existent!
Um ein Modell auszuführen, muß zunächst die Entwurfshierarchie, welche das Modell beschreibt, elaboriert werden. Danach erfolgt die Initialisierung der Netze des Modells, um anschließend die Simulation des Modells zu starten. Diese beinhaltet das mehrmalige Durchlaufen des Simulationszyklus. Dabei werden die Prozesse ausgeführt und die Netzlistenparameter neu berechnet bzw. aktualisiert.
Elaboration eines Blockheaders
Die Generic-Anweisung
Die Elaboration der in der Generic-Anweisung enthaltenen Generic-Deklarationen erfolgt in der vorgegebenen Reihenfolge. Dabei werden die Untertypen des Generics gebildet, sowie eine Generic-Konstante zu jedem dieser Untertypen bereitgestellt. Der jeweilige Wert wird erst bei der späteren Elaboration nachfolgender Generic-Abbildungsanweisungen ermittelt. Fehlen diese Abbildungsanweisungen, so verwendet das System den der jeweiligen Generic-Konstante zugeordneten Defaultwert.
Die Generic-Abbildungsanweisung
Hier wird die Generic-Verknüpfungsliste elaboriert. Diese enthält ein implizit definiertes Zuordnungselement für jede nicht explizit zugeordnete Generic-Konstante.
GENERIC (explicit_generic : INTEGER := 9);
Der zu berechnende Teil des implizit definierten Zuordnungselements ist dabei der in der Deklaration der jeweiligen Auswahl-Konstante enthaltene Ausdruck.
Die Elaboration der Listenelemente, die aus einem formalen und einem aktuellen Teil bestehen, erfolgt sequentiell. Der formale Teil einer Generic-Konstanten wird dabei mit den Werten, die bei der Berechnung des entsprechenden aktuellen Teiles entstehen, belegt.
Die Port-Anweisung
Das System wertet die entsprechenden Port-Deklarationen, die in der Anweisung enthalten sind, in der angegebenen Reihenfolge aus. Die Elaboration einer Port-Deklaration besteht darin, zunächst den Untertyp festzulegen und dann einen Port zu diesem Untertyp zu erzeugen. (vgl. Die Generic-Anweisung )
Die Port-Abbildungsanweisung
Hier wertet das System die Port-Verknüpfungsliste aus. Diese enthält Zuordnungsanweisungen, die dem formalen Ausdruck das im tatsächlichen Ausdruck spezifizierte Signal zuweist. Diese Zuordnung beinhaltet das Prüfen der Regeln und Einschränkungen, die Ports betreffen.
Ein gegebener Ausdruck innerhalb einer Port-Deklaration (Initialisierungsanweisung) wird unter Verwendung der tatsächlichen Werte elaboriert. Falls in der Zuordnungsanweisung kein Signal mit diesem Port verknüpft wird und der Port einen Eingang darstellt, erhält dieser einen Defaultwert, sofern für diesen Port ein solcher definiert worden ist.
Elaboration einer Deklaration
Die Elaboration einer Deklaration entspricht dem Erzeugen des deklarierten Konstrukts. Die syntaktischen Regeln ( hier besonders die Regeln bezüglich des Geltungsbereiches) gestatten es nicht, ein Konstrukt vor Elaboration der betreffenden Deklaration zu verwenden.
Deklaration von Unterprogrammen und Unterprogrammkörpern
Die Elaboration einer Unterprogramm-Deklaration erfolgt durch die Elaboration der zugehörigen Schnittstellen- bzw. Interface- Parameterliste. Dabei wird der Untertyp jedes Schnittstellen-Elements und somit der Untertyp jedes formalen Parameters im Unterprogramm festgelegt.
Die Elaboration des Unterprogrammkörpers erlaubt die Nutzung des Unterprogrammes bei späteren (nicht früheren !) Unterprogrammaufrufen.
Deklaration von Typen
Das System elaboriert die Definition des Typs und erzeugt danach diesen Typ. Bei einer eingeschränkten Felddeklaration jedoch erfolgt die Elaboration des gleichwertigen unbeschränkten Feldtyps (d.h. Elaboration des Untertyps der Elemente), gefolgt von der Elaboration des betreffenden Untertyps des unbeschränkten Feldtyps.
Die Elaboration eines Aufzählungstyps erzeugt den entsprechenden Typ. Bei Integer-, Gleitkomma- oder physikalischen Typdefinitionen werden die entsprechenden Untertypen festgelegt. Bei physikalischen Typdefinitionen erfolgt zusätzlich die Erzeugung der Einheiten.
Ein Datensatz (Record-Konstruktion) wird durch Elaboration der Deklarationen ihrer einzelnen Elemente in der angegebenen Reihenfolge elaboriert. (ähnlich wie beim Feldtyp)
Die Elaboration einer Elementdeklaration besteht in der Festlegung des Untertyps. Die Elaboration einer Zeiger-Deklaration entspricht der Elaboration des entsprechenden Untertyps.
Deklaration von Untertypen
Hier erfolgt die Festlegung und Erzeugung des Untertyps. Falls der Untertyp keine Beschränkungen hat, gleicht dieser dem Grundtyp. Sonst wird zunächst die Beschränkung elaboriert und dann ein Kompatibilitätstest hinsichtlich des Grundtyps durchgeführt.
Die Elaboration einer Beschränkung des Wertebereiches erfolgt durch Berechnung dieses Wertebereichs. Dabei werden die Wertegrenzen und die Zählrichtung des Bereiches definiert. Eine Größenbeschränkung wird durch die Berechnung des entsprechenden Ausdrucks elaboriert.
Deklaration von Objekten
Hier ist zu unterscheiden zwischen Datei-Objekten und sonstigen. Bei ersteren erfolgt die Festlegung und anschließende Erzeugung des Untertyps. Der logische Dateiname wird ermittelt sowie die entsprechende physikalische Datei mit dem neuen Objekt verknüpft.
Folgender Ablauf gilt fuer alle anderen Arten von Objekten (außer Port- und Generic-Deklarationen):
- Der Untertyp des Objekts wird definiert.
- Falls die Deklaration des Objekts einen expliziten Initialisierungsausdruck enthält, erfolgt eine Berechnung des Wertes dieses Ausdrucks. Dieser ist dann der Startwert des Objekts. Anderenfalls erhält das Objekt einen implizit definierten Anfangswert.
- Das Objekt wird erzeugt.
- Der Startwert wird dem Objekt zugewiesen.
Das Initialisieren beinhaltet einen Test auf Zugehörigkeit des Startwertes zum Untertyp des Objekts.
Bei einem durch eine Objekt-Deklaration bezeichneten Feld-Objekt wird als erster Schritt der Untertyp solange umgewandelt, bis das Objekt eine Konstante ist, dessen Untertyp ein Typ eines uneingeschränkten Feldes ist.
Ein Fehler tritt auf, falls die Bezeichnung eines Untertyps des Objekts vor der Elaboration der betreffenden Deklaration verwendet wird.
Wird ein File elaboriert, dessen Deklaration keine Öffnungsinformation enthält, wird zuerst implizit FILE-OPEN aufgerufen.
Deklaration von Aliases
Der mit dem Alias assoziierte Untertyp wird festgelegt und erzeugt. Anschließend wird ein alternativer Name erzeugt.
Das Erzeugen eines Alias für ein Feld-Objekt beinhaltet eine Prüfung auf Konsistenz jedes Elements des zu ersetzenden Objekts mit entsprechenden Elementen, die der Alias-Untertyp enthält.
Deklaration von Attributen
Es wird ein Template erzeugt, mit dem die Definition von Attributen für die jeweiligen Elemente möglich wird.
Deklaration von Komponenten
Das System erzeugt ein Template zur Bildung der Instanzen der Komponente.
Elaboration einer Spezifikation
Hierbei werden zusätzliche Informationen einem vorher deklarierten Programmteil zugeordnet.
Spezifikation von Attributen
Die Elaboration läuft folgendermaßen ab:
- Die Spezifikation einer Entity wird elaboriert, um feststellen zu können, welche einzelnen Elemente von der Attribut-Spezifikation betroffen sind.
- Um den Wert des Attributs festzulegen, wird der Ausdruck ausgewertet.
- Eine neue Instanz des Attributes wird erzeugt und mit jedem der davon beeinflußten Programmelemente bzw. -punkte verbunden.
- Jede neue Instanz des Attributes erhält den Wert des Ausdrucks.
Die unter 4. beschriebene Zuweisung beinhaltet einen Test auf Zugehörigkeit des Wertes zum Untertyp des Attributes.
Bei einem Attribut eines beschränkten Feld-Typs wird als erster Schritt der Untertyp einer impliziten Typkonvertierung unterworfen, wie bei einer Zuweisungsanweisung.
Eine solche Konvertierung ist nicht notwendig für unbeschränkte Feld-Typen.
Spezifikation von Konfigurationen
Die Elaboration läuft folgendermaßen ab:
- Die Komponentenspezifikation wird elaboriert, um festzustellen, welche Instanzen der Komponenten von der Konfiguration beeinflußt werden.
- Die Bindungs-Festlegung wird elaboriert, um diejenige Entity zu identifizieren, an welche die unter 1. bestimmten Komponenten-Instanzen gebunden werden.
- Die Bindungs-Informationen werden mit jeder beeinflußten Komponenten-Instanz verknüpft, damit diese im weiteren Verlauf zur Bildung weiterer Instanzen verwendet werden können.
Das beschriebene Verfahren beinhaltet einen Test darauf, daß die Deklaration der Entity und die entsprechende Architecture, die von den Bindungs-Festlegungen impliziert werden, innerhalb der spezifizierten Bibliothek existieren.
Disconnection-Spezifikation
Dabei werden folgende Schritte ausgeführt:
- Die guarded specification des Signals wird elaboriert, um festzustellen, welche Signale von der Disconnect-Spezifikation beeinflußt werden.
- Der Zeit-Ausdruck wird ermittelt, um die Zeit für die Disconnection-time der Treiber der unter 1. ermittelten Signale zu bestimmen.
- Die Disconnection-time wird mit jedem beeinflußten Signal verknüpft. Diese kann (in Prozessen für guarded signal-Belegungen) zum Formulieren von Disconnection-Anweisungen genutzt werden.
Elaboration eines Anweisungsteils
Die Elaborationsregeln gelten für alle Anweisungsteile mit Ausnahme einer Architektur, die mit dem Attribut FOREIGN versehen ist. Diese werden implementierungsabhängig elaboriert.
Anweisungen innerhalb von Blöcken
Es erfolgt eine sukzessive Elaboration des
- Blockanfangs (falls vorhanden),
my_block : BLOCK (enable = '1') PORT (farbe_1, farbe_2, select : std_ulogic; auswahl : std_ulogic BUS); PORTMAP (farbe_1 => color(0), farbe_2 => color(1), auswahl => point);
- Block-Deklarationsteils,
SIGNAL inter : std_ulogic;
- Block-Anweisungsteils.
BEGIN inter <= farbe_1 WHEN select = '0' ELSE farbe_2; auswahl <= GUARDED inter; END BLOCK my_block;
Die Elaboration einer Block-Anweisung kann unter der Kontrolle einer Konfigurationsdeklaration erfolgen. Eine darin eingeschlossene Blockkonfiguration kann eine Reihe zusätzlicher implizit definierter Spezifikationen erzeugen, die bei der Elaboration der entsprechenden Block-Anweisung verwendet und somit gleichzeitig elaboriert werden.
Jede dieser impliziten Spezifikationen besteht aus derjenigen Spezifikation der Konfiguration, die von den Konfigurationen der Komponenten innerhalb der Blockkonfiguration impliziert werden.
Die Generate-Anweisung
Die Generate-Anweisung wird durch Kopien von Blockanweisungen ersetzt, deren Anweisungsteil aus den in der Generate-Anweisung enthaltenen nebenläufigen Anweisungen besteht. Jede Blockanweisung wird anschließend elaboriert.
Bei einer FOR -Generate-Anweisung wird der jeweilige Wertebereich elaboriert. Danach wird eine Blockanweisung zu jedem Wert innerhalb des Bereichs erzeugt. Diese hat folgende Merkmale:
- Die Namen der Blockanweisung und der Generate-Anweisung sind gleich.
- Der Deklarationsteil enthält eine Konstantendeklaration, die eine Konstante unter dem Namen des Generate-Parameters deklariert. Der Wert der Konstanten entspricht dem des Generate-Parameters, der Typ wird durch den Grundtyp des Wertebereichs des Generate-Parameters bestimmt.
- Der Anweisungsteil enthält die Kopie der nebenläufigen Anweisungen aus der Generate-Anweisung.
Bei einer IF -Generate-Anweisung wird der logische Ausdruck berechnet. Falls der Ausdruck den Wert true annimmt, wird eine Blockanweisung erzeugt. Diese hat folgende Merkmale:
- Die Namen des Blocks und der Generate-Anweisung stimmen überein.
- Der Deklarationsteil des Blocks ist leer.
- Der Anweisungsteil enthält eine Kopie der nebenläufigen Anweisungen (s.o.).
Anweisungen zur Komponenteninstantiierung
Die Komponente muß entweder voll an eine per Entity-Deklaration und Architecture festgelegte Entity oder an eine Konfiguration einer Entity gebunden sein. Es wird sowohl die implizit definierte Blockanweisung, welche die Instanz der Komponente beschreibt, als auch die ebenfalls implizite, auf die oben erwähnte Entity bezugnehmende Blockanweisung elaboriert.
Weitere nebenläufige Anweisungen
Alle weiteren nebenläufigen Anweisungen sind entweder Prozess-Anweisungen oder aber solche Anweisungen, für die eine gleichwertige Prozess-Anweisung existiert. Die Elaboration besteht aus folgenden Schritten:
- Der Deklarationsteil des Prozesses wird elaboriert.
- Die von der Prozess-Anweisung angeforderten Treiber werden bereitgestellt.
- Der durch Defaultwerte von skalaren Signalen definierte Anfangsvorgang wird in den entsprechenden Treiber geladen.
Die Elaboration aller nebenläufigen Signal-Zuordnungsanweisungen und aller nebenläufigen Assertion-Anweisungen besteht aus der Erzeugung einer gleichwertigen Prozess-Anweisung gefolgt von deren Elaboration.
Dynamische Elaboration
Die Ausführung von Programmteilen, die sequentielle Anweisungen enthalten, erfordert ebenfalls deren Elaboration. Diese erfolgt während der Ausführung des Modells. Als Beispiele, bei denen die Elaboration dynamisch während der Simulation erfolgt, sind folgende zu nennen:
- Die Ausführung einer FOR -Iterationsschleife beinhaltet die Elaboration der Schleifen-Parameter, bevor die innerhalb der Schleife liegenden Anweisungen ausgeführt werden können. Die Elaboration erzeugt die Schleifen-Parameter und berechnet deren Wertebereiche.
- Die Ausführung eines Unterprogrammaufrufes setzt die Elaboration der Parameter-Schnittstellenliste der entsprechenden Unterprogrammdeklaration voraus. Dabei wird jede Schnittstellen-Deklaration elaboriert, um die formalen Parameter erzeugen zu können. Diese werden dann mit den actual-Parametern verknüpft. Schließlich erfolgt die Elaboration des Deklarationsteils des zugehörigen Unterprogrammkörpers. Die Anweisungsfolge des Unterprogrammkörpers wird ausgeführt.
- Die Berechnung eines Zeigers, der eine Untertyp-Kennzeichnung enthält, erfordert die Elaboration der Untertyp-Festlegung, bevor die erzeugte Instanz zugeordnet wird.
Als eine Folge der obigen Regeln ergibt sich, daß Deklarationen im Deklarationsteil eines Unterprogrammkörpers jedesmal elaboriert werden, wenn das entsprechende Unterprogramm aufgerufen wird. In einem solchen Fall kann die Elaboration einer Deklaration zu verschiedenen Ergebnissen mit unterschiedlichen Charakteristika führen.
So kann zum Beispiel die Elaboration von ein und derselber Deklaration eines Untertyps in einem Unterprogrammkörper zu Untertypen mit unterschiedlichen Eigenschaften führen.
FUNCTION diff_subtypes (N : INTEGER) RETURN INTEGER IS SUBTYPE my_int IS INTEGER RANGE 0 TO N; VARIABLE out_sig : my_int; BEGIN ...
N ist hier als formaler Parameter eine Konstante (Default für formale Parameter vom Modus IN). Der actual Parameter, der mit N verknüpft wird, kann aber z.B. ein Signal sein ⇒ abhängig von N kann sich so der Untertyp my_int von Funktionsaufruf zu Funktionsaufruf ändern!
Elaboration einer Entwurfshierarchie
Durch die Elaboration einer Entwurfshierarchie werden eine Reihe von durch Netze verbundene Prozesse erzeugt, die anschließend zur Verhaltens-Simulation des zugrundeliegenden Entwurfs (Modell) ausgeführt werden können.
Eine durch eine Entity definierte Entwurfshierarchie wird durch die Elaboration einer Blockanweisung umgesetzt, die dem durch die Entity definierten externen Block entspricht. Es besteht auch die Möglichkeit, die Entwurfshierarchie durch eine Konfiguration festzulegen. Dabei erfolgt eine Elaboration der Blockanweisung, die dem externen Block entspricht, der innerhalb der durch den entsprechenden Konfigurationsteil konfigurierten Entity definiert wird.
Innerhalb einer Blockanweisung erfolgt die Elaboration jedes noch nicht ausgewerteten Packages und der wiederum darin enthaltenen Packages, wobei zunächst der Deklarationsteil der Package-Deklaration und, falls vorhanden, anschließend der Deklarationsteil des entsprechenden Package Bodys ausgeführt wird.
Ausführung eines Modells
Ein erzeugtes Modell wird ausgeführt, indem die vom Anwender spezifizierten Prozesse elaboriert werden. Der Kernprozess stellt in der Entwurfshierarchie den Vorgang dar, welcher
- die Aktivitäten der vom Anwender bereitgestellten Prozesse während der Simulation überwacht und koordiniert,
- die Übertragung von Signalwerten sowie die Aktualisierung der Werte implizit definierter Signale (z.B. S'Stable(t)) bewirkt,
- Ereignisse registriert und als Antwort darauf die Ausführung geeigneter Prozesse veranlaßt, eine Variable für jedes explizit im Modell deklariertes Signal mit dem gegenwärtigen Wert dieses Signals belegt und bei allen Berechnungen mit dem Signal den Wert der Variable bereitstellt,
- die o.g. Variablenwerte während des Simulationsablaufs in regelmäßen Zeitabständen aktualisiert,
- eine Variable für jedes implizit deklariertes guarded signal mit dem gegenwärtigen Wert dieses Signals belegt und je einen Treiber sowie eine den jeweils tatsächlichen Wert enthaltende Variable für
- S'Stable(t)-Signale,
- S'Quiet(t)-Signale,
- S'Transaction-Signale und
- im Modell verwendete Präfixe S und Zeiten t zur Verfügung stellt.
Die Ausbreitung von Signalwerten
Mit fortschreitender Simulationszeit erhalten die Signalverläufe in der Waveform die Werte der entsprechenden Treiber. Ein Treiber ist aktiv , wenn ihm ein neuer Wert zugewiesen wird. Ein Signal ist gerade aktiv , falls
- eine der Signalquellen aktiv ist,
- eines der Unterelemente aktiviert ist,
- das Signal im formalen Teil eines Elements einer Port-Verknüpfungsliste verwendet wird und der tatsächliche Teil gerade aktiv ist oder
- das Signal ein Unterelement eines aktiven resolved Signals ist.
Hat ein Signal eines zusammengesetzten Typs eine auf anderen Typen basierende Quelle, so gilt jedes skalare Unterelement als aktiv, falls die Signalquelle aktiviert wird.
Entsprechendes gilt für Ports und mit diesen verbundene Signale. Ein implizit definiertes Signal ist aktiv, wenn dieses Signal vom Kernprozess aktualisiert wird. Ist ein Signal nicht aktiv, so sagt man, daß das Signal quiet ist.
Für bestimmte Signale verwaltet der Kernprozess zwei unterschiedliche Signalwerte. Der Treiberwert ist der Wert eines Signals, das anderen Signalen als Quelle dient. Der Effektivwert stellt den aus der Berechnung eines Signalbezuges innerhalb eines Ausdrucks erhaltenen Wert dar. Treiberwert und Effektivwert sind insbesondere dann nicht identisch, wenn eine Auflösungsfunktion oder Typumwandlungen involviert sind. Die Besonderheiten beider Signalarten zeigt die folgende Tabelle.
Signalart | Treiberwert | Effektivwert |
---|---|---|
Skalares Signal S | S quellenlos: Treiberwert = Defaultwert | S deklariert per Signaldeklaration, Port vom Typ buffer oder unverbundener Port vom Typ inout : Effektivwert=Treiberwert |
Quelle von S ist Treiber, S nicht resolved: Treiberwert = Wert des Treibers | S ist verbundener Port vom Typ in oder inout : Effektivwert von S = Effektivwert des aktuellen Teiles des Zuordnungselements, Berechnung des Ist-Teiles | |
Quelle von S ist Port, S nicht resolved: Treiberwert = Treiberwert des formalen Teils des Verbindungselements, das S mit dem Port verbindet | S sei unverbundener Port vom Typ in : Effektivwert = Defaultwert | |
S ist resolved: Treiberwert = resolved Wert von S, Berechnen der “Auflösungsfunktion” mit den Treiberwerten der Quellen von S als Übergabeparameter | Steuer- und Effektivwert haben den Untertyp von S | |
Verbundsignal V zusammengesetztes Signal | Treiberwert = Zusammenfassung der Treiberwerte jedes skalaren Unterelements von V | Effektivwert = Zusammenfassung der Effektivwerte jedes skalaren Unterelements von V |
Bei der Aktualisierung eines Signals berechnet der Kernprozess zunächst den Treiber- und Effektivwert. Dann wird die dem Signal zugehörige Variable neu belegt. Ist das Signal nicht von einem Array-Typ abgeleitet, so wird der Effektivwert verwendet. Es wird geprüft, ob dieser Wert zum Untertyp des Signals gehört. Die den gegenwärtigen Signalwert speichernde Variable erhält durch Zuweisung den Effektivwert. Liegt dem Signal ein Array-Typ zugrunde, wird der Effektivwert implizit in den Untertyp des Signals umgewandelt (einschließlich Test auf Konsistenz zwischen den Signal-Elementen und den Elementen des Effektivwertes). Das Ergebnis der Typumwandlung wird der o.g. Variablen zugewiesen.
Anmerkung
Ein Element eines Verbundsignals kann quiet sein, während das Signal selbst aktiv ist.
Für Ports vom Typ out ist kein Effektivwert spezifiziert, da diese nicht gelesen werden dürfen.
Obige Regeln gelten nicht für implizit definierte Signale.
Das Aktualisieren implizit definierter Signale
Vom Kernprozess werden die Werte implizit definierter guarded signals mit einer Blockanweisung, die einen guarded Ausdruck enthält, verbunden. Gleichzeitig aktualisiert das System die impliziten Signale S'Stable(t), S'Quiet(t) und S'Transaction sowie deren Treiber.
Ein guarded Signal wird hinsichtlich seiner Momentanwerte nur verändert, falls der zugehörige guarded Ausdruck einen Bezug zum Signal herstellt und dieses Signal aktiv ist. Dabei wird der Wert des Ausdrucks berechnet und der Variablen zugewiesen, die den Momentanwert des Signals enthält.
Für die Signale S'Stable(t), S'Quiet(t) sowie S'Transaction gibt es folgende Besonderheiten.
Merkmal | S'Stable(t) | S'Quiet(t) | S'Transaction |
---|---|---|---|
Momentanwertänderung nur bei | Eintritt eines Ereignisses im momentanen Simulationszyklus | Aktivieren des Signals | Aktivieren des Signals |
Aktivieren des Treibers | Aktivieren des Treibers | ||
Aktualisieren durch | Zuweisen des Wertes ' false ' an die zugehörige Variable, Treiber erhält die Form ' true ' nach der Zeit t | Zuweisen des Wertes ' false ' an die zugehörige Variable, Treiber erhält die Form ' true ' nach der Zeit t | Zuweisen des Ausdruck-Wertes an die zugehörige Variable (maximal eine Zuweisung inner-halb eines Simulationszyklus möglich) |
Zuweisen des Momentanwertes des Treibers an die zugehörige Variable | Zuweisen des Momentanwertes des Treibers an die zugehörige Variable |
Der Augenblickswert eines impliziten Signals D ist abhängig vom Momentanwert eines anderen Signals E, falls
- D ein guarded signal darstellt und E innerhalb der guarded expression , die den Augenblickswert von D festlegt, auftaucht,
- D vom Typ S'Stable(t), S'Quiet(t) oder S'Transaction ist.
Innerhalb eines Simulationszyklus wird der Momentanwert von E zeitlich vor dem Augenblickswert von D aktualisiert, sodaß stets das Kausalitätsprinzip gilt.
Der Simulationszyklus
Die Ausführung eines Modells erfolgt durch die wiederholte Ausführung von Prozess-Anweisungen aus der Modellbeschreibungsebene. Eine Wiederholung bezeichnet man als Simulationszyklus. Innerhalb eines Zyklus werden alle Signalwerte berechnet. Davon abhängig startet das System die Ausführung von Prozess-Anweisungen, d.h. wenn an einem Signal ein Event auftritt werden alle Prozesse gestartet, die auf dieses Signal sensitiv sind. Der Ausführung geht eine aus den folgenden Schritten bestehende Initialisierung voran:
- Die Treiber-und Effektivwerte aller explizit deklarierten Signale werden berechnet. Die Momentanwerte erhalten den effektiven Wert und gelten bis zum Zeitpunkt des Simulationsbeginns.
- Der Wert implizit deklarierter Signale der Form S'Stable(t) oder S'Quiet(t) wird mit 'true' festgelegt. Signale des Typs S'Transaction bleiben undefiniert.
- Das System belegt den Wert impliziter guarded signals mit dem Wert der entsprechenden guarded expression .
- Jeder nonpostponed process des Modells wird einzeln ausgeführt (bis zur Unterbrechung).
- Jeder postponed process des Modells wird bis zur Unterbrechung ausgeführt.
- Die Zeit für den nächsten Simulationszyklus wird entsprechend 6. unten errechnet.
Dem Simulationsbeginn ordnet man gewöhnlicherweise die Zeit 0 ns zu.
Der Simulationszyklus besteht aus folgenden Teilen:
- Sind alle Treiber inaktiv, wird die Simulationszeit auf den Zeitpunkt gesetzt, zu dem ein Treiber aktiv wird oder die Ausführung eines unterbrochenen Prozesses wieder aufgenommmen wird. Die Simulation ist beendet, wenn die Simulationszeit den Maximalwert erreicht hat.
- Jedes aktivierte, explizit deklarierte Signal wird aktualisiert. Es können dabei sog. Ereignisse auftreten, auf deren Grundlage das System später entscheidet, welche Prozess-Anweisungen ausgeführt werden.
- Alle implizit deklarierten Signale werden aktualisiert.
- Jeder Prozess, der ein bestimmtes Signal in Verbindung mit einem Ereignis momentan beeinflußt, wird in der Ausführung fortgesetzt.
- Alle bereits wiederaufgenommen nonpostponed process werden fortgesetzt und ausgeführt, bis eine Unterbrechung auftritt.
- Die Zeit für den nächsten Simulationszyklus wird festgesetzt als früheste von folgenden Zeiten:
- TIME'HIGH
- Nächste Zeit zu der ein Treiber aktiv wird
- Nächste Zeit zu der eine Prozeßabarbeitung wieder aufgenommen wird
- Ist diese Zeit gleich der aktuellen Simulationszeit, wird ein neuer Delta Zyklus begonnen.
- Soll kein neuer Delta Zyklus mehr begonnen werden, werden alle noch nicht ausgeführten postponed process abgearbeitet. Nun darf kein weiterer Delta Zyklus begonnen werden. Die Zeit für den nächsten Simulationszyklus wird nach 6. neu berechnet.
Lexikalische Elemente
Buchstabenmenge
Spezifikation
(g) Formatierungsanweisungen ( format_effectors ) sind
- Tabulator (horizontal und vertikal),
- Wagenrücklauf (carriage return),
- Zeilenvorschub (line feed) und
- Seitenvorschub (form feed).
Trenn- und Begrenzungszeichen
Anmerkungen
Jedes lexikalische Element muß in eine Zeile passen, da das Zeilenende ein Trennzeichen bildet.
Bezeichner
Anmerkungen
Ein Basis-Bezeichner darf keine Leerzeichen enthalten !
Abstrakte Buchstabensymbole
Anmerkungen
- Der Exponent darf für integer_literals nicht negativ sein.
- Führende Nullen sind erlaubt.
- Space ist nicht erlaubt, weil space ein Trennzeichen ist.
- _ dient nur der Lesbarkeit und hat keinen Einfluß auf den Wert.
- zulässige Basisangaben: 2,..,16
Beispiele
Integer-Zahlen
12 0 1E6 123_456
Real-Zahlen
12.0 0.0 0.4556 3.14159_26
Real-Zahlen mit Exponent
1.34E-12 1.0E+6 6.023E+24
Integer-Zahlen vom Wert 255
2#1111_1111# 16#FF# 016#0FF#
Integer-Zahlen vom Wert 224
16#E#E1 2#1110_0000#
Real-Zahlen vom Wert 4095.0 (32 bit IEEE-Gleitkommaformat)
16#F.FF#E+2 2#1.1111_1111_111#E11
Buchstaben
Zeichenketten
Anmerkungen
- Eine Zeichenkette darf nicht auf nachfolgende Zeilen übergreifen, da sie ein lexikalisches Element darstellt.
- Zeichenketten, die nicht in eine Zeile passen, können in zwei oder mehrere Zeichenketten aufgeteilt und miteinander verkettet bzw. verbunden werden (s. Beispiel).
- '“' innerhalb einer Zeichenkette muß als '”“' eingegeben werden.
Beispiele
eine Fehlermeldung
"setup time too small"
eine leere Zeichenkette
""
drei Zeichenketten der Länge 1
" " "a" """"
"Zeichen wie $, % und } dürfen in Zeichenketten enthalten sein"
"erster Teil einer Zeichenkette," & "die erst auf der nächsten Zeile endet""
Bit-Zeichenketten
Anmerkungen
Bei den Basisangaben steht B für binär, O für oktal und X für hexadezimal.
Kommentare
Definition
Kommentare werden zur Erklärung des VHDL-Codes verwendet.
Beispiele
-- letzter Satz vor Wiedergabe des ALGOL 68-Berichts END ; -- Bearbeitung der Zeile beendet -- ein umfangreicher Kommentar kann in zwei oder mehrere -- aufeinanderfolgende Zeilen aufgeteilt werden ------- die ersten zwei Anstriche leiten den Kommentar ein
Reservierte Wörter
Anmerkungen
Ein reserviertes Wort darf nicht als ein explizit deklarierter Bezeichner verwendet werden.
Ersetzen von Zeichen
Definition
Ein vertikaler Strich (|) kann durch ein Ausrufezeichen (!), das für ein Operationszeichen ( delimiter ) steht, ersetzt werden.
Die Doppelkreuze (#) in based literals können durch Doppelpunkte (:) ersetzt werden, vorausgesetzt die Ersetzung erfolgt bei beiden Zeichen.
Die Anführungsstriche (”) am Anfang und Ende von Zeichenketten können durch Prozentzeichen (%) ersetzt werden. Dabei müssen sowohl die Anführungsstriche am Anfang, wie auch die am Ende der Zeichenkette ersetzt werden. Dann dürfen aber innerhalb der Zeichenkette keine Anführungsstriche enthalten sein. Jedes in der Zeichenkette enthaltene Prozentzeichen muß dann verdoppelt werden. Dieses doppelte Prozentzeichen wird als ein einfaches Zeichen interpretiert. Der gleiche Austausch ist für bit string literals gestattet,vorausgesetzt es werden beide umschließende Anführungsstriche ersetzt.
Vordefinierte Attribute
T'BASE
Art | type |
---|---|
Prefix | beliebiger Typ oder Untertyp T |
Ergebnistyp | Basistyp von T |
Beschränkungen | Dieses Attribut ist nur als Präfix zu Namen anderer Attribute zu verwenden, z. B. T'BASE'LEFT. |
T'LEFT
Art | value |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Ergebnistyp | gleicher Typ wie T |
Ergebnis | linker Wert von T |
T'RIGHT
Art | value |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Ergebnistyp | gleicher Typ wie T |
Ergebnis | rechter Wert von T |
T'HIGH
Art | value |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Ergebnistyp | gleicher Typ wie T |
Ergebnis | obere Grenze von T |
T'LOW
Art | value |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Ergebnistyp | gleicher Typ wie T |
Ergebnis | unterer Grenze von T |
T'ASCENDING
Art | value |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Ergebnistyp | boolean |
Ergebnis | TRUE wenn T einen steigenden Indexbereich hat, ansonsten FALSE. |
T'IMAGE(X)
Art | function |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Parameter | ein Ausdruck, der den Typ der Basistyp von T ist |
Ergebnistyp | string |
Ergebnis | Der Wert von X wird als string ausgegeben. Im Zweifelsfall in kleinen Buchstaben und ohne zusätzliche Zeichen (Ausnahmen: Extended Identifier → \ ; Character Litera → `). Physikalische Typen werden allgemein mit der Basiseinheit ausgegeben, außer der Typ TIME. Bei diesem bestimmt die eingestellte Auflösungsgrenze des Simulators die Einheit. Reale Zahlen werden entsprechend der Einstellung auf R Kommastellen genau ausgegeben. Unnötige Nullen werden bei Zahlen weggelassen. Die Zeicheersetzungen aus See Ersetzen von Zeichen sind nicht erlaubt. |
Beschränkungen | Der Parametertyp muß im Subtyp des Prefix enthalten sein. |
T'VALUE(X)
Art | function |
---|---|
Prefix | beliebiger skalarer Typ oder Untertyp T |
Parameter | ein Ausdruck vom Typ string |
Ergebnistyp | Basistyp von T |
Ergebnis | Der Wert von T dessen string-Darstellung X ist. Zusätzliche Leerzeichen vorne oder hinten sind erlaubt und werden ignoriert. Numerische Typen werden können als Zahlen mit einer erlaubten Basis dargestellt werden. Bei Physikalischen Typen kann eine beliebige gültige Einheit verwendet werden. Die Zeicheersetzungen aus See Ersetzen von Zeichen sind erlaubt. |
Beschränkungen | Der Parameter muß eine gültige string-Darstellung eines Wertes vom Typ T sein. |
T'POS(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | Ausdruck, dessen Typ Basistyp von T ist |
Ergebnistyp | universal_integer |
Ergebnis | Position des Parameterwertes |
T'VAL(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | Ausdruck, dessen Typ integer ist |
Ergebnistyp | Basistyp von T |
Ergebnis | Wert des Elements, dessen Positionsnummer gleich X ist |
Beschränkungen | Es tritt ein Fehler auf, wenn das Ergebnis nicht im Bereich T'LOW to T'HIGH liegt. |
T'SUCC(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | Ausdruck, dessen Typ Basistyp von T ist |
Ergebnistyp | Basistyp von T |
Ergebnis | Wert des Elements, dessen Positionsnummer gleich X+1 ist |
Beschränkungen | Es tritt ein Fehler auf, wenn X=T'HIGH gilt, oder wenn X nicht im Bereich T'LOW to T'HIGH liegt. |
T'PRED(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | Ausdruck, dessen Typ Basistyp von T ist |
Ergebnistyp | Basistyp von T |
Ergebnis | Wert des Elements, dessen Positionsnummer gleich X-1 ist |
Beschränkungen | Es tritt ein Fehler auf, wenn X=T'LOW gilt, oder X nicht im Bereich T'LOW to T'HIGH liegt. |
T'LEFTOF(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | Ausdruck, dessen Typ Basistyp von T ist |
Ergebnistyp | Basistyp von T |
Ergebnis | Wert des Elements, das sich links von dem mit X angesprochenen Element befindet |
Beschränkungen | Es tritt ein Fehler auf, wenn X=T'LEFT gilt, oder X nicht im Bereich T'LOW to T'HIGH liegt. |
T'RIGHTOF(x)
Art | function |
---|---|
Prefix | beliebiger diskreter oder physischer Typ oder Untertyp T |
Parameter | expression whose base type is of the type T |
Ergebnistyp | Basistyp von T |
Ergebnis | Wert des Elements, das sich rechts von dem mit X angesprochenen Element befindet. |
Beschränkungen | Es tritt ein Fehler auf, wenn X=T'RIGHT gilt, oder X nicht im Bereich T'LOW to T'HIGH liegt. |
A'LEFT[(n)]
Art | function |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet. |
Ergebnistyp | Typ des linken Grenzelements des n'ten Indexbereiches von A. |
Ergebnis | Linkes Grenzelement des n'ten Indexbereiches von A |
A'RIGHT[(n)]
Art | function |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet |
Ergebnistyp | Typ des rechten Grenzelements des n'ten Indexbereiches von A |
Ergebnis | Rechtes Grenzelement des n'ten Indexbereiches von A |
A'HIGH[(n)]
Art | function |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet |
Ergebnistyp | Typ des oberen Grenzelements des n'ten Indexbereiches von A |
Ergebnis | Oberes Grenzelement des n'ten Indexbereiches von A |
A'LOW[(n)]
Art | function |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet. |
Ergebnistyp | Typ des unteren Grenzelements des n'ten Indexbereiches von A |
Ergebnis | Unteres Grenzelement des n'ten Indexbereiches von A |
A'RANGE[(n)]
Art | range |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist, ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet |
Ergebnistyp | Typ des n'ten Indexbereiches von A |
Ergebnis | Der Bereich A'RIGHT(n) to A'LEFT(n) für eine ansteigende oder A'RIGHT(n) downto A'LEFT(n) für eine abfallende Richtung des n'ten Indexbereiches von A. |
A'REVERSE_RANGE[(n)]
Art | range |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist, ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet |
Ergebnistyp | Typ des n'ten Indexbereiches von A |
Ergebnis | Der Bereich A'RIGHT(n) downto A'LEFT(n) für eine ansteigende oder A'RIGHT(n) to A'LEFT(n) für eine abfallende Richtung des n'ten Indexbereiches von A. |
A'LENGTH[(n)]
Art | value |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist ein alias von diesem oder ein bedingter Array-Untertyp |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet |
Ergebnistyp | universal_integer |
Ergebnis | Anzahl der Werte des n'ten Indexbereiches |
A'ASCENDING[(n)]
Art | value |
---|---|
Prefix | Beliebiger Prefix, der als Arrayobjekt geeignet ist, ein alias von diesem oder ein bedingter Array-Untertyp. |
Parameter | Lokal statischer Ausdruck vom typ universal_integer, dessen Wert nicht die Dimension von A überschreiten darf. Bei Fehlen des Parameters wird der Defaultwert 1 verwendet. |
Ergebnistyp | boolean |
Ergebnis | TRUE wenn der n'te Indexbereich von A steigend definiert ist, ansonsten FALSE. |
S'DELAYED[(t)]
Art | signal |
---|---|
Prefix | Beliebiges Signal |
Parameter | Statischer Ausdruck des Typs time, der einen Wert größer 0 liefert. Bei Fehlen von t wird der Defaultwert 0 verwendet. |
Ergebnistyp | Basistyp von S |
Ergebnis | Ein um t Zeiteineheiten verzögertes Signal, äquivalent zu S. |
S'STABLE[(t)]
Art | signal |
---|---|
Prefix | Beliebiges Signal |
Parameter | Statischer Ausdruck des Typs time, der einen Wert größer 0 liefert. Bei Fehlen von t wird der Defaultwert 0 verwendet. |
Ergebnistyp | boolean |
Ergebnis | Ein Signal, das den Wert TRUE besitzt, wenn für t Zeiteinheiten kein Event an S aufgetreten ist; ansonsten besitzt es den Wert FALSE. |
S'QUIET[(t)]
Art | signal |
---|---|
Prefix | Beliebiges Signal |
Parameter | Statischer Ausdruck des Typs time, der einen Wert größer 0 liefert. Bei Fehlen von t wird der Defaultwert 0 verwendet. |
Ergebnistyp | boolean |
Ergebnis | Ein Signal, das den Wert TRUE besitzt, wenn S für t Zeiteinheiten ruhig war; ansonsten besitzt es den Wert FALSE. |
S'TRANSACTION
Art | signal |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | bit |
Ergebnis | Ein Signal, dessen Wert innerhalb jeden Simulationszykluses, in dem das Signal S aktiviert wird, invertiert wird. |
Beschränkungen | Eine Beschreibung darf nicht vom Anfangswert von S'TRANSACTION abhängen. |
S'EVENT
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | boolean |
Ergebnis | Ein Signal, das den Wert TRUE besitzt, wenn im aktuellen Simulationszyklus ein Event an S aufgetreten ist; ansonsten besitzt es den Wert FALSE. |
S'ACTIVE
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | boolean |
Ergebnis | Ein Signal, das den Wert TRUE besitzt, wenn S im aktuellen Simulationszyklus aktiv ist; ansonsten besitzt es den Wert FALSE. |
S'LAST_EVENT
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | time |
Ergebnis | Die Anzahl der Zeiteinheiten seit dem letzten Eintreten eines Events an S. |
S'LAST_ACTIVE
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | time |
Ergebnis | Die Anzahl der Zeiteinheiten seit dem letzten Zeitpunkt, an dem S aktiv war. |
S'LAST_VALUE
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | Basistyp von S |
Ergebnis | Der letzte Wert von S vor dem letzten Wechsel |
S'DRIVING
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | boolean |
Ergebnis | S = skalar: FALSE wenn der Wert des Treibers von S im betrachteten Prozeß von einer NULL Transaktion bestimmt wird (inaktiv); ansonsten TRUE (aktiv). S = zusammengesetzt: TRUE wenn für jedes Element R von S gilt R'DRIVING=TRUE; ansonsten FALSE. S = leerer Arrayausschnitt: S'DRIVING=TRUE. |
Beschränkungen | Dieses Attribut ist nur innerhalb eines Prozesses, einer nebenläufigen Anweisung, für die ein entsprechender Prozeß ezistiert, und in Unterprogrammen verfügbar. Ist S ein Schnittstellensignal, muß dieses den mode inout, out oder buffer haben. Taucht dieses Attribut in einem Unterprogramm auf, so muß S ein formaler Parameter des Unterprogramms oder eines seiner Eltern sein und ein deklariertes Objekt einer Prozeß Anweisung sein. Der formale Parameter des Unterprogramms muß den mode inout oder out besitzen. |
S'DRIVING_VALUE
Art | function |
---|---|
Prefix | Beliebiges Signal |
Ergebnistyp | Basistyp von S |
Ergebnis | S = skalar: Aktueller Wert des Treibers von S im betrachteten Prozeß. S = zusammengesetzt: Entsprechendes Aggregat. S = leerer Arrayausschnitt: leerer Arrayausschnitt. |
Beschränkungen | Dieses Attribut ist nur innerhalb eines Prozesses, einer nebenläufigen Anweisung, für die ein entsprechender Prozeß ezistiert, und in Unterprogrammen verfügbar. Ist S ein Schnittstellensignal, muß dieses den mode inout, out oder buffer haben. Taucht dieses Attribut in einem Unterprogramm auf, so muß S ein formaler Parameter des Unterprogramms oder eines seiner Eltern sein und ein deklariertes Objekt einer Prozeß Anweisung sein. Der formale Parameter des Unterprogramms muß den mode inout oder out besitzen. S'DRIVING muß TRUE sein zur Zeit, wenn S'DRIVING_VALUE berechnet werden soll. |
E'SIMPLE_NAME
Art | value |
---|---|
Prefix | Beliebiges benamtes Objekt (siehe See Attribut Spezifikation) |
Ergebnistyp | string |
Ergebnis | Der einfache Name, Character Symbol oder Operator Symbol des benamten Objekts ohne zusätzliche Leerzeichen vorne oder hinten. (Ausnahmen: Charakter Symbole → ` und erweiterte Bezeichner→ \). Außer bei erweiterten Bezeichnern werden kleine Buchstaben verwendet. |
E'INSTANCE_NAME
Art | value |
---|---|
Prefix | Beliebiges benamtes Objekt (siehe See Attribut Spezifikation)), außer lokale Ports und Generics einer Komponentendeklaration |
Ergebnistyp | string |
Ergebnis | Der komplette hierarchische Pfad samt eingebundenen Entities beginnend von der aktuellen Ebene bis zu dem bezeichneten Objekt. |
E'PATH_NAME
Art | value |
---|---|
Prefix | Beliebiges benamtes Objekt (siehe See Attribut Spezifikation)), außer lokale Ports und Generics einer Komponentendeklaration |
Ergebnistyp | string |
Ergebnis | Der komplette hierarchische Pfad ohne eingebundenen Entities beginnend auf der obersten Ebene bis zu dem bezeichneten Objekt. |
B'BEHAVIOUR (nur VHDL'87)
Art | value |
---|---|
Prefix | Beliebiger Block oder beliebige Architektur einer Entity |
Ergebnistyp | boolean |
Ergebnis | Ein Wert, der TRUE ist, wenn der Block bzw. die Architektur keine Komponenteninstatiierung enthält; asnonsten ist der Wert FALSE. |
B'STRUCTURE (nur VHDL'87)
Art | value |
---|---|
Prefix | Beliebiger Block oder beliebige Architektur einer Entity |
Ergebnistyp | boolean |
Ergebnis | Ein Wert, der TRUE ist, wenn der Block bzw. die Architektur weder eine passive Prozeßanweisung noch eine nebenläufige Anweisung mit einer entsprechenden Prozeßanweisung enthält; asnonsten ist der Wert FALSE. |