Kampis Elektroecke

Das Processing System

Zynq FPGA

Der Zynq kombiniert ein FPGA und einen Dual Core ARM Prozessor. Beide Komponenten kann man unabhängig voneinander programmieren um sie so beliebig einsetzen zu können.
In diesem Artikel zeige ich, wie das Processing System (PS) des Zynq genutzt werden kann und wie man mit dem PS auf das FPGA zugreift.

Das Blockschaltbild:

Als erstes wird in Vivado ein neues Projekt angelegt und dort wird anschließend über Create Block Design ein neues Blockschaltbild mit dem Namen System angelegt und geöffnet:

Mit einem Klick auf Add IP werden nun folgende Blöcke eingefügt:

  • 2x AXI GPIO
  • 1x ZYNQ7 Processing System

Durch einen Klick auf einen der Blöcke erscheint links unten neben dem Blockschaltbild ein Fenster wo die Blöcke umbenannt werden können. Auf diese Weise werden die GPIO Blöcke in LED und Schalter umbenannt.
Danach wird mit einem Klick auf Run Connection Automation ein am oberen Rand des Blockschaltbild ein Assistent gestartet werden, welcher die einzelnen Blöcke miteinander verbindet.
Im letzten Schritt werden die Verbindungen der GPIO Blöcke nach außen geführt, indem mit der rechten Maustaste auf das Verbindungsstück des Anschlusses GPIO geklickt und anschließend der Menüpunkt Make External ausgewählt wird:

Durch einem Doppelklick kann der GPIO Block konfiguriert werden. Dort stellt wird für den Wert GPIO Width der Wert 4 eingestellt. Dadurch ist der GPIO-Block 4-Bit breit, führt also insgesamt 4 Ein- oder Ausgänge:

Diese Schritte werden anschließend für den zweiten GPIO Block wiederholt. Zuletzt benenne ich die Ausgangssignale noch um. Die fertige Schaltung sieht am Ende dann so aus:

Jetzt wird das PS konfiguriert, indem das Konfigurationsmenü mit einen Doppelklick auf den ZYNQ7 Processing System-Block geöffnet wird.
Über Import XPS Settings wird mit Hilfe der Konfigurationsdatei System.xml die Grobkonfiguration durchgeführt:

Dazu einfach die Auswahl der Datei mit einem Klick auf OK bestätigen und kurz warten.
Danach werden folgende Punkte abgewählt:

  1. PS-PL Configuration:
    General -> Enable Clock Resets -> FCLK_RESET0_N
  2. MIO Configuration:
    Memory Interfaces -> Quad SPI Flash
    I/O Peripherals -> ENET 0, USB 0, SD 0
    Application Processor Unit -> Timer 0

Mit einem Klick auf OK bestätigt wird die Änderung bestätigt. Das Processing System nimmt im Designer nun folgende Form an:

Nun wird das Design gespeichert und mit einem Klick auf Project Manager wird das Menü Sources des Projektes geöffnet und die Datei System.bd ausgewählt und mit einem Rechtsklick das Menü geöffnet:

Dort werden jetzt folgende Punkte ausgeführt:

  1. Generate Output Products…
  2. Create HDL Wrapper…

Diese beiden Schritte dauern etwas. Mit ihnen wird eine Datei kreiert die zum erstellen des Bitstreams notwendig ist und welche die Verbindung zwischen Peripherie und Prozessor beschreibt.
Sobald der HDL Wrapper erstellt wurde, wird der Name des aktuell aktiven Designs (in diesem Fall System.bd) fett hervorgehoben.
Nun kann über Run Synthesis die Hardwaresynthese gestartet werden.
Dieser Vorgang dauert etwa 3-4 Minuten und in dem sich danach öffnenden Fenster wird dann auf Open Synthesized Design geklickt um das IO Planing zu starten:

In diesem Fenster werden die Signale, welche eben nach außen geführt wurden, den I/Os des FPGAs zugeordnet.

Die Zuweisung wird gespeichert und nun kann mit einem Klick auf Generate Bitstream der Bitstream erzeugt werden (eine eventuelle Warnung einfach mit einem Klick auf OK bestätigen). Sobald die Generierung des Bitstreams abgeschlossen ist, wird die sich öffnende Meldung mit OK bestätigt.
Damit wäre das PS hardwaretechnisch fertig. Nun geht es an die Software für den ARM Prozessor!

Die passende Software:

Im ersten Schritt wird die Hardware für das SDK exportiert.
Dazu klickt ihr auf File und dann auf Export:

Danach klickt ihr auf Launch SDK um das Xilinx SDK zu starten.
Sobald das SDK geöffnet ist, solltet ihr im Project Explorer bereits einen Ordner namens System_wrapper_hw_plattform_0 sehen.
Dies ist der automatisch erzeugte Code für das Processing System im System Wrapper.
Über einen Klick auf File → New → Board Support Package werden die notwendigen Treiber und Informationen für die programmierbare Logik angelegt:

Dieses Fenster einfach mit einem Klick auf Finish und OK schließen.
Anschließend legt ihr über File → New→New Application Projekt ein neues Projekt an:

Über einen Klick auf Next könnt ihr Beispielprojekte auswählen. Da wir kein fertiges Beispielprojekt benötigen, wählen wir Empty Application aus und klicken auf Finish.
Der neu angelegte Ordner System wird nun geöffnet und das Verzeichnis src ausgewählt. Über File → New → Source File wird eine neue C-Datei mit dem Namen main.c erstellt:

In diese Datei müssen zuerst die notwendigen Headerdateien eingefügt werden:

Die erste Headerdatei beinhaltet die IDs und Adressen jedes IP-Cores die in dem Design integriert sind.
Mit der zweiten Headerdatei werden spezielle Funktionen für den AXI GPIO Block eingefügt.
Bevor ein IP-Block verwendet werden kann muss er initialisiert werden. In dem Reiter system.mss finden sich alle aktiven IP-Blöcke und dort kann man zu jedem IP-Block eine Dokumentation öffnen. Dort kann man dann die einzelnen Funktionen eines IP-Blocks nachschlagen.
Der AXI GPIO Block wird über die Funktion

initialisiert. Die Variable Instanz ist ein Zeiger vom Typ XGpio der auf den fertig initialisierten GPIO Block zeigt und muss bei jeder weiteren Funktion mit angegeben werden.
Die Variable ID ist die eigentliche ID des Blockes. Sie dient der Identifikation und ist in der Datei xparameters.h zu finden.

Die Codezeilen um beide GPIO Blöcke zu initialisieren lauten also wie folgt:

Im nächsten Schritt müssen die Blöcke als Ein- bzw. Ausgang gesetzt werden. Dies geschieht mit der Funktion

Dabei ist die Variable Instanz der vorhin initialisierte GPIO Block, die Variable Kanal der verwendete Kanal des GPIO Blocks (die Blöcke haben zwei Kanäle. Wir verwenden Kanal 1) und mit Direction gibt man an ob ein Pin ein Eingang oder ein Ausgang sein soll. Der Wert 1 setzt einen Pin als Ausgang und der Wert 0 setzt den Pin dann als Eingang:

Theoretisch braucht man nur die ersten vier Bits des GPIO Blocks zu konfigurieren, da wir die Breite der Signale der Blöcke im Schaltbild auf vier beschränkt haben. Ich konfiguriere der Einfachheit halber aber alle Bits.
Die GPIO Blöcke sind nun einsatzbereit. Mit dem Befehl

kann der Status der Eingänge abgefragt werden, was wir in einer while()-Schleife auch direkt machen:

Um Daten anschließend in den GPIO Block zu schreiben wird die Funktion

verwendet. Mit Hilfe dieser Funktion wollen wir die Daten, welche wir eben von den Schaltern eingelesen haben, nun auf den LEDs ausgeben:

Das fertige Programm sollte jetzt so aussehen:

Die fertigen Dateien können nun auf das Board übertragen werden. Über den Menüpunkt Xilinx Tools kann das FPGA direkt aus dem Xilinx SDK programmiert werden:

Danach kann über einen Rechtsklick auf den Projektordner des C-Programmes der ARM-Prozessor programmiert werden:

Sobald beide Teile programmiert sind kann die Anwendung getestet werden.
Dafür werden einfach die Schalter auf dem Board umgelegt und pro Schalter sollte dann eine LED aufleuchten.

→ Zurück zu FPGA + VHDL

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.