HDLs führen keinen Übergang von VB zu RTL durch, d.h. die Systembeschreibung unter Verwendung einer HDL erfordert explizite Formulierung der RTL, anders als bei prozessororientierten Programmiersprachen wie C.
HDLs ermöglichen sowohl SB als auch VB des Systems, häufig gemischt und hierarchisch.
Eine HDL sollte technologieunabhängig sein, d.h. eine VB muß für FPGAs genauso wie für ASICs verwendbar sein, und muss die gleiche Funktionalität ergeben.
Die Abstraktionsebene einer HDL ist durch VB höher als reine SB, was kürzere Entwicklungszeiten und eine höhere Entwurfssicherheit bedeutet.
VHDL bietet im Gegensatz zu Verilog HDL ein universelles und nutzerdefinierbares Typensystem. VHDL ist semantisch streng typisiert.
VHDL bietet ein
bit, signed, float, string,
…],
type defintion
],
type a
≠ type b
]
Typsystem. Strenge Typisierung reduziert Entwurfsfehler, erhöht aber den syntaktischen und semantischen Programmieraufwand.
VHDL unterstützt statische Funktionen, die mit unterschiedlichen Funktionstypen überladen werden können.
function ”+” (std_logic_vector;std_logic_vector)
return std_logic_vector;
function ”+” (std_logic_vector;integer)
return std_logic_vector;
function ”+” (signed;signed)
return signed;
Eine Funktion beschreibt in VHDL eine Abbildungsvorschrift (i.A. kombinatorische Logik) von Eingangs- auf Ausgangssignale! Rein funktional ohne Speicher und sequenziellen Ablauf!
VHDL ist modulorientiert und hierarchisch strukturiert.
Die Beschreibung einer Digitallogikschaltung, Komponente genannt, benötigt wenig- stens zwei Strukturelemente. Ein Modul (≡eine VHDL Quelldatei) ist daher unterteilt in:
Die Port-Schnittstelle legt Typ und Richtung des Anschlüsse einer Entity fest. Die Architektur unterteilt sich in einen Deklarationsteil und einen Körper, der die eigentlichen VHDL-Anweisungen (VB & SB)aufnimmt.
Wie bei elektrischen Schaltkreisen können verschiedene Module gleichen oder verschiedenen Typs strukturell miteinander verbunden werden.
Diesen Vorgang der Einbindung bezeichnet man als Komponenteninstanzierung. Eine externe Komponente ≡ Modul muß im VHDL Deklarationskopf gemäß ihrer Anschlüsse deklariert werden, und kann im VHDL-Anweisungsteil (Architektur-Körper) eingebunden werden (SB).
Die strukturelle Modellierung unter- scheidet zwischen der Komponentende- finition, der Verhaltensbeschreibung einer Komponente (Entity), und der Kom- ponenteninstanziierung, d.h. die Einbin- dung von Komponenten.
Die einzubindenden Komponenten müssen mit ihrer Port-Schnittstelle (identisch zum Entity-Port) im Dekla- rationsteil der Architektur eingeführt werden.
Eine Komponente eines bestimmten Typs kann beliebig oft dupliziert im Ar- chitekturkörper eingebunden werden.
Jede Komponenteninstanz ist unabhängig von jeder anderen, d.h. mit eigener Digitallogik synthetisiert.
Definition 1. |
Definition 2. |
Signale sind die eigentlichen Datenobjekte in VHDL.
Der einfachste Signaltyp ist ein Bit mit der Wertemenge bit={0,1}.
Ein Signal kann aus einer Bitgruppe == Datenwort mit beliebiger Anzahl von Einzelsignalen bestehen, genannt Vektor.
Synthese von Signalen erfolgt durch
Signale können in der Port-Deklaration global sichtbar oder innerhalb des Architekturdeklarationsteils lokal sichtbar erzeugt werden.
Definition 3.
Beispiel einer Port-Deklaration:
port (
data : in bit;
addr : in bit_vector(7 downto 0)
);
Definition 4.
Signalvektoren der Datenbreite N werden wie Signale definiert.
Der Typbezeichner wird um ”_vector” ergänzt. Die Angabe des Index-Intervalls kann auf zwei Arten erfolgen, entsprechend der Stelle des höchstwertigsten Bits (MSB).
Wird die Indexrichtung b downto
a verwendet, befindet sich das MSB immer auf der linken Seite einer Binärzahl MSB .. LSB , wird die Indexrichtung a to
b gewählt, auf der rechten Seite LSB .. MSB.
Der untere Index a kann mit jedem beliebigen natürlichen Zahlenwert gewählt werden. Der Wert 0 mit der b downto
a Darstellung ist aber zweckmäßig anzuwenden.
architecture main of en is
signal incr: bit;
signal data : signed(7 downto 0);
begin
incr <= WE and ADDR=X"01" ;
process (write,data)
if incr = '1' then
data <= data + 1;
else
data <= data - 1;
end if;
end process;
end;
Definition 5.
Nebenläufige Signalzuweisungen, dass sind alle Toplevelanweisungen im Architekturkörper und ausgenommen bedingte Ausrücke in Prozessen, dürfen immer nur eine Quelle besitzen, d.h. in obigen Beispiel ist immer nur eine Signalzuweisung erlaubt!
Wertemenge {true
,false
}
{keine spezifische Datenbreite, wird bei der Syntehse bestimmt, i.A. wird aber nur eine Wertemenge von 32/64 Bit unterstützt}
Wertemenge {natural ⊆ integer ≥ 0}
Wertemenge {positive ⊆ integer > 0}
Wertemenge {0,1
}
Definiert ein Array von Bits
Textzeichen, Wertemenge mit ASCII Kodierung
Definiert ein Array von Textzeichen
Wertemenge {0,1,H,L,U,Z,-
}, muss über das Paket IEEE.STD_LOGIC_1164.ALL eingebunden werden.
Definiert ein Array von std_logic {0,1,H,L,U,Z,-
}, muss über das Paket IEEE.STD_LOGIC_1164.ALL
eingebunden werden.
Vorzeichenbehaftete und vorzeichenlose ganze Zahlen mit Binärkodierung, muss über das Paket IEEE.NUMERIC_BIT.ALL
eingebunden werden.
Abstrakte Aufzählungstypen werden z.B. zur symbolischen Beschreibung der Zustände eines Zustandsautomaten verwendet.
Abstrakte konstante Aufzählungstypen definieren eine Menge von Symbolen, die noch keine konkrete Kodierung zugeordnet sind.
Definition 6.
Der Symbolelementname ist ein beliebiger Identifizierername (nutzerdefiniert)
Datentypen werden i.A. im Kopfteil einer Architektur definiert.
...
type states is (
S_start,
S_loop,
S_end
);
signal state: states;
signal next_state: states;
begin
...
process fsm()
case state is
when S_start => next_state := S_loop;
when S_loop => ...
end case;
end process;
Welche Kodierungen könnten die Symbolemente eines Aufzählungstyps in der Digitallogik besitzen?
Nenne Vorteile und Nachteile der unterschiedlichen Kodierungen
VHDL unterstützt zur einsortigen Aggregation Arrays.
Der Arraytyp kann beliebig sein. Arrays können wie RAM-Blöcke mit adressierbaren Speicherzellen aufgefasst werden.
Ob jedoch ein monolithischer RAM-Block während der Synthese erzeugt werden kann, hängt von der Verwendung in der Verhaltensbeschreibung eines Arrays ab.
Wenn nebenläufig z.B. mehrere Arrayzellen gelesen werden, ist die Inferenz eines klassischen RAM Speicher mit nur einem Leseport nicht mehr möglich!
Arrays werden wie generische Typen aufgefasst, anders als in imperativen Programmiersprachen wie C.
Definition 7.
Zuerst muss ein Arraytyp definiert werden, dann können Signale definiert werden.
Beispiel für Arrays
type ram is array(0 to 255) of bit_vector(7 downto 0);
signal ram1: ram;
signal data: bit_vector(7 downto 0);
... data <= ram1(addr); ...
Bei der VB wird das Verhalten einer Komponente durch die Reaktion der Ausgangssignale auf Änderungen der Eingangssignale beschrieben.
Bei einer reinen VB findet keine weitere Verzweigung in Unterkomponenten statt.
In der VB werden zwei Anweisungsklassen unterschieden:
Sequenzielle Anweisungen können nur in Prozessen verwendet werden und erzeugen Speicher.
Sequenzielle Anweisungen einer Hardwarebeschreibungssprache sind nicht mit Programmsequenzen zu verwechseln.
Wenn überhaupt ist eine Sequenz im Sinne einer Laufzeithierarchie und Evaluierungsreihenfolge zu verstehen.
Register können nur in Prozessen erzeugt werden.
VHDL synthetisiert Register (FLIP-FLOPs, Latches) implizit, d.h. es gibt in VHDL keine Möglichkeit, ein Register explizit zu erzeugen. Die Registerinferenz ergibt sich aus der Verhaltenbeschreibung mit entsprechenden VHDL-Anweisungen.
Ein Prozess ist eine Blockkapselung von VHDL Anweisungen und gehört zur VB. Prozesse werden zusammen mit Toplevelanweisungen ausserhalb von Prozessen konkurrierend/nebenläufig ausgeführt.
Anweisungen (= Evaluierungsvorschriften) in einem Prozess sind auf gleicher Ebene zueinander nebenläufig zu betrachten.
Alle Anweisungen (Signalzuweisungen) in einem Prozess werden zu einem einzigen finalen Ausdruck synthetisiert!
Definition 8.
Unvollständige bedingte Verzweigungen können (und sollen!) Register erzeugen.
Immer wenn es einen bedingten Fall (Ausdruck) in einem Prozess gibt, der bei einer bestimmten Eingangsvektor kein Ergebnis eines bestimmten Ausgnagssignals ergibt, ist gemäss dem zu grundeliegenden Modell ein Register als Zustandsspeicher erforderlich.
Dabei muss man zwischen taktflankengesteuerten (dynamischen) und Registern und datengesteuerten (statischen) Latches unterscheiden.
Eine Signaländerung (Flanke) kann kombinatorisch durch ein event Attribut ageleitet werden: signalname'event
.
Definition 9.
Prozesse modellieren prozedurale Vorgänge.
Das Modell eines prozeduralen Verhaltens sieht neben Ablaufsteuerung die “scheinbare” Aktivierung und Suspendierung (Blockierung) des Ablaufes eines Prozesses vor.
Toplevelanweisungen sind im Gegensatz zu Prozessen immer aktiv, worin begründet ist, daß Toplevelanweisungen keine Register modellieren können, da diese nur unter bestimmten Bedingungen aktiv sind, d.h. Daten für die Speicherung übernehmen können.
Prozesse werden durch zwei verschiedene Möglichkeiten aktiviert, die sich gegenseitig ausschliessen:
Prozesse bestehen aus einem Deklarations- und Anweisungsteil (Körper).
Prozesse mit Eingangssignalaktivierung | Prozesse mit Wait Aktivierung |
Das zeiltiche Konditional bei der wait Anweisung ist nicht synthetisierbar, nur simulierbar.
Es gibt in VHDL verschiedene temporale Verzögerungsmodelle die an die Ausdrucksevaluierung gebunden sind [I]:
Standard-Verzögerungsmodell: Geeignet für die Modellierung von Verzögerungen durch Geräte mit Trägheit (z.B. Logikgattern). Impulse, die kürzer als die Verzögerung eines Geräts sind, werden nicht an den Ausgang weitergeleitet
Modellverzögerungen durch Elemente ohne “Trägheit”, z. B. Drähte. Keine Trägheit bedeutet alle Eingangsereignisse werden zu Ausgangssignalen übertragen. Ein beliebiger Impuls, nicht zu kurz, wird weitergeleitet.
Die Delta-Verzögerung ist ein Sonderfall der Verzögerung, die unendlich klein ist
Signalzuweisungen in Prozessen werden erst am Ende der Aktivierung eines Prozesses sichtbar!
signal a,x,y: integer;
process (a,x,y)
begin
x <= a+1;
y <= x-1;
wait for 10ns; -- Nur zur Simulation
end process
Zusammenfassung:
Definition 10.
signal y: integer;
proces (a,b)
variable v1,v2: integer;
begin
v1 := 3 * a + 7 * b;
v2 := a * b + 5 * v1;
y <= v1 + v2;
end process;
Prüfe den Vergleich von abhängigen Signal- und Variablezuweisung in Prozessen an einem einfachen Beispiel mit dem Simualtor ghdl (und Visualisierung mit gtkwave)
Unetrusche und vergleiche die verschiedenen VHDL Verzögerungsemodelle in der Simulation
Definition 11.
Beispiel
Y <= '0' when I = "00" else
'0' when I = "11" else
'1';
Definition 12.
Beispiel
process
if Y = "00" then
I <= '0';
elsif Y = "11" then
I <= '0';
else
I <= '1';
end if;
end process;
Definition 13.
In VHDL lassen sich ähnlich wie in imperativen Programmiersprachen Anweisungsblöcke mit Schleifen iterativ wiederholen.
Man unterscheidet zwischen
Bei statischen Zählschleifen in VHDL muss der Schleifenindex nicht deklariert werden.
Statische Schleifen werden bei der Synthese abgerollt, und die Statements im Schleifenkörper mit den entsprechenden Indexwert repliziert.
Definition 14.
Man unterscheidet zwei Klassen von Simulatoren und Simulationen:
Eine Simulation besteht aus dem Device under Test (DUT) und einer Testbesschreibung (Stimuli)
GHDL ist ein Verhaltenssimulator für die VHDL-Sprache.
Mit GHDL kann VHDL-Code direkt in eine Maschinenprogramm kompiliert und ausgeführt werden.
fixed_generic_pkg
oder float_generic_pkg
zu unterstützen).
Durch die Verwendung eines Codegenerators ist GHDL viel schneller als jeder interpretierende Simulatoren.
Erstellung eines DUT Modells in einer separaten Textdatei. Wichtig: Der Einheitsname und der Dateiname ohne Endung müssen identisch sein.
Erstellung einer Testbench die folgende Teile enthält:
Analyse des VHDL Modells
> ghdl -a <testbench>.vhdl
> ghdl -e <testbench>
> <testbench> --stop-time=xxus --vcd=<testbench>.vcd
gtkwave <testbench>.vcd
> ghdl -r <testbench> --stop-time=xxus --vcd=<testbench>.vcd
library ieee ; use ieee.std_logic_1164.all ;
entity shift_reg is
port ( serial_in , clk , shift_ena : in std_logic ;
serial_out : out std_logic);
end shift_reg ;
architecture behav of shift_reg is
signal q : std_logic_vector (3 downto 0);
begin
-- shift register process --
process ( clk )
begin
if rising_edge ( clk ) then
if shift_ena = '1' then
q (3 downto 1) <= q (2 downto 0);
q (0) <= serial_in ;
end if ;
end if ;
end process ;
serial_out <= q (3);
end behav;
library ieee; use ieee.std_logic_1164.all;
entity shift_tb is
port (
clk_out : out std_logic;
monitor : out std_logic
);
end shift_tb ;
architecture behaviour of shift_tb is
constant clk_period : time := 100 ns;
component shift_reg
port ( serial_in , clk , shift_ena : in std_logic ;
serial_out : out std_logic );
end component;
signal clk, serial_in_test, shift_ena_test : std_logic;
begin
...
end behaviour;
|
|