ザイリンクスFPGAのVHDLで50MHzを2Hzに分割する方法


13

50MHzの水晶を搭載したザイリンクスFPGAボードがあります。VHDLで2Hzに分割する必要があります。どうすればいいですか?


13
実際に何を試しましたか?
マットヤング

ザイリンクスのクロックマネージャーIPを使用しないのはなぜですか?
アーツヴァンカンス

回答:


19

基本的に、これを行うには2つの方法があります。1つは、ザイリンクスネイティブクロックシンセサイザーコアを使用することです。この利点の1つは、Xlinxツールがクロックをそのように認識し、必要な経路を介してクロックをルーティングすることです。ツールはタイミング制約も処理します(2Hzクロックであるため、この場合は実際には適用されません)

2番目の方法は、カウンターを使用して、低速クロック周期の半分が経過するまで高速クロックパルスの数をカウントすることです。たとえば、あなたの場合、遅いクロックサイクルの1クロック周期を構成する高速クロックパルスの数は50000000/2 = 25000000です。クロック周期の半分が必要なので、各半サイクルで25000000/2 = 12500000です。 。(各高または低の期間)。

VHDLでは次のようになります。

library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.all;

entity scale_clock is
  port (
    clk_50Mhz : in  std_logic;
    rst       : in  std_logic;
    clk_2Hz   : out std_logic);
end scale_clock;

architecture Behavioral of scale_clock is

  signal prescaler : unsigned(23 downto 0);
  signal clk_2Hz_i : std_logic;
begin

  gen_clk : process (clk_50Mhz, rst)
  begin  -- process gen_clk
    if rst = '1' then
      clk_2Hz_i   <= '0';
      prescaler   <= (others => '0');
    elsif rising_edge(clk_50Mhz) then   -- rising clock edge
      if prescaler = X"BEBC20" then     -- 12 500 000 in hex
        prescaler   <= (others => '0');
        clk_2Hz_i   <= not clk_2Hz_i;
      else
        prescaler <= prescaler + "1";
      end if;
    end if;
  end process gen_clk;

clk_2Hz <= clk_2Hz_i;

end Behavioral;

注意事項:

  • 生成されたクロックはリセット中はゼロです。これは一部のアプリケーションでは問題ありませんが、他のアプリケーションでは問題ありません。クロックの必要性に依存します。
  • 生成されたクロックは、ザイリンクス合成ツールによって通常の信号としてルーティングされます。
  • 2Hzは非常に遅いです。1秒のシミュレーションには時間がかかります。少量のコードであるため、1秒間でも比較的迅速にシミュレートする必要がありますが、コードの追加を開始すると、2 Hzのクロックサイクルのシミュレートにかかる時間が非常に長くなる可能性があります。

編集:clk_2Hz_iは、出力信号をバッファリングするために使用されます。VHDLは、出力でもある割り当ての右側の信号を使用することを好みません。


1
悪くない、しかし、あなたは/がそう、整数と符号なしの比較を追加することができますif prescaler = 50_000_000/4 then ...し、prescaler <= prescaler + 1;少し単純になります。
ブライアンドラモンド

@StaceyAnneこれを試すと、「「out」オブジェクトclk_oから読み取れません。「buffer」または「inout」を使用してください」というメッセージが表示されます。
回避

@evading、出力にバッファが必要です。VHDLはclk_2Hz出力であるという事実を嫌いますが、その値はこの行で読み取られていますclk_2Hz <= not clk_2Hz;。修正で編集しました。
スタンリ

+1すばらしい例。しかし、ここに私の無知が示されています(VHDLの新機能)。違いは何であるprescaler <= (others => '0');とはprescaler <= '0';
cbmeeks

NVM!私othersが持っているVHDLの本を読んだときに何が使われていたのか、まったく見逃していました。それは、「... 000000000000000000」などを共通の値にすべての「その他」のビットを宣言する代わりのようなものを使用するためだけのショートカットだ
cbmeeks

9

クロックプリスケーラを使用します。

プリスケーラーの値は(clock_speed / desired_clock_speed)/ 2であるため、(50Mhz(50,000,000)/ 2hz(2))/ 2 = 12,500,000で、バイナリでは101111101011110000100000になります。

もっと簡単に:(50,000,000)/ 2)/ 2 = 12,500,000 バイナリに変換-> 101111101011110000100000

実行するコードは次のとおりです。2hzが必要なものにはnewClockを使用します...

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ClockPrescaler is
    port(
        clock   : in STD_LOGIC; -- 50 Mhz
        Led     : out STD_LOGIC
    );
end ClockPrescaler;

architecture Behavioral of ClockPrescaler is
    -- prescaler should be (clock_speed/desired_clock_speed)/2 because you want a rising edge every period
    signal prescaler: STD_LOGIC_VECTOR(23 downto 0) := "101111101011110000100000"; -- 12,500,000 in binary
    signal prescaler_counter: STD_LOGIC_VECTOR(23 downto 0) := (others => '0');
    signal newClock : std_logic := '0';
begin

    Led <= newClock;

    countClock: process(clock, newClock)
    begin
        if rising_edge(clock) then
            prescaler_counter <= prescaler_counter + 1;
            if(prescaler_counter > prescaler) then
                -- Iterate
                newClock <= not newClock;

                prescaler_counter <= (others => '0');
            end if;
        end if;
    end process;


end Behavioral;

0.5 Hzと1 Hzの2つのクロックを生成しているようです。(クロック周期はプリスケーラ* 2ですか?)。また、slvsを追加しているため、「+」はエラーになります。どのような場合でも、この方法でaddのオーバーフロープロパティを使用するかどうかはわかりません。なぜただ行くのnewClock : std_logic := '0'ではなく、prescaler / 2までカウントして割り当てnewClk <= not newClkますか?
スタンリ

おかげで、私の論理は少しずれていました。最初の投稿をいくつかのテスト済みコードといくつかの提案で更新しました:)
MLM

うーん-それらのすべてとゼロとそれが本当に何であるかを言うためのコメント!コンパイラを使用してそれを行うのはなぜですか?とにかく整数を使用しないのはなぜですか?
マーティントンプソン

私は間違っているかもしれませんが、「:=(others => '0')」のようにアーキテクチャでシグナルを定義するときにデフォルト値を使用することは合成できません。
アーサーズヴァンカンス

合成可能ですが、ザイリンクス、アルテラ、またはラティスからのほとんどのように、基本的にSRAMベースのFPGAでのみ動作します。
ヤンヴェルニエ

8

通常、実際には遅いものをクロックする必要はなく、正しいレートでイネーブルを作成し、それをロジックで使用するだけです。

 if rising_edge(50MHz_clk) and enable = '1' then

次のようにして有効化を作成できます。

process 
   variable count : natural;
begin
   if rising_edge(50MHz_clk) then
       enable <= '0';
       count := count + 1;
       if count = clock_freq/desired_freq then
          enable <= '1';
          count := 0;
       end if;
    end if;
end process;

起動する自己文書化コードを使用して、クロック周波数と必要なイネーブル周波数を使用していくつかの定数を作成します。



0

係数=入力信号周波数/出力プリスケーラ周波数。

CE =クロックイネーブル。使用しない場合は、1クロック(clk)幅のパルスまたはハイにする必要があります。

Q =必要な周波数の1クロック幅パルスの出力信号。

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity prescaler is

  generic (
    FACTOR : integer);

  port (
    clk : in  std_logic;
    rst : in  std_logic;
    CE  : in  std_logic;
    Q   : out std_logic);

end prescaler;

architecture for_prescaler of prescaler is
  signal counter_reg, counter_next : integer range 0 to FACTOR-1;
  signal Q_next: std_logic;
begin  -- for_prescaler

  process (clk, rst)
  begin  -- process
    if rst = '1' then                   -- asynchronous reset (active low)
      counter_reg <= 0;
    elsif clk'event and clk = '1' then  -- rising clock edge
      counter_reg <= counter_next;
    end if;
  end process;

  process (counter_reg, CE)
  begin  -- process
    Q_next <= '0';
     counter_next <= counter_reg;
     if CE = '1' then
        if counter_reg = FACTOR-1  then
          counter_next <= 0;
           Q_next <= '1';
         else
           counter_next <= counter_reg + 1;
        end if;
      end if;
  end process;

  process (clk, rst)
  begin  -- process
    if rst = '1' then                   -- asynchronous reset (active low)
      Q <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
      Q <= Q_next;
    end if;
  end process; 

end for_prescaler;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.