FC2カウンター FPGAの部屋 DCMカスケード接続の罠(CLKDV編)2(解決編)
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

DCMカスケード接続の罠(CLKDV編)2(解決編)

DCMカスケード接続の罠(CLKDV編)”で、DCMをカスケードする場合に1番目のDCMのLOCKED信号を反転して3クロック遅延して、2番目のDCMのリセットに入れる必要があることを学んだ。しかし、そのVHDLコードを書いて置かなかったので、備忘録として書いておく。(シミュレータはISE13.1のISim、FPGAはVirtex-5, xc5vlx110t-1ff1136使用)

最初に参考資料を示しておく。
1.”Virtex-II/-II Pro/-4/-5、Spartan-3/-3E/-3A/-3ADSP - 2 つの DCM を直列にカスケード接続する場合のルール
2.Virtex-4については、”Virtex-4 FPGA User Guide UG070 (v2.6) December 1, 2008”75ページ、Figure 2-5: Cascading DCMs

DCMモジュールのVHDLソースから示す。100MHzクロックをDCMで1/4倍(clkdv使用)して、2番目のDCMに入力し、25MHzの0度クロックと90度クロックを生成する。

-- DCM module

library ieee;
use ieee.std_logic_1164.all;
-- pragma translate_off
library unisim;
use unisim.vcomponents.all;
-- pragma translate_on
library work;

entity dcm_inst is
    port (
        clkin : in std_logic;
        reset : in std_logic;
        clkout : out std_logic;
        clk90 : out std_logic;
        locked : out std_logic
    );
end dcm_inst;

architecture RTL of dcm_inst is
component DCM
  generic (
     CLKDV_DIVIDE : real := 2.0;
     CLKFX_DIVIDE : integer := 1;
     CLKFX_MULTIPLY : integer := 4;
     CLKIN_DIVIDE_BY_2 : boolean := false;
     CLKIN_PERIOD : real := 10.0;
     CLKOUT_PHASE_SHIFT : string := "NONE";
     CLK_FEEDBACK : string := "1X";
     DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS";
     DFS_FREQUENCY_MODE : string := "LOW";
     DLL_FREQUENCY_MODE : string := "LOW";
     DSS_MODE : string := "NONE";
     DUTY_CYCLE_CORRECTION : boolean := true;
     FACTORY_JF : bit_vector := X"C080";
     PHASE_SHIFT : integer := 0;
     SIM_MODE : string := "SAFE";
     STARTUP_WAIT : boolean := false
  );
    port ( CLKIN     : in  std_logic;
           CLKFB     : in  std_logic;
           DSSEN     : in  std_logic;
           PSINCDEC  : in  std_logic;
           PSEN      : in  std_logic;
           PSCLK     : in  std_logic;
           RST       : in  std_logic;
           CLK0      : out std_logic;
           CLK90     : out std_logic;
           CLK180    : out std_logic;
           CLK270    : out std_logic;
           CLK2X     : out std_logic;
           CLK2X180  : out std_logic;
           CLKDV     : out std_logic;
           CLKFX     : out std_logic;
           CLKFX180  : out std_logic;
           LOCKED    : out std_logic;
           PSDONE    : out std_logic;
           STATUS    : out std_logic_vector(7 downto 0)
          );
end component;
component BUFG 
  port (
    I   : in std_logic;
    O    : out std_logic
    ); 
end component;
component IBUFG 
  port (
    I   : in std_logic;
    O    : out std_logic
    ); 
end component;

signal clk_ibuf : std_logic;
signal clkfb : std_logic;
signal gnd, clk_node : std_logic;
signal clkdv_node, clkdv_bufg : std_logic;
signal clk_node2, clk90_node : std_logic;
signal clk90_bufg, clk_bufg : std_logic;
signal dcm1_locked : std_logic;
signal dcm2_reset : std_logic;
begin
    gnd <= '0';
    
    ibufg_inst : ibufg port map(
        i => clkin,
        o => clk_ibuf
    );
    
    dcm1 : dcm generic map(
        CLKFX_DIVIDE => 4,
        CLKFX_MULTIPLY => 1,
        CLKDV_DIVIDE => 4.0
    )port map(
        clkin => clk_ibuf,
        clkfb => clkfb,
        dssen => gnd,
        psincdec => gnd,
        psen => gnd,
        psclk => clk_ibuf,
        rst => reset,
        clk0 => clk_node,
        clk90 => open,
        clk180 => open,
        clk270 => open,
        clk2x => open,
        clk2x180 => open,
        clkdv => clkdv_node,
        clkfx => open,
        clkfx180 => open,
        locked => dcm1_locked,
        psdone => open,
        status => open
    );
    
    bufg_inst : bufg port map(
        i => clk_node,
        o => clkfb
    );
--    clkout <= clkfb;
    
    bufg_clkdv : bufg port map(
        i => clkdv_node,
        o => clkdv_bufg
    );
    dcm2_reset <= not dcm1_locked;
    
    dcm2 : dcm generic map(
        CLKDV_DIVIDE => 4.0
    )port map(
        clkin => clkdv_bufg,
        clkfb => clk_bufg,
        dssen => gnd,
        psincdec => gnd,
        psen => gnd,
        psclk => clk_ibuf,
        rst => dcm2_reset,
        clk0 => clk_node2,
        clk90 => clk90_node,
        clk180 => open,
        clk270 => open,
        clk2x => open,
        clk2x180 => open,
        clkdv => open,
        clkfx => open,
        clkfx180 => open,
        locked => locked,
        psdone => open,
        status => open
    );
    bufg_clk0_2 : bufg port map(
        i => clk_node2,
        o => clk_bufg
    );
    bufg_clk90 : bufg port map(
        i => clk90_node,
        o => clk90_bufg
    );
    
    clkout <= clk_bufg;
    clk90 <= clk90_bufg;
        
end RTL;


dcm1のリセットを反転して、dcm2のrst端子に入れてシミュレーションすると、下のようにdcm2のLOCKED信号が不定になってしまう。
Cascading_DCMs_110415.png


次に、SRL16プリミティブを使用して3クロック遅延させる。”Spartan-3デバイスでのシフト レジスタ(SRL 16)としてのルックアップテーブルの使用”参照。

(2011/04/23:修正)
3クロック遅延させるためには、A0=1, A1=1, A2=0, A3=0 とすれば良い基本的には3クロックだが、その下の修正コードでは、元のクロックにSRL16Eのクロックを接続しているので、4分周*3クロック=12クロック遅延させる。A0=0, A1=0, A2=1, A3=1。(下記にVirtex-5 ライブラリ ガイド (HDL 用)UG621 (v13.1) 2011 年 3 月 1 日の371ページから引用したSRL16Eのインスタンス例を示す)

SRL16E_inst : SRL16E
generic map (
 INIT => X"0000")
port map (
 Q => Q, -- SRL data output
 A0 => A0, -- Select[0] input
 A1 => A1, -- Select[1] input
 A2 => A2, -- Select[2] input
 A3 => A3, -- Select[3] input
 CE => CE, -- Clock enable input
 CLK => CLK, -- Clock input
 D => D -- SRL data input
);


これを参考に、上のVHDLコードを修正した。VHDLを下に示す。

-- DCM module

library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
library work;

entity dcm_inst is
    port (
        clkin : in std_logic;
        reset : in std_logic;
        clkout : out std_logic;
        clk90 : out std_logic;
        locked : out std_logic
    );
end dcm_inst;

architecture RTL of dcm_inst is
component DCM
  generic (
     CLKDV_DIVIDE : real := 2.0;
     CLKFX_DIVIDE : integer := 2;
     CLKFX_MULTIPLY : integer := 4;
     CLKIN_DIVIDE_BY_2 : boolean := false;
     CLKIN_PERIOD : real := 10.0;
     CLKOUT_PHASE_SHIFT : string := "NONE";
     CLK_FEEDBACK : string := "1X";
     DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS";
     DFS_FREQUENCY_MODE : string := "LOW";
     DLL_FREQUENCY_MODE : string := "LOW";
     DSS_MODE : string := "NONE";
     DUTY_CYCLE_CORRECTION : boolean := true;
     FACTORY_JF : bit_vector := X"C080";
     PHASE_SHIFT : integer := 0;
     SIM_MODE : string := "SAFE";
     STARTUP_WAIT : boolean := false
  );
    port ( CLKIN     : in  std_logic;
           CLKFB     : in  std_logic;
           DSSEN     : in  std_logic;
           PSINCDEC  : in  std_logic;
           PSEN      : in  std_logic;
           PSCLK     : in  std_logic;
           RST       : in  std_logic;
           CLK0      : out std_logic;
           CLK90     : out std_logic;
           CLK180    : out std_logic;
           CLK270    : out std_logic;
           CLK2X     : out std_logic;
           CLK2X180  : out std_logic;
           CLKDV     : out std_logic;
           CLKFX     : out std_logic;
           CLKFX180  : out std_logic;
           LOCKED    : out std_logic;
           PSDONE    : out std_logic;
           STATUS    : out std_logic_vector(7 downto 0)
          );
end component;
component BUFG 
  port (
    I   : in std_logic;
    O    : out std_logic
    ); 
end component;
component IBUFG 
  port (
    I   : in std_logic;
    O    : out std_logic
    ); 
end component;

signal clk_ibuf : std_logic;
signal clkfb : std_logic;
signal gnd, clk_node : std_logic;
signal clkdv_node, clkdv_bufg : std_logic;
signal clk_node2, clk90_node : std_logic;
signal clk90_bufg, clk_bufg : std_logic;
signal dcm1_locked : std_logic;
signal dcm2_reset : std_logic;
signal dcm2_reset_SRL16E : std_logic;
begin
    gnd <= '0';
    
    ibufg_inst : ibufg port map(
        i => clkin,
        o => clk_ibuf
    );
    
    dcm1 : dcm generic map(
        CLKFX_DIVIDE => 8,
        CLKFX_MULTIPLY => 2,
        CLKDV_DIVIDE => 4.0
    )port map(
        clkin => clk_ibuf,
        clkfb => clkfb,
        dssen => gnd,
        psincdec => gnd,
        psen => gnd,
        psclk => clk_ibuf,
        rst => reset,
        clk0 => clk_node,
        clk90 => open,
        clk180 => open,
        clk270 => open,
        clk2x => open,
        clk2x180 => open,
        clkdv => clkdv_node,
        clkfx => open,
        clkfx180 => open,
        locked => dcm1_locked,
        psdone => open,
        status => open
    );
    
    bufg_inst : bufg port map(
        i => clk_node,
        o => clkfb
    );
--    clkout <= clkfb;
    
    bufg_clkdv : bufg port map(
        i => clkdv_node,
        o => clkdv_bufg
    );
    dcm2_reset <= not dcm1_locked;
    
    SRL16E_inst : SRL16E generic map(
        INIT => X"FFFF")
    port map(
        Q => dcm2_reset_SRL16E,
        A0 => '0',
        A1 => '0',
        A2 => '1',
        A3 => '1',
        CE => '1',
        CLK => clk_ibuf,
        D => dcm2_reset
    );
    
    dcm2 : dcm generic map(
        CLKDV_DIVIDE => 4.0
    )port map(
        clkin => clkdv_bufg,
        clkfb => clk_bufg,
        dssen => gnd,
        psincdec => gnd,
        psen => gnd,
        psclk => clk_ibuf,
        rst => dcm2_reset_SRL16E,
        clk0 => clk_node2,
        clk90 => clk90_node,
        clk180 => open,
        clk270 => open,
        clk2x => open,
        clk2x180 => open,
        clkdv => open,
        clkfx => open,
        clkfx180 => open,
        locked => locked,
        psdone => open,
        status => open
    );
    bufg_clk0_2 : bufg port map(
        i => clk_node2,
        o => clk_bufg
    );
    bufg_clk90 : bufg port map(
        i => clk90_node,
        o => clk90_bufg
    );
    
    clkout <= clk_bufg;
    clk90 <= clk90_bufg;
        
end RTL;


修正後シミュレーション結果を下に示す。
Cascading_DCMs_2_110415.png

lockedも'X'状態にならないで、正常に'1'になった。
これで問題は解決した。

(注)
SRL16Eプリミティブを使用していると、インプリメント時にunisimをuseする必要があった。

library unisim;
use unisim.vcomponents.all;

  1. 2011年04月15日 14:02 |
  2. FPGAチップ内の配線方法
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/1779-c97ef535
この記事にトラックバックする(FC2ブログユーザー)