Estoy tratando de entender cómo funcionan las asignaciones con 'después de foo', así que leí sobre el modelo de retraso y simulé el siguiente código:
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;
En Vivaldo de Xilinx, obtengo el siguiente resultado:
time(ns) : 10 15 20 25
_________ ________________________ ...
goes_in : _______'0'________/ '1'
goes_out : ----'U'-----|---------'Z'----------\_____'0'___________ ...
Cuando lo que esperaba era simplemente un retraso de 10 ns. ¿Alguien puede explicar qué está pasando aquí?
EDITAR: para ser claros, mi problema aquí es que, si el comportamiento que estoy describiendo es realmente predeterminado, suena como una terrible fuga de abstracción: cuando escribo
goes_out <= temp after 10ns;
el comportamiento que espero sería uno que simule la activación de un pestillo (la temperatura es la entrada, la salida es la salida), por lo que la temperatura tendría que mantener su nuevo valor durante 10 ns para accionar correctamente el pestillo (de ahí el "retraso inercial " modelo).
Ahora, si este fuera realmente el caso, el comportamiento adecuado para mi circuito sería no hacer nada, ya que intento escribir una 'Z' en going_out e inmediatamente después de eso, esa 'Z' se sobrescribe con un '1', por lo tanto , el valor de temp que acciona el pestillo no se conserva y no se puede accionar does_out. (Obviamente, no puede manejar pestillos con 'Z', pensé que podría usar '0' y '1' y mi punto se mantendría)
Entonces mi pregunta es: ¿hay una buena razón para este comportamiento extraño? Para mí, parece trivial "hacer las cosas bien": el algoritmo que simula el retraso inercial podría verificar los cambios en el valor de la temperatura en el ciclo delta al que se le está asignando going_out, y cancelar la asignación si algo está sucediendo, en su lugar de solo cancelar la asignación si el NUEVO valor de temp no cambia.
La clave aquí es su uso de <=
, lo que hace que las asignaciones se realicen en paralelo.
Considere la asignación de 1 a input
. Eso desencadena el process(input)
. La primera línea temp <= input;
pone en cola la asignación de 1 temp
inmediatamente después del paso de tiempo actual . temp
conserva el valor de 0 para la ejecución de la siguiente línea, lo que se interpreta como "poner en cola la asignación del valor que temp
tenía al inicio de este proceso para ser asignado goes_out
en 10ns de tiempo".
Si lo contrae goes_out <= input after 10ns;
y lo elimina temp
por completo, parece un poco más intuitivo. O vea los valores de temperatura y entrada en su simulador.
process
begin
temp <= input;
goes_out <= temp after 10ns; -- (*)
end process;
temp
no ha cambiado en el momento en que lo lee para asignarlo a goes_out
. Hasta que pase algún tiempo (es decir, todos los procesos desencadenados durante este ciclo delta se hayan completado), las asignaciones realizadas en esos procesos simplemente se programan para que sucedan en el siguiente paso de tiempo.
Podrías hacerlo:
process
begin
wait until input'event;
temp <= input;
wait for 0 ps;
goes_out <= temp after 10ns;
end process;
Las wait for 0 ps;
fuerzas para que pase algún tiempo (0ps cuenta como forzar la finalización de los ciclos delta)
FrancoVS
martin thompson