Ich versuche zu verstehen, wie Zuweisungen mit 'after foo' funktionieren, also habe ich etwas über das Verzögerungsmodell gelesen und den folgenden Code simuliert:
library IEEE;
use ieee.std_logic_1164.all;
entity test is
port (
goes_in, goes_out : out std_logic := 'U'
);
end entity;
architecture a of test is
signal temp : std_logic := 'U';
signal input : std_logic := 'Z';
begin
goes_in <= input;
process (input)
begin
temp <= input;
goes_out <= temp after 10ns; -- (*)
end process;
--Removing the line with the (*) and uncommenting the following snippet solves the problem.
--process (temp)
-- begin
-- goes_out <= temp after 10ns;
-- end process;
process
begin
input <= '0';
wait for 15 ns;
input <= '1';
wait;
end process;
end a;
In Vivaldo von Xilinx erhalte ich folgende Ausgabe:
time(ns) : 10 15 20 25
_________ ________________________ ...
goes_in : _______'0'________/ '1'
goes_out : ----'U'-----|---------'Z'----------\_____'0'___________ ...
Was ich erwartet hatte, war einfach eine Verzögerung von 10 ns. Kann jemand erklären, was hier los ist?
EDIT: Um es klar zu sagen, mein Beef hier ist, dass, wenn das Verhalten, das ich beschreibe, tatsächlich Standard ist, es wie ein schreckliches Abstraktionsleck klingt: wenn ich schreibe
goes_out <= temp after 10ns;
Das Verhalten, das ich erwarte, wäre eines, das das Ansteuern eines Latches simuliert (temp ist der Eingang, goes_out ist der Ausgang), und daher müsste temp seinen neuen Wert für 10 ns beibehalten, um den Latch richtig anzusteuern (daher die "Trägheitsverzögerung " Modell).
Wenn dies tatsächlich der Fall wäre, wäre das richtige Verhalten für meine Schaltung, nichts zu tun, da ich versuche, ein 'Z' in goes_out zu schreiben, und unmittelbar danach wird dieses 'Z' durch eine '1' überschrieben - also , wird der Wert von temp, der den Latch antreibt, nicht beibehalten, und er kann goes_out nicht ansteuern. (Offensichtlich kann man keine Latches mit 'Z' fahren, dachte ich könnte '0' und '1' verwenden und mein Punkt würde stehen)
Meine Frage ist also: Gibt es einen guten Grund für dieses seltsame Verhalten? Mir erscheint es trivial, "die Dinge richtig zu machen": Der Algorithmus, der die Trägheitsverzögerung simuliert, könnte nach Änderungen des Werts von temp im Delta-Zyklus suchen, dem er goes_out zugewiesen wird, und die Zuweisung abbrechen, wenn etwas passiert - stattdessen die Zuweisung nur aufzuheben, wenn sich der NEUE Wert von temp nicht ändert.
Der Schlüssel hier ist Ihre Verwendung von <=
, wodurch Zuweisungen parallel erfolgen.
Betrachten Sie die Zuordnung von 1 zu input
. Das löst die aus process(input)
. Die erste Zeile temp <= input;
stellt die Zuweisung von 1 bis temp
unmittelbar nach dem aktuellen Zeitschritt in die Warteschlange . temp
behält den Wert 0 für die Ausführung der nächsten Zeile, was interpretiert wird als "die Zuweisung des Werts, der temp
zu Beginn dieses Vorgangs zugewiesen werden musste, goes_out
in 10 ns Zeit in die Warteschlange stellen".
Wenn Sie es zusammenklappen goes_out <= input after 10ns;
und temp
vollständig entfernen, sieht es etwas intuitiver aus. Oder sehen Sie sich die Werte von temp und input in Ihrem Simulator an.
process
begin
temp <= input;
goes_out <= temp after 10ns; -- (*)
end process;
temp
hat sich nicht geändert, wenn Sie es lesen, um es zuzuweisen goes_out
. Bis einige Zeit vergeht (dh alle während dieses Delta-Zyklus ausgelösten Prozesse abgeschlossen sind), werden alle in diesen Prozessen vorgenommenen Zuweisungen lediglich für den nächsten Zeitschritt geplant.
Du könntest es tun:
process
begin
wait until input'event;
temp <= input;
wait for 0 ps;
goes_out <= temp after 10ns;
end process;
Das wait for 0 ps;
erzwingt einige Zeit zum Verstreichen (0 ps zählen als Erzwingen des Abschlusses von Delta-Zyklen).
FrancoVS
Martin Thomson