Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

Stimulus-Datei in Testbench mit TEXTIO eingelesen

Das Lesen von Signalwerten aus einer Datei ist eine alternative Möglichkeit, Stimuli für das zu testende Gerät (DUT) zu erzeugen. Die Testbench-Sequenz und das Timing sind in einer Stimulus-Datei fest codiert, die von der VHDL-Testbench Zeile für Zeile gelesen wird. Auf diese Weise können Sie das Muster der Wellenform, die Sie dem Testobjekt zuführen möchten, einfach ändern.

Manchmal haben Sie ein sehr spezifisches Testmuster oder eine Abfolge von Ereignissen, denen Sie Ihr DUT unterziehen möchten. Sie können dies erreichen, indem Sie in einer ASCII-Datei die Signalwerte angeben, die jedes Signal haben soll, sowie die relative Simulationszeit, zu der sie sich ändern sollen. Die Rolle der VHDL-Testbench bei einer solchen Strategie besteht darin, die Daten aus der Stimulusdatei zu lesen und die Werte zum richtigen Zeitpunkt auf die DUT-Eingänge anzuwenden.

Dieser Artikel ist der zweite in einer Reihe über den Dateizugriff in VHDL. Wir haben uns im vorherigen Blogbeitrag angesehen, wie man Hexadezimal-, Oktal- und Binärwerte aus einer Datei liest. Gehen Sie zurück und lesen Sie ihn, wenn Sie mehr über das Lesen aus einer Datei mit TEXTIO erfahren möchten Bibliothek in VHDL.

Dieser Blogbeitrag ist Teil einer Reihe über die Verwendung der TEXTIO-Bibliothek in VHDL. Lesen Sie die anderen Artikel hier:

So initialisieren Sie RAM aus einer Datei mit TEXTIO

BMP-Datei-Bitmap-Bild, gelesen mit TEXTIO

Der Testfall

Das Beispiel-DUT ist ein 4-Eingangs-Multiplexer (MUX), der einem meiner früheren Blog-Beiträge entnommen wurde. Es ist ein standardmäßiger, asynchroner 4-zu-1-MUX mit einer Datenbreite von einem Byte. Wie es funktioniert, ist für diesen Artikel nicht wichtig, da wir die Ausgaben nicht überprüfen werden, sondern nur zu Demonstrationszwecken.

Die Entität des MUX ist unten gezeigt.

entity mux_4 is
  port(
    -- Data in
    din_0 : in unsigned(7 downto 0);
    din_1 : in unsigned(7 downto 0);
    din_2 : in unsigned(7 downto 0);
    din_3 : in unsigned(7 downto 0);

    -- Selector
    sel  : in unsigned(1 downto 0);

    -- Data out
    dout : out unsigned(7 downto 0));
end entity;

Nachdem wir die erforderlichen Pakete am Anfang der VHDL-Datei importiert haben, deklarieren wir die Eingangssignale, die wir mit dem DUT verbinden werden. Wie Sie der folgenden Auflistung entnehmen können, handelt es sich um Blaupausen aus der MUX-Entitätsdeklaration.

signal din_0 : unsigned(7 downto 0);
signal din_1 : unsigned(7 downto 0);
signal din_2 : unsigned(7 downto 0);
signal din_3 : unsigned(7 downto 0);
signal sel  : unsigned(1 downto 0);
signal dout : unsigned(7 downto 0);

Wir verwenden die Entitäts-Instanziierungsmethode, um eine Instanz des MUX mit der Bezeichnung „DUT“ oben im Architekturbereich unserer Testbench zu erstellen. Die Entity-Signale sind mit den lokalen Testbench-Signalen mit denselben Namen verbunden, wie im folgenden Code gezeigt.

DUT: entity work.mux_4(rtl)
port map (
    din_0 => din_0,
    din_1 => din_1,
    din_2 => din_2,
    din_3 => din_3,
    sel  => sel,
    dout => dout
);

Die Stimulus-Datei

Eine Stimulus-Datei kann viele verschiedene Formate haben, das hier vorgestellte ist nur ein Beispiel, das mir beim Schreiben dieses Artikels spontan eingefallen ist. Wenn Sie jedoch verstehen, wie ich es erstellt habe, sollten Sie in der Lage sein, es an Ihre Bedürfnisse anzupassen.

Die folgende Auflistung zeigt die vollständige Stimulus-Datei, die in diesem Beispiel verwendet wird.

# Column description:
# wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout

0 ns 0 AA BB CC DD # Setting initial values
10 ns 1 AA BB CC DD # Testing by changing the selector signal
10 ns 2 AA BB CC DD
10 ns 3 AA BB CC DD
10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs
10 ns 3 A2 B2 C2 D2
10 ns 3 A3 B3 C3 D3
10 ns 3 00 00 00 D2 # Changing all unselected inputs
10 ns 3 01 02 03 D2
10 ns 3 11 22 33 D2
1 ns 0 CC DD EE FF # Changing all inputs fast
1 ns 1 DD EE FF CC
1 ns 2 EE FF CC DD
1 ns 3 FF CC DD EE
10 ns 0 00 00 00 00 # Simulation stop

Ignorieren wir die Kommentare vorerst, das sind die grün markierten, die immer mit einem ‚#‘-Zeichen beginnen. Jede Linie repräsentiert einen Zeitschritt in der Simulation. In jeder Zeile befinden sich sechs Spalten mit Befehlen, eigentlich sieben Textspalten, aber die ersten beiden Spalten gehören zum selben Datenelement.

Die Textspalten eins und zwei beschreiben einen Zeitwert, wie lange der Simulator auf dieser Zeile pausieren soll, bevor er die in den anderen Spalten aufgelisteten Werte anwendet. Somit ist die absolute Simulationszeit bei Ausführung des Befehls relativ zu dem in der vorherigen Zeile beschriebenen Ereignis. Wir verwenden nur 0, 1 oder 10 Nanosekunden, aber es könnte alles sein, 1000 Nanosekunden oder 1000 Stunden (1000 hr ) übrigens.

Die verbleibenden fünf Textspalten beschreiben die an die DUT-Eingänge anzulegenden Signalwerte. Sie werden als hexadezimale Literale angegeben und die Signalreihenfolge ist sel , din_0 , din_1 , din_2 , und schließlich din_3 .

Nun zu den Kommentaren. Es gibt zwei Arten von Kommentaren; einzeilige Kommentare und abschließende Kommentare. Sie werden von unserer Prüfbank unterschiedlich behandelt. Einzeilige Kommentare, wie die am Anfang der Datei, werden ignoriert. Nachlaufende Kommentare hingegen sollen auf der Simulatorkonsole ausgegeben werden. Wir können sie verwenden, um uns Hinweise darauf zu geben, was passiert, während die Simulation läuft.

Lesen der Stimulus-Datei in VHDL

VHDL ist nicht die beste Sprache für die Textverarbeitung, aber es erfüllt seinen Zweck. Die Unterstützung für dynamische Zeichenketten ist begrenzt, und es fehlen Komfortroutinen zum Beispiel zum Entfernen oder Überspringen von Leerzeichen. Um es uns selbst leichter zu machen, gehen wir davon aus, dass die Stimulus-Datei gut geschrieben ist. Lassen Sie uns sehr darauf achten, dass zwischen Textelementen immer ein Leerzeichen und zwischen dem ‚#‘-Zeichen und dem Kommentartext immer ein Leerzeichen steht. Auch keine zusätzlichen führenden oder nachgestellten Leerzeichen irgendwo in der Stimulus-Datei.

PROC_SEQUENCER : process
  file text_file : text open read_mode is "stimulus.txt";
  variable text_line : line;
  variable ok : boolean;
  variable char : character;
  variable wait_time : time;
  variable selector : sel'subtype;
  variable data : dout'subtype;
begin

Der deklarative Bereich von PROC_SEQUENCER Verfahren ist oben gezeigt. Zuerst deklarieren wir den speziellen file -Objekt, ein VHDL-Dateihandlertyp. Dann deklarieren wir eine Variable vom Typ line . Dies ist einfach ein Zugriffstyp auf eine Zeichenfolge, ein Zeiger auf ein dynamisch zugewiesenes Zeichenfolgenobjekt. Die ok Variable vom Typ Boolean dient zur Überprüfung, ob die Leseoperationen erfolgreich sind. Schließlich deklarieren wir die vier Variablen char , wait_time , selector , und data . Diese Variablen dienen zum Extrahieren der Daten aus jeder Spalte aus jeder Textzeile.

  while not endfile(text_file) loop

    readline(text_file, text_line);

    -- Skip empty lines and single-line comments
    if text_line.all'length = 0 or text_line.all(1) = '#' then
      next;
    end if;

Im Prozesshauptteil gehen wir direkt in eine While-Schleife, die durch jede Textzeile in der Stimulusdatei iteriert. Die readline Prozedur weist text_line eine neue Textzeile zu Variable bei jeder Iteration dieser Schleife. Nach dem Lesen der Zeile prüfen wir, ob die Zeile leer ist oder ob das erste Zeichen ein ‘#’ ist, in diesem Fall gehen wir sofort zur nächsten Zeile, indem wir den next verwenden Schlüsselwort, um eine Iteration der Schleife zu überspringen. Beachten Sie, dass wir text_line.all verwenden um Zugriff auf die Zeichenfolge innerhalb von line zu erhalten Objekt.

    read(text_line, wait_time, ok);
    assert ok
      report "Read 'wait_time' failed for line: " & text_line.all
      severity failure;

    hread(text_line, selector, ok);
    assert ok
      report "Read 'sel' failed for line: " & text_line.all
      severity failure;
    sel <= selector;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_0' failed for line: " & text_line.all
      severity failure;
    din_0 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_1' failed for line: " & text_line.all
      severity failure;
    din_1 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_2' failed for line: " & text_line.all
      severity failure;
    din_2 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_3' failed for line: " & text_line.all
      severity failure;
    din_3 <= data;

Als nächstes folgt eine Reihe von Lesevorgängen von text_line Objekt. Der read und hread Prozeduraufrufe überspringen führende Leerzeichen, sodass wir keine Dummy-Lesevorgänge ausführen müssen, um die interne Lesestartposition innerhalb von text_line zu verschieben Objekt. Wir hätten die Assert-Anweisungen weglassen können, aber ich möchte, dass die Simulation stoppt, wenn ein Lesevorgang fehlschlägt. Zumindest in ModelSim stoppt die Simulation in diesem Fall nicht automatisch. Mit Ausnahme von wait_time ordnen wir jede erfolgreich gelesene Variable dem entsprechenden DUT-Signal zu Variable, die keinen entsprechenden DUT-Eingang hat.

    wait for wait_time;

Nach Zuweisung der Signalwerte warten wir die angegebene Zeit ab. Das Drücken der Wait-Anweisung bewirkt, dass die geplanten Signalwerte mit demselben Delta-Zyklus wirksam werden.

    -- Print trailing comment to console, if any
    read(text_line, char, ok); -- Skip expected newline
    read(text_line, char, ok);
    if char = '#' then
      read(text_line, char, ok); -- Skip expected newline
      report text_line.all;
    end if;

  end loop;

  finish;

end process;

Wenn das Programm schließlich aus der Wait-Anweisung aufwacht, suchen wir nach einem zusätzlichen nachgestellten Kommentar zu text_line Objekt. Jeder Kommentar wird mithilfe der report-Anweisung auf der Konsole ausgegeben, nachdem wir das ‚#‘-Zeichen und die folgenden Leerzeichen mit Dummy-Reads entfernt haben.

Nachdem die letzte Textzeile aus der Stimulus-Datei verarbeitet wurde, endet die While-Schleife. Es gibt ein VHDL-2008 finish Schlüsselwort am Ende des Prozesses, der für das Stoppen der Testbench verantwortlich ist.

Die Ausgabe

Die Beispiel-Testbench gibt den unten gezeigten Text an die Simulatorkonsole aus, wenn sie in ModelSim ausgeführt wird. Wir können sehen, dass die Kommentare die aus der Stimulus-Datei sind. Die gedruckten Zeitwerte sind die akkumulierten Simulationszeiten basierend auf den Nanosekunden-Verzögerungen, die in der Stimulus-Datei angegeben wurden.


# ** Note: Setting initial values
#    Time: 0 ns  Iteration: 1  Instance: /file_stim_tb
# ** Note: Testing by changing the selector signal
#    Time: 10 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Testing by changing all data inputs
#    Time: 40 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all unselected inputs
#    Time: 70 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all inputs fast
#    Time: 91 ns  Iteration: 0  Instance: /file_stim_tbf
# ** Note: Simulation stop
#    Time: 104 ns  Iteration: 0  Instance: /file_stim_tb
# Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98

Die Wellenform für die Simulation ist unten dargestellt. Es zeigt eine visuelle Darstellung, wie die Werte aus unserer Stimulus-Datei zu den angegebenen Simulationszeiten auf die Signale angewendet werden.

Abschließende Gedanken

Das Lesen von Testbench-Stimuli aus einer Datei kann vorteilhaft sein, wenn Sie ein sehr spezifisches Testmuster anwenden müssen. Die gesamte Testbench muss nicht über die Textdatei gesteuert werden, dieses Beispiel soll lediglich die Möglichkeiten des Dateizugriffs in VHDL aufzeigen.

Eine Sache, die wir jedoch nicht besprochen haben, ist die Überprüfung der DUT-Ausgänge. Unsere Beispiel-Testbench überprüft die Ausgaben überhaupt nicht. Sie können das DUT-Verhalten genau wie in einer vollständigen VHDL-Testbench überprüfen, indem Sie beispielsweise ein Verhaltensmodell zum Vergleich verwenden. Oder Sie könnten den Code und die Stimulus-Datei so ändern, dass sie die erwarteten Ausgabewerte enthalten. Unabhängig davon, welche Strategie Sie wählen, stellen Sie sicher, dass Sie eine selbstüberprüfende Testbench erstellen und sich nicht darauf verlassen, die Wellenform manuell zu überprüfen.


VHDL

  1. C# verwenden
  2. C Dateiverwaltung
  3. Java-Dateiklasse
  4. So initialisieren Sie RAM aus einer Datei mit TEXTIO
  5. So erstellen Sie eine selbstüberprüfende Testbench
  6. Java BufferedReader:Lesen von Dateien in Java mit Beispiel
  7. Python JSON:Codieren (Dumps), Decodieren (Laden) und JSON-Datei lesen
  8. Verilog-Datei-IO-Operationen
  9. C - Header-Dateien
  10. Was ist eine dreieckige Datei?