I recently have been designing a clock divider for my system - which I redesigned, and now has an asynchronous reset, which generates a synchronous reset for the rest of the system. To do this, I followed the answers & advice to my own question and used a clock enable to toggle an output, thus generating clock with a 50% duty cycle (which is desired).
However, this has thrown up the error when generating the bitstream of
PhysDesignRules:372 - Gated clock. Clock net ... is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
Reading into this question about using the clock enable, it appears when creating a clock enable is correct, however, because I need a square wave (and not just a 1/200MHz pulse), and thus using the enable to toggle another signal, it appears in this question that this is an intentional gated clock.
So my questions are; is this gated clock warning significant? Both in simulation, and on an oscilloscope it appears to function correctly (so I'm inclined to ignore it), but am I storing problems for later? Is there a way of getting a very slow 50% duty cycle pulse without a gated clock?
I've put my code below!
Thanks very much (especially to the handful of people who have collectively given a lot of time to my recent non-stop questions)
David
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
ENTITY CLK_DIVIDER IS
GENERIC(INPUT_FREQ : INTEGER;
OUT1_FREQ : INTEGER;
OUT2_FREQ : INTEGER
);
PORT(SYSCLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
RESET_N_OUT : OUT STD_LOGIC;
OUT1 : OUT STD_LOGIC;
OUT2 : OUT STD_LOGIC);
END CLK_DIVIDER;
architecture Behavioral of Clk_Divider is
constant divider1 : integer := INPUT_FREQ / OUT1_FREQ / 2;
constant divider2 : integer := INPUT_FREQ / OUT2_FREQ / 2;
signal counter1 : integer := 0;
signal counter2 : integer := 0;
signal output1 : std_logic := '0';
signal output2 : std_logic := '0';
signal reset : boolean;
begin
reset_proc : process(RESET_N, SYSCLK)
variable cycles : integer := 0;
variable reset_counter : integer := 0;
begin
if rising_edge(SYSCLK) then
if cycles < 2 then
if reset_counter >= divider1 then
cycles := cycles + 1;
reset_counter := 0;
else
reset_counter := reset_counter + 1;
end if;
reset <= true;
else
reset <= false;
end if;
end if;
if RESET_N = '0' then
cycles := 0;
reset_counter := 0;
reset <= true;
end if;
end process;
output1_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter1 >= divider1 - 1 then
output1 <= not output1;
counter1 <= 0;
else
counter1 <= counter1 + 1;
end if;
if RESET_N = '0' then
counter1 <= 0;
output1 <= '1';
end if;
end if;
end process;
output2_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter2 >= divider2 - 1 then
output2 <= not output2;
counter2 <= 0;
else
counter2 <= counter2 + 1;
end if;
if RESET_N = '0' then
counter2 <= 0;
output2 <= '1';
end if;
end if;
end process;
OUT1 <= output1;
OUT2 <= output2;
RESET_N_OUT <= '0' when reset else '1';
end Behavioral;