VHDL:创建基于一个非常快的时钟速度很慢时钟脉冲(VHDL: creating a very sl

2019-07-21 02:08发布

(我会发布这EE但似乎这里还有更多VHDL问题...)

背景:我使用赛灵思Spartan-6LX9 FPGA与赛灵思ISE 14.4(的WebPack)。

今天警告,我看到有讨论在那里有关,一般很多 - “时钟门控372 PhysDesignRules”我偶然发现了可怕的。 的共识似乎是使用DCM中的一个在FPGA上做时钟分频,但是......我DCM似乎并不能够从32兆赫将4.096千赫(每精灵它在5MHz基于见底32MHz的...它似乎很荒谬,试图链多个DCM这种低频的目的)。

我目前的设计采用CLK_IN计数到指定值(15265),重置该值为零,将切换CLK_OUT位(所以我最终以50%的占空比,FWIW)。 它的工作,我可以很容易地使用CLK_OUT的上升沿,以提高我设计的下一个阶段。 这似乎工作得很好,但是...... 门控时钟 (即使它不是在时钟偏移会恕我直言,是非常相关的范围内)。 (注:所有时钟测试是使用在给定的时钟敏感过程rising_edge()函数来完成。)

所以,我的问题:

  • 如果我们谈论的更快 CLK_IN得出一个相对缓慢的CLK_OUT,被门控仍然被认为是坏? 或者是这种“数到x和发出一个脉冲”的事情非常典型的为FPGA产生在千赫范围内的“时钟”,而是其他一些不必要的副作用可以代替触发这个警告呢?

  • 有没有更好的方式来从兆赫范围的主时钟创建一个低千赫范围时钟,牢记使用多个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;

虽然此配置不导致警告:

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;

所以,在这种情况下,这一切都是因为缺乏一个else(就像我说的,50%的占空比原本是有趣的,但并不是最终的要求,而“本地”时钟位的切换似乎在相当聪明时间......)我主要是它出现在正确的轨道上。

什么是不很清楚,我在这一点上也是为什么使用计数器(存储大量的位)不会导致警告,但受存储和切换输出位确实会导致警告。 思考?

Answer 1:

如果你只需要一个时钟驱动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;

在200kHz的是近似的,虽然,但上面可以扩展到任何基本时钟使能,你需要的频率。 此外,应该可以直接通过在大多数FPGA(它是在赛灵思份至少)FPGA硬件支持。

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

时钟使能有没有这些缺点。 一切都在相同的时钟域中运行(尽管以不同的速度),所以你可以很容易地使用相同的信号,而无需任何同步器或类似。



Answer 2:

注意此示例工作这一行,

信号clk_enable_counter:std_logic_vector(9 DOWNTO 0);

必须改变,以

信号clk_enable_counter:未签名(9 DOWNTO 0);

你会需要包括这个库,

库IEEE; 使用ieee.numeric_std.all;



Answer 3:

既您的样品产生信号,其中的一个切换以缓慢的速度,并且其中的一个以“慢速率”脉冲窄脉冲。 如果这两个信号去其他触发器的时钟输入端,我希望关于时钟警告路由是最优的。

我不知道为什么你得到一个门控时钟的警告,这通常是当你做一下:

gated_clock <= clock when en = '1' else '0';


Answer 4:

下面是一个完整的示例代码:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY Test123 IS

    GENERIC (
        clk_1_freq_generic : unsigned(31 DOWNTO 0) := to_unsigned(0, 32); -- Presented in Hz
        clk_in1_freq_generic : unsigned(31 DOWNTO 0) := to_unsigned(0, 32) -- Presented in Hz, Also
    );

    PORT (
        clk_in1 : IN std_logic := '0';
        rst1 : IN std_logic := '0';
        en1 : IN std_logic := '0';
        clk_1 : OUT std_logic := '0'
    );

END ENTITY Test123;

ARCHITECTURE Test123_Arch OF Test123 IS
    --
    SIGNAL clk_en_en : std_logic := '0';
    SIGNAL clk_en_cntr1 : unsigned(31 DOWNTO 0) := (OTHERS => '0');
    --
    SIGNAL clk_1_buffer : std_logic := '0';
    SIGNAL clk_1_freq : unsigned(31 DOWNTO 0) := (OTHERS => '0'); -- Presented in Hz, Also
    SIGNAL clk_in1_freq : unsigned(31 DOWNTO 0) := (OTHERS => '0'); -- Presented in Hz
    --
    SIGNAL clk_prescaler1 : unsigned(31 DOWNTO 0) := (OTHERS => '0'); -- Presented in Cycles (Relative To The Input Clk.)
    SIGNAL clk_prescaler1_halved : unsigned(31 DOWNTO 0) := (OTHERS => '0');
    --

BEGIN
    clk_en_gen : PROCESS (clk_in1)
    BEGIN
        IF (clk_en_en = '1') THEN

            IF (rising_edge(clk_in1)) THEN
                clk_en_cntr1 <= clk_en_cntr1 + 1;

                IF ((clk_en_cntr1 + 1) = clk_prescaler1_halved) THEN   -- a Register's (F/F) Output Only Updates Upon a Clock-Edge : That's Why This Comparison Is Done This Way !

                    clk_1_buffer <= NOT clk_1_buffer;
                    clk_1 <= clk_1_buffer;
                    clk_en_cntr1 <= (OTHERS => '0');

                END IF;

            END IF;

        ELSIF (clk_en_en = '0') THEN

            clk_1_buffer <= '0';
            clk_1 <= clk_1_buffer;
            clk_en_cntr1 <= (OTHERS => '0'); -- Clear Counter 'clk_en_cntr1'

        END IF;

    END PROCESS;

    update_clk_prescalers : PROCESS (clk_in1_freq, clk_1_freq)
    BEGIN
        clk_prescaler1 <= (OTHERS => '0');
        clk_prescaler1_halved <= (OTHERS => '0');
        clk_en_en <= '0';

        IF ((clk_in1_freq > 0) AND (clk_1_freq > 0)) THEN

            clk_prescaler1 <= (clk_in1_freq / clk_1_freq); -- a Register's (F/F) Output Only Updates Upon a Clock-Edge : That's Why This Assignment Is Done This Way !
            clk_prescaler1_halved <= ((clk_in1_freq / clk_1_freq) / 2); -- (Same Thing Here)

            IF (((clk_in1_freq / clk_1_freq) / 2) > 0) THEN -- (Same Thing Here, Too)
                clk_en_en <= '1';
            END IF;

        ELSE
            NULL;
        END IF;

    END PROCESS;

    clk_1_freq <= clk_1_freq_generic;
    clk_in1_freq <= clk_in1_freq_generic;

END ARCHITECTURE Test123_Arch;


文章来源: VHDL: creating a very slow clock pulse based on a very fast clock
标签: vhdl clock fpga