Ich verwende quartus II, um einen JK Flip Flop zu entwerfen. Meine Ergebnisse zeigen jedoch eine unbekannte Ausgabe. Warum ist es?
Beabsichtigte Designschaltung:
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;
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.)
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 J
und K
zusammen behaupten, bevor Sie entweder einzeln behaupten, die Ausgabe in der Simulation Q
undefiniert 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;
outx
Das 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 outx
Signaldefinitionen 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 J
oder K
auf 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 Q
umgeschaltet 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;
after
Normalerweise 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 uut
Instanziierung 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:
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 uut
Instanziierung 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:
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
Anfänger
Staszek
Staszek
scary_jeff
Anfänger
Staszek
Anfänger
Toni M
Staszek
Toni M
Staszek
Toni M
Staszek
JH Bonarius