Ich habe Unterricht über VHDL in einer meiner Universitätsklassen und muss einfach schreiben, entity
was einen Takt aus einer 1-MHz-Quelle generiert. Ich verwende das CoolRunner-II CPLD Starter Kit mit ISE Webpack 13.1.
Wenn ich die Simulation meines Codes ausführe, erhalte ich seltsame Ergebnisse. Ich habe keine Ahnung, wo das Problem liegt. Meine VHDL-Entität sieht so aus:
entity clock is
Port ( clk_in : in STD_LOGIC;
clk_1M : out STD_LOGIC;
clk_500k : out STD_LOGIC;
clk_100k : out STD_LOGIC;
clk_1k : out STD_LOGIC;
clk_1hz: out STD_LOGIC);
end clock;
Der Eingang ist ein 1-MHz-Signal vom Oszillator, und ich möchte ein Ausgangssignal von 1 MHz, 500 kHz, 100 kHz, 1 kHz und 1 Hz erzeugen. Ich habe mehrere Signale definiert:
signal c100k: std_logic_vector(3 downto 0) := (others => '0' );
signal c1k: std_logic_vector(9 downto 0) := (others => '0' );
signal c1hz: std_logic_vector(9 downto 0) := (others => '0' );
--
signal c500k_out: std_logic := '0';
signal c100k_out: std_logic := '0';
signal c1k_out: std_logic := '0';
signal c1hz_out: std_logic := '0';
Und schließlich ist mein Code:
process (clk_in) begin
if clk_in'event and clk_in = '1' then
-- 500kHz
c500k_out <= not c500k_out;
end if;
end process;
process (clk_in) begin
if clk_in'event and clk_in = '1' then
-- 100kHz
c100k <= c100k + '1';
if c100k = X"A" then
c100k <= (others => '0' );
c100k_out <= '1';
else
c100k_out <= '0';
end if;
end if;
end process;
--
-- Code for 1kHz and 1Hz is same as 100kHz
--
clk_1M <= clk_in; -- Clock source 1Mhz
clk_500k <= c500k_out; -- Clock source 500kHz
clk_100k <= c100k_out; -- Clock source 100kHz
clk_1k <= c1k_out; -- Clock source 1kHz
clk_1hz <= c1hz_out; -- Clock source 1Hz
Wenn ich die Simulation durchführe, habe ich diese seltsamen Ergebnisse erhalten:
Was ist falsch an meinem Code?
Das erste, was ich sehe, was wahrscheinlich nicht Ihr Problem verursacht, ist das Fehlen jeglicher Art von Reset. ModelSim deklariert nicht automatisch alle Signale als '0', und der Versuch, s <= nicht s zu sagen, wenn s nicht 1 oder 0 ist, wird Ihnen nicht das geben, was Sie wollen. Ich sehe, dass Sie sie alle oben mit '0' deklarieren, aber eine richtige Schaltung hätte einen Reset-Eingang, den Sie zu Beginn Ihrer Simulation kurz ansteuern.
Ihr grundlegender Gegenprozess sieht falsch aus; Wenn die Zählung zehn erreicht, geben Sie im Grunde eine „1“ aus und für die anderen 9/10 der Zeit geben Sie eine „0“ aus (für das 100k-Beispiel wäre das 1-Hz-Beispiel ein 1us-Impuls hoch und ein 999us Niedrige Zeit. Ich denke, was Sie wollen, ist ungefähr Folgendes:
gen_clk100: process(clk, rst)
begin
if rising_edge(clk) then
if count = 10 then
clk100 <= not clk100;
count <= 0;
else
count <= count + 1;
end if;
end if;
if rst = '1' then
clk100 <= '0';
count <= 0;
end if;
end process;
Beachten Sie mehrere Dinge:
Ich steigere nicht ständig. Ich inkrementiere, wenn die Zählung nicht auf ihrem Maximum ist, und inkrementiere andernfalls.
Ich schalte den Ausgangstakt um, wenn die maximale Anzahl erreicht ist
Ich habe ein asynchrones Zurücksetzen (mit synchronem Löschen) eingefügt - dies stellt sicher, dass Ihre Signale korrekt initialisiert werden und keine Metastabilitätsprobleme auftreten, wenn das Zurücksetzen freigegeben wird.
Sie erwähnen auch, dass die anderen Abschnitte gleich sind. Ich denke, Sie haben ein Problem mit mehreren Treibern, wie Yann erwähnt hat. Überprüfen Sie Ihren Code mehrmals, um sicherzustellen, dass Sie die Ausgabe nicht in zwei verschiedenen Prozessen zuweisen, denn genau das sagt die Simulation. Besser entweder ein generisches Zählermodul bauen oder ...
Warum so viele Zähler? Alle Ihre Frequenzteiler können mit einer einzigen Zählung behandelt werden und dann die Bedingungen "abziehen", um die Divisionen durchzuführen, an denen Sie interessiert sind. Sie könnten auch einen einzelnen Zähler haben und den (Modulus) -Operator verwenden, um jeden Teilerfall zu behandeln mod
.
Schließlich würde ich anstelle von s auch reelle oder ganzzahlige Typen für die Anzahl verwenden, std_logic_vector
aber das bin nur ich.
if rising_edge(clk) then if ce_100k = '1' then ... end if; end if;
) verwenden, anstatt neue Uhren zu erstellen ( if rising_edge(clk100k) then ... end if;
), und es gibt verschiedene Möglichkeiten, das System zu optimieren, wie @DavidKessner betonte, aber ich denke, was ich vorgeschlagen habe, war der beste "allgemeine Zweck" und "sicherste" Ratschlag , und Beratung, die eine sehr hohe Wahrscheinlichkeit hat, das zu tun, was er braucht.Sie ordnen die Signale clk_1M, clk_500k, clk_100k, clk_1k und clk_1hz in verschiedenen Prozessen im Prüfstand zu. Gleichzeitig haben Sie Ihr DUT instanziiert, das (wie Yann Vernier vorschlägt) dieselben Signale ansteuert. Entkommentieren Sie die Prüfstandsprozesse (außer clk_in!) Und alles wird gut.
Außerdem würde ich Ihnen raten, der Clock-Entität ein asynchrones Reset-Signal hinzuzufügen, um sie synthetisierbar zu machen.
Sie haben mehrere Treiber. Sie werden nicht in Ihren geposteten Code-Snippets angezeigt, sind aber in den nicht snippetisierten Dateien offensichtlich .
Wenn Sie sich die Datei test_clock.vhd ansehen, instanziieren Sie Ihre zu testende Einheit. In der Portmap weisen Sie clk_1M einen Ausgang von clock() zu. Später haben Sie diesen Codeabschnitt:
clk_1M_process :process
begin
clk_1M <= '0';
wait for clk_1M_period/2;
clk_1M <= '1';
wait for clk_1M_period/2;
end process;
Dieser Code weist auch clk_1M einen Wert zu - daher haben Sie mehrere Treiber für Ihre Signale.
Andere Signale haben ähnliche Probleme, daher werde ich hier nicht darauf eingehen.
Ich sehe es nicht in den Codeausschnitten, aber die Simulation sieht ganz so aus, als hätten Sie mehrere Treiber für einige Signale. Wenn sie zustimmen, erhalten Sie eine Logikebene, aber wenn sie nicht einverstanden sind, erhalten Sie X - einen Konflikt in der Simulation, der wahrscheinlich nicht synthetisierbar ist (wenn dies der Fall wäre, würde dies einen Frittierkurzschluss bedeuten). Eine Vermutung ist, dass Sie beim Kopieren dieses Taktteilerprozesses möglicherweise einen Fehler gemacht haben und mit einer Komponente, die Sie stattdessen instanziieren könnten, gut bedient wären.
Vasco