Modellierung des Verhaltens eines Quartus-Projekts in Verilog in der ModelSim-Umgebung

Im letzten Artikel haben wir ein ziemlich komplexes Modul erstellt. Natürlich habe ich das bereits debuggte Ergebnis in den Hauptteil des Artikels eingefügt. Aber es schien mir ziemlich seltsam, wenn der Autor "mach wie ich" sagt, aber keinen sehr wichtigen Prozess zeigt. Lassen Sie mich Ihnen zeigen, wie Sie ein System im Allgemeinen durch Simulation debuggen. Darüber hinaus wird der nächste Artikel Informationen enthalten, die selbst ich vor einer Woche nicht kannte. Aber um zu ihnen zu gelangen, müssen Sie die Grundprinzipien verstehen. Damit. Lassen Sie uns einen Blick darauf werfen, wie Sie den Modellierungsprozess in der ModelSim-Umgebung schnell vorbereiten und genauso schnell starten können.









Wie funktioniert ein gewöhnliches Computerprogramm? Es gibt eine bestimmte externe Umgebung (Monitor und Tastatur mit "Maus" sind die typischsten Vertreter dieser Umgebung). Das Programm interagiert mit ihnen. Beim Debuggen können Sie echte Einflüsse aus der externen Umgebung ziehen oder sie emulieren. Unsere Tester schreiben oft alle Arten von Skripten, die nur äußere Einflüsse emulieren. Danach werden die Log-Analysatoren gestartet, die überprüfen, ob die Antworten am Mittwoch korrekt sind.



Was ist, wenn in diesem Computerprogramm alles fehlerhaft ist? Sie können Haltepunkte festlegen und eine Momentaufnahme des Systems in dem Moment untersuchen, in dem sie getroffen werden. Das System-Slice sind die Werte der Variablen. Möglicherweise die Zustände verschiedener Mutexe und anderer Synchronisationsobjekte. Im Allgemeinen eine Momentaufnahme der internen Parameter des debuggten Systems.



Beim Debuggen für FPGAs können Sie dasselbe tun. Wenn die Umgebung real ist, ist das Stoppen und Studieren eines Teils des Systems zwar problematisch, wenn auch möglich. Als Teil der Geschichte über Redd fördere ich immer wieder die Idee, dass alles einfach und schnell sein sollte. Wir entwerfen keine komplexen Systeme. Wir machen eine Art von Modulen, wie im letzten Artikel . Es ist raffiniert, aber sehr, sehr unkompliziert. Im Allgemeinen werden wir die Verhaltensmodellierung durchführen.



Und hier stellt sich die Frage nach dem äußeren Umfeld. Wie simuliere ich es? Modelle helfen uns. Verilog (sowie VHDL und andere ähnliche) ist durchaus möglich, das Verhalten von irgendetwas zu beschreiben. Wir machen ein System, das mit dem ULPI-Mikroschaltkreis funktioniert ... Um seine Funktion zu testen, muss sich am anderen Ende etwas befinden, das sich genau wie das ULPI verhält. Das heißt, das ULPI-Modell. Das reicht aber nicht. Unser Block reagiert auf Befehle vom ALAVON_MM-Bus. Es ist dieser Bus, der den Block zum Leben erweckt. Daher müssen wir auch das Busmodell AVALON_MM hinzufügen, und dieses Modell muss aktiv sein. Sie wird Testeinflüsse einreichen.







Letztendlich müssen wir genau ein solches System machen. Und dann können wir Zeitdiagramme von Signalen auf allen Bussen und sogar in allen Modulen aufzeichnen. Wenn ein Fehler auftritt, können wir Haltepunkte setzen und Schnappschüsse des Systems untersuchen, um den Feind zu finden. Obwohl ich persönlich diese Haltepunkte normalerweise nicht setze, reicht meistens die Analyse von Zeitdiagrammen aus. Tatsache ist, dass Signale nicht nur Schnittstellensignale, sondern auch interne Signale angezeigt werden können. Wenn Sie ein oder zwei Dutzend interne Signale in der Tabelle herausziehen, können Sie normalerweise erraten, was in der Logik falsch implementiert ist.



Der Zweck des heutigen Artikels besteht nicht darin, darüber zu sprechen, was Modellierung im Allgemeinen ist (dies ist eine lange Geschichte), sondern zu zeigen, wie diese Modellierung am schnellsten durchgeführt werden kann. Und wir werden dies nicht auf einer Kampfmission betrachten, sondern an einem einfachen Beispiel. Lassen Sie uns ein sehr einfaches Testsystem erstellen, damit wir bereits im nächsten Artikel verstehen, woher die Beine einer komplexeren Version davon stammen, denn beim Lesen ist es bequemer, nicht zu sitzen und sich zu fragen: „Warum macht er das?“, Aber alle Grundprinzipien zu kennen, aus denen sich bereits Komplikationen ergeben ... Übrigens stellte sich kürzlich heraus, dass einer meiner Bekannten, obwohl er die Fähigkeit zum Modellieren besitzt, nicht wusste, dass Mechanismen in die Quartus-Umgebung eingebaut sind, die es Ihnen ermöglichen, dies einfach und natürlich zu tun. Er hat viel mehr Mühe darauf verwendet, als erforderlich ist. Vielleicht lernt jetzt auch jemand etwas Neues über die Möglichkeiten von Quartus. Damit,Lass uns anfangen.



Verilog



Menschen fallen in zwei Kategorien. Diejenigen, die alles mit ihren Händen von Grund auf neu erstellen möchten und diejenigen, die es gerne mit der Maus tun. Alles mit den Händen zu erstellen ist korrekter. Sie können jede Aktion steuern und alles, was Sie wissen, perfekt ausführen. Aber das Gedächtnis ist unzuverlässig. Wenn sie die ganze Zeit das Gleiche tut, behält sie die Details im Auge und wenn sie die ganze Zeit zwischen den Sprachen wechseln muss, muss sie sich nach ein oder zwei Monaten daran erinnern, was dort zu tun ist. Daher hat das Durcharbeiten der Option "Mit der Maus basteln" das Recht, zumindest aus diesem Grund zu existieren. Wenn das zu debuggende Modul etwa ein Dutzend Schnittstellensignale enthält, ist es mir immer langweilig, die Routine zu erledigen, sie erneut zu deklarieren und weiterzuleiten. Daher werden wir uns jetzt überlegen, wie man ein Modell mit der "Maus" erstellt. Und dann - jeder wird selbst entscheiden, ob dies für ihn ausreicht oder ob er auf manuelle Arbeit umsteigen soll.



Wir wollen also das Modul simulieren. Was "simulieren" ist, geht über den Rahmen unseres Zyklus hinaus. Sie können einen separaten großen Zyklus zu diesem Thema schreiben. Das heißt, im Rahmen dieses Abschnitts wird davon ausgegangen, dass Sie mit der Methodik zur Entwicklung eines Modells vertraut sind. Aber dann muss alles in das Projekt einbezogen werden ... Oder nicht? Seltsamerweise müssen Sie nicht einmal ein eigenes Projekt erstellen, um ein Modul zu modellieren. Wir können uns als Parasit an jedes Projekt binden, ohne etwas Neues darin aufzunehmen, sondern nur, indem wir eine Testsuite erstellen, die in keiner Weise an der Hauptversammlung teilnimmt.



Lassen Sie uns aus Gründen des Interesses unserem ULPI-Projekt ein so lustiges Modul auf SystemVerilog hinzufügen, das von mir speziell zur Veranschaulichung geschrieben wurde und nichts mit dem entwickelten Analysator zu tun hat. Vor einiger Zeit hatte ich viel mit der Berechnung von Prüfsummen zu tun, also kam es mir in den Sinn.

module sum(
input         clk,
input [7:0]   data,
input         we,
input         sof,
output [15:0] sum
);

logic [15:0] temp;

always @ (posedge clk)
begin
     if (we) 
     begin
         if (sof)
             temp <= data;
         else
             temp <= temp + data;
     end
end

//   - 
//assign sum = (~temp)+1;
//    :
assign sum = temp;
endmodule


Es ist ersichtlich, dass die Daten über den Bus zu ihm gelangen, der sehr entfernt an AVALON_MM erinnert und einfach in parallelem Code ausgegeben wird.



Lassen Sie uns die resultierende Datei in das Verzeichnis mit unserem Projekt einfügen, aber wir werden sie nicht in das Projekt in Quartus aufnehmen. Stattdessen erstellen wir eine Testsuite speziell dafür. Wählen Sie dazu den Menüpunkt Zuordnungen -> Einstellungen:







und suchen Sie in der angezeigten Baumstruktur nach dem Punkt EDA-Werkzeugeinstellungen -> Simulation:







Übrigens über die Art der Simulation, die durch den grünen Rahmen hervorgehoben wird. Vielleicht erinnert sich jemand daran, dass ich in den ersten Artikeln gesagt habe, dass ich beim Erstellen eines Projekts aus Gewohnheit ModelSim Altera gewählt habe? Es war genau die Waffe auf der Bühne, die früher oder später schießen musste. Wenn der Modellierungstyp beim Erstellen des Projekts jedoch nicht ausgewählt wurde, können Sie ihn hier auswählen oder ändern.



Wir erstellen weiterhin eine Testsuite. Schalten Sie das Optionsfeld auf Prüfstand kompilieren (übrigens, wie lässt sich dieser Begriff wunderbar ins Russische übersetzen? Ich kann mich nicht dazu bringen, "Prüfstand" zu schreiben, da ich keinen Prüfstand sehe) und drücken Sie die Schaltfläche Prüfstände : Drücken Sie im daraufhin angezeigten







Dialogfeld auf Neu :







Wenn Testfall manuell können Sie die Felder in einem Durchgang ausfüllen. Aber da wir alles mit der Maus machen, füllen wir jetzt nur einen Teil der Felder aus und den Rest werden wir später ausfüllen. Im Feld Name des PrüfstandsIch habe das Wort Parazit eingegeben (wie soll man einen Test nennen, der das Projekt nur parasitiert?). Das Wort Parazit darunter wurde automatisch ausgefüllt. Jetzt werden wir es nicht ändern, aber in Zukunft müssen wir es noch tun. Außerdem habe ich mit der Schaltfläche "..." die Datei sum.sv mit dem Code des zu debuggenden Addierers ausgewählt und sie dann mit der Schaltfläche Hinzufügen in die Liste der Testdateien verschoben. Im Moment ist es das. Schließen des Dialogfelds ...







Als Nächstes werden wir den Test in der ModelSim-Umgebung fortsetzen. Wählen Sie dazu den Menüpunkt Extras -> Simulationstools ausführen -> RTL-Simulation:







Das ModelSim-Fenster wird geöffnet. Möglicherweise werden Fehler im Verilog-Code gefunden. Dann müssen Sie ModelSim schließen, die Fehler korrigieren und erneut öffnen. Aber früher oder später wird die Liste der Fehler rein organisatorisch. Für mich sieht es so aus:







Kein Top-Level-Modul gefunden. Es ist in Ordnung. Wir haben es noch nicht einfach erstellt. Deshalb haben wir gehen Arbeit in der Liste der Bibliotheken und öffnen. Hier ist es, unser Addierer.







Bewegen Sie den Mauszeiger darüber, drücken Sie die rechte Maustaste und wählen Sie den Menüpunkt Wave erstellen. Das ist alles so langweilig im Text. Wenn ich ein Video drehen würde, würde der gesamte Vorgang mehrere zehn Sekunden dauern. Seien Sie also nicht beunruhigt, sondern beobachten Sie Ihre Hände weiter. Also, Wave erstellen ...







Die Schnittstellensignale des Moduls werden automatisch in das Diagramm verschoben:







Es ist notwendig, einem von ihnen einen Wert zuzuweisen. Es spielt keine Rolle, welche, es ist wichtig zu ernennen. Die sehr alte Modellierungsumgebung von Quartus war gut darin, Taktsignale zu erzeugen. Leider wurde es vor langer Zeit aus der Lieferung genommen, da sie anfingen, ModelSim anzubringen, und hier ist mit so etwas nicht alles so schön. Ich habe nicht den Sinn gesehen, hier einen Generator zu generieren, deshalb werde ich ihn nicht einmal zeigen. Also ... Nun, lassen Sie uns die Linie we auf Null setzen. Wir zielen auf das Signal, drücken die rechte Taste, wählen den Menüpunkt Bearbeiten -> Wave-Editor -> WaveForm erstellen / ändern.







Wählen Sie im angezeigten Dialogfeld Konstante aus . Gleichzeitig ändern wir die Zeit beispielsweise um 100 Mikrosekunden:







Als Nächstes geben wir den Wert 0 an:







Wir haben den minimal erforderlichen Datensatz erstellt, und der Rest ist mit Stiften einfacher zu erledigen. Wir exportieren die Datei. Wählen Sie dazu den Menüpunkt Datei -> Exportieren -> Wellenform:







Wählen Sie den Dateityp Verilog Testbench (es ist übrigens schade, dass es sich nicht um SystemVerilog handelt, aber in Zukunft kann es mit Stiften korrigiert werden). Wir setzen auch den Dateinamen. Ich nannte es parazit_tb und folgte dem "Warum nicht?"







Das war's, ModelSim kann geschlossen werden, während das temporäre Haus nicht gespeichert werden muss.



Was tun als nächstes mit dem Modell?



Hier ist eine so krumme, aber immer noch vorgefertigte Verilog-Datei, das System, das für uns erstellt wurde:

`timescale 1ns / 1ns
module parazit_tb  ; 
 
  reg    sof   ; 
  reg    we   ; 
  wire  [15:0]  sum   ; 
  reg  [7:0]  data   ; 
  reg    clk   ; 
  sum  
   DUT  ( 
       .sof (sof ) ,
      .we (we ) ,
      .sum (sum ) ,
      .data (data ) ,
      .clk (clk ) ); 



// "Constant Pattern"
// Start Time = 0 ns, End Time = 100 us, Period = 0 ns
  initial
  begin
  end

  initial
	#0 $stop;
endmodule


Die Automatisierung hat uns vor dem Schreiben von Bausteinen bewahrt. Wenn es mehr Schnittstellensignale gäbe, würde die Automatisierung außerdem gehorsam alle Schaltungen registrieren und verbinden. Wenn ich persönlich Testsuiten manuell erstelle, ist der Prozess der Beschreibung von Signalen und ihrer Weiterleitung bedrückend. Nun, in dieser Datei werden wir nun ein Umgebungsmodell erstellen, das die gedebuggt beeinflusst Summe Modul .



Wie Sie sehen, macht es keinen Sinn, die vom Oszillator erstellten Konstanten einzustellen. Trotzdem wurden alle Schaltkreise erstellt, das zu testende Modul wird angeschlossen, sogar der erste Abschnitt wurde erstellt. Lassen Sie uns den Code verfeinern. Der erste besteht darin, den Haltepunkt durch Löschen der Zeilen zu entfernen:

  initial
	#0 $stop;


Als nächstes werden wir ein Taktgeneratormodell hinzufügen (wie ich den wunderbaren Generator vermisse, den der alte Quartus hergestellt hat! Dort könnte man die Frequenz in Megahertz einstellen und nicht daran denken, sie in eine Periode neu zu berechnen, und noch mehr - eine halbe Periode).

  always 
  begin
      clk = 0;
      #5;
      clk = 1;
      #5;
  end


Jetzt müssen wir einige Datenbytes senden. Der einfachste Weg, dies zu tun, ist direkt im ersten Abschnitt , aber wenn ich jede Buszugriffsphase dort schreibe, wird der Code in diesem Abschnitt verwirrend. Daher werde ich folgende Aufgabe erledigen (sie ist es, die als Reifenmodell fungiert):

task SendByte (input reg[7:0] D);
    begin
        data = D;
        we = 1;
        @(posedge clk);
        #1
        we = 0;
   end
endtask


Nun, ich werde den Zweck der Konstanten und den Aufruf von Zyklen für die Arbeit mit dem Bus im Anfangsblock schreiben . Ich möchte Sie daran erinnern, dass der Datensatztyp # 123 "123 Zeiteinheiten warten" bedeutet. Wir haben es in Nanosekunden. Ich erinnere Sie auch daran, dass wir, da die Zuweisungen sequentiell sind, die "gleiche" Operation verwenden, nicht den "Pfeil". Wir haben also den folgenden Haupttestcode:

Schau hier
  initial
  begin
     sof = 0;
     we = 0;
     data = 0;
     #13;
     //   
     sof = 1;
     SendByte (1);
     //  
     sof = 0;
     SendByte (5);
     SendByte (1);
     //      
     #20;
     SendByte (1);
  end




Insgesamt sieht unser vollständiger Modulcode folgendermaßen aus:

Zeigen Sie den vollständigen Modulcode an.
`timescale 1ns / 1ns
module parazit_tb  ; 
 
  reg    sof   ; 
  reg    we   ; 
  wire  [15:0]  sum   ; 
  reg  [7:0]  data   ; 
  reg    clk   ; 
  sum  
   DUT  ( 
       .sof (sof ) ,
      .we (we ) ,
      .sum (sum ) ,
      .data (data ) ,
      .clk (clk ) ); 


  always 
  begin
      clk = 0;
      #5;
      clk = 1;
      #5;
  end

task SendByte (input reg[7:0] D);
    begin
        data = D;
        we = 1;
        @(posedge clk);
        #1
        we = 0;
   end
endtask

// "Constant Pattern"
// Start Time = 0 ns, End Time = 100 us, Period = 0 ns
  initial
  begin
     sof = 0;
     we = 0;
     data = 0;
     #13;
     //   
     sof = 1;
     SendByte (1);
     //  
     sof = 0;
     SendByte (5);
     SendByte (1);
     //      
     #20;
     SendByte (1);
  end

endmodule






Abschluss der Testfallvorbereitung



Es ist Zeit, diesen Text zur Testsuite hinzuzufügen. Gehen Sie dazu zu dem







uns bereits bekannten Dialog. Jetzt erstellen wir unser Set nicht mehr, sondern wählen es aus der Liste aus. In Zukunft wird die Liste mit dem Hinzufügen der Sets erweitert ... Nachdem Sie ausgewählt haben, klicken Sie auf die Schaltfläche Bearbeiten. Ich habe drei Änderungen an den Einstellungen vorgenommen:

  1. Die Datei parazit_tb.v wurde zur Liste hinzugefügt .
  2. Da das Modul der obersten Ebene in der Datei parazit_tb.v den Namen parazit_tb hat (Sie können dies anhand der Quelle aus dem vorherigen Abschnitt sicherstellen), habe ich diesen Namen im Modul der obersten Ebene in der Prüfstandszeile eingegeben .
  3. Ich sagte, ich solle die Simulation 10 Mikrosekunden lang ausführen und dann pausieren. Wenn überhaupt, werde ich es tun, indem ich die manuellen Steuertasten drücke.








Gesamt



Wir schließen alles. Führen Sie ModelSim erneut aus. Wir sehen, dass alles richtig funktioniert. Die Daten kommen herein und werden in der Menge gezählt. Wenn es keine Daten auf der Uhr gibt ( wir sind Null), erhöht sich der Betrag nicht.







Die Verwendung der Modellierungsumgebung selbst ist ein Thema für mehrere Artikel. Und eher im Videoformat. Im Allgemeinen haben wir uns jedoch mit der Methode vertraut gemacht, Tests in der Verilog-Sprache aus der Quartus-Umgebung schnell vorzubereiten und auszuführen.



Nachdem wir nun wissen, wie die Simulation schnell ausgeführt werden kann, können wir ein Umgebungsmodell für unseren USB-Analysatorkopf skizzieren und dessen Funktion testen. Gleichzeitig haben wir keinen einzigen ModelSim-Zauber auswendig gelernt, da Sie mit Quartus alles mit der "Maus" konfigurieren können. Er generiert alle erforderlichen Skripte selbst und ruft die ModelSim-Umgebung selbst auf. Wir haben auch die Basis für das Modell im automatischen Modus erstellt, obwohl wir es dann manuell ändern mussten.



Ach und ah. Eines der Elemente der externen Umgebung ist das ULPI-Modul. Um das Modell selbst zu entwickeln, müssen Sie zunächst die Logik des Betriebs dieser Mikroschaltung sorgfältig verstehen. Und im vorherigen Artikel habe ich gesagt, dass es sehr schwierig ist. Nun, und zweitens müssen Sie viel Zeit damit verbringen, den Modellcode zu entwickeln. Und die Beseitigung von Fehlern darin ... Es ist klar, dass es einfacher ist, etwas Fertiges zu finden. Das fertige Modell wurde jedoch nur in der SystemC-Sprache gefunden. Daher werden wir im nächsten Artikel lernen, ein System mit dieser Sprache zu modellieren.



All Articles