0
votes

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;
2
Wasn't this question here a few days ago? But, I cannot find it anymore???Martin Zabel
I don't think so? I certainly haven't asked it before, and I did quite a wide search before asking a question that's already quite closely related to the other questions I mentioned.davidhood2
It was a question of another user. Nevermind. Your code works fine with ISE 14.7. So which tool are you using?Martin Zabel
I'm synthesizing with XST. The exact complaint comes from Clk_Div/output2...davidhood2

2 Answers

2
votes

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.

1
votes

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.