Unterlagen zu Versuch 2
Unterlagen zu Versuch 2
Unterlagen zu Versuch 2
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
IL<br />
IS<br />
VS<br />
PRAKTIKUM ZUR<br />
VORLESUNG<br />
Rechnergesteuerte Systeme 2<br />
VERSUCH 2<br />
VHDL-VERHALTENSBESCHREIBUNG<br />
Name: Matrikelnummer:<br />
Vorname: Gruppennummer:<br />
Betreuer: Datum:<br />
Universität Duisburg-Essen<br />
Fak. 5, Abt. IIMT, Institut für<br />
Informationstechnik (IT)<br />
Verteilte Systeme (VS)<br />
© Dr.-Ing. Heinz-Dieter Hümmer<br />
Universität Duisburg-Essen<br />
Fak. 5, IIMT, IT/VS
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
Hinweise<br />
• Arbeiten Sie den anliegenden Vorbereitungstext sorgfältig durch.<br />
• Lösen Sie die im Vorbereitungstext gestellten Aufgaben und bringen Sie Ihre Ergebnisse <strong>zu</strong>m <strong>Versuch</strong>stermin<br />
mit.<br />
• Beantworten Sie <strong>zu</strong>m Antestat die folgenden Fragen.<br />
Vorbereitende Fragen<br />
1. Wie werden Anweisungen einer „Architecture“ innerhalb, bzw. außerhalb eines Prozesses behandelt?<br />
a) außerhalb: sequentiell b) außerhalb: simultan<br />
c) innerhalb: sequentiell d) innerhalb: simultan<br />
2. Aus welchen Bestandteilen besteht eine „Testbench“ und welche Funktionen erfüllen sie?<br />
3. Könnte die “port-map“-Anweisung der „Testbench“ auf Seite 6 auch unterhalb des Prozesses stehen?<br />
Begründen Sie Ihre Antwort.<br />
4. Erläutern Sie die Unterschiede zwischen Signalen und Variablen in Hinsicht auf deren Deklaration,<br />
Zuweisung und Wertaktualisierung.<br />
5. Wie groß ist der Ergebnisvektor in Aufgabe 2 <strong>zu</strong> wählen, damit selbst die Multiplikation der größtmöglichen<br />
Werten keinen Überlauf verursacht:<br />
a) 4 Bit b) 8 Bit c) 16 Bit<br />
6. Wie oft wird die Multiplikationsschleife bei der Multiplikation zwei vierstelliger Zahlen durchlaufen?<br />
a) 4 mal b) 8 mal c) 16 mal<br />
7. Entwerfen Sie eine Prozess die das gleiche Verhalten der ersten 40 ns des folgenden Codes aufweist.<br />
Überlegen Sie sich dabei, nach welchen Regeln eine Signalaktualisierung erfolgt.<br />
entity counter is<br />
end counter;<br />
architecture behave of counter is<br />
signal val2: integer :=0 ;<br />
begin<br />
val2
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
1. Einleitung<br />
Das Ziel dieses <strong>Versuch</strong>es ist es VHDL-Anfänger anhand praktischer Beispiele in die sequentiellen Modellierungsmöglichkeiten<br />
von VHDL ein<strong>zu</strong>führen. Zunächst werden die Syntaxkonstrukte von VHDL, die<br />
<strong>zu</strong>r sequentiellen Modellierung notwendig sind, vorgestellt. Anschließend werden Analogien zwischen<br />
der Programmierung in einer Hochsprache (Ada, C, usw.) und der VHDL-Programmierung anhand eines<br />
Beispiels aufgezeigt, was das Verständnis der Thematik dieses <strong>Versuch</strong>es erleichtern soll.<br />
Dieser <strong>Versuch</strong> setzt ein gewisses Maß an Basiswissen über VHDL voraus. Neben dem grundlegenden<br />
Aufbau von entity und architecture sollte einem die Vorgehensweise bei der Erstellung eines einfachen<br />
Testbenches in Grundzügen bekannt sein.<br />
2. Sequentielle Syntaxkonstrukte in VHDL<br />
Programmierung in einer Hochsprache wie z.B Ada oder C entspricht der algorithmischen Modellierung.<br />
Dies ist eine sehr hohe Abstraktionsebene der Modellierung, bei der die Lösung eines Problems in Anweisungen,<br />
die zeitlich hintereinander ausgeführt werden sollen, angegeben wird. Eine Sprache, die<br />
algorithmische Modellierung erlaubt, sollte dem<strong>zu</strong>folge Notationen anbieten, mittels derer sequentielle<br />
Anweisungen gebildet werden können. Das grundlegende Syntaxkonstrukt in VHDL in diesem Zusammenhang<br />
ist process. Innerhalb von Prozessen werden die Anweisungen zeitlich hintereinander, also<br />
sequentiell ausgeführt.<br />
Die Deklaration von Prozessen, die nur innerhalb einer architecture erfolgen, hat folgendes Schema:<br />
[:] process [( )] is<br />
<br />
begin<br />
{}<br />
end process []<br />
Darin bedeuten:<br />
einen Bezeichner, der den VHDL-Prozess eindeutig kennzeichnet. Prinzipiell kann<br />
der Bezeichner auch weggelassen werden. Zur besseren Lesbarkeit sollte man jedoch möglichst alle<br />
Prozesse mit Namen versehen.<br />
(sensitivity list) eine geklammerte Liste von Signalen, die durch Kommata<br />
getrennt werden. Wertänderungen der Signale, die in der Empfindlichkeitsliste stehen, stoßen den<br />
Prozess an. Ist ein Prozess angestoßen, wird er bis <strong>zu</strong>m end process ausgeführt.<br />
eine Liste von Deklarationen. In Prozessen können insbesondere auch Variable<br />
deklariert werden (neben Konstanten und selbstdefinierten Datentypen). Als Datentypen für Variable<br />
kommen alle Typen in Frage, die auch für Signale erlaubt sind. Signale dürfen nicht in Prozessen<br />
deklariert werden, allerdings sind alle lokalen Signale der <strong>zu</strong>gehörigen architecture sowie die<br />
der port-Schnittstelle verwendbar.<br />
Innerhalb eines Prozesses sind nur sequentielle Anweisungen sowie Signal<strong>zu</strong>weisungen erlaubt, die<br />
durch die Schlüsselworte begin und end process eingerahmt werden.<br />
Bei Zuweisungen innerhalb eines Prozesses sind zwischen zwei Arten <strong>zu</strong> unterscheiden: Variablen<strong>zu</strong>weisung<br />
und Signal<strong>zu</strong>weisung.<br />
Der Wert einer Variable wird sofort nach einer Zuweisung – ähnlich wie die Variablen von Programmiersprachen<br />
- innerhalb des Prozesses verändert. Wenn der Prozess verlassen wird, bleibt der Variablenwert<br />
bis <strong>zu</strong>m nächsten Durchlauf erhalten.<br />
Beispiel:<br />
architecture arch1 of test is<br />
begin<br />
beispiel: process(a) is<br />
variable var : std_logic;<br />
begin<br />
var := '1';<br />
...;<br />
if var = '1' then<br />
Universität Duisburg-Essen; Fakultät 5; Abt. IIMT; Inst. Informationstechnik (IT), Verteilte Systeme (VS) Seite 3
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
var := '0'; -- wird in jedem Durchlauf ausgeführt<br />
...;<br />
else<br />
...;<br />
end if;<br />
end process beispiel;<br />
end arch1;<br />
Bei den Signal<strong>zu</strong>weisungen ist <strong>zu</strong> beachten, dass Signaländerungen, die bei der Ausführung der<br />
sequentiellen Anweisungen durch<strong>zu</strong>führen sind, erst am Prozessende aktualisiert werden.<br />
Beispiel:<br />
architecture arch2 of test is<br />
signal sig : std_logic;<br />
begin<br />
beispiel: process(a) is<br />
begin<br />
sig
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
}<br />
return n;<br />
void main(void) {<br />
char x,y;<br />
printf("x := ");<br />
scanf("%c",&x);<br />
y = numbits(x);<br />
printf("Anzahl der gesetzten Bits = %d \n",y);<br />
return;<br />
}<br />
Man beachte, dass in der Hochsprache C auf einen Datentyp char bitweise logische Verknüpfungen<br />
über das gesamte Datenwort (d & 1) und Verschiebeoperationen (d >> 1) möglich sind! Aus der arithmetischen<br />
Sicht entspricht (d & 1) der Abfrage, ob d gerade oder ungerade ist, also (d%2 == 1),<br />
wenn die Zahl auf ungerade <strong>zu</strong> prüfen ist.<br />
Ein Vergleich <strong>zu</strong>r Ada Lösung soll das aufzeigen. Ada ist strenger und lässt bitweise logische Verknüpfungen<br />
wie UND, ODER, usw. nicht einfach <strong>zu</strong>, wie C. Also muss char erst nachgebildet werden. Das<br />
erfolgt in der Typ-Vereinbarung type byte is mod 2**8;, dem sog. Modulartyp. Dieser Typ entspricht<br />
dem char im C-Programm. Modulartypen in Ada erlauben bitweise logische Verknüpfungen, wie im Programm<br />
mit (d and 1) <strong>zu</strong> sehen ist, aber keine Verschiebungen! Hier nutzen wir den Zusammenhang,<br />
dass die Rechtsverschiebung (Verschiebung <strong>zu</strong> kleineren Stellenwertigkeiten) einer ganzzahligen Dualzahl<br />
um eine Stelle der Division durch die Zahl 2 entspricht.<br />
Der Rest des Ada Programmes sollte nicht näher erläutert werden, sondern dient nur der Vollständigkeit,<br />
damit ein ablauffähiges Programm vorliegt. Nur soviel: Das Package ada.text_io.modular_io dient<br />
der Ein- Ausgabe auf dem Bildschirm. Es wird mit dem Typ byte neu erzeugt und mit dem Namen<br />
byte_io versehen, um die Ein- und Ausgabeprozeduren für Daten vom Typ byte bereit<strong>zu</strong>stellen.<br />
with ada.text_io, ada.integer_text_io;<br />
use ada.text_io, ada.integer_text_io;<br />
procedure test is<br />
type byte is mod 2**8; -- new type<br />
package byte_io is new ada.text_io.modular_io(byte);<br />
use byte_io;<br />
a,b : byte;<br />
function numbits(a :in byte) return byte is<br />
n, k, d : byte := 0;<br />
begin<br />
d := a;<br />
for k in 1..8 loop<br />
if (d and 1) = 1 then<br />
n := n + 1;<br />
end if;<br />
d := d / 2;<br />
end loop;<br />
return n;<br />
end numbits;<br />
begin<br />
put("a := ");<br />
get(a);<br />
b:= numbits(a);<br />
put("Anzahl der gesetzten Bits =");<br />
put(b);<br />
new_line;<br />
end test;<br />
Universität Duisburg-Essen; Fakultät 5; Abt. IIMT; Inst. Informationstechnik (IT), Verteilte Systeme (VS) Seite 5
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
Im VHDL Modell wollen wir nun <strong>zu</strong>r Multiplikation auf einen Bitvektor für den Operanden übergehen.<br />
Dies wurde uns oben bereits im C-Programm etwas näher gebracht. Den Bitzähler n für die gesetzen<br />
Bits wollen wir <strong>zu</strong>nächst als Integer-Typ belassen. Unser Modell ist also so noch nicht vollständig synthetisierbar!<br />
Der Test des niedrigstwertigen Bits im Datenwort mit dem Wert 1 zeigt hier die Bitfauflösung<br />
mit dem Bitvektor (d and "00000001"). Interessant und wichtig für die weiteren Betrachtungen ist die<br />
Schiebeoperation, die hier durch die Zuweisung d := ’0’ & d(7 downto 1); erreicht wird. Das ist nur<br />
<strong>zu</strong> verstehen, wenn man weiß, dass ein Bitvektor eine Zeichenkette ist und der &-Operator Zeichen aneinander<br />
kettet. Hier wird also die neue Zeichenkette d gebildet durch die ’0’, an die das verschobene d<br />
gekettet wird!<br />
entity numbits is<br />
port( inp :in bit_vector(7 downto 0);<br />
num :out integer);<br />
end numbits;<br />
architecture behavior of numbits is<br />
begin<br />
count: process(inp)<br />
variable d : bit _vector(7 downto 0);<br />
variable n, k : integer := 0;<br />
begin<br />
d := inp;<br />
for k in 1 to 8 loop<br />
if (d and "00000001") = "00000001" then<br />
n := n + 1;<br />
end if;<br />
d := '0' & d(7 downto 1);<br />
end loop;<br />
num
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
3. <strong>Versuch</strong>sziel<br />
In diesem <strong>Versuch</strong> soll die übliche Vorgehensweise bei einer Hardwareentwicklung - von der Idee bis<br />
<strong>zu</strong>r realisierbaren Schaltung - angedeutet werden. Ziel ist hier, die Entwicklung eines Multiplizierers, der<br />
zwei binäre, 4-Bit-breite, positive Zahlen miteinander multipliziert.<br />
3.1. Vorgehensweise<br />
Zunächst sollte der Entwickler den grundlegenden, sprachunabhängigen Algorithmus seiner Problemlösung<br />
finden. In unserem Fall kann dieser aus der bekannten schriftlichen Multiplikation mit mehrstelligem<br />
Multiplikator gewonnen werden.<br />
Multipliziert man zwei mehrstellige Zahlen, so führt man die Multiplikation stellenweise von der 10 0 Stelle<br />
<strong>zu</strong> höheren Stellenwertigkeiten durch. Üblicherweise bildet man <strong>zu</strong>erst alle Stellenmultiplikationen und<br />
addiert dann alle Zwischenergebnisse.<br />
Beispiel:<br />
536 * 237<br />
3752 -- 10 0<br />
1608 -- 10 1<br />
1072 -- 10 2<br />
127032<br />
Hier wird die Aufgabe - im Zehnersystem - auf zwei Multiplikationen<br />
mit einstelligem Multiplikator <strong>zu</strong>rückgeführt. Die Multiplikation<br />
mit der “(i - 1)-ten” Potenz der Zahlenbasis erfolg<br />
implizit durch die Stellenverschiebung der Ergebnisse.<br />
Für die Durchführung der Rechnung sind folgende Werkzeuge<br />
nötig:<br />
Stellenverschiebung<br />
Multiplikation mit einstelligem Multiplikator<br />
Addition<br />
Für eine technische Realisierung muss man die Dualzahlen-Darstellung annehmen. Die Stellenmultiplikation<br />
ergibt entweder Null, wenn die Multiplikatorstelle ’0’ ist oder den Multiplikanden, wenn sie ’1’ ist.<br />
Die Addition erfolgt nach jeder Stellenberechnung akkumulativ. Das weitere Beispiel für positive 4-bit<br />
Dualzahlen soll dies zeigen:<br />
Beispiel:<br />
3.2. Aufgabe 1<br />
1010 * 0110<br />
0000<br />
+ 0000 -- 2 0<br />
0000 – ZE1<br />
+ 1010 -- 2 1<br />
10100 – ZE2<br />
+ 1010 -- 2 2<br />
110100 – ZE2<br />
+ 0000 -- 2 3<br />
0110100 -- Erg<br />
Im Dualsystem ist jeweils die Summenbildung nach jeder<br />
Stelle angedeutet durch ZEi.<br />
Man erkennt den Algorithmus durch iterative Stellenverschiebung<br />
und Addition (Shift & Add).<br />
Entwickeln Sie einen Multiplizierer nach dem oben vorgestellten Algorithmus, der zwei positive, vierstellige<br />
Zahlen des Typs Integer im Zehnersystem Multipliziert.<br />
Erlaubte Werkzeuge sind:<br />
Schleifenkonstrukte (z.B. for-Schleifen);<br />
for k in 1 to 8 loop<br />
.....<br />
Universität Duisburg-Essen; Fakultät 5; Abt. IIMT; Inst. Informationstechnik (IT), Verteilte Systeme (VS) Seite 7
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
end loop;<br />
Stellenverschiebung in Form einer Multiplikation oder<br />
Division mit der (i-1)-ten Potenz der Basis 10<br />
Additionsoperator im Zehnersystem (+);<br />
Modulo Operator (mod);<br />
Multiplikation im Zehnersystem mit einem einstelligen Multiplikator (*).<br />
Gehen Sie dabei wie folgt vor:<br />
1.1 Finden Sie den Zusammenhang zwischen der schriftlichen Vorgehensweise und der entsprechenden<br />
Realisierung in einer Ihnen bekannten höheren Programmiersprache.<br />
1.2 Adaptieren Sie Ihr Programm dann auf VHDL.<br />
Dieser allgemein bekannte Algorithmus <strong>zu</strong>r Multiplikation im Zehnersystem kann auch unabhängig vom<br />
Zahlensystem angewandt werden. Seine Implementierung ist jedoch meistens nicht trivial, weshalb einige<br />
weitere Überlegungen hinsichtlich benötigter Hardware nötig sind:<br />
Ziel ist die Multiplikation von binären Zahlen, wodurch eine digitale Realisierung des Rechenwerkes interessant<br />
wird.<br />
Eine Multiplikation eines mehrstelligen, binären Multiplikanden mit einem einstelligen binären Multiplikator<br />
lässt nur zwei mögliche Ergebnisse <strong>zu</strong>: den gleichen Wert des Multiplikanden oder den Wert “0”.<br />
Die Verschiebung der Multiplikationsergebnisse ist in VHDL trivial, nur die Addition der einzelnen Subergebnissen<br />
stellt eine größere Aufgabe dar. Hier<strong>zu</strong> ist eigentlich der Entwurf eines Volladdierers nötig.<br />
Um eine Vertiefung in Addierwerke an dieser Stelle <strong>zu</strong> ersparen, soll nun eine Methode erläutert werden,<br />
mit der der Additionoperator „+“ im Zusammenhang mit Bitvektoren verwendet werden kann.<br />
Ein Blick auf das folgende Beispiel lässt die Problematik klar erkennen:<br />
Die Variablen a, b und c seien vom Typ bit_vector(3 downto 0).<br />
Unter dieser Annahme, erzwingt die folgende Anweisung eine Fehlermeldung vom Compiler, da<br />
der Operator „+“ für Bitvektoren nicht definiert ist.<br />
c := a + b; -- geht nicht!<br />
Der Additionsoperator ließe sich aber verwenden, wenn die Operanden a und b z.B. vom Typ unsigned<br />
wären. unsigned ist ein vordefinierter Typ u.a. in dem Package NUMERIC_BIT aus der<br />
standardisierten Bibliothek IEEE. Statt die Variablen nun in unsigned um<strong>zu</strong>wandeln, kann man<br />
besser die Konvertierungsfunktionen dieser Bibliothek nutzen, um die geforderte Funktionalität <strong>zu</strong><br />
bewerkstelligen. Die fehlerhafte Anweisung aus dem obigen Beispiel ist also folgendermaßen um<strong>zu</strong>formen(a,<br />
b und c seien weiterhin vom Typ bit_vector(3 downto 0):<br />
Universität Duisburg-Essen; Fakultät 5; Abt. IIMT; Inst. Informationstechnik (IT), Verteilte Systeme (VS) Seite 8
Praktikum <strong>zu</strong> RgS 2 <strong>Versuch</strong>2: VHDL-VERHALTENSBESCHREIBUNG<br />
c := BIT_VECTOR( UNSIGNED(a) + UNSIGNED(b) );<br />
Die Konvertierungsfunktion<br />
BIT_VECTOR(Parameter) wandelt<br />
den Parameter in<br />
bit_vector um. Dies ist nötig,<br />
da c vom Typ bit_vector ist.<br />
Um diese Konvertierungsfunktionen verwenden <strong>zu</strong> können, müssen am Anfang der VHDL-Datei<br />
folgende Zeilen stehen:<br />
library ieee;<br />
use ieee.numeric_bit.all;<br />
Dem Entwickler stehen die anderen logischen Operationen wie or, and, not u.s.w. nach wie vor <strong>zu</strong>r Verfügung,<br />
sowie auch Abfrage- und Schleifenkonstrukte.<br />
3.3. Aufgabe 2<br />
Entwerfen Sie einen digitalen Multiplizierer nach dem oben vorgestellten Algorithmus, der zwei positive,<br />
vier-Bit-breite Zahlen im Binärsystem Multipliziert.<br />
Erlaubte Werkzeuge sind:<br />
Schleifenkonstrukte (z.B. for); [siehe oben]<br />
Abfragekonstrukte (z.B. if);<br />
if Bedingung then<br />
.....<br />
else<br />
.....<br />
end if;<br />
Stellenverschiebung;<br />
Additionsoperator im Binärsystem (+);<br />
Konvertierungsfunktionen aus ieee.numeric_bit<br />
Logische Verknüpfungen (Gatter) (or, and, not, xor ).<br />
Gehen Sie dabei wie folgt vor:<br />
2.1 Überlegen Sie sich, wie die einstellige Multiplikation im Binärsystem durch einen Vergleich des Multiplikators<br />
ersetzt werden könnte.<br />
2.2 Überlegen Sie sich, welche Breite das Ergebnis einer Multiplikation von zwei vier-Bit-breiten Zahlen<br />
erreichen kann und berücksichtigen sie dies bei der Wahl der Variablen-Breiten.<br />
2.3 Berücksichtigen Sie die Tatsache, dass nur zwei gleichbreite Zahlen binär addiert werden können.<br />
Über den Tellerrand hinaus<br />
Die Konvertierungsfunktion UNSIGNED(Parameter) wandelt den<br />
Parameter in unsigned um.<br />
Das Ergebnis der Addition(innerhalb der fettgedruckten Klammern)<br />
ist vom Typ unsigned<br />
Dieser Teil der <strong>Versuch</strong>unterlagen widmet sich den Studenten, die sich tiefer mit VHDL beschäftigen<br />
möchten.<br />
Möchte man das Rechenwerk noch ausführlicher beschreiben, so kann der Additionsoperator durch einen<br />
Volladdierer ersetzt werden, der sich – wie ja aus dem <strong>Versuch</strong> 1 bekannt ist – aus Halbaddieren<br />
<strong>zu</strong>sammensetzt.<br />
Ebenso interessant wäre, das Rechenwerk auch auf negative Zahlen <strong>zu</strong> erweitern.<br />
Universität Duisburg-Essen; Fakultät 5; Abt. IIMT; Inst. Informationstechnik (IT), Verteilte Systeme (VS) Seite 9