7

(私はこれを EE に投稿したいと思いますが、VHDL に関する質問がはるかに多いようです...)

背景: Xilinx ISE 14.4 (webpack) で Xilinx Spartan-6LX9 FPGA を使用しています。

今日、恐ろしい「PhysDesignRules:372 - Gated clock」という警告に出くわしました。一般的に、それに関して多くの議論が行われているようです。コンセンサスは、FPGA 上の DCM の 1 つを使用してクロック分周を行うことのようですが...私の DCM は 32 MHz から 4.096 KHz に移行できないようです (ウィザードによると、 32MHz...そして、この低周波数の目的で複数の DCM をチェーンしようとするのはばかげているようです)。

私の現在の設計では、clk_in を使用して指定された値 (15265) までカウントアップし、その値をゼロにリセットして clk_out ビットをトグルします (したがって、50% のデューティ サイクル (FWIW) になります)。それは仕事をし、clk_out の立ち上がりエッジを簡単に使用して、デザインの次の段階を駆動できます。うまく動作しているように見えますが...ゲート付きクロックです(クロックスキューが非常に関連する範囲ではありませんが)。(注: すべてのクロック テストは、指定されたクロックに敏感なプロセスで、rising_edge() 関数を使用して実行されます。)

だから、私の質問:

  • はるかに高速な clk_in から比較的低速な clk_out を導出することについて話している場合、ゲーティングは依然として悪いと見なされますか? または、この種の「x までカウントしてパルスを送信する」ことは、FPGAが KHz 範囲で「クロック」を生成するのに非常に一般的であり、代わりに他の不要な副作用がこの警告をトリガーしている可能性がありますか?

  • ここで複数の DCM を使用するのはやり過ぎのように見えることを念頭に置いて、MHz 範囲のマスター クロックから低 KHz 範囲のクロックを作成するより良い方法はありますか (出力周波数が非常に低い場合に可能であれば)。50% のデューティ サイクルは不必要かもしれませんが、オンボード DCM を使用せずにクロックを 1 つ入力すると仮定すると、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%のデューティサイクルはもともと興味深いものでしたが、最終的には要件ではありませんでした。「ローカル」クロックビットのトグルは非常に巧妙に見えました時間...) 私はほとんど正しい軌道に乗っていたようです。

この時点ではっきりしないのは、カウンター (多くのビットを格納する) を使用しても警告が発生しない理由ですが、格納されてトグルされた出力ビットでは警告発生する理由です。考え?

4

4 に答える 4

11

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 内部でより多くのクロック ラインを使用するため、ゲーテッド クロックが多数ある場合は、使用可能なすべてのラインをすぐに使い果たしてしまう可能性があります。

クロック イネーブルには、これらの欠点はありません。すべてが同じクロック ドメインで (速度は異なりますが) 実行されるため、シンクロナイザーなどを使用せずに同じ信号を簡単に使用できます。

于 2013-03-06T10:50:55.623 に答える
3

この例がこの行を機能させることに注意してください。

信号 clk_enable_counter : std_logic_vector(9 downto 0);

に変更する必要があります

信号 clk_enable_counter : unsigned(9 から 0);

このライブラリを含める必要があります

ライブラリieee; ieee.numeric_std.all を使用します。

于 2014-08-20T17:49:32.170 に答える
0

両方のサンプルが信号を作成し、そのうちの 1 つは低速でトグルし、もう 1 つは「低速」で狭いパルスをパルスします。これらの信号が両方とも他のフリップフロップのクロック入力に送られる場合、クロック配線が最適ではないという警告が表示されると思います。

ゲーテッドクロックの警告が表示される理由はわかりません。通常、次の場合に発生します。

gated_clock <= clock when en = '1' else '0';
于 2013-03-07T09:57:19.983 に答える
-2

完全なサンプル コードは次のとおりです。

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;
于 2017-07-04T00:21:33.857 に答える