Cómo conectar en cascada los divisores de frecuencia

0

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:

  1. ¿Cómo puedo obtener la sincronización de reloj completo sin usar divisores de frecuencia individuales?
  2. ¿Podría esta sincronización causar algún problema en algún tipo de sistema especial o es simplemente insignificante?
pregunta Jaime_mc2

0 respuestas

Lea otras preguntas en las etiquetas