Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...
Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...
Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
Universität Stuttgart<br />
<strong>Institut</strong> <strong>für</strong> <strong>Kommunikationsnetze</strong> <strong>und</strong> <strong>Rechnersysteme</strong><br />
Prof. Dr.-Ing. A. Kirstädter<br />
Entwurf digitaler Systeme<br />
<strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse<br />
In dieser <strong>Übung</strong> soll das Verhalten zweier VHDL-Implementierungen eines Speichers untersucht<br />
werden. Während die eine Implementierung korrekt funktioniert, weist die andere Implementierung<br />
diverse Fehler auf. Ihre Aufgabe besteht darin, eine Testbench zu entwickeln, mit<br />
deren Hilfe Sie durch Simulation alle Fehler der zweiten Implementierung aufdecken können.<br />
Sie können dabei auf einer bestehenden Testbench aufbauen, die im Folgenden näher beschrieben<br />
wird. Die VHDL-Beschreibungen der in den nächsten Abschnitten vorgestellten Komponenten<br />
finden Sie in einem Zip-Archiv eds-ex3-files.zip, das Sie von der Homepage der<br />
Vorlesung herunterladen können. Das Archiv enthält außerdem ein ModelSim-Projekt<br />
(ex3.mpf), das Sie als Gr<strong>und</strong>lage <strong>für</strong> die Bearbeitung der Aufgaben heranziehen können. Die<br />
Quellen des ModelSim-Projekts sind in zwei Libraries ex3_public <strong>und</strong> ex3_secret aufgeteilt.<br />
Letztere enthält die Architecture der enthaltenen Komponente Memory nur in kompilierter<br />
Form, während die Modellierung der in der Library ex3_public enthaltenen Komponenten<br />
vollständig einsehbar ist.<br />
clk_res_gen<br />
clk res_n<br />
memory_tester<br />
clk: std_logic<br />
res_n: std_logic<br />
wena: std_logic<br />
address: address_t<br />
wdata: data_t<br />
rdata: data_t<br />
memory<br />
clk: std_logic<br />
wena: std_logic;<br />
address: address_t<br />
wdata: data_t<br />
rdata: data_t<br />
Bild 1: Struktur der Testbench<br />
Testbench memory_tb<br />
Bild 1 zeigt den Aufbau der Testbench (Entity memory_tb). Sie umfasst den zu validierenden<br />
Speicher memory, einen Speichertester memory_tester <strong>und</strong> eine Komponente clk_res_gen, die<br />
ein Takt- <strong>und</strong> ein Resetsignal erzeugt. memory_tb liegt in zwei Varianten vor; diese unterscheiden<br />
sich darin, welche Implementierung des Speichers eingeb<strong>und</strong>en wird:<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 1
• Die Architecture memory_tb(struct) instanziiert den fehlerfreien Speicher (Komponente<br />
memory aus Library ex3_public).<br />
• Die Architecture memory_tb(struct_faulty) instanziiert den fehlerbehafteten Speicher<br />
(Komponente memory aus Library ex3_secret).<br />
Die Typen data_t <strong>und</strong> address_t sind im Package ex3_public.types definiert.<br />
Speicher memory<br />
Die Komponente memory modelliert einen Speicher, der synchron geschrieben <strong>und</strong> asynchron<br />
gelesen wird:<br />
• Liegt an seinem Write-Enable-Eingang (wena) eine ’1’ an, so wird das am Eingang<br />
wdata anliegende Datum mit der steigenden Taktflanke in die durch address gegebene<br />
Speicherzelle geschrieben.<br />
• Am Ausgang rdata liegt immer der Inhalt der momentan durch address angegebenen<br />
Speicherzelle an.<br />
Speichertester memory_tester<br />
Aufgabe von memory_tester ist es, Schreib- <strong>und</strong> Lesezugriffe auf den Speicher auszuführen,<br />
um evtl. vorhandene Fehler aufzudecken. Insbesondere sollte der Tester bei jedem Lesezugriff<br />
prüfen, ob das gelesene Datum mit dem zuletzt an die entsprechende Speicherstelle geschriebenen<br />
Datum übereinstimmt.<br />
Die vorgegebene Fassung des Testers ist noch sehr unvollständig. Sie schreibt die Werte 1 <strong>und</strong><br />
3 an die Adressen 4 <strong>und</strong> 10 <strong>und</strong> liest diese direkt anschließend wieder aus. Eine Überprüfung<br />
der gelesenen Werte findet nicht statt.<br />
Takt- <strong>und</strong> Resetgenerator clk_res_gen<br />
Die Komponente clk_res_gen erzeugt ein Taktsignal clk mit der Periodendauer 1µs <strong>und</strong> ein<br />
low-aktives Reset-Signal res_n, das die ersten 3.7µs Simulationszeit aktiv ist.<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 2
Aufgabe 1<br />
Erste Schritte<br />
Im Folgenden soll zunächst die vorgegebene Fassung der Testbench mit dem korrekt funktionierenden<br />
Speicher simuliert werden. In den folgenden Aufgabenteilen werden Sie die Testbench<br />
dann schrittweise erweitern.<br />
Öffnen Sie das ModelSim-Projekt ex3.mpf <strong>und</strong> compilieren Sie dieses anschließend:<br />
• Entpacken Sie das Archiv eds-ex3-files.zip<br />
• Starten Sie ModelSim<br />
• File >> Open >> Files of Type: Project Files (*.mpf) >> ex3.mpf auswählen >> Open<br />
• Compile >> Compile Order >> Auto Generate<br />
Simulieren Sie die nun die Architecture struct von memory_tb. Vergewissern Sie sich, dass<br />
sich Tester <strong>und</strong> Speicher wie zuvor beschrieben verhalten.<br />
Wählen Sie dazu im Workspace-Fenster den Tab Library aus <strong>und</strong> klicken Sie mit der rechten<br />
Maustaste auf den Eintrag work >> memory_tb >> struct. Wählen Sie im erscheinenden Kontext-Menü<br />
den Punkt Simulate aus. Fügen Sie die Testbench-Signale einem Wave-Window<br />
hinzu <strong>und</strong> simulieren Sie eine Zeitspanne von 10µs.<br />
Im Folgenden soll der Tester erweitert werden.<br />
Frage 1<br />
Frage 2<br />
Frage 3<br />
Ändern Sie den Prozess tester_p in memory_tester(behav) so ab, dass er zunächst<br />
alle Speicherzellen nacheinander einmal mit beliebigen Werten beschreibt<br />
<strong>und</strong> die Speicherzellen dann nacheinander wieder ausliest.<br />
Überprüfen Sie die korrekte Funktion im Wave-Window.<br />
Hinweis: Benutzen Sie Funktionen aus dem Package ieee.numeric_std.<br />
Erweitern Sie den Tester so, dass er im Fehlerfall eine Meldung ausgibt<br />
(Adresse, gelesener Wert, erwarteter Wert). Benutzen Sie dazu eine assertoder<br />
report-Anweisung.<br />
Hinweis:<br />
Auf Gr<strong>und</strong> der Simulationsmethodik von VHDL ändert sich der Ausgang<br />
rdata des Speichers erst nach einem (infinitesimal) kleinen Zeitraum nachdem<br />
seine Eingangssignale gesetzt wurden. In der Testbench müssen Sie daher<br />
ein wait-statement zwischen dem Setzen von wena/address/wdata <strong>und</strong><br />
dem Lesen von rdata einfügen. Beispielsweise könnten Sie bis zur nächsten<br />
negativen Taktflanke warten.<br />
Simulieren Sie nun memory_tb(struct_faulty).<br />
An welchen Adressen meldet Ihr Tester Fehler? Stellen Sie eine Vermutung<br />
an, wie ein solches Fehlermuster zustande kommen kann.<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 3
Aufgabe 2<br />
Pseudozufällige Speicherzugriffe<br />
Nun soll der Tester so abgeändert werden, dass er pseudozufällige Speicherzugriffe ausführt.<br />
Zur Erzeugung der dazu nötigen Pseudozufallszahlenfolge (x i ) soll ein sogenannter linearer<br />
Kongruenzgenerator benutzt werden. Dabei wird das Folgenglied x i+1 aus dem Folgenglied x i<br />
gemäß folgender Vorschrift erzeugt:<br />
x i 1<br />
+<br />
= ( A ⋅ x i<br />
+ B) mod M<br />
Im Folgenden wird A=16807, B=0 <strong>und</strong> M=2147483647 gewählt.<br />
Frage 1<br />
Frage 2<br />
Frage 3<br />
Fügen Sie der Architecture memory_tester(behav) eine Funktion random hinzu,<br />
der als Argument ein Glied der Folge übergeben wird <strong>und</strong> die das jeweils<br />
nächste Glied zurückgibt.<br />
In welchem Bereich können die Werte dieser Folge liegen? Berücksichtigen<br />
Sie diese Erkenntnis im Folgenden bei der Wahl des Startwerts x 0 .<br />
Prüfen Sie nun die korrekte Funktion von random. Ergänzen Sie dazu<br />
memory_tester(behav) um einen Prozess, der die Folge x i mit x 0 =1 in der Simulationskonsole<br />
ausgibt.<br />
Zur Vereinfachung der späteren Aufgaben soll nun eine Funktion random entwickelt werden,<br />
die mit Wahrscheinlichkeitswerten (d.h. Zahlen im Bereich ]0,1]) statt Ganzzahlen arbeitet.<br />
Frage 4<br />
Frage 5<br />
Frage 6<br />
Deklarieren Sie einen Typ probability_t zur Modellierung von Wahrscheinlichkeitswerten.<br />
Fügen Sie die neue Funktion random der Architecture hinzu <strong>und</strong> testen Sie<br />
diese wiederum mit Hilfe eines einfachen Prozesses.<br />
Erweitern Sie den Prozess tester_p nun so, dass er in einer Endlosschleife jeweils<br />
zunächst ein zufälliges Datum an eine zufällig gewählte Speicherstelle<br />
schreibt <strong>und</strong> dieselbe Speicherstelle im jeweils folgenden Taktzyklus ausliest.<br />
Im Fehlerfall soll wiederum eine Meldung ausgegeben werden.<br />
Nun sollen Schreib- <strong>und</strong> Lesezugriffe zufällig gemischt werden. Um in diesem Fall noch feststellen<br />
zu können, ob ein gelesenes Datum korrekt ist, soll innerhalb der Architecture<br />
memory_tester(behav) eine Datenstruktur memory_state genutzt werden, in der <strong>für</strong> jede<br />
Adresse festgehalten wird, ob diese schon beschrieben wurde <strong>und</strong> wie der zuletzt geschriebene<br />
Wert lautet.<br />
Frage 7<br />
Ergänzen Sie die Architecture memory_tester(behav) um die Datenstruktur<br />
memory_state. Definieren Sie zuvor geeignete Typen.<br />
Aus Modularisierungsgründen sollen drei Prozesse in der Architecture verwendet werden:<br />
• Der Prozess control_p entscheidet in jedem Taktzyklus, ob ein Schreib- oder ein Lesezugriff<br />
stattfinden soll <strong>und</strong> treibt die Ausgangsports entsprechend. Die Wahrscheinlichkeit<br />
beider Zugriffsarten soll jeweils 50% betragen. Die Folge der Schreibadressen soll sich<br />
von der der Leseadressen unterscheiden.<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 4
• Der Prozess updater_p aktualisiert bei jedem Schreibzugriff memory_state.<br />
• Der Prozess checker_p prüft jeden Lesezugriff <strong>und</strong> wertet dazu den Inhalt von<br />
memory_state aus. Im Fehlerfall soll wie bisher eine Fehlermeldung über die Simulationskonsole<br />
ausgegeben werden.<br />
Frage 8<br />
Frage 9<br />
Aufgabe 3<br />
Ergänzen Sie die Architecture um die drei Prozesse control_p, updater_p <strong>und</strong><br />
checker_p.<br />
Simulieren Sie die Testbench memory_tb(struct_faulty).<br />
Welche weiteren Fehler des Speichers memory aus der Library ex3_secret<br />
finden Sie? Hinweis: Identifizieren Sie zunächst die Fehlermuster, die sich<br />
durch den in Aufgabe 1 identifizierten Fehler nicht erklären lassen. Suchen<br />
Sie dann nach Auffälligkeiten im Zugriffsmuster.<br />
Erzeugung einer Protokolldatei<br />
Nun soll der Tester so ergänzt werden, dass er jeden erfolgten Speicherzugriff in einer Datei<br />
access.log protokolliert (vgl. Bild 2).<br />
[...]<br />
Writing 0010101000000101 to address 1110<br />
Reading 0001111000011011 from address 0010<br />
Writing 1010010111011110 to address 0010<br />
Writing 1000110000000100 to address 0011<br />
Writing 0011111110101111 to address 0110<br />
[...]<br />
Bild 2: Beispielhafte Protokolldatei<br />
Für den Dateizugriff soll das Package std.textio benutzt werden. Den mit dieser <strong>Übung</strong> ausgeteilten<br />
Unterlagen können Sie entnehmen, wie es verwendet wird.<br />
Frage 1<br />
Ergänzen Sie den Tester um einen Prozess logger_p, der eine Protokolldatei<br />
gemäß Bild 2 erzeugt.<br />
Hinweise:<br />
• Im Package textio gibt es keine write-Prozedur, die einen std_logic_vector direkt ausgeben<br />
kann. Sie können aber eine entsprechende Prozedur leicht selber schreiben. Verzichten<br />
Sie dabei der Einfachheit halber auf die Parameter justified <strong>und</strong> field.<br />
• Im Package textio ist sowohl eine write-Prozedur deklariert, die als Argument einen<br />
string erwartet, als auch eine Variante, die einen bit_string als Argument erwartet. Da der<br />
Compiler nicht ohne Weiteres string- von bit_string-Literalen unterscheiden kann (Bsp.:<br />
Welchen Typ hat "0011"?), müssen Sie beim Aufruf der write-Prozedur den Typ solcher<br />
Literale explizit qualifizieren:<br />
write(line,string’("Hello World!"));<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 5
Aufgabe 4<br />
Fehlererkennung mittels Parity<br />
Nun soll der bisher benutzte, korrekt funktionierende Speicher memory(behav) so erweitert<br />
werden, dass er zusammen mit jedem Datenwort ein Parity-Bit abspeichert.<br />
Frage 1<br />
Frage 2<br />
Frage 3<br />
Aufgabe 5<br />
Ergänzen Sie die Entity memory um zwei Ports wparity <strong>und</strong> rparity <strong>und</strong> erweitern<br />
Sie die Architecture memory(behav) entsprechend.<br />
Ändern Sie den Tester so ab, dass beim Schreiben jeweils die Parity berechnet<br />
<strong>und</strong> geschrieben <strong>und</strong> beim Lesen geprüft wird, ob die Parity zu den Daten<br />
passt.<br />
Passen Sie die Testbench memory_tb(struct) an <strong>und</strong> simulieren Sie das Design.<br />
Modellierung einer fehlerhaften Übertragungsstrecke<br />
Nun soll ein Fall modelliert werden, in dem der Speicher selbst zwar fehlerfrei funktioniert, bei<br />
der Übertragung von Signalen vom oder zum Speicher aber Bits verfälscht werden können.<br />
Dabei soll von folgender Annahme ausgegangen werden: Bei jeder Änderung des Werts von<br />
wdata, rdata <strong>und</strong> address besteht eine Wahrscheinlichkeit von jeweils 0.1%, dass genau ein<br />
Bit des entsprechenden Wortes invertiert wird.<br />
Modelliert wird dieser fehlerhafte Kanal durch eine Komponente channel, die in der Testbench<br />
memory_tb(struct) zwischen memory_tester <strong>und</strong> memory(behav) eingefügt wird.<br />
Frage 1<br />
Frage 2<br />
Entwickeln Sie Entity <strong>und</strong> Architecture der Komponente channel.<br />
Ergänzen Sie das Design so, dass einerseits die Häufigkeit gestörter Zugriffe<br />
<strong>und</strong> andererseits die Häufigkeit erkannter Fehler registriert wird.<br />
Setzen Sie die Werte in Bezug zueinander <strong>und</strong> versuchen Sie, ihr Verhältnis<br />
nährungsweise herzuleiten.<br />
Lösungsvorschläge können in Papierform abgegeben oder alternativ per E-Mail an die Adresse<br />
domenic.teuchert@ikr.uni-stuttgart.de geschickt werden.<br />
Bei Fragen <strong>und</strong> Problemen bei der Durchführung der <strong>Übung</strong>en wenden Sie sich bitte an Dipl.-<br />
Ing. D. Teuchert (Telefon 685-69003, Zimmer 1.305), an Dipl.-Ing. J. Häussler (Telefon 685-<br />
67991, Zimmer 1.365) oder an Dipl.-Ing. M. Meyer (Telefon 685-67975, Zimmer 1.334).<br />
Entwurf digitaler Systeme <strong>Übung</strong> 3: Testbench-Modellierung <strong>und</strong> Fehleranalyse - Bl. 6