Para la generación de reloj concurrente, no olvides inicializar el reloj (falta en tu código y no funcionará sin él).
signal clock : std_logic := '0' ;
clock<=NOT clock AFTER clk_period/2;
¿Por qué funciona? Todas las asignaciones simultáneas se pueden convertir a un proceso equivalente extrayendo todas las señales en el lado derecho (y seleccione la expresión) y agregándolas a una lista de sensibilidad del proceso. Por lo tanto, su código anterior se convierte en:
process(clock)
begin
clock<=NOT clock AFTER clk_period/2;
end process ;
Yendo más allá, todos los procesos se ejecutan en su totalidad durante la inicialización (fase de ejecución del ciclo 0 delta). Por lo tanto, este proceso proyecta que el reloj cambie a 1 después de la mitad del período de reloj. Cuando el nuevo valor se coloca en el reloj, el proceso se ejecuta de nuevo y programa el valor opuesto un período de medio reloj más tarde. Uno de cada cambio de reloj, el proceso (juego de palabras previsto) se repite.
Para su reloj basado en procesos:
clk_process : process
begin
clk <= '0';
wait for clk_period/2; --for 0.5 ns signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns signal is '1'.
end process;
Esperar es simplemente un medio de control de ejecución de procesos. El proceso se ejecuta hasta una instrucción de espera, se suspende hasta que la instrucción de espera indica que se activa y luego se reanuda. Cuando llega al final, simplemente se reanuda en la parte superior del proceso hasta que llega a la siguiente declaración de espera.
Para ayudarlo a entender por qué esto se repite, considere el siguiente proceso:
process(Sel, A, B)
begin
case Sel is
when '0' => Y <= A ;
when '1' => Y <= B ;
when others => Y <= (others => 'X') ;
end case ;
end process ;
La forma en que el lenguaje se ejecuta puede describirse mediante el siguiente proceso con una instrucción de espera. La espera se encuentra al final del proceso porque durante la inicialización, el proceso con una lista de sensibilidad se ejecuta una vez.
process
begin
case Sel is
when '0' => Y <= A ;
when '1' => Y <= B ;
when others => Y <= (others => 'X') ;
end case ;
wait on Sel, A, B ;
end process ;
Por lo tanto, todos los procesos forman un bucle natural. Para evitar el bucle, necesita una instrucción de espera similar a la que hizo en el proceso de datos.
Si bien su proceso de datos puede ser correcto, recomiendo mejorar la legibilidad mediante el uso de un bucle en lugar de la naturaleza en bucle de un proceso:
data_process : process
variable timedata : time;
begin
for i in 1 to 100 loop
timedata := i*clk_period;
data <= not data;
wait for timedata;
data <= not data;
-- just added the following wait.
-- With out it, the previous assignment to data is meaningless.
wait for timedata;
end loop ;
std.env.stop ; -- stop the testbench
wait ;
end process;