Zuordnungen mit After und Signalen

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.

Antworten (2)

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 . tempbehält den Wert 0 für die Ausführung der nächsten Zeile, was interpretiert wird als "die Zuweisung des Werts, der tempzu Beginn dieses Vorgangs zugewiesen werden musste, goes_outin 10 ns Zeit in die Warteschlange stellen".

Wenn Sie es zusammenklappen goes_out <= input after 10ns;und tempvollstä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;

temphat 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).

Hat nicht funktioniert. Der Compiler sagt: "Prozess kann nicht sowohl eine Warteanweisung als auch eine Vertraulichkeitsliste haben".
Ja, ich habe keinen vollständigen Prozess eingebaut, ich wollte nur zeigen, wie man Zeit vergeht. Siehe Update für Code, der den gesamten Prozess zeigt