Ein Fachportal der eVision Systems GmbH

EDA Praxis / Application Notes

Vom KI-generierten VHDL-Code zum Simulationstest: ein vollständiges Beispiel

Zähler mit festen Anforderungen, vollständiger Testbench und echten GHDL-Tests; Aldec-Ablauf mit klar ausgewiesenem Teststatus.

Diese Application Note führt FPGA- und Verifikationsentwickler von einer festgelegten Zählerspezifikation zu einem reproduzierbaren Simulationstest. Das Beispiel wurde für EDA Praxis mit Codex ausgearbeitet; die fehlerhaften Varianten sind bewusst konstruierte Testfälle. Sie sind keine nachträgliche Erzählung über einen zufällig beobachteten Modellfehler. Sie erhalten vollständige eigene VHDL-Dateien, eine selbstprüfende Testbench, einen lokalen Runner und die tatsächlich entstandenen GHDL-Protokolle. Die Aldec-Schrittfolge ist dokumentationsbasiert; Hersteller-Tooltest ausstehend.

Voraussetzungen und prüfbarer Umfang

Sie sollten synchrone Logik, VHDL-Prozesse und einfache Zahlenoperationen kennen. Das Projekt verwendet VHDL-2008, ieee.std_logic_1164, ieee.numeric_std und std.env.finish. Für den reproduzierten Test brauchen Sie eine vorhandene GHDL-Installation und Python 3 ohne Zusatzpakete. Für den beschriebenen Aldec-Weg benötigen Sie eine berechtigte Active-HDL- oder Riviera-PRO-Installation mit passender VHDL-Unterstützung. Der Download enthält keine Hersteller-Software, Lizenzen oder Modellzugänge.

Geprüft wurde lokal unter Windows x64 mit GHDL 6.0.0, mcode-Backend. Das vollständige Versionsbanner steht im Ergebnisbericht. Weder Aldec noch Sigasi wurde für dieses Beispiel ausgeführt. Der kleine Prüfling hat einen Takt, Reset, Enable und einen vorzeichenlosen Zählerausgang. Vor dem ersten Reset ist sein Wert nicht festgelegt. Die Steuerleitungen werden als binär und synchron vorausgesetzt; unbekannte Logikwerte und das Überschreiten von Taktgrenzen gehören nicht zu dieser Spezifikation.

Schritt 1: Anforderungen vor der Korrektur festlegen

Unveränderte Anforderungen des Beispiels
IDAnforderungAbnahme
R1Aktiver High-Reset an der steigenden Flanke; Vorrang vor Enable.Reset mit Enable 0 und 1, auch aus einem Wert ungleich null.
R2Bei Reset 0 und Enable 1 um eins erhöhen.Gezielte Folge mehrerer aktivierter Takte.
R3Bei Reset 0 und Enable 0 halten.Mehrere deaktivierte Takte vor und nach Reset.
R4Modulo 2 hoch WIDTH überlaufen.Zwei vollständige Umläufe, einschließlich Maximum nach null.
R5Reset wirkt synchron.Reset zwischen Flanken darf den Ausgang noch nicht ändern.

WIDTH ist ein positiver Parameter. Die Testbench prüft die Breiten 1, 4 und 8; ihr Referenzmodell ist ausdrücklich auf 1 bis 8 begrenzt. Das kleinste Format ist besonders hilfreich, weil der Überlauf dort bereits nach zwei Zählschritten erreicht wird. Eine größere Breite prüft, ob der Code tatsächlich parametrisiert ist. Diese Auswahl belegt nicht jede denkbare Parameterkombination. Die Anforderungen und die daraus abgeleitete Testbench bleiben während der Fehlerkorrektur unverändert.

Schritt 2: Dateien und Agentenauftrag vorbereiten

ai-counter/
  rtl/ai_counter.vhd
  tb/tb_ai_counter.vhd
  run.py
  README.md
  LICENSE
  results/report.json
  results/*.log

Vollständiges Beispiel mit echten GHDL-Ergebnissen herunterladen (ZIP). Entpacken Sie es in einen eigenen lokalen Arbeitsordner. Die Quelldateien und der Runner stehen unter MIT-Lizenz; Herstellerdateien sind nicht enthalten. Erzeugen Sie Ihre eigenen Ergebnisse in einem anderen Ausgabeordner, damit der mitgelieferte Referenzstand erhalten bleibt.

Ein geeigneter Agentenauftrag nennt die fünf Anforderungen, die beiden Quelldateien, die allein zur Änderung freigegebene RTL-Datei und das Prüfschema. Beispielsweise: „Prüfen Sie die Implementierung gegen R1 bis R5. Ändern Sie nur rtl/ai_counter.vhd. Führen Sie den vorhandenen Runner aus und berichten Sie Quelländerung, tatsächliche Befehle, Version und Rückgabecode. Ändern Sie weder Sollwerte noch Assertions. Bei fehlendem Werkzeug, Lizenzproblem oder unvollständigem Lauf halten Sie an und kennzeichnen die Prüfung als nicht bestanden beziehungsweise nicht ausgeführt.“

Eine separate Kopie eignet sich zum Experimentieren. Der bereitgestellte Runner erzeugt seine absichtlich fehlerhaften Varianten selbst in temporären Verzeichnissen. Er verändert die mitgelieferte RTL-Datei nicht. Damit bleiben die Fehlerdemonstration und die nutzbare Referenzimplementierung eindeutig getrennt. Nutzen Sie bei einer eigenen KI-Änderung zusätzlich die Versionsverwaltung und betrachten Sie den Diff vor der Ausführung, insbesondere Änderungen an Testskripten und erwarteten Resultaten.

Schritt 3: Die Hardwarebeschreibung nachvollziehen

Die entscheidende Reihenfolge im Taktprozess lautet Reset, danach Enable. Der Ausgang erhält den Wert des internen Registers. ieee.numeric_std liefert die typisierte Addition für unsigned; die feste Breite bildet den modularen Überlauf ab. Eine fehlende Zuweisung im deaktivierten Zweig bewahrt in diesem getakteten Prozess den Registerwert. Die vollständige Entity und Architektur stehen in rtl/ai_counter.vhd; der folgende Ausschnitt zeigt den prüfentscheidenden Teil.

if rising_edge(clk) then
  if rst = '1' then
    count <= (others => '0');
  elsif en = '1' then
    count <= count + 1;
  end if;
end if;

Eine Projektanalyse kann davor falsche Bezeichner, Typfehler oder fehlende Abhängigkeiten sichtbar machen. Die Sigasi-Anleitung zeigt die dokumentierte Agentenanbindung einschließlich Lizenzgrenzen. Für dieses kleine Projekt ist sie eine zusätzliche, separat zu evaluierende Stufe. Ein akzeptierter Analysebericht würde R4 nicht automatisch bestätigen: Auch ein korrekt formulierter sättigender Zähler wäre sprachlich plausibel und fachlich falsch.

Schritt 4: Die Testbench verstehen

Testbench und DUT: Die Erwartung entsteht unabhängig
Zwei Wege zur AssertionDie Anforderungen R1 bis R5 liefern Sollwerte. Stimuli treiben clk, rst und en des Zählers. Die Assertion vergleicht dessen Ausgang q mit dem unabhängigen Sollwert eine Nanosekunde nach der steigenden Flanke. Ein Watchdog beendet einen unvollständigen Test.Anforderungen R1–R5Sollwerte vorher festlegenStimuli / tickclk · rst · enDUT: ai_counterZu prüfendes RTLAssertionq = erwarteter Wert?Unabhängiger SollwertqPrüfung: ↑ clk + 1 nsAbschluss: PASS erst nach allen Assertions · Watchdog: 20 µs Simulationszeit

Die Testbench vergleicht festgelegtes Verhalten; sie übernimmt nicht die Implementierung als Sollmodell. Die 1 ns Wartezeit dient dem Simulationsablauf und ist keine physikalische Timingvorgabe.

Die Prozedur tick setzt Reset und Enable an der fallenden Flanke und prüft den Ausgang eine Nanosekunde nach der nächsten steigenden Flanke. Diese Wartezeit lässt die Signalzuweisungen im Simulationsmodell wirksam werden. Sie ist keine Vorgabe für das physikalische Timing der späteren Schaltung. Die Testbench vergleicht jeden Sollwert mit q und nennt bei einem Fehler die zugehörige Anforderung. Der Reset zwischen Flanken erhält eine zusätzliche, ausdrücklich vor der nächsten steigenden Flanke ausgeführte Prüfung.

tick('0', '1', 1, "R2 enabled increment");
tick('0', '0', 1, "R3 disabled hold");
tick('1', '1', 0, "R1 reset priority with enable");
-- The complete file also checks two wraps and synchronous reset.
-- PASS is emitted only after every assertion has succeeded.

Assertions melden Fehler mit severity failure. Erst nach sämtlichen Prüfungen erscheint EDA_AI_COUNTER_PASS mit der aktuellen Breite, danach beendet finish(0) die Simulation. Ein Watchdog bricht nach 20 Mikrosekunden Simulationszeit ab, falls der Test nicht fertig wird. Der Python-Runner begrenzt zusätzlich die reale Laufzeit jedes Analyse-, Elaborierungs- und Simulationsprozesses auf 30 Sekunden. So bleiben ein fehlender Simulationsabschluss und ein positives Testergebnis unterschiedliche Zustände. Die GHDL-Laufzeitoptionen sind im offiziellen Simulationshandbuch beschrieben.

Erwartetes Timing der ersten sechs Prüfungen

Aus der Testbench abgeleitet, WIDTH = 4. Eingänge wechseln an der fallenden Flanke; geprüft wird jeweils 1 ns nach der nächsten steigenden Flanke.

Synchroner Reset, Zählen und HaltenSteigende Flanken bei 15, 25, 35, 45, 55 und 65 Nanosekunden. Erwartete geprüfte q-Werte: 0, 1, 1, 1, 0, 1. Bei 55 Nanosekunden setzt Reset trotz aktivem Enable zurück. Vor dem ersten Reset ist q nicht festgelegt. Die Datentabelle enthält alle Prüfpunkte.15 ns25 ns35 ns45 ns55 ns65 nsclkrstenq?011101Prüfung162636465666? = vor erstem Reset nicht festgelegt · q nach Signalaktualisierung dargestellt55 ns: rst = 1 hat Vorrang vor en = 1
Sollwerte; rst und en gelten an der jeweils vorangehenden steigenden Flanke
Prüfzeit (ns)rstenq erwartetGeprüftes Verhalten
16100Reset ohne Enable
26011Inkrement
36001Halten
46001Erneut halten
56110Reset hat Vorrang
66011Erneutes Inkrement

Eigene schematische Darstellung, keine neue Simulatoraufnahme und kein Aldec-Test. Die weiteren Überlauf- und Resetprüfungen stehen in der vollständigen Testbench.

Schritt 5: Mit Active-HDL simulieren

Öffnen Sie eine berechtigte Active-HDL-Installation und legen Sie einen neuen Workspace mit Design in einem leeren Evaluierungsordner an. Fügen Sie die beiden Originaldateien hinzu. Wählen Sie in den Compiler-Einstellungen VHDL-2008 und kompilieren Sie zuerst die RTL-Datei, danach die Testbench in work. Wählen Sie tb_ai_counter als Simulationstop und beginnen Sie mit WIDTH gleich 4. Initialisieren Sie die Simulation und setzen Sie in der Konsole set breakassertlevel 2.

Führen Sie Run All aus. Erwartet werden das vollständige PASS-Kennzeichen für WIDTH=4 und ein normaler Abschluss ohne Assertion-Fehler. Wiederholen Sie nach erneuter Initialisierung mit WIDTH=1 und WIDTH=8. Für den Gegenversuch ändern Sie ausschließlich in einer Arbeitskopie elsif en = '1' then zu else. Nach Neukompilierung und Initialisierung muss R3 scheitern; ein PASS darf nicht erscheinen. Stellen Sie anschließend die Originaldatei wieder her. Quelle für den Kontrollwert: Aldec: Assertion-Schwellen.

Aldec dokumentiert außerdem den Shell-/Batch-Ablauf mit Bibliotheksanlage, Kompilierung, Initialisierung und Lauf. Übernehmen Sie Compilerstandard, Optionen und Prozessende aus der Hilfe Ihrer tatsächlich installierten Version, bevor Sie daraus eine Pipeline bauen. Der beschriebene GUI-Ablauf ist hier vollständig nachvollziehbar, aber nicht lokal mit Aldec getestet. Quelle: Active-HDL Batch Mode. Verwenden Sie kein Fortsetzen-nach-Fehler-Muster, um einen roten Lauf scheinbar erfolgreich abzuschließen.

Schritt 6: Riviera-PRO und automatisierte Fehlerauswertung

Für Riviera-PRO gilt derselbe fachliche Ablauf mit den Originaldateien: neues Design, VHDL-2008, RTL vor Testbench, tb_ai_counter als Top, Initialisierung und vollständiger Lauf. Die dokumentierte Assertion-Steuerung lautet dort vhdlassert.break error. Das ist ein anderer Befehl als in Active-HDL. Ein Halt bei einer Assertion garantiert noch keinen von null verschiedenen Betriebssystem-Rückgabecode. Vor einer CI-Anbindung muss der absichtliche Fehler deshalb zusätzlich als fehlgeschlagener Job nachgewiesen werden.

Dieser Herstellerlauf bleibt ausstehend. Notieren Sie bei Ihrer Evaluation Buildnummer, Edition, Betriebssystem, verwendete Befehle und Verhalten von finish(0). Wenn die Simulation nur pausiert, die Lizenz fehlt oder kein Abschlusskennzeichen erscheint, ist die Abnahme offen. Der veröffentlichte GHDL-Runner ist keine ungeprüfte Aldec-Schnittstelle. Er zeigt das Auswertungsprinzip, dessen Umsetzung für das jeweilige Produkt separat getestet werden muss.

Schritt 7: Tatsächlich ausgeführte lokale Tests

python run.py --ghdl ghdl --output test-results

Führen Sie den Runner im entpackten Projektordner aus. Für einen einzelnen manuellen Lauf legen Sie dort den neuen Unterordner manual-run an und wechseln hinein; dadurch beziehen sich ../rtl und ../tb auf die mitgelieferten Quellen. Verwenden Sie einen noch nicht vorhandenen Ordnernamen, damit keine alte Arbeitsbibliothek übernommen wird.

mkdir manual-run
cd manual-run
ghdl -a --std=08 ../rtl/ai_counter.vhd ../tb/tb_ai_counter.vhd
ghdl -e --std=08 tb_ai_counter
ghdl -r --std=08 tb_ai_counter -gWIDTH=4 --assert-level=error

Am 19.10.2026 bestanden die drei positiven Breiten mit Rückgabecode 0 und passendem Kennzeichen. Vier absichtliche Varianten wurden nach erfolgreicher Kompilierung durch Assertions abgewiesen: Reset abhängig von Enable, Sättigung statt Überlauf, ignoriertes Enable und asynchroner Reset. Alle vier lieferten Rückgabecode 1 und kein PASS. Ein Kompilierfehler zählt im Runner ausdrücklich nicht als erfolgreicher Nachweis eines Verhaltensfehlers. Die einzelnen Protokolle und report.json sind im Download enthalten.

Auswertung, Grenzen und nächster Schritt

Bei einem Fehler lesen Sie zuerst die genannte Anforderung, dann die letzte Eingangskombination und den erwarteten Wert. Ein Fehler in R3 weist beispielsweise auf unerwünschtes Zählen bei deaktiviertem Enable hin. Prüfen Sie danach den kleinsten verantwortlichen RTL-Abschnitt und wiederholen Sie den vollständigen unveränderten Test. Ein zusätzlicher Testfall darf die Suite stärken; eine entfernte Assertion würde dagegen die Aussage des bisherigen Ergebnisses verändern.

Das Ergebnis belegt Verhalten für die beschriebenen Stimuli und Parameter. Es belegt keine Synthesefähigkeit in einer bestimmten FPGA-Werkzeugversion, keine Taktfrequenz, keine CDC-/RDC-Eigenschaften und keine vollständige funktionale Korrektheit aller möglichen Erweiterungen. Die Quellenprüfung ist vom tatsächlichen GHDL-Test und einer menschlichen Fachfreigabe getrennt; eine solche Fachfreigabe wird nicht behauptet. Für eine Aldec-/Sigasi-Evaluation für Ihr Projekt können Sie dieses kleine Beispiel um einen repräsentativen eigenen Testfall ergänzen.

Sie möchten diese Vorgehensweise in Ihrem Projekt einsetzen?

Passende Entwicklungswerkzeuge besprechen

EDA PRAXIS / NEWSLETTER

Neue Perspektiven.
Direkt ins Postfach.

Praxiswissen zu HDL, Simulation und Verifikation. Neue Beiträge, Application Notes und Hinweise zu passenden Werkzeugen.