Entwicklung FPGA-basierender Systeme

Die selbsttestende Testbench

28. November 2012, 11:05 Uhr | Von Eugen Krassin
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 1

Die selbsttestende Testbench

Weiterhin dienen Labels zur Identifizierung von Verzweigungspunkten beziehungsweise von Unterprogrammen. Das Label »INT:« definiert zum Beispiel die Einsprung-adresse der ISR (siehe auch Programm zum Anwendungsbeispiel). Mit Befehlen zur Interrupt-Steuerung lässt sich das Interruptsig-nal einschalten (ENAI) beziehungsweise sperren (DISI). Per Default ist der Interrupt ausgeschaltet. Außerdem gibt es noch allgemeine Befehle, welche die Lesbarkeit des Programms erleichtern. Dazu zählen zum Beispiel »*« als Kommentarzeichen, NOP (»Tue nichts«. Es vergeht die Zeit »time_nop_ins-truction«), END (Programmende) oder der »PRINT! string«-Befehl, der in der Tracedatei den String als Debug-Information ausgibt.

Die Compiler-Logdatei

Wie in Bild 3 gezeigt, liest die Funktion »get_instructions()« das Steuerprogramm mit dem Namen »instruction.txt« in eine interne Struktur ein. Die Funktion überprüft dabei die Syntax gemäß der Definition des Befehlssatzes. Im nächsten Schritt sucht die Prozedur »search_replace()« diese Struktur nach Labels ab und ersetzt symbolische Sprungadressen durch absolute Adressen, wobei die ursprünglichen Labels auskommentiert werden. Dabei wird auch das Compiler-Logfile mit dem Namen »compiler_log.txt« erzeugt. Im Anschluss führt die Prozedur »execute()« das Programm aus.

Die Tracedatei »program_trace.txt« hingegen listet die vom Prozessor ausgeführten Befehle in der zeitlich korrekten Reihenfolge auf und registriert neben dem aktuellen Zeitpunkt stets auch den gesamten Status des Prozessors, bestehend aus den Inhalten der internen Register sowie dem Statusregister und dem Status des Interrupt-Pins. Eventuelle mit dem »Print! string;«-Befehl definierte Kommentare werden ebenfalls in die Tracedatei eingetragen. Wünscht der Anwender ein weniger detailliertes Trace-Protokoll, kann er die Darstellungs-tiefe über einen Eintrag in »trace_configuration.vhd« ändern.

Der A/D-Wandler

Der »AD7767« von Analog Devices wandelt eine analoge Eingangsspannung im Bereich 0 V bis VREF in einen digitalen 24-Bit-Wert. Die Darstellung des digitalen Wertes erfolgt im 2er-Komplement gemäß der Formel N = (VIN/VREF - 0,5) ∙ 224. Vor der Wandlung ist eine Initialisierung des Bausteins erforderlich. Das Modell protokolliert alle Zugriffe und stellt die gewandelten Daten über die SPI-Schnittstelle zur Verfügung.

passend zum Thema

Die selbsttestende Testbench

Bild 4: Anwendungsbeispiel
© PLC2
Bild 5: OMAP-L138: Asynchrones Read-Timing
© PLC2
Bild 6: OMAP-L138: Asynchrones Write-Timing
© PLC2

Alle Bilder anzeigen (5)

Gemäß dem in Bild 4 gezeigten Anwendungsbeispiel, bestehend aus dem ARM-Mikrocontroller »OMAP-L138«, dem A/D-Wandler »AD7767« und einem FPGA, soll eine Hardwareplattform entwickelt und verifiziert werden. Der Wandler wandelt Daten und stellt diese über SPI zur Verfügung. Das FPGA besitzt neben dem SPI-Controller noch zusätzliche Register, die zur Steuerung der Funktionen vorgesehen sind.

Nach jeder Datenübertragung vom A/D-Wandler zum FPGA erzeugt der SPI-Controller ein Interruptsignal an den Mikrocontroller. Der IRQ-Eingang des Interruptcontrollers im OMAP-L138 ist als high-aktiver, flankengesteuerter Interrupt konfiguriert. Die daraufhin aufgerufene ISR soll die entsprechenden Daten einlesen. Die in Bild 5 bis Bild 8 dargestellten Timing-Diagramme des OMAP-L138 sowie des AD7767 lassen leicht erahnen, dass der Verifikationsaufwand hoch sein und dementsprechend auch lange dauern kann.

Vor allem müssen die Timing-Diagramme immer wieder manuell überprüft werden. Zyklische Abläufe sind hier auf herkömmliche Art und Weise entweder nur schwer realisierbar oder überhaupt nicht wirklich möglich. Die Verwendung von »intelligenten« und vorzugsweise programmierbaren autonomen Modellen bietet hier eine sinnvolle Alternative. Der im Kasten »Testprogramm« gezeigte Code vereinfacht die Verifikation erheblich.

Testprogramm   

 *****************************************
*Testprogram zur Verifikation der
Funktionalität des FPGA Designs
* mit OMAP-L138 und ADC AD7767
******************************************

PRINT! Read / Write Register Test ;
* Register 0: Adresse 8000:
* Bit0 -> Start Data Aquisition
* Bit1 -> Power ON Init
*
* Register 1: Adresse 8002:
*
* Register Status : Adresse 8100:
*
* Register datreg_h : Adresse 8102:
* oberen 8 Bit des 24 Bit Resultats
*
* Register datreg_1 : Adresse 8104:
* unteren 16 Bit des 24 Bit Resultats
*
MOVE R0,#8000;         * Adresse reg0 ist in R0
CALL testreg;
MOVE R0,#8002;
CALL testreg;
MOVE #8000,#0000;   * Setze Register reg0 auf 0
MOVE #8002,#0000;   * Setze Register reg1 auf 0
PRINT! Read / Write Register Test erfolgreich;
ENAI; * Enabele Interrupt
JUMP test2;

testreg:
MOVE R4, (R0); * lese FPGA register.
JUMPNZ error;   * Muss 0 sein
MOVE (R0),R0;
MOVE R4, (R0); * lese FPGA register zurück.
CMP R4,R0;      * Muss den WErt von R0 haben
JUMPNZ error1;
RETURN;
***********************
* Beginn Test 2
***********************
test2:
MOVE #8000,#0003;    * starte AD Init Sequenz
MOVE #8000,#0001;    * erzeuge nur einen Puls
wait:
JUMP wait;        * warte auf den rdy interrupt

**********************************
* Das ist die Interrupt Service Routine
**********************************
INT:
PRINT! Entering Interrupt Service Routine;
MOVE R0,#8102;         * Adresse datreg_h ist in
R0
MOVE R1, (R0); * lese datreg_h in Register 1
MOVE R0,#8104;         * Adresse datreg_1 ist in
R0
MOVE R2, (R0); * lese datreg_h in Register 2
PRINT! Leaving Interrupt Service Routine;
RETURN;

error1:
PRINT! test 1: Read / Write Register Test
fehlgeschlagen;

Testprogramm


Dabei wird nur ein kleiner Teil der insgesamt verfügbaren Assemblerbefehle des Modells verwendet. Zunächst greift das Programm auf die im FPGA implementierten Register zu und führt einen einfachen Schreib/Lese-Test mit Hilfe von Unterprogrammen durch. Dies demonstriert gleichzeitig auch die Verwendung von Call/Return-Befehlen. Danach stößt das Programm die Initialisierungssequenz des A/D-Wandlers an.

Da der AD7767 die Daten nun zyklisch wandelt, wird auch zyklisch ein Interrupt-Request an den Prozessor ausgelöst. Die ISR, definiert durch das Label »INT:«, wird bei jeder Interrupt-Anforderung durchlaufen. Sind die Daten eingelesen, steht es dem Anwender frei, diese Daten weiter im Programm zu verarbeiten; der Anwender kann jetzt die Daten also beliebig auswerten, modifizieren oder was auch immer er damit anfangen möchte.

Gleichzeitig ist hiermit auch eine sehr einfache Methode zur Leistungsoptimierung beziehungsweise Optimierung des Datendurchsatzes respektive Messung der Latenzzeiten usw. gegeben. Compiler-Logdatei und Tracedatei sind in der Online-Version dieses Artikels unter www.elektroniknet.de zu sehen. Natürlich ist auch das Modell des AD7767 an der Verifikation aktiv beteiligt.

Es wandelt nicht nur die analoge Eingangsspannung in den entsprechenden digitalen Wert um, sondern führt auch Setup- und Hold-Checks durch, um eventuelle Verletzungen zu melden. Das Modell weigert sich auch, Datenwandlung durchzuführen, bevor nicht eine entsprechend korrekt ausgeführte Initialisierungssequenz, wie vom Hersteller spezifiziert, ausgeführt wurde. Dazu erstellt das Modell des Bausteins eine entsprechende Logdatei.

Eine solche ist ebenfalls im Online-Artikel zu sehen. Der Anwender muss nach Abschluss der Simulation nur die Tracedatei des Mikrocontrollers sowie das Log-File des ADCs analysieren, um die Funktion seines FPGA-Entwurfs zu verifizieren. Aus der Tracedatei ist sowohl der allgemeine Status des Mikrocontrollers als auch der aktuelle Stand des Statusregisters nebst den 15 allgemeinen Registern ersichtlich.

Die Logdatei zeigt sowohl die erfolgreiche und korrekte Initialisierung des A/D-Wandlers als auch die aktuell gewandelten analogen und digitalen Werte an. Im aktuellen Fall werden treppenförmig auf- und absteigende analoge Eingangssignale im Wertebereich von 0 V bis VREF gewandelt. Sollten Abtastwerte erzeugt, aber nicht abgeholt werden, generiert das Modell eine Warnung.

Andere zusätzliche Prüfungen und Ergänzungen sind dem Anwender überlassen. Bei dieser Art der Verifikation ist es offensichtlich, dass zeitaufwendige und vor allem wiederkehrende Analysen der Wellenform nicht notwendig sind. Die Modelle überprüfen automatisch beispielsweise Pulsbreiten oder Setup- und Hold-Zeiten. Weitere Überprüfungen und Checks kann der Anwender beliebig hinzufügen.

Die Analyse einer eventuell komplexen Wellenform entfällt komplett. Bereits dieses kleine Beispiel demonstriert sehr gut das Konzept von selbsttestenden Testbenches. Das Modell des Prozessors kann einfach auf andere, unter Umständen gänzlich unterschiedliche Prozessorstrukturen erweitert oder geändert werden. Im vorliegenden Fall wurde das allgemeine Modell auf den Mikrocontroller OMAP-L138 abgestimmt.

Um das allgemeine Modell auf unterschiedliche Bausteine anzuwenden, ist lediglich die von der Prozedur execute()aufgerufene Prozedur move() zu ändern und das Timing des Prozessors anzupassen. Alle anderen Dateien und insbesondere die Programmierung des Prozessors selbst bleiben unverändert. Das ist natürlich ein entscheidender Vorteil, der sich in verkürzten Entwicklungszeiten niederschlägt.

Über den Autor:

Eugen Krassin ist Geschäftsführer von PLC2.


  1. Die selbsttestende Testbench
  2. Die selbsttestende Testbench

Lesen Sie mehr zum Thema


Jetzt kostenfreie Newsletter bestellen!