Esta es una pregunta interesante. Algo que entendí intuitivamente, pero no sabía la razón por la cual. Gracias a tu pregunta, investigué y aprendí algo nuevo.
Parece que test_pipe_1(0)
tiene solo 1 controlador (en pr1
). Sin embargo, cuando simulo su código en Modelsim (¡felicitaciones por el MCVE!), Veo 2 controladores: pr1
y test_1
. Por ejemplo:
# vsim -c work.vhdl_loop_assignment
# Start time: 07:28:12 on Jun 06,2016
# Loading std.standard
# Loading std.textio(body)
# Loading ieee.std_logic_1164(body)
# Loading work.vhdl_loop_assignment(testing)
VSIM 1> run 20 us
VSIM 2> drivers test_pipe_1(0)
# Drivers for /vhdl_loop_assignment/test_pipe_1(0):
# U : Signal /vhdl_loop_assignment/test_pipe_1(0)
# 1 : Driver /vhdl_loop_assignment/pr1
# U : Driver /vhdl_loop_assignment/test_1
#
Ahora, cuando eliminas el comentario de test_pipe_1(0) <= 'Z';
, esto controla todos los valores en test_pipe_1
. Y como test_pipe_1
se construye a partir de tipos resueltos, se invoca la función de resolución y la 'Z' se resuelve con el controlador en pr1
. Para aclarar, aquí están sus 2 casos:
Sin test_pipe_1(0) <= 'Z';
, tiene el ejemplo anterior. Tanto '1'
como 'U'
se manejan en test_pipe_1(0)
, que se resuelve en 'U'
.
Con test_pipe_1(0) <= 'Z';
, obtienes los siguientes controladores:
# vsim -c work.vhdl_loop_assignment
# Start time: 07:33:24 on Jun 06,2016
# Loading std.standard
# Loading std.textio(body)
# Loading ieee.std_logic_1164(body)
# Loading work.vhdl_loop_assignment(testing)
VSIM 1> run 20 us
VSIM 2> drivers test_pipe_1(0)
# Drivers for /vhdl_loop_assignment/test_pipe_1(0):
# 1 : Signal /vhdl_loop_assignment/test_pipe_1(0)
# 1 : Driver /vhdl_loop_assignment/pr1
# Z : Driver /vhdl_loop_assignment/test_1
#
Ahora, obtienes '1'
y 'Z'
en test_pipe_1(0)
. Y la función de resolución se resuelve en un '1'
. Y es por esto que tu código comienza a funcionar.
Aparte de eso, si hubiera cambiado a std_ulogic_vector
, su simulación no se habría compilado o fallado durante la elaboración.
Por último, a la causa raíz: varios controladores. El problema es que los controladores se crean durante la elaboración y los índices en las construcciones for ... loop
no se determinan hasta la ejecución. Por lo tanto, los simuladores crean un controlador para cada elemento individual en test_pipe_1
en el proceso test_1
durante la elaboración. Lo admito, aunque sabía que algo estaba mal, no tenía claro por qué. Tuve que cavar alrededor para averiguar por qué.
Desde el LRM VHDL (Sección 12.4.4):
La elaboración de una declaración de proceso procede de la siguiente manera:
a) Se elabora la parte declarativa del proceso.
b) Se crean los controladores requeridos por la declaración de proceso.
c) La transacción inicial de fi nida por el valor predeterminado asociado con cada señal escalar controlada por la declaración de proceso se inserta en el controlador correspondiente.
Entonces, primero se elabora el proceso. En este punto, el simulador no sabe qué bits de test_pipe_1
tendrán controladores (el rango de for ... loop
aún no se ha evaluado). Por lo tanto, crea todos los controladores requeridos de acuerdo con 12.4.4b.
Ahora, en VHDL LRM (Sección 12.5):
Hay tres casos particulares en los que la elaboración ocurre dinámicamente durante la simulación. Estas areas
sigue:
a) La ejecución de una sentencia de bucle con un esquema de iteración implica la elaboración de la especificación del parámetro de bucle antes de la ejecución de las sentencias encerradas en el bucle (consulte 8.9). Esta elaboración crea el parámetro de bucle y evalúa el rango discreto.
El for ... loop
se elabora 'antes de la ejecución' del bucle.
Entonces, su solución es 1) deshacerse del bucle for o 2) separar las señales.
Por lo tanto, aquí hay un pellizco para tu publicación original. Agregué una señal test_pipe_1_0_in
para que sea el valor que entrará en test_pipe_1
(suponiendo que este valor y test_d0
no estén relacionados, aunque en este ejemplo están claramente relacionados. En su lugar, podría usar test_d0
y obtener el mismo resultado.).
library ieee;
use ieee.std_logic_1164.all;
entity vhdl_loop_assignment is
end;
architecture testing of vhdl_loop_assignment is
signal test_d0: std_logic;
signal test_pipe_1: std_logic_vector(9 downto 0);
signal test_pipe_1_0_in : std_logic;
signal clk: std_logic;
begin
test_1: process(clk)
begin
if rising_edge(clk) then
l: for n in 0 to 8 loop
test_pipe_1(n+1) <= test_pipe_1(n);
end loop;
test_pipe_1(0) <= test_pipe_1_0_in;
end if;
end process;
pr1: process(clk)
begin
if rising_edge(clk) then
if test_d0 /= '0' then
test_d0 <= '0';
test_pipe_1_0_in <= '0';
else
test_d0 <= '1';
test_pipe_1_0_in <= '0';
end if;
end if;
end process;
pr2: process
begin
clk <= '0';
wait for 500 ns;
clk <= '1';
wait for 500 ns;
end process;
end;
Espero que ayude.