方波时钟分频器中的门控时钟

Gated Clock in Clock Divider for a Square Wave

我最近一直在为我的系统设计一个时钟分频器——我重新设计了它,现在有一个异步复位,它为系统的其余部分生成一个同步复位。为此,我按照 提出了我自己的问题,并使用时钟启用来切换输出,从而生成具有 50% 占空比(这是需要的)的时钟。

然而,这在生成 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.

的比特流时抛出了错误

阅读这个 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 这是一个有意的门控时钟。

所以我的问题是;这个门控时钟警告重要吗?在模拟和示波器上它似乎都能正常工作(所以我倾向于忽略它),但我是否将问题存储起来以备后用?有没有办法在没有门控时钟的情况下获得非常慢的 50% 占空比脉冲?

我把我的代码放在下面了!

非常感谢(尤其是少数几个人,他们集体花了大量时间来回答我最近不停的问题)

大卫

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;

reset_proc 进程是用 elsif cycles > 1 then 在时钟部分之外编写的,条件是从 cycles 派生的,它也被分配为重置的一部分。不清楚这里实际描述的是什么硬件,但是这让综合工具不高兴了。

如果你想使用RESET_N作为异步复位,那么只需做一个简单的if RESET_N = '0' then ... end if;,并分配任何需要复位的信号或变量。其他作业应移至计时部分。

注意:代码在上述更新后发生了变化...这可能已经消除了问题的原因。

顺便说一句。 RESET_Nreset_proc 中用作异步复位,但在其他进程中用作同步复位,这种不一致的使用看起来可能是复位方案存在潜在问题。

评论表明,时钟分频器是在更大的设计中实例化的。 如果你想在那里使用生成的时钟,你必须在信号 output2 和输出 out2 之间添加一个 BUFG,如下所示:

out2_bufg : BUFG port map(I => output2, O => out2);

组件 BUFG 在库 unisim.vcomponents 中定义。同样适用于输出 out1.

BUFG 确保生成的时钟使用时钟树进行分配,以便时钟信号同时到达所有目标触发器。这最大限度地减少了保持时间违规,并为数据信号的设置提供了更多空间。

如果您仍然得到 warning/error,那么您将生成的时钟信号与较大设计中其他地方的另一个信号组合在一起。