Reputation: 1367
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;
Upvotes: 0
Views: 351
Reputation: 3659
The comments suggest, that the clock-divider is instantiated in a larger design.
If you want to use the generated clock there, you must add a BUFG between signal output2
and the output out2
like this:
out2_bufg : BUFG port map(I => output2, O => out2);
The component BUFG is defined in the library unisim.vcomponents
. Same applies to output out1
.
The BUFG ensures, that the generated clock is distributed using a clock-tree, so that the clock signal arrives at all destination flip-flops at the same time. This minimizes hold-time violations and gives more room for the setup of data signals.
If you still get the warning/error, then you combined the generated clock signal with another signal elsewhere in the larger design.
Upvotes: 2
Reputation: 15924
The reset_proc
process is written with a elsif cycles > 1 then
outside the clocked part, and with the condition derived from cycles
which is also assigned as part of reset. It is unclear what hardware is actually described here, but it makes the synthesis tool unhappy.
If you want to use RESET_N
as asynchronous reset, then just make a simple if RESET_N = '0' then ... end if;
, and assign whatever signals or variables required to be reset. Other assignments should be moved to the clocked part.
NOTE: Code was changed after the above update... which may have removed the reason for the question.
Btw. RESET_N
is used as asynchronous reset in the reset_proc
, but as synchronous reset in the other processes, and this inconsistent use looks like there may be a potential problem with the reset scheme.
Upvotes: 1