-------------------------------------------------------------------------------- -- -- File: WrapBufg.vhd -- Author: Robert Atkinson -- Original Project: RF-RIO -- Date: 13 January 2012 -- -------------------------------------------------------------------------------- -- Copyright 2012 Ettus Research, A National Instruments Company -- SPDX-License-Identifier: GPL-3.0 -------------------------------------------------------------------------------- -- -- Purpose: This is a simple wrapper around a BUFG to make instantiating BUFGCTRLs -- easier without a headache to relearn the port usage each time. This -- wrapper only supports a single input clock. When disabled, the BUFG -- output is zero. -- -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; library UNISIM; use UNISIM.vcomponents.all; entity WrapBufg is generic( -- ClkIn is selected by default if set to true, otherwise zero. kEnableByDefault : boolean := false; -- If kIgnore is set to true, then the BUFG will switch inputs whenever -- the aCe signal changes as opposed to waiting for ClkIn to transition low. kIgnore : boolean := false; -- If aCe is asynchronous to ClkIn, set this generic to true and the select -- lines of the BUFGCTRL will be used. If aCe is synchronous to ClkIn, then the CE pins -- will be used - note that this requires that setup and hold times be met! If aCe is -- synchronous to ClkIn but no timing relationship is really needed then set this to true. kEnableIsAsync : boolean := false ); port( -- Input clock ClkIn : in std_logic; -- Enable to the BUFG - this signal is treated either asynchronously -- or synchronously based on the value of the kEnableIsAsync generic. aCe : in std_logic; -- Clock output ClkOut : out std_logic ); end WrapBufg; architecture rtl of WrapBufg is signal iCe0, iCe1, aSel0, aSel1, kIgnore0 : std_logic; begin -- From Data Sheet: -- The BUFGCTRL is designed to switch between two clock inputs without the possibility of a -- glitch. When the presently selected clock transitions from High to Low after S0 and S1 -- changes, the output is kept Low until the other (to-be-selected) clock has transitioned from -- High to Low. Then the new clock starts driving the output. The default configuration for -- BUFGCTRL is falling edge sensitive and held at Low prior to the input switching. -- BUFGCTRL can also be rising edge sensitive and held at High prior to the input switching -- by using the INIT_OUT attribute. -- In some applications the conditions previously described are not desirable. Asserting the -- IGNORE pins will bypass the BUFGCTRL from detecting the conditions for switching -- between two clock inputs. In other words, asserting IGNORE causes the MUX to switch -- the inputs at the instant the select pin changes. IGNORE0 causes the output to switch away -- from the I0 input immediately when the select pin changes, while IGNORE1 causes the -- output to switch away from the I1 input immediately when the select pin changes. -- Selection of an input clock requires a "select" pair (S0 and CE0, or S1 and CE1) to be -- asserted High. If either S or CE is not asserted High, the desired input will not be selected. -- In normal operation, both S and CE pairs (all four select lines) are not expected to be -- asserted High simultaneously. Typically only one pin of a "select" pair is used as a select -- line, while the other pin is tied High. -- If the aCe input is async to the I clock, then use the select pins -- of the BUFGCTRL since setup and hold times at the S* pins do not have -- to be met. Enable both Select pins if the aCe signal is synchronous to the I clock. aSel0 <= aCe when kEnableIsAsync else '1'; aSel1 <= not aCe when kEnableIsAsync else '1'; -- Only use the CE pins when the input aCe signal is synchronous to the I clock. iCe0 <= '1' when kEnableIsAsync else aCe; iCe1 <= '1' when kEnableIsAsync else not aCe; -- No PkgNiUtilities for me. kIgnore0 <= '1' when kIgnore else '0'; --vhook_i BUFGCTRL GlobalBuffer --vhook_a {^IS_(.*)} '0' --vhook_a INIT_OUT 0 --vhook_a PRESELECT_I0 kEnableByDefault --vhook_a PRESELECT_I1 not kEnableByDefault --vhook_a O ClkOut --vhook_a CE0 iCe0 --vhook_a CE1 iCe1 --vhook_a I0 ClkIn --vhook_a I1 '0' --vhook_a IGNORE0 kIgnore0 --vhook_a IGNORE1 '1' --vhook_a S0 aSel0 --vhook_a S1 aSel1 GlobalBuffer: BUFGCTRL generic map ( INIT_OUT => 0, --integer:=0 IS_CE0_INVERTED => '0', --bit:='0' IS_CE1_INVERTED => '0', --bit:='0' IS_I0_INVERTED => '0', --bit:='0' IS_I1_INVERTED => '0', --bit:='0' IS_IGNORE0_INVERTED => '0', --bit:='0' IS_IGNORE1_INVERTED => '0', --bit:='0' IS_S0_INVERTED => '0', --bit:='0' IS_S1_INVERTED => '0', --bit:='0' PRESELECT_I0 => kEnableByDefault, --boolean:=false PRESELECT_I1 => not kEnableByDefault) --boolean:=false port map ( O => ClkOut, --out std_ulogic CE0 => iCe0, --in std_ulogic CE1 => iCe1, --in std_ulogic I0 => ClkIn, --in std_ulogic I1 => '0', --in std_ulogic IGNORE0 => kIgnore0, --in std_ulogic IGNORE1 => '1', --in std_ulogic S0 => aSel0, --in std_ulogic S1 => aSel1); --in std_ulogic --vscan Begin Add Explain Clock --vscan # These are the outputs of the BUFGCTRLs in the WrapBufg module. VScan --vscan # sees the output as glitchy but the clocks are guaranteed to switch --vscan # in a glitchless fashion provided that either setup and hold times --vscan # are met at the CE pins of the BUFGCTRL (these paths are analyzed by the --vscan # tools for timing) or the CE pins are hardwired and the S pins are used --vscan # which require no timing relationship to the input clocks. --vscan *[WrapBufg]GlobalBuffer/[BUFGCTRL]O --vscan End Add Explain Clock -- Check that enable lines match up with the generics of the BUFGCTRL --vscan vscan_off --synthesis translate_off SimProcess: process begin wait for 1 ns; if kEnableIsAsync then assert kEnableByDefault = (aSel0 = '1') report "Initial condition on enable lines do not match between" & LF & "the BUFGCTRL generic and the SEL line" severity error; else assert kEnableByDefault = (iCe0 = '1') report "Initial condition on enable lines do not match between" & LF & "the BUFGCTRL generic and the CE line" severity error; end if; wait; end process SimProcess; --synthesis translate_on --vscan vscan_on end rtl;