Example VHDL Code for CLIP Clocks (FPGA Module)

LabVIEW 2018 FPGA Module Help


Edition Date: March 2018
Part Number: 371599P-01
View Product Info

DOWNLOAD (Windows Only)


LabVIEW 2016 FPGA Module Help
LabVIEW 2017 FPGA Module Help
LabVIEW 2018 FPGA Module Help
LabVIEW 2019 FPGA Module Help
LabVIEW 2020 FPGA Module Help

You can use component-level IP (CLIP) clocks in FPGA VIs. The following code is an example of how to derive clocks using Xilinx DCMs inside CLIP and use features such as phase shifting. The code also shows how to lock and reset a DCM and to use a BUFGCE for clocks that might stop.

Tip Tip   If you want to use this code, copy the code to a text file and save the file as ClipGenerateClks.vhd. Then use the Configure Component-Level IP wizard to create the declaration XML file automatically from the ClipGenerateClks.vhd.


-------------------------------------------------------------------------------
--
-- File: ClipGenerateClks.vhd
-- Author: National Instruments Corporation
-- Date: April 2009
--
-------------------------------------------------------------------------------
--
-- Purpose:
--
-- This CLIP component generates clocks using a Xilinx DCM. A 40 Mhz clock is
-- used to derive an 80 Mhz clock, and a phase shifted version of 80Mhz clock
-- that is shifted by 180 degrees.
--
-- This example illustrates to use other Xilinx DCM features
-- such as phase shifting.
--
-- Signal naming convention:
--
-- All asynchronous signals are pre-fixed with a.
-- All Clk40 synchronous signals are pre-fixed with c40.
-- All Clk80FromDcm0 synchronous signals are pre-fixed with c80.
-- All metastable signals are suffixed with _ms.
--
-- Ports:
--
-- aDiagramReset : This is the LabVIEW FPGA asynchronous diagram reset.
--
-- Clk40 : This is the LabVIEW FPGA generated 40 Mhz clock. This
-- clock is stable and free-running only when aDiagramReset
-- is low.
--
-- ClkOut80 : This is an 80 Mhz clock generated from Xilinx DCM.
--
-- ClkOut80P180 : This is an 80 Mhz clock phase shifted by 180 degrees
-- generated by Xilinx DCM.
--
-------------------------------------------------------------------------------

library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity ClipGenerateClks is
  port (
    aDiagramReset : in std_logic;
    Clk40 : in std_logic;
    ClkOut80 : out std_logic;
    ClkOut80P180 : out std_logic
  );
end ClipGenerateClks;

architecture rtl of ClipGenerateClks is

  -- BUFG component declaration
  component BUFG
    port (
       I : in std_logic;
       O : out std_logic);
  end component;

  -- BUFGCE component declaration
  component BUFGCE
    port (
       I : in std_logic;
       CE : in std_logic;
       O : out std_logic);
  end component;

  -- DCM component declaration
  component DCM
    generic (
       CLKIN_PERIOD : real;
       CLK_FEEDBACK : string;
       CLKDV_DIVIDE : real;
       CLKFX_DIVIDE : integer;
       CLKFX_MULTIPLY : integer;
       CLKIN_DIVIDE_BY_2 : boolean;
       CLKOUT_PHASE_SHIFT : string;
       DESKEW_ADJUST : string;
       DFS_FREQUENCY_MODE : string;
       DLL_FREQUENCY_MODE : string;
       DSS_MODE : string;
       DUTY_CYCLE_CORRECTION : Boolean;
       PHASE_SHIFT : integer;
       STARTUP_WAIT : boolean
    );
    port (
       CLKIN, CLKFB, RST, DSSEN, PSINCDEC, PSEN, PSCLK : in std_logic;
       CLK0, CLK90, CLK180, CLK270,
       CLK2X, CLK2X180, CLKDV, CLKFX, CLKFX180 : out std_logic;
       LOCKED : out std_logic;
       STATUS : out std_logic_vector(7 downto 0);
       PSDONE : out std_logic
    );
  end component;

  constant kDcmResetDuration : positive := 3;
  signal c40ResetToDcm0_ms : std_logic := '1';
  signal c40ResetToDcm0 : std_logic_vector(kDcmResetDuration downto 1) := (others => '1');
  signal Clk0FromDcm0, ClkFbToDcm0 : std_logic;
  signal Clk80FromDcm0, Clk80P180FromDcm0, Clk80ThruBufg : std_logic;
  signal aLockedFromDcm0 : std_logic;
  signal c80Locked_ms, c80Locked : std_logic := '0';

begin

  -- Dcm0RstShiftReg ----------------------------------------------------------
  -- This shift register makes sure that when the DCM reset asserts, it
  -- remains asserted for at least three clock cycles of DCM CLKIN. This
  -- is required for correct DCM locking sequence. Refer to the Xilinx FPGA
  -- user guide for more information.
  --
  -- The DCM should be reset when aDiagramReset asserts. This is important
  -- because some LabVIEW FPGA generated clocks (base or derived clocks) may
  -- not be valid when aDiagramReset is asserted. All LabVIEW FPGA clocks
  -- (in this case Clk40) are guaranteed to be stable and free-running
  -- immediately following the de-assertion of aDiagramReset.
  -- However, if externally generated clocks are used to source the DCM, other
  -- reset schemes would have to be used so that the DCM is kept in reset until
  -- the external clock is stable and free-running.
  -----------------------------------------------------------------------------
  Dcm0RstShiftReg : process (aDiagramReset, Clk40)
  begin
    if aDiagramReset = '1' then
       c40ResetToDcm0_ms <= '1';
       c40ResetToDcm0 <= (others => '1');
    elsif rising_edge(Clk40) then
       c40ResetToDcm0_ms <= '0';
       c40ResetToDcm0(1) <= c40ResetToDcm0_ms;
       for i in 1 to kDcmResetDuration-1 loop
           c40ResetToDcm0(i+1) <= c40ResetToDcm0(i);
       end loop;
    end if;
  end process Dcm0RstShiftReg;
  -- DCM0: --------------------------------------------------------------------
  -- This DCM generates a 80 Mhz and a phase shifted version of the 80 Mhz
  -- clock shifted by 180 degrees.
  -----------------------------------------------------------------------------
  DCM0: DCM
    generic map(
       CLKIN_PERIOD => 25.0,
       CLK_FEEDBACK => "1X",
       CLKDV_DIVIDE => 2.0,
       CLKFX_DIVIDE => 1,
       CLKFX_MULTIPLY => 4,
       CLKIN_DIVIDE_BY_2 => FALSE,
       CLKOUT_PHASE_SHIFT => "NONE",
       DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
       DFS_FREQUENCY_MODE => "LOW",
       DLL_FREQUENCY_MODE => "LOW",
       DSS_MODE => "NONE",
       DUTY_CYCLE_CORRECTION => TRUE,
       PHASE_SHIFT => 0,
       STARTUP_WAIT => FALSE
    )
    port map (
       RST => c40ResetToDcm0(kDcmResetDuration),
       CLKIN => Clk40,
       CLKFB => ClkFbToDcm0,
       CLK0 =>Clk0FromDcm0,
       CLK180 =>OPEN,
       CLK270 =>OPEN,
       CLK2X =>Clk80FromDcm0,
       CLK2X180 =>Clk80P180FromDcm0,
       CLK90 =>OPEN,
       CLKDV =>OPEN,
       CLKFX =>OPEN,
       CLKFX180 =>OPEN,
       DSSEN =>'0',
       PSCLK =>'0',
       PSEN =>'0',
       PSINCDEC =>'0',
       LOCKED =>aLockedFromDcm0,
       PSDONE =>OPEN,
       STATUS =>OPEN);
  -- BufgClkFbofDcm0: ---------------------------------------------------------
  -- This BUFG is used to drive the feedback clock input of DCM0.
  -----------------------------------------------------------------------------
  BufgClkFbofDcm0: BUFG
    port map (
       I =>Clk0FromDcm0,
       O =>ClkFbToDcm0);
  -- BufgClk80: ---------------------------------------------------------------
  -- This BUFG is used to drive the clock used by the synchronizer on locked
  -- signal from DCM0.
  -----------------------------------------------------------------------------
  BufgClk80: BUFG
    port map (
       I => Clk80FromDcm0,
       O => Clk80ThruBufg);
  -- DblSyncLocked: -----------------------------------------------------------
  -- This double synchronizer synchronizes the asynchronous locked signal from
  -- DCM0 to the Clk80FromDcm0 clock domain. This signal will be used to drive
  -- the CE pin of the BUFGCE. This is because CE must not change during a short
  -- setup window just prior to the rising clock edge on the BUFGCE input I.
  -- Violating this setup time requirement can result in glitchy output pulse.
  -- Refer to the Xilinx FPGA user guide for more information.
  --
  -- However, when aDiagramReset asserts, c80Locked could violate the setup
  -- time requirement of Clk80FromDcm0, and it could result in a glitchy output
  -- pulse at output O of BUFGCE. This glitch is acceptable because the FPGA VI
  -- will be in an asynchronous reset. However, if this clock is being used for
  -- other circuitry not reset by aDiagramReset, that circuitry should be
  -- disabled before this reset asserts.
  -----------------------------------------------------------------------------
  DblSyncLocked : process (aDiagramReset, Clk80ThruBufg)
  begin
    if aDiagramReset = '1' then
       c80Locked_ms <= '0';
       c80Locked <= '0';
    elsif rising_edge(Clk80ThruBufg) then
       c80Locked_ms <= aLockedFromDcm0;
       c80Locked <= c80Locked_ms;
    end if;
  end process DblSyncLocked;

  -- BufgceClk80: -------------------------------------------------------------
  -- This BUFGCE remains disabled until DCM0 achieves lock. This ensures that
  -- the global clock network is driven only when the 80 Mhz derived clock is
  -- valid and glitch free.
  -----------------------------------------------------------------------------
  BufgceClk80: BUFGCE
    port map (
       I =>Clk80FromDcm0,
       CE =>c80Locked,
       O =>ClkOut80);

  -- BufgceClk80P180: ---------------------------------------------------------
  -- This BUFGCE remains disabled until DCM0 achieves lock. This ensures that
  -- the global clock network is driven only when the phase shifted 80 Mhz
  -- derived clock is valid and glitch free.
  -----------------------------------------------------------------------------
  BufgceClk80P180: BUFGCE
    port map (
       I =>Clk80P180FromDcm0,
       CE =>c80Locked,
       O =>ClkOut80P180);

end rtl;

WAS THIS ARTICLE HELPFUL?

Not Helpful