Wie debugge ich rote Signale in ModelSIM?


11

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 einer Uhr von 1 GHz / 53 laufen.

Bevor Sie mich jetzt mit "Wir machen Ihre Hausaufgaben nicht für Sie" angreifen, möchte ich Ihnen sagen, dass ich alles verschrottet habe, nachdem ich Tage Arbeit investiert habe, und alles wieder strenger gemacht habe. Ich möchte dies alleine tun, aber ich erhalte 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 gemacht habe, im folgenden Bild:

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 eingebaut habe) nicht zu schwierig sein.

Aber mein erstes Problem tritt 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 in diesem Beitrag werden Sie sehen, dass ich in VHDL die Eingänge in1Q3plus bis in11Q3plus (11 Eingänge) benannt habe, da dies nicht der letzte Block ist (der letzte kombinatorische Logikblock besteht aus den vier verdrahteten Blöcken Q3 +, Q2 +, Q1 +, Q0 + zu Signalen).

Also musste ich alles mit NAND-Gates machen, das heißt, ich musste einen strukturellen Ansatz verfolgen. Jedes Gate basiert im Wesentlichen auf NAND-Gates und baut sich dann in seiner Komplexität auf (aber nur AND-, OR- und NOT-Gates werden strukturell aus NAND-Gates 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), die jeweils auf den vorherigen UND-ODER-Gattern mit 2 Eingängen basieren.

Jeder Prüfstand bis zum Q3plus (siehe Abbildung oben) funktionierte. Mein Testverfahren besteht darin, Signale für jeden Eingang zu erstellen, sodass ich die Signale im Simulationsfenster bequem 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, bei dem er 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 veröffentlichen und noch einmal feststellen, 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üfstandsimulation

Wie Sie sehen können, hat das erste Signal ein merkwürdiges Verhalten, die nächsten Signale funktionieren einwandfrei und das letzte 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 absoluter Noob in diesem Durcheinander eines Programms, und ich möchte das wirklich beenden. Vielen Dank im Voraus für jede Antwort.


1
Sehr gute Fragenpräsentation. Während Modelsim möglicherweise zulässt, dass 18nses im VHDL-Standard ausdrücklich illegal ist und dies auch bleiben wird. Es gibt zwei separate lexikalische Elemente: abstraktes Literal 18und Bezeichner ns. Siehe IEEE Std 1076-2008 15.3 Lexikalische Elemente, Trennzeichen und Trennzeichen, Abs. 4 - ".... Es ist mindestens ein Trennzeichen zwischen einem Bezeichner oder einem abstrakten Literal und einem benachbarten Bezeichner oder einem abstrakten Literal erforderlich." Sie hätten Ihren Stimulus als einen Prozess mit inkrementeller Zeit in Warteanweisungen schreiben können. Möglicherweise hat es direkt auf das nicht gesteuerte Signal hingewiesen.
user8352

Können Sie bitte den Reizteil näher erläutern? Ich denke, 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 ? Bearbeiten Verifiziert, das war das Problem.
Azurium

Antworten:


9

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

Es gibt zwei einfache Möglichkeiten, ein Signal zu beschädigen:

  • Fahren Sie es von mehreren Signalquellen
  • Fahren Sie nicht von einem

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

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

Du wirst lachen ...

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

z.B

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

2
All diese Frustration, die sich stundenlang angesammelt hatte, brach in ein gutes Lachen aus. Auch ich verdiene einen guten Schlag auf mein Gesicht. Der Prüfstand scheint jetzt zu funktionieren!
Azurium
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.