Schieberegister und Ringzähler mit FPGA und VHDL
Aufgabenstellung
Ein Schieberegister wird als Flankendetektor eingesetzt. Der Flankendetektor wird simuliert und mit dem Oszilloskop auf dem FPGA vermessen. Ein Ringzähler steuert die 10 roten LEDS. Der Flankendetektor wird dann als Enablegenerator für den Ringzähler eingesetzt.
Vorbereitung
Logikanalysator im MSO-X 4034A
Das Oszilloskop MSO-X 4034A hat vier analoge Kanäle. Zusätzlich gibt es noch 16 digitale Kanäle. Wenn man mit digitalen Kanälen arbeitet, dann nennt sich dies Logikanalysator.
Abb. 1: 8 Kanal Logicprobe Agilent 54620-61601
In Abbildung 1 ist eine 8 Kanal Logicprobe für die digitalen Kanäle 0 bis 7 dargestellt. Es gibt noch eine weitere Logicprobe für die Kanäle 8 bis 15. Das besondere an den Logicprobes ist, dass die analoge Spannung direkt am Eingang des Oszilloskops mit einer Vergleichsspannung verglichen wird. Danach wird nur noch gespeichert ob es sich um eine 0 oder 1 handelt. Wenn die Spannung größer als die Vergleichsspannung ist, dann wird eine 1 gespeichert, sonst eine 0. Wie Sie die Logicprobes einschalten und wie Sie die Vergleichsspannung einstellen finden Sie in Kapitel 6 vom Handbuch des Oszilloskops.
Projekt aktualisieren
Aktualisieren Sie das dtlab Projekt mit
cd ~/projects/dtlab git pull
VHDL toplevel top_shift
Die Datei top_shift.vhd beschreibt das Modul “top_shift”. “top_shift” stellt den toplevel auf dem FPGA dar. In Abbildung 2 sind die Ein- und Ausgänge von “top_shift” dargestellt.
Abb. 2: Toplevel top_shift
Im VHDL Code von “top_shift.vhd” werden zunächst einige Eingänge vom FPGA auf Signale mit einem passenderen Namen zugewiesen. Das Taktsignal CLOCK_50 kommt vom 50 MHz Taktoszillator auf der FPGA Platine.
clk <= CLOCK_50; rst_n <= KEY(0); x <= KEY(1);
Der Taster KEY(0) kontrolliert den asynchronen Reset und der Taster KEY(1) stimuliert das Signal x.
Schieberegister als Flankendetektor
Der folgende Codeteil in top_shift.vhd beschreibt ein Schieberegister.
sr <= "00" when rst_n = '0' else srnext when rising_edge(clk); srnext(1) <= x; srnext(0) <= sr(1); en <= sr(1) xor sr(0);
Zeichnen Sie die Schieberegisterschaltung.
In Abbildung 3 ist ein beispielhafter Signalverlauf für clk, rst_n und x dargestellt. Ergänzen Sie das Timingdiagramm.
Abb. 3: Timingdiagramm Schieberegister
Anschluss an den Expansionport 1
Auf dem FPGA Board gibt es zwei Expansionports, mit denen zusätzliche Hardware angeschlossen werden kann. Der Ausgangsport EXP[7..0] von top_shift ist den Pins auf dem FPGA zugeordnet, die auf der FPGA Platine mit acht Pins von Expansionport 1 verbunden sind.
Abb. 4: Expansionport auf dem FPGA und aus dem Schaltplan
In Abbildung 4 ist die Zuordnung des Ports EXP[7..0] zu den Pins auf der FPGA Platine zu sehen. Der folgende Code aus “top_shift.vhd” zeigt welche Signale am Ausgangsport zu sehen sind. Auf EXP(0) wird beispielsweise das Signal vom Eingangsport CLOCK_50 ausgegeben.
EXP <= (7 downto 4 => '0', 3 => en, 2 => x, 1 => rst_n, 0 => clk);
Simulation der Schaltung
Die Funktion der Schaltung soll im Simulator überprüft werden, bevor die Schaltung auf dem FPGA mit dem Oszilloskop getestet wird. Dazu wird der Schaltungssimulator ghdl eingesetzt. Für die Simulation müssen die Eingänge der Schaltung stimuliert werden. Hier sind das der
- Takteingang CLOCK_50
- Der Taster KEY(0) für den Reset
- Der Taster KEY(1) für den Eingang x
Der Eingang SW wird in der Simulation mit einem konstanten Wert simuliert.
Für die Stimulation der Eingänge wird die Testbench in t_top_shift.vhd eingesetzt.
Dort ist die Schaltung top_shift als Device Under Test (DUT) instantiiert. In der Testbench gibt es VHDL Code für die Simulation des 50 MHz Taktsignals, den asynchronen Reset und den Taster KEY(1) für den Eingang x des Schieberegisters.
Starten Sie den Schaltungssimulator in einem Terminal mit
cd ~/projects/dtlab/sim/top_shift make wave
Mit dem Kommando “make wave” werden die VHDL Dateien kompiliert und der VHDL Code simuliert. Danach wird das Simulationsergebnis mit “gtkwave” angezeigt.
Abb. 5: gtkwave zeigt die Simulationsergebnisse der ghdl Simulation von top_shift
In Abbildung 5 ist die Darstellung der Simulationsergebnisse mit gtkwave abgebildet. gtkwave zeigt nicht alle Signale, sondern einige ausgewählte, die in der Datei view_signals.gtkw festgelegt sind. Mit der aktuellen Auswahl wird das Schieberegister mit Takt, reset und dem Eingang x dargestellt.
Diese Signale sollen auf dem Expansionport ausgegeben werden. Mit der aktuellen Signalauswahl wird der Expansionport in der Simulation nicht dargestellt. In der Testbench ist das Signal “sim_exp” an den Ausgangsport EXP von top_shift angeschlossen. Wählen Sie das Signal sim_exp links aus und stellen Sie sim_exp in gtkwave dar. Machen Sie einen Screenshot. Beurteilen Sie ob alle relevanten Signale am Expansionport zu sehen sind.
Wenn Sie die Auswahl der dargestellten Signale in gtkwave geändert haben und gtkwave schließen und neu starten, dann wird wieder die vorkonfigurierte Signalauswahl dargestellt. Sie können gtkwave auch geöffnet lassen, den VHDL Code ändern, dann im Simulationsverzeichnis “make” eingeben und auf den Reloadknopf in gtkwave drücken. Alternativ können Sie die Signalauswahl auch mit “File → Write Save File” speichern. Dann wird auch nach einem Neustart von gtkwave die gespeicherte Signalauswahl dargestellt.
Umstrukturierung und Instantiierung des Flankendetektors
Die Funktion des Flankendetektors ist direkt in top_shift.vhd beschrieben. Der Flankendetektor soll jetzt in eigenes Modul und damit in eine eigene Datei bewegt werden. Die Funktion der Schaltung soll sich nicht ändern, d.h. wir strukturieren den Code nur etwas anders. Dazu ist schon die Datei edge.vhd vorbereitet. Die Datei enthält schon die entity “edge” mit den geplanten Ein- und Ausgängen.
Abb. 6: Das Modul “edge” als Flankendetektor
Wie in Abbildung 6 dargestellt, hat “edge” einen Takteingang “clk”, einen asynchronen Reseteingang “rst_n”, einen Eingang “x_i” und einen Ausgang “edge_o”.
Strukturieren Sie den Code um und bringen Sie die Funktion des Flankendetektors in das Modul “edge”. Das Modul “edge” wird dann in “top_shift” instantiiert. Überprüfen Sie mit dem Simulator, dass die Funktion sich nicht geändert hat. Machen Sie einen Screenshot von der Simulation der neuen Schaltung.
Ringzähler für die roten LEDs
Die roten LEDs werden derzeit direkt von den Schaltern SW gesteuert. Die roten LEDs sollen mit einem 10 Bit Ringzähler angesteuert werden. Der Ringzähler soll in die Datei ringcnt.vhd kommen. Die Datei ist schon vorbereitet, aber es fehlen u.a. die Ports in der entity.
Abb. 7: Ein- und Ausgänge des Moduls ringcnt
Die Ein- und Ausgänge des Moduls “ringcnt” sollen wie in Abbildung 7 dargestellt sein. Der Ausgangsport y_o stellt den Zustand der zehn Flipflops im Ringzähler dar. Der Ringzähler wird dann im Toplevel top_shift instantiiert. Der Ausgang y_o soll die roten LEDs ansteuern.
- Ergänzen Sie die port Definition in der entity von ringcnt
- Konstruieren Sie den Ringzähler so, dass im Resetfall die rote LED9 leuchtet
- Der en_i Eingang soll den Ringzähler anhalten können, d.h. wenn en_i=0 ist, dann soll der Ringzähler stehen bleiben. Wenn en_i = 1 ist dann zählt der Ringzähler in jedem Takt um eins weiter.
- Skizzieren Sie Schaltung des 10 Bit Ringzählers
- Ergänzen Sie den Code um die Funktion des 10 Bit Ringzählers zu erhalten
- Instantiieren Sie den Ringzähler in top_shift
- Wenn der Schalter SW0 an ist, dann soll en_i auf '1' liegen. Wenn der Schalter SW0 aus ist, dann soll der Ausgang des Flankendetektors mit dem Eingang en_i von ringcnt verbunden sein.
- Verbinden Sie den Ausgang y_o von “ringcnt” mit einem neuen Signal “led” in “top_shift”
- Verbinden Sie das Signal led mit dem Ausgang für die roten LEDs
- Verbinden Sie das Signal led[9..6] mit EXP[7..4]. Damit sollen vier Bit des Ringzählers auf dem Expansionport sichtbar sein.
- Simulieren Sie die Funktion der Schaltung für den Fall SW0 = “an” und zeigen Sie, dass der Ringzähler funktioniert
- Simulieren Sie die Schaltung für den Fall SW0 = “aus” und zeigen Sie, dass der Ringzähler nur bei einer Flanke an x zählt
- Laden Sie die Schaltung auf das FPGA und zeigen Sie die Funktion der Schaltung
Flankendetektor über sechs Takte
Der derzeitige Flankendetektor zeigt eine Flanke bei einem Übergang von 0 nach 1 oder 1 nach 0 an x_i an. Um die Stabilität zu erhöhen und ganz kurze Pulse am Eingang x nicht als Flanke zu werten, sollen Sie den Flankendetektor verändern. Der neue Flankendetektor soll
- die Folge 000111 und die Folge 111000 als Flanke erkennen
Erweitern Sie den Flankendetektor, damit er nur bei längeren Folgen eine Flanke erkennt. Passen Sie Testbench an und zeigen Sie, dass
- kurze Pulse wie in der Folge an x_i 0000011000 oder 111110011111 nicht als Flanke erkannt werden
- längere Folgen wie 0000000111111 oder 1111111000000 als Flanke erkannt werden
Dokumentieren Sie den Nachweis der Funktion mit Screenshots des Simulators.
Aufgaben für die Vorbereitung
- Zeichnung der Schaltung aus “Schieberegister als Flankendetektor”
- Ergänzung des Timingdiagramms in Abbildung 2
- Simulation der Schaltung und Nachweis, dass EXP korrekt funktioniert (Screenshot)
- Neustrukturierung des Codes. Funktion Flankenerkennung in die Datei “edge.vhd”
- Simulation der neuen Struktur mit edge (Screenshot)
- Zeichnung des Ringzählerschaltung
- Simulation Ringzähler mit en_i = '1' (Screenshot)
- Simulation Ringzähler mit en_i am Flankendetektor (Screenshot)
- Nachweis am FPGA ohne Logikanalysator
- Anpassung des Flankendetektors und der Testbench an Flankendetektor mit 6 Takten
- Nachweis des neuen Flankendetektors im Simulator (Screenshot)
Labor
Stellen Sie im Labor Ihre Ergebnisse vor. Bringen Sie die Zeichnungen und die Screenshots der Simulationen mit.
Nachweis Ringzähler en_i = '1' auf dem FPGA am Expansionport
Schliessen Sie zunächst eine Analogprobe des Oszilloskops an den Expansionport an und zeigen Sie das Taktsignal.
Schliessen Sie die Probes 0 bis 7 vom Logikanalysator an den Expansionport an um die Signale clk, rst_n, x, en und die vier Bit des Ringoszillators sichtbar zu machen. Sorgen Sie dafür, dass der en_i Eingang des Ringzählers permanent auf '1' ist. Zeigen Sie die Funktion des Ringoszillators für en_i = '1' am Logikanalysator anhand der vier beobachteten Bits des Ringoszillators. Dokumentieren Sie die Funktion mit einem Screenshot.
Nachweis Flankendetektor auf dem FPGA am Expansionport
Stellen Sie das Oszilloskop auf “Singleshot” Betrieb um und zeigen Sie, dass die Flankenerkennung funktioniert. Machen Sie einen Screenshot um die Funktion zu dokumentieren.
Nachweis Ringzähler + Flankenerkennung auf dem FPGA am Expansionport
Schalten Sie die Schaltung jetzt so um, dass der en_i Eingang des Ringzählers mit dem Ausgang des Flankendetektors verbunden ist. Zeigen Sie die Funktion der Schaltung und dokumentieren Sie die Funktion mit einem Screenshot.
Abgabe Untersuchungsbericht
Laden Sie den Untersuchungsbericht mit den Zeichnungen, den Screenshots der Simulation und den Screenshots vom Logikanalysator in Moodle in der Aktivität "Untersuchungsbericht Schieberegister und Ringzähler" hoch.