Suchen

Gutes FPGA-Schaltungsdesign: Stau ist nicht gleich Stillstand

| Autor / Redakteur: Harald Flügel * / Michael Eckstein

Stau bedeutet Stillstand – oder? Was beim Autofahren nervt, steht im FPGA für optimale Ressourcennutzung – und damit für gutes Schaltungsdesign, das mit wenig Speicher auskommt.

Firmen zum Thema

Schlange stehen: Gut gefüllte Pipelines stehen beim FPGA-Design für bestmögliche Ressourcennutzung.
Schlange stehen: Gut gefüllte Pipelines stehen beim FPGA-Design für bestmögliche Ressourcennutzung.
(Bild: gemeinfrei / Pixabay )

In vielen Fällen ist die Beurteilung einer Sache eine Frage des Standpunkts. Mit dem Auto im Verkehr festzustecken, ist fraglos nervig. Denn Stau ist Stillstand, wo man doch eigentlich zügig vorankommen will. Aus der Sicht eines Mautstreckenbetreibers ist ein Stau vor den Kassenhäuschen jedoch eine positive Sache, sichert er ihm doch über die nächsten Stunden hohe Einnahmen zu. Ein Stau im FPGA (Field Programmable Gate Array) kann ebenfalls etwas Positives sein, steht er doch für die optimale Lösung einer Designaufgabe.

In dem Beispieldesign dieses Artikels geht es um die Ausgabe einiger konstanter Datenbytes aus einem FPGA heraus über eine serielle Schnittstelle. Ein an die Schnittstelle angeschlossenes Terminal macht die Daten sichtbar. Die Bausteine der MachXO2/XO3-Familien von Lattice beinhalten einige interne Konstanten – etwa eine Device-ID oder eine Trace-ID, die das FPGA-Design auslesen kann. Einige dieser Datenbytes sind vom individuellen Baustein abhängig, andere vom geladenen Design. Alle diese Daten sind im Embedded Function Block abgelegt, der ein Wishbone-Interface besitzt. Vereinfacht gesprochen handelt es sich hier um eine Menge von 8 Bit breiten Registern, die über eine 8 Bit breite Adresse angesprochen wird.

60 Zugriffe zum Auslesen von 20 Bytes an Informationen

Beim Lesen der Daten muss dabei ein bestimmtes Protokoll eingehalten werden. So muss vor jedem Zugriff auf ein Register der Registersatz durch einen Schreibzugriff geöffnet und danach wieder geschlossen werden. Besonders kompliziert ist das aber nicht. Etwa 60 Schreib- und Lesezugriffe müssen durchgeführt werden, um die insgesamt 20 Bytes an Informationen zu lesen. Unabhängig von der Art der Implementierung sind für die Erfüllung der Aufgabe also folgende Schritte durchzuführen: Lesen der Daten aus dem Embedded Function Block, Umwandeln der Daten in ASCII-Zeichen, Ausgabe der ASCII-Zeichen über einen UART für die Anzeige.

Eine solche Aufgabe ruft eigentlich nach einem kleinen Prozessor im FPGA, um diese Arbeitsschritte in Software auszuführen. Für solche einfachen Anwendungen gibt es bei Lattice den MICO8, einen 8-Bit Soft-Prozessor mit System Builder und C-Entwicklungsumgebung. Ein System aus MICO8, Embedded Function Block und UART ist schnell zusammengebaut und das C-Programm zum Lesen der Daten und zur Ausgabe über die serielle Schnittstelle ist keine 300 Zeilen lang. Etwa 750 LUT plus fünf Block-RAM mit je 9 kBit sind für die Schaltung nötig. In Zeiten, in denen manche FPGA-Anbieter die Ressourcen in Mega-LUT angeben, ist dieser Ressourcenverbrauch sehr überschaubar.

Trotz der Einfachheit dieses Ansatzes ist das bei Weitem nicht die günstigste Lösung. Die drei Arbeitsschritte können nämlich auch von drei kleinen Logikmodulen erledigt werden. Ein solches FPGA-Design belegt deutlich weniger Ressourcen als ein Mikrocontroller im FPGA. Es ist nur leider so, dass die drei Module ihre jeweilige Aufgabe unterschiedlich schnell erledigen.

Das erste Modul liest die Daten aus dem Embedded Function Block, was ca. 50 µs benötigt. Die Wandlung der gelesenen Daten in zwei ASCII-Zeichen pro 8 Bit Daten ist in weniger als einer Mikrosekunde pro Byte erledigt. Die Ausgabe der ASCII-Zeichen über den UART verbraucht am meisten Zeit, da das Senden eines einzelnen ASCII-Zeichens bei angenommenen 115.200 Baud knapp 90 µs benötigt. Ausgerechnet das letzte Modul der Signalkette ist das langsamste!

Dieser Sachverhalt erfordert entweder den Einbau von Speichern für den Fluss der Daten von links nach rechts, was viele Ressourcen kostet, oder die Erzeugung bzw. Berücksichtigung einer Warte-Information von rechts nach links. So kann ein Modul, das Daten annehmen soll, signalisieren, dass es dazu gerade nicht in der Lage ist. Das datenliefernde Modul muss dann eben warten, was dazu führen kann, dass es selbst keine weiteren Daten an seinem Eingang annehmen kann. So baut sich im FPGA ein Datenstau auf, und was zunächst nach einem Problem klang, ist jetzt die Lösung der Designaufgabe mit minimalem Ressourcenverbrauch.

Bild 1: Die Schnittstellen aller Logikmodule im Datenpfad müssen für den Rückstau lediglich zwei Signale pro Eingang bzw. Ausgang aufweisen: take und busy.
Bild 1: Die Schnittstellen aller Logikmodule im Datenpfad müssen für den Rückstau lediglich zwei Signale pro Eingang bzw. Ausgang aufweisen: take und busy.
(Bild: Arrow Electronics)

Die Schnittstellen aller Logikmodule im Datenpfad müssen für den Rückstau lediglich zwei Signale pro Eingang bzw. Ausgang aufweisen: Ein Signal (take), das angibt, dass Daten vom sendenden zum empfangenden Modul übergeben werden sollen und ein zweites Signal (busy), das in die entgegengesetzte Richtung wirkt und die Übergabe verhindert.

Ein sendendes Modul kann nur in dem Fall die Daten als übergeben betrachten und sich um die Beschaffung respektive Annahme der nächsten Daten kümmern, wenn zum Zeitpunkt einer Taktflanke gilt: Das Übernahmesignal take ist aktiv und das Wartesignal busy ist inaktiv. Wenn alle Module diese Signale erzeugen beziehungsweise berücksichtigen, kann man die Module einfach in eine Reihe schalten und der Rest erledigt sich quasi von selbst.

Beschreibung der einzelnen benötigten Module

(Bild: Arrow Electronics)

Read Data: Dieses Modul liest die in der Tabelle 1 aufgeführten Daten aus dem Embedded Function Block. Für die Durchführung der Schreib- und Lesezyklen wird ein Embedded Block RAM genutzt, in dem alle Zugriffsadressen und bei Schreibzyklen auch die Daten abgelegt sind. Ein einfacher Zustandsautomat arbeitet die Liste der Zugriffe ab und erzeugt Steuersignale gemäß der Wishbone-Spezifikation. Wichtig ist eben die Tatsache, dass der Automat die Warte-Information berücksichtigt und keine weiteren Daten liest und ausgibt, wenn das empfangende Modul keine Daten annehmen kann.

Byte2Ascii: Dieses Modul wandelt die eingehenden Daten in zwei ASCII-Zeichen pro Byte, verdoppelt also die Datenmenge. Auch hier arbeitet ein kleiner Zustandsautomat, der den Eingang des Moduls solange sperrt, bis beide ASCII-Zeichen gesendet wurden. Zusätzliche Eingänge ermöglichen das Einfügen weiterer Zeichen nach der Ausgabe eines Bytes, wie z.B. Leerzeichen oder Zeilenschaltung. Damit kann man der Ausgabe eine einfache Formatierung geben. Natürlich muss auch während der Ausgabe der zusätzlichen Zeichen die Warteinformation am Eingang aktiv sein.

Event-Tipp: FPGA conference europe 2020

Die FPGA conference europe 2020 (29. bis 30. September 2020) ist Europas führende Entwicklerkonferenz und Networking-Plattform für den Einsatz der flexibel einsetzbaren programmierbaren Logik-SoCs.

Corona-bedingt findet die Veranstaltung in diesem Jahr virtuell statt – mit stark vergünstigten Ticket-Preisen!

Hier geht's zum Programm

UART: Dieses Modul serialisiert die empfangenen ASCII-Zeichen und sendet sie mit definierter Baudrate am Pin TxD aus. Bei vielen Evaluation-Boards kann man die dort ausgegeben Zeichen über einen virtuellen UART und ein Terminalprogramm auf dem PC sichtbar machen.

Das gesamte Design belegt etwa 110 LUT im FPGA plus ein Block-RAM. Nach dem Start des Designs zeigt die Terminalemulation folgende Ausgabe:

Bild 2: Die Terminalemulation zeigt nach dem Start der Schaltung die Device-ID, die 64-Bit große Trace-ID sowie den Usercode.
Bild 2: Die Terminalemulation zeigt nach dem Start der Schaltung die Device-ID, die 64-Bit große Trace-ID sowie den Usercode.
(Bild: Arrow Electronics)

Die erste Zeile enthält die Device-ID des verwendeten Bauteiltyps MachXO2-4000. Die zweite Zeile zeigt die 64-Bit Trace-ID, bei der die höchsten 8 Bit (hier 0x42) in den Projekteinstellungen frei definiert werden können. In der dritten Zeile steht der Usercode, der ebenfalls in den Projekteinstellungen frei vorgegeben werden kann. Dieser Usercode wird von der Entwicklungsumgebung als lesbarer Text in die JEDEC-Programmierdatei geschrieben. Dort kann man ihn mit einem einfachen Editor manuell verändern, solange die Auswirkung dieser Änderung auf die JEDEC-Checksumme berücksichtigt wird. Dieser manuell geänderte Usercode wird bei Programmieren ebenfalls im Embedded Function Block abgelegt. Die vierte Zeile in dem Bild zeigt den veränderten Usercode.

Diesen Beitrag lesen Sie auch in der Fachzeitschrift ELEKTRONIKPRAXIS Ausgabe 17/2020 (Download PDF)

Fazit: Mit der Methode des Rückstaus wird verhindert, dass Daten erzeugt werden, die nicht verarbeitet werden können. Das spart Logikressourcen und reduziert den Speicherbedarf enorm.

* Harald Flügel ist Senior Field Application Engineer bei Arrow Electronics.

(ID:46752307)