25.01.2014 Aufrufe

Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...

Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...

Übung 3 - Institut für Kommunikationsnetze und Rechnersysteme ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!