Wie debugge ich rote Signale in ModelSIM?

Ich muss eine Zustandsmaschine entwerfen, die nur NAND-Gatter für den kombinatorischen Teil und D-Flip-Flops für die sequentielle Logik verwendet. Alles sollte mit einem Takt von 1ghz/53 laufen.

Bevor Sie mich jetzt mit "wir machen Ihre Hausaufgaben nicht für Sie" überfallen, lassen Sie mich Ihnen sagen, dass ich alles verschrottet habe, nachdem ich Tage Arbeit investiert habe, und wieder angefangen habe, alles konsequenter zu machen. Ich möchte das alleine machen, aber ich bekomme ständig zufällige undefinierte Signale in den einfachsten Teilen des Projekts und es ist frustrierend.

Ok, also zuerst habe ich die Zustandsmaschine und die Wahrheitstabelle, die ich dafür im folgenden Bild gemacht habe:

Zustandsmaschinendiagramm und Wahrheitstabelle dafür

Das nächste sind die kmaps:

Die Kmaps

Da für D-Flip-Flops D = Q + ist, sollte die Verdrahtung der kombinatorischen Logik (sobald ich sie in einen vereinfachten Block einbaue) nicht zu schwierig sein.

Aber mein erstes Problem taucht im Prüfstand für Q3+ auf. Lassen Sie mich hier zur Vereinfachung der Informationen ein schnelles Diagramm einfügen, das ich für Q3+ zusammengestellt habe:

Logikdiagramm für Q3+

Später im Beitrag werden Sie sehen, dass ich in VHDL die Eingänge tatsächlich in1Q3plus bis in11Q3plus (11 Eingänge) benannt habe, da dies nicht der letzte Block ist (der letzte kombinatorische Logikblock besteht aus den vier Blöcken Q3+, Q2+, Q1+, Q0+, die verdrahtet sind zu Signalen).

Also musste ich alles mit NAND-Gattern machen, das heißt, ich musste einen strukturellen Ansatz wählen. Jedes Gatter basiert im Grunde auf NAND-Gattern und baut dann an Komplexität auf (aber nur UND-, ODER- und NICHT-Gatter werden strukturell aus NAND-Gattern geschrieben). Ich habe dann ein ODER-Gatter mit 3 Eingängen, ein UND-Gatter mit 3 Eingängen und ein ODER-Gatter mit 5 Eingängen (wie im Beispiel des Logikdiagramms), jeweils basierend auf den vorherigen 2-Eingangs-UND&ODER-Gattern.

Jeder Prüfstand bis zum Q3plus (das Diagramm oben) hat funktioniert. Mein Testverfahren besteht darin, Signale für jeden Eingang zu erzeugen, sodass ich die Signale bequem im Simulationsfenster beobachten kann. Zum Beispiel habe ich die folgenden Signale für ein UND-Gatter mit 3 Eingängen:

process
    begin
a1 <= '0' ; wait for 4ns;
a1 <= '1' ; wait for 4ns;
end process;

process
    begin
b1 <= '0' ; wait for 8ns;
b1 <= '1' ; wait for 8ns;
end process;

process
    begin
c1 <= '0' ; wait for 2ns;
c1 <= '1' ; wait for 2ns;
end process;

Und die Verbindungen würden so aussehen:

u1:ANDgate3 port map(A=>a1, B=>b1, C=>c1, fand3=>q1 );

Das Problem tritt also auf, wenn ich den Q3plus-Prüfstand simulieren möchte. Es scheint, dass ich einen Fehler habe, wo es am wenigsten erwartet wird, bei einem Testsignal, das nur mit einer Periode von 2 ns von 0 auf 1 wechselt: |. Ich werde hier den Code des Prüfstands posten, der noch einmal feststellt, dass jeder andere Gate-Prüfstand einwandfrei funktioniert hat:

library ieee;
use ieee.std_logic_1164.all;

entity Q3plusTEST is
end Q3plusTEST;

architecture behavior of Q3plusTEST is
    component Q3plus is
    port(outQ3plus: out std_Logic;
    in1Q3plus: in std_Logic;
    in2Q3plus: in std_Logic;
    in3Q3plus: in std_Logic;
    in4Q3plus: in std_Logic;
    in5Q3plus: in std_Logic;
    in6Q3plus: in std_Logic;
    in7Q3plus: in std_Logic;
    in8Q3plus: in std_Logic;
    in9Q3plus: in std_Logic;
    in10Q3plus: in std_Logic;
    in11Q3plus: in std_Logic);
    end component;

signal a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11, outsignal: std_logic;

begin
    process
    begin
        a1<= '0'; wait for 4ns;
        a1<= '1'; wait for 4ns;
    end process;

    process
    begin
        a2<= '0'; wait for 6ns;
        a2<= '1'; wait for 6ns;
    end process;

    process
    begin
        a3<= '0'; wait for 8ns;
        a3<= '1'; wait for 8ns;
    end process;

    process
    begin
        a4<= '0'; wait for 10ns;
        a4<= '1'; wait for 10ns;
    end process;

    process
    begin
        a5<= '0'; wait for 12ns;
        a5<= '1'; wait for 12ns;
    end process;

    process
    begin
        a6<= '0'; wait for 14ns;
        a6<= '1'; wait for 14ns;
    end process;

    process
    begin
        a7<= '0'; wait for 16ns;
        a7<= '1'; wait for 16ns;
    end process;

    process
    begin
        a8<= '0'; wait for 18ns;
        a8<= '1'; wait for 18ns;
    end process;

    process
    begin
        a9<= '0'; wait for 20ns;
        a9<= '1'; wait for 20ns;
    end process;

    process
    begin
        a10<= '0'; wait for 22ns;
        a10<= '1'; wait for 22ns;
    end process;

    process
    begin
        a1<= '0'; wait for 24ns;
        a1<= '1'; wait for 24ns;
    end process;

    U1: Q3plus port map(in1Q3plus=> a1, in2Q3plus=>a2, in3Q3plus=>a3, in4Q3plus=>a4, in5Q3plus=>a5, in6Q3plus=>a6, in7Q3plus=>a7, in8Q3plus=>a8, in9Q3plus=>a9, in10Q3plus=>a10, in11Q3plus=>a11, outQ3plus=> outsignal); end behavior;

Und der Code für den eigentlichen Q3plus-Block lautet:

 library ieee;
use ieee.std_logic_1164.all;

entity Q3plus is
    port(outQ3plus: out std_Logic;
    in1Q3plus: in std_Logic;
    in2Q3plus: in std_Logic;
    in3Q3plus: in std_Logic;
    in4Q3plus: in std_Logic;
    in5Q3plus: in std_Logic;
    in6Q3plus: in std_Logic;
    in7Q3plus: in std_Logic;
    in8Q3plus: in std_Logic;
    in9Q3plus: in std_Logic;
    in10Q3plus: in std_Logic;
    in11Q3plus: in std_Logic);
    end Q3plus;

architecture behavior of Q3plus is
    component ORgate5 is
    port(AOR5: in std_logic;
    BOR5: in std_logic;
    COR5: in std_logic;
    DOR5: in std_logic;
    EOR5: in std_logic;
    f5or: out std_logic);
    end component;

    component ANDgate3 is
    port(A: in std_logic;
    B: in std_logic;
    C: in std_logic;
    fand3: out std_logic);
    end component;

    component ANDgate is
    port(xand: in std_logic;
    yand: in std_logic;
    fand: out std_logic);
    end component;

signal z1,z2,z3,z4,z5: std_logic;

begin
    U1: ANDgate port map(xand=> in1Q3plus, yand=> in2Q3plus, fand=> z1);
    U2: ANDgate port map(xand=> in3Q3plus, yand=> in4Q3plus, fand=> z2);
    U3: ANDgate port map(xand=> in5Q3plus, yand=> in6Q3plus, fand=> z3);
    U4: ANDgate port map(xand=> in7Q3plus, yand=> in8Q3plus, fand=> z4);
    U5: ANDgate3 port map(A=> in9Q3plus, B=> in10Q3plus, C=> in11Q3plus, fand3=> z5);
-- urmeaza toate portile de mai sus conectate la OR5
    U6: ORgate5 port map(AOR5=>z1, BOR5=> z2, COR5=> z3, DOR5=> z4, EOR5=> z5, f5or=> outQ3plus);

end behavior;

Der Prüfstand liefert folgendes Ergebnis:

Prüfstandssimulation

Wie Sie sehen können, hat das erste Signal ein merkwürdiges Verhalten, die nächsten Signale funktionieren einwandfrei und das letzte an ist völlig undefiniert. Natürlich ist das endgültige Signal, der Ausgang, fehlerhaft.

Meine einfache Frage wäre: Wie kann ich verfolgen, wo das Signal beschädigt wird? Ich fühle mich wie ein totaler Noob in diesem Durcheinander von einem Programm, und ich möchte das wirklich beenden. Vielen Dank im Voraus für jede Antwort.

Sehr gute Fragestellung. Obwohl Modelsim dies möglicherweise zulässt 18ns, ist dies im VHDL-Standard ausdrücklich illegal und wird dies auch bleiben. Es gibt zwei separate lexikalische Elemente, abstraktes Literal 18und Bezeichner ns. Siehe IEEE Std 1076-2008 15.3 Lexical elements, separators and delimiters, para. 4 - "... . Zwischen einem Bezeichner oder einem abstrakten Literal und einem angrenzenden Bezeichner oder abstrakten Literal ist mindestens ein Trennzeichen erforderlich." Sie hätten Ihren Stimulus als einen Prozess mit inkrementeller Zeit in Warteanweisungen schreiben können. Es kann direkt auf das nicht angesteuerte Signal gezeigt haben.
Können Sie bitte den Stimulus-Teil näher erläutern? Ich denke, das, was Sie gesagt haben, habe ich auch viel gesucht, aber nichts gefunden: die Warnungen, die jeder Prüfstand erzeugt. Meinst du, ich sollte ein Leerzeichen zwischen 18 und ns eingeben ? edit Bestätigt, das war das Problem.

Antworten (1)

Schön, eine richtige Testbench und Code zu sehen, die zur Abwechslung tatsächlich zur Frage passen ...

Es gibt zwei einfache Möglichkeiten, wie ein Signal beschädigt werden kann:

  • fahren Sie es von mehreren Signalquellen
  • vertreibe es nicht von irgendwem

Jetzt bleibt A11 durchgehend 'U', was darauf hindeutet, dass es keinen Treiber hat. Während A1 zwischen gültigen und 'X' ungültigen Werten wechselt, was darauf hindeutet, dass es mehr als einen Treiber hat.

Überprüfen Sie in diesem Sinne Ihren Code, wo Sie A1 und A11 fahren.

Du wirst lachen...

Um den Teil der Frage "wie man debuggt" zu erweitern: Nachdem Sie den Verdacht geweckt haben, dass Signale nicht von den erwarteten Quellen getrieben wurden, können Sie den Befehl "drivers" von Modelsim verwenden, um die Treiber auf einem Signal aufzulisten. Wenn Sie etwas ausführlicheres VHDL geschrieben und jeden Prozess beschriftet hätten, würden Sie die gleiche Antwort erhalten, ohne Ihren Code überprüfen zu müssen ...

z.B

Drive_A1 : process
begin
   a1 <= '0' ; wait for 4ns;
   ... etc