I'm implementing some modules using VHDL and for some of them I need the FPGA's global clock signal, and for some others I need to update to two different frequencies. A common solution to this is using frequency dividers based on counters, so if I have a 8MHz clock and I need 2KHz, I can just count up to 4000 and generate and enable signal for the other components.
But when many clocks are needed, a way of reducing the size for frequency dividers could be cascading them. For example, to generate 2KHz and 1Hz, I could count up to 2000 using the previous generated 2KHz enable signal.
My problem is that, since it's a good practice for scalability and performance the use of a single global clock, using the previous clocks as enable signals causes delays on subsequent clock generation. This is my VHDL code to generate two new clocks based on the global one:
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;
If I simulate its behavior, we can see that the first clock is generated synchronized with the global one, but since the second depends on the first one's activation, it's delayed one cycle of the global clock:
So my questions are:
- How can I get full clock synchronization without using individual frequency dividers?
- Could this synchronization cause any problem on some kind of special systems or is this just negligible?