Estoy implementando algunos módulos usando VHDL y para algunos de ellos necesito la señal de reloj global del FPGA, y para algunos otros debo actualizar a dos frecuencias diferentes. Una solución común a esto es usar divisores de frecuencia basados en contadores, así que si tengo un reloj de 8 MHz y necesito 2 KHz, puedo contar hasta 4000 y generar y habilitar la señal para los otros componentes.
Pero cuando se necesitan muchos relojes, una forma de reducir el tamaño de los divisores de frecuencia podría estar en cascada. Por ejemplo, para generar 2KHz y 1Hz, podría contar hasta 2000 usando la señal de habilitación de 2KHz generada anteriormente.
Mi problema es que, dado que es una buena práctica para la escalabilidad y el rendimiento el uso de un solo reloj global, el uso de los relojes anteriores como señales de activación provoca retrasos en la generación de relojes posterior. Este es mi código VHDL para generar dos nuevos relojes basados en el global:
library ieee;
use ieee.std_logic_1164.all;
entity clock_generator is
generic(
global_freq : integer;
display_freq : integer
);
port(
clk : in std_logic;
reset : in std_logic;
clk_2KHz : out std_logic;
clk_1min : out std_logic
);
end clock_generator;
architecture behavioral of clock_generator is
constant MAX_2KHz : integer := (global_freq / display_freq) - 1;
constant MAX_1min : integer := (display_freq * 60) - 1;
signal cnt_2KHz : integer range 0 to MAX_2KHz;
signal en_2KHz : std_logic;
signal cnt_1min : integer range 0 to MAX_1min;
begin
gen_2KHz : process(clk, reset)
begin
if reset = '0' then
cnt_2KHz <= 0;
elsif rising_edge(clk) then
if cnt_2KHz = MAX_2KHz then
cnt_2KHz <= 0;
else
cnt_2KHz <= cnt_2KHz + 1;
end if;
end if;
end process;
en_2KHz <= '1' when cnt_2KHz = MAX_2KHz else '0';
gen_1min : process(clk, reset)
begin
if reset = '0' then
cnt_1min <= 0;
elsif rising_edge(clk) then
if en_2KHz = '1' then
if cnt_1min = MAX_1min then
cnt_1min <= 0;
else
cnt_1min <= cnt_1min + 1;
end if;
end if;
end if;
end process;
clk_2KHz <= en_2KHz;
clk_1min <= '1' when cnt_1min = MAX_1min else '0';
end behavioral;
Si simulo su comportamiento, podemos ver que el primer reloj se genera sincronizado con el global, pero como el segundo depende de la activación del primero, se retrasa un ciclo del reloj global:
Así que mis preguntas son:
- ¿Cómo puedo obtener la sincronización de reloj completo sin usar divisores de frecuencia individuales?
- ¿Podría esta sincronización causar algún problema en algún tipo de sistema especial o es simplemente insignificante?