Verwenden von VHDL-Code zum Entwerfen eines JK-Flip-Flops

Ich verwende quartus II, um einen JK Flip Flop zu entwerfen. Meine Ergebnisse zeigen jedoch eine unbekannte Ausgabe. Warum ist es?

Beabsichtigte Designschaltung:

Geben Sie hier die Bildbeschreibung ein

VHDL-Code:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity JKFlipFlopGate is
    port(
        J,K,Clk : in std_logic;             --JK Flip-Flop gate input 1 & 2
        Q,Qbar : out std_logic              --JK Flip-Flop gate output
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is        
signal out1,out2,out3,out4 : std_logic;

begin
    out1    <= NOT(J AND Clk AND out4);                 
    out2    <= NOT(K AND Clk AND out3); 
    out3    <= out1 NAND out4;
    out4    <= out2 NAND out3; 
    Q       <= out3;
    Qbar    <= out4;    
end result;

Antworten (3)

Wenn Sie die Uhr verwenden möchten, müssen Sie einen Prozess schreiben, der an einer bestimmten Taktflanke empfindlich ist. BEARBEITEN: Sie müssen auch out3 und out4 initialisieren:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity JKFlipFlopGate is
    port(
        J,K,Clk : in std_logic;        --JK Flip-Flop gate input 1 & 2
        Q,Qbar : out std_logic         --JK Flip-Flop gate output
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is        
signal out1,out2: std_logic;
signal out3 : std_logic := '0'; -- Need proper initialization
signal out4 : std_logic := '0'; -- Need proper initialization

begin

    process(clk)

    begin
       if(rising_edge(clk)) then
           out1    <= NOT(J AND out4);
           out2    <= NOT(K AND out3); 
       end if;
    end process

    out3    <= out1 NAND out4;
    out4    <= out2 NAND out3; 
    Q       <= out3;
    Qbar    <= out4;    

end result;

So sollte es funktionieren (ich habe es aber nicht getestet.)

Jetzt verstehe ich das Problem, danke für deine Hilfe. Deinen Code werde ich ausprobieren.
Es kann ein Problem geben - Sie müssen möglicherweise einige der outx-Signale initialisieren. Versuchen Sie dies und posten Sie hier, und ich werde meine Antwort bei Bedarf bearbeiten. Und bitte akzeptieren Sie die Antwort, wenn sie nützlich ist :)
Ok, jetzt weiß ich (aus einer anderen Antwort, danke Claudio Avi Chami) - Sie müssen out3 und out4 initialisieren
Das Problem bei dieser Antwort besteht darin, dass der Schaltplan in der Frage nicht implementiert wird. Das Diagramm zeigt 4 NAND-Gatter, aber dieser Code implementiert 4 NAND-Gatter und zwei Register.
@scary_jeff Aber ohne Verwendung der Register werden unbekannte Ausgaben angezeigt
Gut hat dieser Entwurf Uhr. 4 nackte NAND-Gatter hätten keine Uhr. Tatsächlich hat diese Schaltung also zwei Register, die in den ersten beiden Gattern versteckt sind. Ist es nicht? Oder habe ich die Frage vielleicht falsch verstanden?
Eigentlich ist die Frage, nur ein JK-Flip-Flop zu entwerfen, jede verwendete Methode ist akzeptabel
Dies implementiert zwei DFFs und einige kombinatorische Logik, nicht die erforderliche Schaltung. Verwenden Sie außerdem niemals Anfangswerte für Signale in synthetisierbarer Logik, verwenden Sie ein ordnungsgemäßes Zurücksetzen. Das ist der Unterschied zwischen dem „Schreiben von VHDL“ und dem Entwurf von Logikschaltungen. Abwertung.
Ich habe oft Anfangswerte für Signale in synthetisiertem Code verwendet und hatte nie Probleme damit. Warum sollte ich das nicht tun? Außerdem gibt es in dieser Schaltung kein Zurücksetzen. Wenn wir uns also streng an das Design halten, würde ich im Falle der Verwendung von Zurücksetzen scheitern. Und wie ich bereits betont habe, besteht dieses Design NICHT aus 4 nackten NAND-Gattern. @Elzy hat bereits zugestimmt (wenn ich das richtig verstanden habe), dass dieser Zirkel eigentlich nicht speziell das ist, was er erreichen wollte. In der Beschreibung fügte er einige zusätzliche Informationen hinzu
Auf RAM-basiertem FPGA sind Sie damit durchgekommen. Anfangswerte sind eine schreckliche Angewohnheit. Ein Reset ist einfach durchzuführen, sehr alltäglich (sehen Sie sich diese Unmengen von Pro-IP an) und hält Ihre IP portabel, dh Sie können sie in ein CPLD oder ein anderes (nicht RAM-basiertes) FPGA stecken und es wird funktionieren. Andere können Ihre Designs in anderen Geräten wiederverwenden oder Sie verlassen und arbeiten woanders an anderen FPGAs – lernen Sie, Designs portabel zu halten. Sie können Ihr RAM-basiertes FPGA intern zurücksetzen, indem Sie dort nur den Anfangswert verwenden (DFF SR4-Konfiguration auf 1, CLKd auf 0). Wechseln Sie zu Flash FPGA, die Anfangswerte funktionieren nicht. Entwerfen Sie gute Schaltungen, keine guten Simulationen.
Ok, wie wäre es mit dieser Frage und der ersten Antwort? Es sagt deutlich, dass es in manchen Fällen besser ist, keine Reset-, sondern Initialwerte zu haben. In unserer Frage ging es nicht um Technologie, daher gibt es keinen Grund, abzustimmen, wenn ich eine von zwei verfügbaren Optionen auswähle und richtig auf die Frage geantwortet habe. Wie auch immer, danke, dass du mich provoziert hast, etwas zu recherchieren und mir etwas Neues beizubringen :)
Anstatt „es sagt es deutlich“, heißt es „einige Leute denken“, dass es besser ist. Glücklicherweise wissen wir, dass dies nicht der Fall ist. Diese Leute irren sich - sie sehen nur ihren winzigen Teil der technischen Welt und wissen nicht, wie man reist :-) Ihr Zeug würde in Microsemi, Lattice FPGAs nicht funktionieren: kaputte Schaltkreise durch faules Design. Manche schreiben einfach VHDL. Ich schaue mir die ganze Schaltung an, beurteile, was sie braucht, entwerfe die Schaltung und schreibe das schließlich in VHDL. Wie ich zu Beginn sagte, sehen Sie diese 10.000 IP-Kerne da draußen - alle mit Reset, Null Komma Null mit Anfangswerten. Downvote war für die Bestätigung schrecklicher Anfangswerte.
Er lieferte ein starkes Argument zur Logik, die keinen eingebauten Reset hat, also ist es nicht „manche Leute denken“. Ich finde, du bist etwas zu arrogant, wenn du das sagst. Aber es ist Ihre Sache. Wie auch immer, danke für das Gespräch und die Tipps für die Zukunft.
Beim Ultra-High-Speed-Design verwenden Sie häufig keine Resets, da Resets Routing-Ressourcen erfordern, die Sie minimieren müssen. Sie benötigen diese Ressourcen, um eine minimale Zeitverzögerung zu erreichen. Xilinx-Anwendungsingenieure raten daher eigentlich dazu, die Verwendung von Resets auf „nur dort, wo wirklich erforderlich“ zu minimieren.

Zunächst einmal würde der herkömmliche Weg, ein JK-Flipflop in VHDL zu entwerfen, folgendermaßen aussehen:

signal Q_s : std_logic;

process(clk)
begin
  if (rising_edge(clk)) then
    if (J = '1' and K = '1') then
      Q_s <= not Q_s;
    elsif(J = '1') then
      Q_s <= '1';
    elsif(K = '1') then
      Q_s <= '0';
    end if;
  end if;
end process;

Q <= Q_s;
Qbar <= not Q_s;

Hier veranlassen wir, dass ein Register abgeleitet wird, das sich äquivalent zu einem JK-Flip-Flop verhält. Beachten Sie, dass bei diesem Code, wenn Sie Jund Kzusammen behaupten, bevor Sie entweder einzeln behaupten, die Ausgabe in der Simulation Qundefiniert ist. Wenn der Anfangszustand aus irgendeinem Grund keine Rolle spielt, können Sie ihn bei der Definition mit initialisieren signal Q_s : std_logic := '0';( '1'wäre ebenso gültig). Wenn der Anfangszustand eine Rolle spielt, sollten Sie eine spezielle Reset-Klausel hinzufügen, um diesen Zustand festzulegen.

Zurück zu Ihrer eigentlichen Frage, an Ihrem Code ist eigentlich nichts falsch; Es wird korrekt synthetisiert und "richtig" funktionieren, aber unter Simulation nicht die erwarteten Ergebnisse liefern. Sie können Ihr JK-Flip-Flop so implementieren, dass es sowohl richtig simuliert als auch synthetisiert werden kann, wobei das Ergebnis genau Ihrem Schaltplan entspricht. Hier ist zunächst ein einfacher Prüfstand:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb is
end tb;

architecture a of tb is
  constant CLK_PERIOD : time      := 100 ns;
  signal J            : std_logic := '0';
  signal K            : std_logic := '0';
  signal Clk          : std_logic := '0';
  signal Q            : std_logic;
  signal Qbar         : std_logic;
begin
  Clk <= not Clk after CLK_PERIOD / 2;

  uut : entity work.JKFlipFlopGate
    port map(
      J    => J,
      K    => K,
      Clk  => Clk,
      Q    => Q,
      Qbar => Qbar
    );

  process
  begin
    wait for CLK_PERIOD;
    J <= '1';
    wait for CLK_PERIOD;
    J <= '0';
    wait for CLK_PERIOD;
    k <= '1';
    wait for CLK_PERIOD;
    K <= '0';
    wait for CLK_PERIOD;
    J <= '1';
    k <= '1';
    wait for CLK_PERIOD;
    J <= '0';
    k <= '0';
    wait;
  end process;

end a;

outxDas Problem bei der Simulation Ihres Codes im Ist-Zustand besteht darin, dass sich die gesamte Schaltung in einem unbekannten Zustand befindet, da alle Ihre Signale nicht initialisiert sind, wobei verschiedene Signale den Wert 'U'zu dem Zeitpunkt haben, an dem die Simulation beginnt. Wenn Sie die Initialisierung hinzufügen, sehen Ihre outxSignaldefinitionen dann so aus:

signal out1 : std_logic := '1';
signal out2 : std_logic := '1';
signal out3 : std_logic := '0';
signal out4 : std_logic := '1';

Beachten Sie, dass diese Initialisierungswerte nur die Simulation beeinflussen; Da Ihr Code keine synchronen Elemente beschreibt (eher eine kombinatorische Funktion mit einem ähnlichen Verhalten wie ein synchrones Element), haben sie keinen Einfluss auf das synthetisierte Design, unabhängig davon, ob Ihre Toolkette sie unterstützt oder nicht.

Die Simulation dieses aktualisierten Designs funktioniert ordnungsgemäß, wenn entweder Joder Kauf festgelegt sind '1'. Wenn jedoch beide hoch eingestellt sind, liegt eine Rennbedingung vor und die Schaltung schwingt. Dies entspricht dem Verhalten der realen Schaltung, wenn der Taktimpuls hoch bleibt, nachdem der Ausgang Qumgeschaltet hat. Da es keine Verzögerungen in der Beschreibung gibt, findet diese Oszillation in Simulations-Delta-Zyklen statt und die Simulationsiterationsgrenze wird erreicht. Wir können diese leichter erkennen, indem wir eine grobe Gate-Verzögerung in das Design integrieren:

entity JKFlipFlopGate is
    generic(
        GATE_DELAY : time := 0 ns   -- Default needed for synth
    );
    port(
        J, K, Clk : in  std_logic;
        Q, Qbar   : out std_logic
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is
    signal out1 : std_logic := '0';
    signal out2 : std_logic := '0';
    signal out3 : std_logic := '1';
    signal out4 : std_logic := '0';

begin
    out1 <= not(J AND Clk AND out4) after GATE_DELAY;
    out2 <= not(K AND Clk AND out3) after GATE_DELAY;
    out3 <= out1 nand out4 after GATE_DELAY;
    out4 <= out2 nand out3 after GATE_DELAY;
    Q    <= out3;
    Qbar <= out4;
end result;

afterNormalerweise würde ich sagen, dass Sie keine Klauseln in Code verwenden sollten , der in echter Hardware implementiert werden soll, aber dies ist nur eine Übung, und diese Klauseln werden von der Synthese ignoriert. Die Simulation fügt Folgendes hinzu:

constant GATE_DELAY : time := 1 ns;

Und die uutInstanziierung wird:

  uut : entity work.JKFlipFlopGate
    generic map(
      GATE_DELAY => GATE_DELAY
    )
    port map(
      J    => J,
      K    => K,
      Clk  => Clk,
      Q    => Q,
      Qbar => Qbar
    );

Sie können nun die Oszillationen sehen, die durch einen zu langen Taktimpuls in der Simulationswellenform entstehen:

JK-Schwingungen

Wir können die Taktimpulsbreite leicht verkürzen, um diese Oszillationen zu beseitigen, indem wir ein neues "Impuls" -Signal hinzufügen, das von der Uhr abgeleitet wird:

signal Clk_pulse    : std_logic := '0';

Beachten Sie, dass dies ein reiner Simulationscode ist, sodass Sie die Anfangswerte beliebig verwenden können. Als nächstes ein Prozess zum Ableiten des Taktimpulses:

  process(Clk)
  begin
    if (rising_edge(Clk)) then
      Clk_pulse <= '1', '0' after 2 * GATE_DELAY;
    end if;
  end process;

Und schließlich wird in der uutInstanziierung zu .Clk => Clk,Clk => Clk_pulse,

Mit all diesen vorgenommenen Änderungen simuliert das Design mit korrektem Verhalten und wird immer noch korrekt in die ursprüngliche Designschaltung umgewandelt:

"Puls"-Uhr

Ausgearbeitete Schaltung

Gute Antwort. Aber ich würde die Gate-Verzögerung nicht auf 0 ns zurücksetzen, oder Sie werden das gleiche Problem wieder haben.
@JHBonarius Der Standard ist, wie es heißt, für die Synthese. Sie könnten Ihrem Tool eine Spezifikation für dieses Generikum hinzufügen, aber das wäre toolspezifisch.

Eine solche VHDL-Simulation wird niemals ohne Reset-Signal funktionieren. Zu Beginn der Simulation ist der Wert von Q und Qbar unbekannt, und da sie zum Eingang zurückgeführt werden, wird der unbekannte Zustand durch alle Gatter weitergegeben

Ja, kann es. Es müssen nur Anfangswerte definiert werden.