Autoren: Wassim Bouchnak, Moujahid Bouhouch
Einführung
Das Projekt wurde im Rahmen eines Abschlussprojektes des Moduls Entwurf digitaler Systeme durchgeführt. Hier wurde als Basis das Morse De- und Encoder mittels FPGA vom Herrn Kai-Frederik Nessitt Projektes aufgenommen. Die wesentlichen Änderungen, Erweiterungen und Testbenches haben wir hier diskutiert.
Das zu entwickelnde System soll dazu fähig sein, die Morse Sprache zu kodieren und decodieren.
Für den Decoder hat man die Möglichkeit über Tastendruck, den Morse Code einzugeben. Dieser wird als Audio-Output ausgegeben und parallel wird der entsprechende ASCII-Code auf dem 16×2 Display angezeigt.
Des Weiteren kann man über UART und anhand eines mit Python programmierten Userinterface die Daten zum FPGA senden, welche dann auf Morse umgewandelt werden. Die Komponente UART-TX wird die bereits verschickten Daten wieder zum Computer senden.

1
Netzteil
2
Audio-Output
3
RS-232 Kabel für die UART Kommunikation
4
PS2-Anschluss
5
16 x 2 LCD-Display
6
Zwei 7 Segmentdisplay zu der Anzeige des entsprechenden vom UART angefangene hexadezimal-Code
7
Tastatur mit PS2-Anschluss
8
Zwei Schalter zu der Auswahl der Wortgeschwindigkeit
9
Reset-Schalter
10
Schalter zu der Auswahl zwischen einem Zeichen Encoder Modus oder einem ganzen Satz
11
8 Rote LEDs zu der Anzeige der aktuellen genutzten Zeile vom RAM
12
Encoding mit der Nutzung vom UART
13
Auswahl zwischen Decoder oder Encoder Modus. 0: Decoder; 1: Encoder
14
Taste zu der Eingabe des Morse Code
15
3 Grüne LEDs zur Anzeige der Länge des Drucken Signal
Top Level Morse
Das Entity verbindet die unterschiedlichen Komponenten miteinander.
Zudem wird das von der Taste angefangene Signal auf Morse decodiert. Hier muss allerdings der Modus anhand des Schalters 13 (Abbildung 1) ausgewählt werden.
Zunächst wird beim Tastendruck geprüft, ob es sich um einen kurzen Druck, Dot, langne Druck, Dash, oder langen Pause handelt.
Abbildung 2 stellt das Ergebnis des Testbench dar.

Clock Divider
Das LCD, AudioCodec und die Wortgeschwindigkeit benötigen unterschiedliche Taktsignale. Diese werden durch Das Entity Clockdevider bereitgestellt. Um dies zu schaffen, wurden Zähler verwendet.
Der Clock divider basiert auf dem folgenden Prinzip.


Abbildung „Clock Divider 50 MHz auf 12 MHz“ stellt das Ergebnis vom Testbench dar.
Clk bezieht sich auf das Systemtaktzyklus, das 50MHz entspricht. Clock_12MHz wird für den AudioCodec benötigt.

Die zwei Schalter (8) in der Abbildung „Ein- und Ausgabe – Systembeschreibung“ sind notwendig, um die Wortgeschwindigkeit für den Decoder und Encoder zu variiren. Hier sind drei Geschwindigkeiten auszuwählen. Diese werden für die andere Komponenten zu bestimmen. Die Komponente clock_divider stellt diese zur Verfügung.
Die Abbildung 6 zeigt das Ergebnis des Testbenches:

Tastendruck
Beim Decodieren von Morsecode wird der Status der Taste (Abbildung 1 (14)) ständig überprüft. Diese zeigt an, ob die Taste gedrückt wurde und ob es sich um ein langes oder kurzes Drücken handelt. Dies hängt auch von der Wortgeschwindigkeit ab.

Zum Testen der Funktionalität des Tastendrucks wurde ein Testbench erstellt.
Abbildung „Tastendruck – Testbench“ zeigt das erhaltene Ergebnis.

PS2-Anschluss Tastatur
Tastatur Entity enthält die Logik der Tastatur Encoder. Die Architektur besteht aus drei Prozessen. Es werden der Taktzyklus von der Clock und die Data der Tastatur mit der Clock vom System synchronisiert. Sobald eine Taste gedrückt wurde, wird der Wert der gedrückten Taste in Hexadezimalzahl ermittelt und geschaut, ob diese gedrückte Taste losgelassen und die Hexadezimalzahl zu einem Token-Signal konvertiert wurde. Das Signal gibt den Morse Code für die entsprechende Taste an. Beim Token Signal wird jeder zweite Bits als ein Dot oder Dash beschrieben.
- „11“ repräsentiert einen Dash
- „01“ repräsentiert einen Dot.
Es gibt die Möglichkeit zwischen zwei Modi zum Encoding mit der Nutzung einer PS2-Tastatur auszuwählen. Entweder die Encodierung von einzelnen Werten oder einer Reihe von Werten.
Beim Encoding von einzelnen Werten wird aus dem Token Signal ein Sound Signal erstellt. Dieses Sound-Signal wird dann zum AudioCodec weitergeschickt. Das Lesen vom Token Signal fängt von rechts nach links an.
Beim Encoding einer Reihe von Werten, wird das Token Signal in einem Single Port RAM gespeichert. RAM-Matrix besteht aus 257 Zeilen und jede Zeile ist ein Array von 16 Bits.

Die Wortgeschwindigkeit weist einen ram_clk auf. Der ausgabe_modus erlaubt die Nutzung vom RAM und bei jedem Speichern wird die Adresse des RAMs um 1 inkrementiert. Enter-Taste zeigt auf, ob man in dem RAM schreiben oder lesen kann. Das Token-Signal ist ein 16 Bit Vektor und dieser wird in der angegebenen Adresse gespeichert.
Beim Drücken auf die Enter-Taste, wird dann dieses RAM von der ersten Zeile gelesen und die Token-word-Signale dann nacheinander auf Sound encodiert, sodass sie zum Audiocodec weitergeschickt werden können.
Das Auslesen vom RAM wird wie folgt geschehen.
Quellcode - Auslesen RAM
Das Bild stellt das Ergebnis vom ersten Modus dar. Die Werte werden codiert, ohne dies in den RAM zu speichern.


Die folgende Abbildung stellt das Ergebnis vom zweiten Modus dar. Die Werte werden codiert und im RAM gespeichert. Beim Drücken auf die Enter-Taste wird das Sound-Signal erstellt.


AudioCodec
Das Untergeordnete Top Level verbindet 4 benötigte Komponente zur Steuerung des Audio-Codecs miteinander. Darüber hinaus werden in dieser Entity durch eine Finite State Machine die Konfiguration Daten des Audio-Codecs „WM8731“ bereitgestellt und mit Hilfe der Komponente I2C zum Audio Codec. übertragen.
Die Komponenten sind:
- ROM-Speicher: Beinhaltet die Werte, die eine Periode eines 500 Hz Audiosignal repräsentieren.
- Read Audio Data: die unter einige Voraussetzungen die Werte des ROM-Speichers ausliest und zur Komponente Audiogeneration weitergibt.
- Audiogeneration: die die vom Rom-Speicher ausgelesene Daten bitweise an den Audiocodec DAC sendet.
- I2C : sendet die Konfigurationsdaten zum Audio Codec.
Im Vergleich zum angepassten Programmcode vom Herrn Nessit, wurde zunächst anstelle des mit QSYS Tool erstellte Memory System, eine neue Romspeicher entworfen. Dabei wurde ein Package verwendet, indem neue Datentype und den Inhalt des Romspeichers deklariert sind. Den Inhalt beide Speicher (Audio digitale Daten) ist gleich gehalten.
Außerdem wurde für eine bessere strukturierung und lesbarkeit die Componente Audio Generation Prozess in einer Komponente gekapselt.
Die Komponente Read Audio Data, wurde verändert und angepasst damit die empfangenen daten durch Uart_TOP, in einem Ton umgewandelt werden können.
Quellcode - Soundmap
Um die Funktionalität dieser Komponenten zu testen, haben wir ein Testbench erstellt.
Dabei wird nach 10 Taktzyklus des 50 MHz Taktsignal das nrst (reset) Eingangssignal desaktiviert. Danach wird zunächst das decoder Modus aktiviert und Buchstabe A Durch Tastendruck eingegeben. Nachfolgend wird encoder Modus eingeschaltet und Buchstabe Z durch das Sound Signal eingegeben. Anschließend wird Uart Modus aktiviert und Buchstabe Z eingegeben.
Die folgenden Bilder stellen das Ergebnis der Simulation dar.


LCD Display
Nun findet die Initialisierung und der Datenfluss zu 8-Bit-Schnittstellen-LCD-Modulen HD44780 statt. Zudem wird sowohl der Token im Decoder-Modus als auch die Tastaturdaten im Encoder-Modus ausgewertet und auf dem LCD-Display dargestellt.
Mit einer FSM wird hier das LCD auf einen entsprechenden Betrieb Modus eingestellt.
Im Vergleich zur Quellcode vom Herrn Nessit wird dieser Komponente mit einem GENERIC versehen, wobei die Einstellungsparameter geändert werden können. Weiterhin werden die FSM benannt und die Anfangsbedingung, die im Datenblatt zu finden sind, durch einen Zähler eingehalten und weitere Anpassungen.
Quellcode - LCD-Controller
Die Ergebnisse vom Testbench werden in den folgenden Abbildungen dargestellt.


UART
Implementierung vom UART in VHDL
Bei der UART Datenübertragung handelt es sich um eine asynchrone Datenübertragung. Es existiert also kein Taktsignal mit dem sich Sender und Empfänger synchronisieren können. Die Baudrate (Übertragungsgeschwindigkeit) müssen bei beiden Kommunikationspartnern identisch eingestellt werden.
Die Datenübertragung per UART erfolgt mit einem festen Datenrahmen. Dieser muss beiden Kommunikationspartnern bekannt sein. [1]
Der UART-Frame besteht aus einem Start-Bit, 8 Datenbits und einem Stop-Bits (siehe Abbildung).

Im Idle-Zustand ist der UART-Bus auf logisch 1. Das Startbit ist logisch 0 und signalisiert den Start eines UART Frames. Die Kommunikation fängt an, wenn der Computer ein 0 logic sendet. Dieses wird im Receiver detektiert. Dann folgen die acht Bits und der Stop-Bit. Die Abtastung der Bits wird mit Hilfe eines Zählers, der die Dauer eines Bit rechnet, realisiert.

Nach dem Erhalt eines Datenrahmens werden die extrahierte 8-Daten-Bits und ein Valid-Bit (w_rx_dv) zum UART Transmitter gesendet. Der Transmitter sendet zunächst den Start-Bit (0 Logic), danach folgen die Datenbits und anschließend das Stop Bit. (siehe folgende Abbildung)

Der Datenaustausch erfolgt durch einen RS 232-Anschluss, um eine Verbindung zwischen dem Altera FPGA-board und dem PC herzustellen. (siehe obere Abbildung )
Die Entity UART-Top besteht aus drei Komponenten.
- Entity uart_rx dient dazu, die Daten die vom PC zugesendet aufzufangen und entsprechend die 8 Daten Bits in einem 8 Bit Vektor zu speichern. Dieser wird in Top_UART innerhalb der Prozessen „ token_generation “ und „ audio_sound “ zu morse enkodiert und zum AudioCodec übertragen.
- Entity uart_tx sendet die Daten zum PC.
- Entity Binary_To_7Segment, die sich die angefangenen hexadezimalzahlen Daten auf dem Board anzeigen lassen.
Quellcode - UART_rx
Um die Funktionalität dieser Komponenten zu testen, wurde ein Testbench erstellt, indem das untergeordnete Top Level Uart_Top instanziiert ist.
Zunächst wird nach 10 Taktzyklus das nrst (reset) Eingangssignal desaktiviert, danach werden 2 Datenpaket (ASCII A (x 41) und ASCII Z (x 5A)) bitweise zum rx Eingangssignal geschickt. Dabei wird nach dem Empfang der Daten die durch uart_tx gesendeten Bits geprüft, ob sie richtig oder falsch sind.
Die folgenden Bilder stellen das Ergebnis der Simulation dar.


Python
Da Python bei der Datenverarbeitung sehr stark ist, wurde eine Schnittstelle mit dem PC und dem FPGA Board mit Hilfe der Bibliothek Pyserial erstellt. Darüber hinaus wurde eine Userinterface zum Senden vom Werten zum Board erstellt, welche dann auf Morse Codiert und einen Ton erzeugen.
Damit hat man die Möglichkeit zunächst den Port und Baud Rate in den Entrees zu schreiben. Diese werden für eine erfolgreiche Kommunikation benötigt.

Bei den falschen Eingaben wird die folgende Fehlermeldung angezeigt.

Bei einer erfolgreichen Verbindung kann man mit Hilfe der Daten einen String senden z.B. auf Morse Codieren.

Quellcode - Schnittstelle Laptop/FPGA
Quellen
Scott Larson
forum.digikey.com
AntonZero / WM8731-Audio-codec-on-DE10Standard-FPGA-board
NAND LAND / Drive a 7-Segment Display With Your FPGA
Academy VHDL Whiz
Der Schlaufuchs.de / Die UART Schnittstelle