VHDL:基于非常快的时钟创建非常慢的时钟脉冲

Mar*_*ver 6 clock fpga vhdl

(我会在EE中发布这个,但似乎这里有更多的VHDL问题......)

背景:我正在使用Xilinx Spartan-6LX9 FPGA和Xilinx ISE 14.4(webpack).

我偶然发现了可怕的"PhysDesignRules:372 - 门控时钟"警告,我看到有很多关于这一点的讨论.一致意见似乎是使用FPGA上的其中一个DCM进行时钟分频但是...我的DCM似乎无法从32 MHz到4.096 KHz(根据向导它在5MHz时达到最低点) 32MHz ......尝试为这种低频目的链接多个DCM似乎很荒谬.

我当前的设计使用clk_in计数到指定值(15265),将该值重置为零并切换clk_out位(因此我最终得到50%的占空比,FWIW).它完成了这项工作,我可以轻松地使用clk_out的上升沿来驱动我设计的下一个阶段.它似乎工作得很好,但是...... 门控时钟(即使它不在时钟偏差的范围内,恕我直言也非常相关).(注意:所有时钟测试都是在对给定时钟敏感的进程中使用rising_edge()函数完成的.)

所以,我的问题:

  • 如果我们谈论从更快的 clk_in中获得相对较慢的clk_out,那么门控还是被认为是坏的吗?或者这种"计数到x并发送脉冲"这一点对FPGA来说非常典型,以生成KHz范围内的"时钟",而其他一些不必要的副作用可能会触发此警告?

  • 有没有更好的方法从MHz范围的主时钟创建一个低KHz范围的时钟,请记住,使用多个DCM似乎在这里是过度的(如果在极低的输出频率下可能的话)?我意识到50%的占空比可能是多余的,但假设一个时钟进入并且使用板载DCM,那么用FPGA如何进行主要的时钟分频?

编辑:给定以下内容(其中CLK_MASTER是32 MHz输入时钟,CLK_SLOW是所需的慢速时钟,LOCAL_CLK_SLOW是一种存储整个占空比的时钟状态的方法),我了解到这种配置导致警告:

architecture arch of clock is
    constant CLK_MASTER_FREQ: natural := 32000000; -- time := 31.25 ns
    constant CLK_SLOW_FREQ: natural := 2048;
    constant MAX_COUNT: natural := CLK_MASTER_FREQ/CLK_SLOW_FREQ;
    shared variable counter: natural := 0;
    signal LOCAL_CLK_SLOW: STD_LOGIC := '0';
begin
    clock_proc: process(CLK_MASTER)
    begin
        if rising_edge(CLK_MASTER) then
            counter := counter + 1;
            if (counter >= MAX_COUNT) then
                counter := 0;
                LOCAL_CLK_SLOW <= not LOCAL_CLK_SLOW;
                CLK_SLOW <= LOCAL_CLK_SLOW;
            end if;
        end if;
    end process;
end arch;
Run Code Online (Sandbox Code Playgroud)

鉴于此配置不会导致警告:

architecture arch of clock is
    constant CLK_MASTER_FREQ: natural := 32000000; -- time := 31.25 ns
    constant CLK_SLOW_FREQ: natural := 2048;
    constant MAX_COUNT: natural := CLK_MASTER_FREQ/CLK_SLOW_FREQ;
    shared variable counter: natural := 0;
begin
    clock_proc: process(CLK_MASTER)
    begin
        if rising_edge(CLK_MASTER) then
            counter := counter + 1;
            if (counter >= MAX_COUNT) then
                counter := 0;
                CLK_SLOW <= '1';
            else
                CLK_SLOW <= '0';
            end if;
        end if;
    end process;
end arch;
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,一切都是缺少其他的(就像我说的那样,50%的占空比最初很有趣,但最终并不是一个要求,而且"本地"时钟位的切换似乎非常巧妙.时间......)我出现在正确的轨道上.

此时我不清楚的是,为什么使用计数器(存储大量位)不会引起警告,但存储和切换的输出位确实会引发警告.思考?

son*_*ave 8

如果您只需要一个时钟来驱动FPGA中另一部分逻辑,那么简单的答案就是使用时钟使能.

也就是说,在与其他所有相同的(快速)时钟上运行慢速逻辑,但我们对它的启用速度很慢.例:

signal clk_enable_200kHz  : std_logic;
signal clk_enable_counter : std_logic_vector(9 downto 0);

--Create the clock enable:
process(clk_200MHz)
begin
  if(rising_edge(clk_200MHz)) then
    clk_enable_counter <= clk_enable_counter + 1;
    if(clk_enable_counter = 0) then
      clk_enable_200kHz <= '1';
    else
      clk_enable_200kHz <= '0';
    end if;
  end if;
end process;


--Slow process:
process(clk_200MHz)
begin
  if(rising_edge(clk_200MHz)) then
    if(reset = '1') then
      --Do reset
    elsif(clk_enable_200kHz = '1') then
      --Do stuff
    end if;
  end if;
end process;
Run Code Online (Sandbox Code Playgroud)

200kHz是近似的,但上述内容可以扩展到您需要的任何时钟使能频率.此外,它应该由大多数FPGA中的FPGA硬件直接支持(至少在Xilinx部分).

门控时钟几乎总是一个坏主意,因为人们经常忘记他们正在创建新的时钟域,因此在这些时钟之间接口信号时不采取必要的预防措施.它还在FPGA内部使用了更多的时钟线,因此如果你有很多门控时钟,你可能会快速耗尽所有可用的线路.

时钟使能没有这些缺点.一切都在同一时钟域运行(尽管速度不同),因此您可以轻松使用相同的信号,而无需任何同步器或类似信号.