目次

DCM(Digital Clock Manager)

 XilinxのFPGAには、DCM(Digital Clock Manager)と呼ばれる
 モジュールが含まれています。

 このモジュールを利用するとクロックを任意の周波数まで
 逓倍あるいは分周できます。

 また、位相を変化させる機能もあり、デジタル回路による
 フィルタや周波数シンセサイザを構成する等には重宝します。

 DCMのブロック図は、以下です。



 上のブロック図を初めてみたとき、PLLのブロック図に
 似ているなと思いました。CLKINとCLKFBがあり、2つの
 クロックを比較し出力を確定するのと、CLKFBが出力から
 フィードバックしているので、PLLが頭に浮かびました。

 PLLのブロック図は次のようになっています。



 ブロック図をみると、クロック出力のブロックには
 DLLと記されています。

 DLL(Delayed Lock Loop)は、遅延ロックループとされて
 いるので、PLLに似た機能を持ちます。

 DLLにある次のクロック出力に関して、データシートを
 読んで、内容を理解してみます。

 CLK0、CLK90、CLK180、CLK270は、位相が90度ずつ
 ずれたクロックになります。このときCLKINに入力
 できる周波数は、24MHzから326MHzの限定範囲に
 なります。

 90度ずつ位相がずれたクロックは、6809のE、Qのように
 マイクロコンピュータのバスインタフェースや信号処理
 で複素数を扱いたいときに使えます。

 アマチュア無線で話題になるSDR(Software Defined Radio)を
 実現するときに、よく使われます。

 位相が90度ずつずれたクロックがあると、無線信号から
 I信号、Q信号の正相、逆相を作るのが簡単になります。
 これが複素数の実数部、虚数部にわけて計算する場面で
 役に立ちます。

 クワドラチャミキサと呼ぶ処理は、ブロック図をみると
 90度位相がずれたクロックが必要になることがわかります。



 クワドラチャミキサは、位相のずれたクロックを利用する
 ので、使いたい周波数の4倍の周波数が必要です。

 7MHzの周波数帯域の信号が欲しければ、28MHzのクロックが
 必要になります。28MHzのクロックから、4つの位相を生成
 しなければ、上のブロック図相当の回路は実現できません。

 CLK0、CLK90、CLK180、CLK270の4つの位相差クロックが
 あると、90度ずつ位相をずらす回路は不要になります。
 アナログで90度ずつ位相をずらすのは大変ですが、デジタル
 はアナログに比べて簡単になります。DCMのような回路がある
 と、さらに簡単になります。

 DCMを使う場合、普通は、CLKIN、CLKFBにバッファを入れます。



 Xilinxの開発環境には、3つのモジュールをコンポーネントが
 Language Templateに用意されています。

 DCMを使う場合、この3つのコンポーネントを呼出して
 VHDLコードの中に入れることになります。

 VHDLコード内で、3つのコンポーネントを使うには
 次の指定記述を入れます。

Library UNISIM;
use UNISIM.vcomponents.all;

 上の記述を入れると、VHDLコードではコンポーネントを
 呼出すだけになります。

  -- input clock buffer handling
  IBUFG_inst : IBUFG
    generic map (IOSTANDARD => "DEFAULT")
    port map (
      O => iCLKIN_IBUFG, -- Clock buffer output
      I => CLOCK         -- Clock buffer input
                         -- (connect directly to top-level port)
    );

  -- DCM 
  DCM_inst : DCM
    generic map (
      CLKDV_DIVIDE          => 2.0,    --  Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
                                       --     7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
      CLKFX_DIVIDE          => 24,     --  Can be any integer from 1 to 32
      CLKFX_MULTIPLY        => 2,      --  Can be any integer from 2 to 32
      CLKIN_DIVIDE_BY_2     => TRUE,   --  TRUE/FALSE to enable CLKIN divide by two feature
      CLKIN_PERIOD          => 20.833, --  Specify period of input clock
      CLKOUT_PHASE_SHIFT    => "FIXED",--  Specify phase shift of NONE, FIXED or VARIABLE
      CLK_FEEDBACK          => "1X",   --  Specify clock feedback of NONE, 1X or 2X
      DESKEW_ADJUST         => "SYSTEM_SYNCHRONOUS", 
                                       --  SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
                                       --     an integer from 0 to 15
      DFS_FREQUENCY_MODE    => "LOW",  --  HIGH or LOW frequency mode for frequency synthesis
      DLL_FREQUENCY_MODE    => "LOW",  --  HIGH or LOW frequency mode for DLL
      DUTY_CYCLE_CORRECTION => TRUE,   --  Duty cycle correction, TRUE or FALSE
      FACTORY_JF            => X"C080",--  FACTORY JF Values
      PHASE_SHIFT           => 0,      --  Amount of fixed phase shift from -255 to 255
      SIM_MODE              => "SAFE", --  Simulation: "SAFE" vs "FAST", see "Synthesis and Simulation
                                       --  Design Guide" for details
      STARTUP_WAIT => FALSE)           --  Delay configuration DONE until DCM LOCK, TRUE/FALSE
    port map (
      CLK0     => iCLK0_OUT,    -- 0 degree DCM CLK ouptput
      CLK180   => iCLK180_OUT,  -- 180 degree DCM CLK output
      CLK270   => iCLK270_OUT,  -- 270 degree DCM CLK output
      CLK2X    => open,         -- 2X DCM CLK output
      CLK2X180 => open,         -- 2X, 180 degree DCM CLK out
      CLK90    => iCLK90_OUT,   -- 90 degree DCM CLK output
      CLKDV    => open,         -- Divided DCM CLK out (CLKDV_DIVIDE)
      CLKFX    => open,         -- DCM CLK synthesis out (M/D)
      CLKFX180 => open,         -- 180 degree CLK synthesis out
      LOCKED   => open,         -- DCM LOCK status output
      PSDONE   => open,         -- Dynamic phase adjust done output
      STATUS   => open,         -- 8-bit DCM status bits output
      CLKFB    => iCLKFB_IN,    -- DCM clock feedback
      CLKIN    => iCLKIN_IBUFG, -- Clock input (from IBUFG, BUFG or DCM)
      PSCLK    => '0',          -- Dynamic phase adjust clock input
      PSEN     => '0',          -- Dynamic phase adjust enable input
      PSINCDEC => '0',          -- Dynamic phase adjust increment/decrement
      RST      => '0'           -- DCM asynchronous reset input
    );

  -- output clock buffer handling
  BUFG_inst : BUFG
    port map (
      O => iCLKFB_IN, -- Clock buffer output
      I => iCLK0_OUT  -- Clock buffer input
    );

 DCMを使いこなすには、Core Generatorを使えば、genericで指定
 される内容を、開発環境に用意されているツールで生成できます。

 DCMのブロック図とgenericの指定パラメータの
 対応を理解しておきます。

 CLKIN、CLKFB
  CLKINは、周波数を指定します。
  CLKIN_PERIODに、周期で数値をnsで記述します。
  50MHzでは20nsですが、小数点以下も必要なので、20.0とします。
  CLKINを2分周してDCMに入れることもできます。
  この場合、CLKIN_DIVIDE_BY_2に与える論理値で
  指定します。



  CLKFBは、CLK0かCLK2Xのどちらかしか使えません。
  CLK_FEEDBACKに与える論理値で指定します。



  CLKINは、そのままの周波数か分周1/2にして
  CLKDVに出力できます。
  この指定は、CLKDV_DIVIDEを使います。



  CLKDV_DIVIDEは、指定値が決まっています。
  次のように小数第1位まで指定します。

 CLKFX、CLKFX180
  DFS(Digital Frequency Synthesizer)を使い、PLLのように
  CLKINの周波数から、次の2パラメータで、目的の周波数を
  合成します。

      CLKFX_MULTIPLY
      CLKFX_DIVIDE




    周波数は、次の式で計算できます。

      (CLKFX_MULTIPLY / CLKFX_DIVIDE ) x (CLKINの周波数)

  2つのパラメータには、範囲制限があります。
      CLKFX_MULTIPLY : 整数で2〜32(ステップは1刻み)
      CLKFX_DIVIDE   : 整数で1〜32(ステップは1刻み)

  DFSを使う時、CLKINの周波数は1MHz〜326MHzです。

 PSCLK、PSEN、PSINCDEC
    生成クロックの位相をずらしたいとき、Phase Shifter
  (位相シフター)を利用します。



  PSを使うか使わないかは、CLKOUT_PHASE_SHIFTで指定します。
  NONE、FIXED、VARIABLEのいずれかを設定します。

  実際にPSを動かす場合、使うかどうかの指定は
  PSENに設定する論理値に依存します。

  PSEN <= '1' PSをenable
  PSEN <= '0' PSをdisable

  位相のもとになるクロックが必要なので
  PSCLKに、CLKIN、CLK0、CLK2Xのいずれかを
  接続します。

  ブロック図にあるPSINCDECには、位相をPSCLKの1/256刻みで
  進みか遅れのいずれかに指定します。どちらの方向にずらす
  のかを論理値で与えます。

  PHASE_SHIFTに、-255から+255を設定するとともに
  PSINCDECに方向を表す論理値を設定します。


動作確認

 3つのブロックのうち、DLL、DFSを利用して  モジュール動作を確認してみます。  手元にあるSpartan3の200kゲートボードには  48MHzのクリスタルが実装されているので、  この48MHzを利用して、「逓倍」による100MHz  を生成してみます。  100MHzクロックを生成しても、測定機器なしでは  確認できません。  100MHzでカウンタを動かし、1MHzまで周波数  を下げると、手持ちの周波数カウンタで観測  できます。  次のブロック図を描いて、信号のつながりを  確認してから、VHDLコードに変換します。  作成したVHDLコードは、以下。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; Library UNISIM; use UNISIM.vcomponents.all; entity tdcm is generic ( TOPX : integer := 5 ; XMAX : integer := 24 -- ; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLK0_OUT : out std_logic ; CLK90_OUT : out std_logic ; CLK180_OUT : out std_logic ; CLK270_OUT : out std_logic ; CLKIN_IBUFG_OUT : out std_logic ; -- COUT : out std_logic ; COUTEX : out std_logic ; SOUT : out std_logic -- ; ) ; end tdcm; architecture Behavioral of tdcm is signal iCLKIN_IBUFG : std_logic ; signal iCLKFB_IN : std_logic ; signal iCLK0_OUT : std_logic ; signal iCLK90_OUT : std_logic ; signal iCLK180_OUT : std_logic ; signal iCLK270_OUT : std_logic ; signal iCLK90_BUF : std_logic ; signal iCLK180_BUF : std_logic ; signal iCLK270_BUF : std_logic ; signal iCLKFX : std_logic ; signal iCLKFX_OUT : std_logic ; signal iCNTX : integer range 0 to 99 ; -- component clock generator component clkgenx is generic ( TOPX : integer ; RMAX : integer --; ); port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- output CLKOUT : out std_logic -- ; ); end component ; signal iSCLK : std_logic ; signal iCNTX90 : integer range 0 to 99 ; begin -- component clock generator (48MHz/48 = 1MHz) CLKX : clkgenx generic map (TOPX,XMAX) port map (nRESET,iCLKIN_IBUFG,iSCLK); -- input clock buffer handling IBUFG_inst : IBUFG generic map (IOSTANDARD => "DEFAULT") port map ( O => iCLKIN_IBUFG, -- Clock buffer output I => CLOCK -- Clock buffer input (connect directly to top-level port) ); -- output clock buffer handling BUFG_inst : BUFG port map ( O => iCLKFB_IN, -- Clock buffer output I => iCLK0_OUT -- Clock buffer input ); -- output clock buffer handling BUFG_instX : BUFG port map ( O => iCLKFX_OUT , -- Clock buffer output I => iCLKFX -- Clock buffer input ); -- DCM DCM_inst : DCM generic map ( CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5 -- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 CLKFX_DIVIDE => 12, -- Can be any integer from 1 to 32 CLKFX_MULTIPLY => 25, -- Can be any integer from 2 to 32 CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature CLKIN_PERIOD => 20.833, -- Specify period of input clock CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift of NONE, FIXED or VARIABLE CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE, 1X or 2X DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or -- an integer from 0 to 15 DFS_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for frequency synthesis DLL_FREQUENCY_MODE => "LOW", -- HIGH or LOW frequency mode for DLL DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE FACTORY_JF => X"C080", -- FACTORY JF Values PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 255 SIM_MODE => "SAFE", -- Simulation: "SAFE" vs "FAST", see "Synthesis and Simulation -- Design Guide" for details STARTUP_WAIT => FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE port map ( CLK0 => iCLK0_OUT, -- 0 degree DCM CLK ouptput CLK180 => iCLK180_OUT, -- 180 degree DCM CLK output CLK270 => iCLK270_OUT, -- 270 degree DCM CLK output CLK2X => open, -- 2X DCM CLK output CLK2X180 => open, -- 2X, 180 degree DCM CLK out CLK90 => iCLK90_OUT, -- 90 degree DCM CLK output CLKDV => open, -- Divided DCM CLK out (CLKDV_DIVIDE) CLKFX => iCLKFX, -- DCM CLK synthesis out (M/D) CLKFX180 => open, -- 180 degree CLK synthesis out LOCKED => open, -- DCM LOCK status output PSDONE => open, -- Dynamic phase adjust done output STATUS => open, -- 8-bit DCM status bits output CLKFB => iCLKFB_IN, -- DCM clock feedback CLKIN => iCLKIN_IBUFG, -- Clock input (from IBUFG, BUFG or DCM) PSCLK => '0', -- Dynamic phase adjust clock input PSEN => '0', -- Dynamic phase adjust enable input PSINCDEC => '0', -- Dynamic phase adjust increment/decrement RST => '0' -- DCM asynchronous reset input ); -- check iSCLK about 1MHz -- COUTEX = 10kHz process (nRESET,iSCLK) begin if ( nRESET = '0' ) then iCNTX90 <= 0 ; elsif rising_edge(iSCLK) then if ( iCNTX90 = 99 ) then iCNTX90 <= 0 ; else iCNTX90 <= iCNTX90 + 1 ; end if ; end if ; end process ; SOUT <= not iSCLK ; COUTEX <= '1' when ( iCNTX90 = 0 ) else '0' ; -- check DFS -- CLKIN = 48MHz -- CLKFX_MULTIPLY = 25 , CLKFX_DIVIDE = 12 -- CLKFX_OUT = 48 * (25 / 12) = 100 MHz process (nRESET,iCLKFX_OUT) begin if ( nRESET = '0' ) then iCNTX <= 0 ; elsif rising_edge(iCLKFX_OUT) then if ( iCNTX = 99 ) then iCNTX <= 0 ; else iCNTX <= iCNTX + 1 ; end if ; end if ; end process ; COUT <= '1' when ( iCNTX = 0 ) else '0' ; -- output CLKIN_IBUFG_OUT <= not iCLKIN_IBUFG ; iCLK90_BUF <= iCLK90_OUT ; iCLK180_BUF <= iCLK180_OUT ; iCLK270_BUF <= iCLK270_OUT ; CLK0_OUT <= not iCLKFB_IN ; CLK90_OUT <= not iCLK90_BUF ; CLK180_OUT <= not iCLK180_BUF ; CLK270_OUT <= not iCLK270_BUF ; end Behavioral;  CLK0_OUT、CLK90_OUT、CLK180_OUT、CLK270_OUTの4信号は  48MHzですが、手持ちのマルチメータでは測定できません。  後日、CLKIN_DIVIDE_BY_2をTRUEにし24MHzが出力されること  を確認できました。また、オシロスコープで波形を表示させ  90度の位相差を持つことも確認しました。  COUTは、100MHzを100分周して1MHzが  出力されることで、間接的に100MHz  のクロック生成を確認しています。  測定は、Spartan3の200kゲートの基板を利用し  LED基板を接続して、マルチメータについている  周波数カウンタでクロック周波数を確認。  上のLED基板とFPGAボードを利用。  LEDのアノード、カソードに端子を出しているので  測定機器のプローブを接続できるようにしています。  周波数カウンタは、マルチメータのもつ機能を使いました。  マルチメータは、秋月電子\1000で販売されているP10です。  接続ピンは、次のUCFファイルに記述。 # tdcm user constraint file NET "CLOCK" LOC = "P55" ; NET "nRESET" LOC = "P73" ; # group B1 NET "CLK0_OUT" LOC = "P116" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "CLK90_OUT" LOC = "P113" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "CLK180_OUT" LOC = "P119" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "CLK270_OUT" LOC = "P118" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "CLKIN_IBUFG_OUT" LOC = "P123" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "COUT" LOC = "P122" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "COUTEX" LOC = "P125" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ; NET "SOUT" LOC = "P124" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;


目次 inserted by FC2 system