Un banco de pruebas para una subentidad en mi sistema actualmente define un proceso auxiliar para generar una forma de onda similar a un reloj al mando del proceso de estímulo principal. Una versión simplificada es:
shared variable gen_period : time := 10 us;
signal gen_all : boolean := false; -- wavegen enabled
signal gen_A : boolean := false; -- run this signal
signal A_in : std_logic; -- manual input (wavegen disabled)
signal A_gen : std_logic; -- generated output (internal)
signal A_out : std_logic; -- final output
...
A_generate: process
if gen_A then
A_gen <= '1';
wait for gen_period/2;
A_gen <= '0';
wait for gen_period/2;
else
A_gen <= '0';
wait for 1 ns;
end if;
end process;
A_out <= A_gen when gen_all else A_in;
El sistema completo tiene algunas señales más, pero esta es la idea básica. gen_all
se aplica a todas las señales y permite que se aplique un patrón de señal manual cuando está deshabilitado, mientras que gen_A
es básicamente un reloj habilitado para esa señal específica. La otra característica importante es que el período del reloj es variable.
Poner todo esto junto significa que el proceso principal de estímulo del banco de pruebas puede generar bordes manualmente o simplemente puede solicitar un tren de pulsos en un intervalo específico y luego esperar un tiempo más largo (típicamente gen_period * N
) para generar pulsos múltiples. Funciona bastante bien.
Ahora, aunque estoy interesado en generalizar esto un poco, en particular para crear una instancia de varios generadores independientes en el banco de pruebas para un diseño de alto nivel que contenga múltiples componentes originales. Sin embargo, estoy teniendo problemas para encontrar la manera correcta de hacerlo.
Mi primer intento fue envolver el código de arriba en su propia entidad, declarando todo menos A_gen
como puertos de la entidad. Hacer esto requiere cambiar gen_period
de una variable a una señal, ya que los puertos AFAIK deben ser señales.
Lamentablemente, de nuevo en el proceso de estímulo original del banco de pruebas, cada vez que intentaba asignar un nuevo período tenía que hacer esto como una asignación de señal, que no tuvo efecto hasta más tarde. Además, las llamadas wait for gen_period * 5
parecían estar usando el valor original para gen_period en lugar de uno solo asignado. (Este no es un comportamiento sorprendente para las señales, pero en este caso no es deseado).
¿Hay una mejor manera de encapsular esta funcionalidad y conservar el comportamiento instantáneo de la variable? El código solo se utilizará en un banco de pruebas, por lo que no necesita ser sintetizable. Estoy usando Xilinx ISim.
(Me doy cuenta de que puedo hacer un for .. generate
para crear instancias múltiples en el banco de pruebas de nivel superior, pero esto no me permite compartir el código entre bancos de pruebas separados, lo que también es conveniente para evitar la duplicación).
Puedo vivir teniendo solo una instancia de la variable gen_period
compartida entre todos los generadores en el banco de pruebas de alto nivel, pero preferiría tener una por instancia de generador.
Como las respuestas parecen estar enfocadas en "reloj" en lugar de "forma de onda", parece que necesito aclarar el uso un poco más. Esto está dentro de un banco de pruebas:
stim_proc : process
begin
-- (reset and other setup instructions here)
-- generate "slow" pulse train
gen_all <= true;
gen_period := 250 ns;
gen_A <= true;
wait for gen_period * 20;
gen_A <= false;
wait for gen_period;
-- (perform tests on logic for slow pulses here)
-- generate "fast" pulse train
gen_period := 10 ns;
gen_A <= true;
wait for gen_period * 50;
gen_A <= false;
wait for gen_period;
-- (perform tests on logic for fast pulses here)
-- generate asymmetric pulses
gen_all <= false;
A_in <= '1';
wait for 100 ns;
A_in <= '0';
wait for 200 ns;
A_in <= '1';
wait for 150 ns;
A_in <= '0';
wait for 50 ns;
-- (perform tests on logic for asymmetric pulses here)
-- etc
end process;
Estos son los simples; hay algunos más complejos que involucran múltiples señales que ocurren simultáneamente, pero eso no es realmente importante para esta pregunta. El punto importante es que esto es todo el código secuencial y tanto la generación de pulsos como la espera deben actuar en el último período establecido, no en ningún valor retrasado.