5

VHDL言語を使用して100MHzのベースクロック(デューティサイクル0.5)から78MHzのクロック(デューティサイクル0.5または0.7)を生成する必要があります(比率は200/156です)。DCM、PLLなどを使用できることは知っていますが、現時点では(残念ながら)使用できません。

したがって、(DCMまたはPLLを除く)単純な分周器を使用することを考えましたが、この場合、周波数は整数(および最小2)でのみ分周できることもわかっています。これを行うにはカウンターを使用するためです。私の場合、ベースクロックを1,2820512820512820512820512820513で割る必要があります...)。

したがって、DCMやその他のものを使用せずにそれを実現する方法がわかりません... 100MHzクロックをより小さな周波数(50MHz、25MHzなど)に分割し、それらを追加することを考えました(たとえば、50 + 25 + 3)、しかし、これは正しい方法ですか(論理的にはそうは思いません)?

4

2 に答える 2

5

これは、問題を解決する一般的な分数 M/​​D クロック分周器の設計です。これは数年前に自分用に書いたものです。ターゲットにしているデバイスによっては、bit の代わりに std_logic を使用したい場合があります。

基本的な考え方は、アキュムレータを使用して分数クロック フェーズを追跡することです。これは、ダイレクト デジタル シンセサイザー (DDS) を実装する方法と非常に似ていますが、クロックについてのみ考慮する必要があります。

楽しみ!=)

これを使用する方法が明確でない場合、 のように 39 の乗数と 50 の除数に使用するパラメーター100 * 39/100 = 78なので、必要なオペランド幅は 6 です ( のため2**6 = 64)。これは入力クロック レートの半分以上であるため、同期ロジックは出力クロック信号を生成できないため、このブロックのそのレートでの唯一の有効な出力はクロック イネーブルになることに注意してください。

また、考えられる除数の最悪のケースは、任意の 1 サイクルで 33%/66% のデューティ サイクルであることに注意してください。乗数と除数の特定の選択はより良いかもしれませんが(伝えるには数学を行う必要があります)、合理的な除算を使用するアルゴリズムでは、一般的に最悪の場合よりも良くなることはありません。このブロックの出力を実際のハードウェア PLL または DLL でクリーンアップして、位相ノイズをフィルター処理し、デューティ サイクルを目標範囲に収めることができます。

-- Copyright © 2010 Wesley J. Landaker <wjl@icecavern.net>
-- 
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- 
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
-- 
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

library ieee;
use ieee.numeric_bit.all;

-- Clock Divider
-- =============
--
-- Fractionally divides the input clock using simultaneous frequency
-- multiplication and division.
--
-- Outputs both a clock enable and a balanced duty-cycle clock. The clock's
-- duty-cycle is as always close to 50% as possible, worst case is 33%/66%.
--
-- Details
-- =======
--
-- Given:
--
--   Fi = input frequency Hz
--   M  = multiplier
--   D  = divisor
--   Fo = output frequency Hz
--
-- Where:
--
--   M ≤ D
--
-- Then:
--
--        ⎧    M
--        ⎪ Fi·—        if M <= D
--   Fo = ⎨    D
--        ⎪
--        ⎩ undefined   if M > D
--
--
-- If (M/D) is greater than 0.5, only the clock enable is valid.
-- If (M/D) is greater than 1.0, both outputs are invalid.

entity Clock_Divider is
  generic (
    operand_width : positive
    );
  port (
    clock : in bit;
    reset : in bit;

    multiplier : in unsigned(operand_width-1 downto 0);
    divisor    : in unsigned(operand_width-1 downto 0);

    out_enable : buffer bit;
    out_clock  : buffer bit
    );
end entity;

architecture any of Clock_Divider is
  signal enable_2x : bit;
begin

  -- Divide the clock by accumulating phase using the mulitplier and
  -- subtracting when we pass the divisor value.

  proc_enable : process is
    variable phase : unsigned(operand_width downto 0);
  begin
    wait until rising_edge(clock);
    phase := phase + multiplier;
    if phase >= divisor then
      phase := phase - divisor;
      out_enable <= '1';
    else
      out_enable <= '0';
    end if;
    if reset = '1' then
      phase := (others => '0');
      out_enable <= '0';
    end if;
  end process;

  proc_enable : process is
    variable phase : unsigned(operand_width downto 0);
  begin
    wait until rising_edge(clock);
    phase := phase + (multiplier & '0');
    if phase >= divisor then
      phase := phase - divisor;
      enable_2x <= '1';
    else
      enable_2x <= '0';
    end if;
    if reset = '1' then
      phase := (others => '0');
      enable_2x <= '0';
    end if;
  end process;


  proc_out_clock : process is
  begin
    wait until rising_edge(clock);
    if enable_2x = '1' then
      out_clock <= not out_clock;
    end if;
  end process;

end architecture;
于 2012-11-12T19:47:05.747 に答える
1

完全に壁から外れたアイデアであり、技術固有であるため、目標に合わない可能性があり、非常に恐ろしいです...

(a)PLL、(b)DLL、(c)はるかに高い周波数のクロック、または(d)5nsppのジッターがないとこれを実行できないことは明らかです。

より多くのクロックエッジを使用できるようにする必要がありますが、(仮定すると)クロックエッジがこれ以上ない場合は、独自のクロックエッジを生成する必要があります。技術固有の(ザイリンクス)方法の1つは、クロックをフィードアウトし、それぞれに異なるIBUFDELAY設定を使用して複数のピンを介してバックインすることです。実際の設定は、実験(または電源投入時)によって調整される可能性があり、当然、温度によってドリフトする可能性があります。

もう1つの方法は、LUTのチェーンがクロックを連続的に遅延させ、n番目が半サイクルより長く遅延したことを検出するロジックを使用することです。(またはサイクル全体)次に、タップn / 2は約90度遅れ、n / 4は45度遅れなどです(これらのタイミングの一貫性を保証することはできません。それでも、フロアプランとこのコアのロックダウンはある程度役立ちます。 )。

いずれにせよ、100MHzクロックの複数のフェーズができたら、それらを上記のDDS(分数分周器)に適用できます。パフォーマンスが安定する可能性は低いですが、現在の最高の5nsよりも優れているはずです...

(そして、はい、これはあなた自身の(そして劣った)DLLをローリングすることに等しいことを私は知っています。それは不正行為としてカウントされますか?)

複雑さを軽減するアプローチとして、PeterAlfkeのdelay/ XORトリックを試して、100MHzクロックから200MHzを取得することができます。M / S比の保証はありませんが、4つのエッジで遊ぶことができます...

于 2012-11-13T16:53:14.723 に答える