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

时间:2015-12-04 12:47:00

标签: time vhdl clock fpga xilinx-ise

我最近一直在为我的系统设计一个时钟分频器 - 我重新设计了它,现在有一个异步复位,它会为系统的其余部分产生同步复位。为此,我按照answers & advice跟我自己的问题并使用时钟使能来切换输出,从而产生占空比为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,但在创建时钟使能时出现是正确的,因为我需要一个方波(而​​不仅仅是1 / 200MHz脉冲),因此使用能够切换另一个信号,在question中显示这是一个有意的门控时钟。

所以我的问题是;这个门控时钟警告是否显着?无论是模拟还是示波器,它似乎都能正常工作(所以我倾向于忽略它),但我是否会存储问题以供日后使用?有没有办法在没有门控时钟的情况下获得非常慢的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;

2 个答案:

答案 0 :(得分:2)

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

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

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

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

如果您仍然收到警告/错误,那么您将生成的时钟信号与较大设计中其他位置的另一个信号合并。

答案 1 :(得分:1)

reset_proc进程在时钟部分之外写有elsif cycles > 1 then,并且从cycles派生的条件也被指定为重置的一部分。目前还不清楚这里实际描述了什么硬件,但这使得综合工具不满意。

如果要将RESET_N用作异步复位,则只需制作一个简单的if RESET_N = '0' then ... end if;,并指定需要重置的任何信号或变量。其他作业应移至计时部分。

注意:上述更新后代码已更改...这可能已删除了问题的原因。

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