vhdl_reference_93:deutsch

Design Entities und Configurations

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 ;

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 ;

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

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.

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 ) ;
  • 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.

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

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).

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.

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 ;

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.

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 ;

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;

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 ; 

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.

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

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

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 ;

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.

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 ;

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

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 ;

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

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 ;

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.

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 ;

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.

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;

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.

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" ;
  • Interface-Declarations definieren Schnittstellenobjekte von einem genau festgelegten Typ.
  • Schnittstellenobjekte sind (Schnittstellen-) Konstanten, (Schnittstellen-) Signale, (Schnittstellen-) Variablen und (Schnittstellen-) Dateien.

[ signal ] identifier_list : [ mode ] subtype_indication [ bus ] [ := static _expression ]

– subtype_indication darf kein Datei- oder Pointertyp sein.

file identifier_list : subtype_indication

– subtype_indication muß einen Untertyp eines Deteityps bezeichnen.

  • 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”.

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.

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

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.

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

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 ;

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

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

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

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.)

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

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

Über einen einfachen Namen können verschiedene Objekte im VHDl-Code angesprochen und manipuliert werden.

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

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 )

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

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

expression

Jeder Ausdruck entspricht einer Gleichung, die eine Vorschrift zur Berechnung eines Wertes bildet.

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.

Das Symbol T steht für true (Typ boolean ), '1' (Typ bit ).

Das Symbol F steht für false (Typ boolean ), '0' (Typ bit ).

  • 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 .

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)

Operator Operation Typ der Operanden Typ des Ergebnisses
= Gleichheit beliebig boolean
/= Ungleichheit beliebig boolean
< <=
> >=
Vergleich jeder skalare Typ oder ein Feldtyp boolean

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

Die Additionsoperatoren + und - sind in ihrer bekannten Bedeutung für jeden numerischen Typ vordefiniert.

Der Verkettungsoperator (Concatination) & ist für beliebige eindimensionale Feldtypen vordefiniert.

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

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)

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.

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

Die Operatoren * und / sind für jeden beliebigen physikalischen Typ vordefiniert.

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

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 .

Operator Operation Typ des Operanden Typ des Ergebnisses
ABS absoluter Wert beliebiger numerischer Typ gleicher Typ
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.

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.

""

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

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

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;

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)

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 )

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.

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ß.

Ein universeller Ausdruck ist ein Ausdruck, der als Ergebnis entweder den Typ universal integer oder universal real liefert.

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

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).

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 ;

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.

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 ;

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.

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

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.

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;

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;

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

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 ;

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 ;

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 ;

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 ;

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 ;

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.

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 ;

Durch die NULL -Anweisung wird explizit erwirkt, daß keine Aktion ausgeführt wird.

NULL ;

Nebenläufige Anweisungen

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 ;

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).

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 ;

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.

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 ;

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.

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 ;

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 !

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 ;

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.

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 ;

In VHDL'87 war kein deklarativer Bereich zugelassen.

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

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

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).

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.

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 ;

Die USE -Anweisung kann auch als Kontext-Anweisung vor jedem Bibliothekenbaustein, d. h. entity, architecture, package, package body und configuration, gestellt werden.

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 ;

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ß.

Die LIBRARY -Anweisung ist als Kontext-Anweisung vor jedem Bibliothekenbaustein, d. h. entity, architecture, package, package body und configuration anführbar.

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!

Simulation Flow

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 of Generic Statement

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.

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.

Elaboration of a Generic Map

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.

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 )

Elaboration of a Port Map

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.

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.

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.

Elaboration of a Subprogram

Elaboration of a Type

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.

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.

Elaboration of a Subtype

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.

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.

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.

Elaboration of an Alias

Es wird ein Template erzeugt, mit dem die Definition von Attributen für die jeweiligen Elemente möglich wird.

Elaboration of an Attribute

Das System erzeugt ein Template zur Bildung der Instanzen der Komponente.

Hierbei werden zusätzliche Informationen einem vorher deklarierten Programmteil zugeordnet.

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.

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.

Elaboration of a Configuration

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 of a Disconnection

Die Elaborationsregeln gelten für alle Anweisungsteile mit Ausnahme einer Architektur, die mit dem Attribut FOREIGN versehen ist. Diese werden implementierungsabhängig elaboriert.

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.

Elaboration of a Block Statement

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.

Elaboration of a Generate Statement

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.).

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.

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.

Elaboration of other concurrent statement

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.

Dynamic Elaboration of a FOR loop

  • 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.

Dynamic Elaboration of a Subprogram

  • 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!

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.

Elaboration of a Design Hierarchy

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

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.

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.

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

(g) Formatierungsanweisungen ( format_effectors ) sind

  • Tabulator (horizontal und vertikal),
  • Wagenrücklauf (carriage return),
  • Zeilenvorschub (line feed) und
  • Seitenvorschub (form feed).

Jedes lexikalische Element muß in eine Zeile passen, da das Zeilenende ein Trennzeichen bildet.

Ein Basis-Bezeichner darf keine Leerzeichen enthalten !

  • 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

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
  • 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.

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

Bei den Basisangaben steht B für binär, O für oktal und X für hexadezimal.

Kommentare werden zur Erklärung des VHDL-Codes verwendet.

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

Ein reserviertes Wort darf nicht als ein explizit deklarierter Bezeichner verwendet werden.

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

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.
Art value
Prefix beliebiger skalarer Typ oder Untertyp T
Ergebnistyp gleicher Typ wie T
Ergebnis linker Wert von T
Art value
Prefix beliebiger skalarer Typ oder Untertyp T
Ergebnistyp gleicher Typ wie T
Ergebnis rechter Wert von T
Art value
Prefix beliebiger skalarer Typ oder Untertyp T
Ergebnistyp gleicher Typ wie T
Ergebnis obere Grenze von T
Art value
Prefix beliebiger skalarer Typ oder Untertyp T
Ergebnistyp gleicher Typ wie T
Ergebnis unterer Grenze von T
Art value
Prefix beliebiger skalarer Typ oder Untertyp T
Ergebnistyp boolean
Ergebnis TRUE wenn T einen steigenden Indexbereich hat, ansonsten FALSE.
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.
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.
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
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.
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.
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.
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.
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.
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
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
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
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
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
Art function
Prefix Beliebiges Signal
Ergebnistyp time
Ergebnis Die Anzahl der Zeiteinheiten seit dem letzten Eintreten eines Events an S.
Art function
Prefix Beliebiges Signal
Ergebnistyp time
Ergebnis Die Anzahl der Zeiteinheiten seit dem letzten Zeitpunkt, an dem S aktiv war.
Art function
Prefix Beliebiges Signal
Ergebnistyp Basistyp von S
Ergebnis Der letzte Wert von S vor dem letzten Wechsel
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.
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.
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.
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.
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.
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.
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.