Following up on John Providenza's question about the DIFF_OUT buffer feature, I've put together a small example which builds a complementary clock input buffer out of two normal IBUFGDS's.
Also for reference, I've copied my original notes about this handy feature of the V2 & S3 families.
Brian
All the V2-ish differential input buffers have a complementary output available, that can be used to create a 180 degree clock without needing a DCM.
These can also be used just to invert a differential input without needing any other logic (or board cuts & jumps).
Look at the DIFFS component in fpga_editor to see what's going on; besides the normal 'phantom' route from the DIFFS to the DIFFM, there's also a route from the DIFFM to a differential receiver in the DIFFS that outputs the complement signal.
I first spotted these when they showed up in early versions of XAPP622 as a hard macro.
Support & tool bugs for these have varied version to version, see Answer Record 21958 for recent problems.
I've banged into various other problems in using them over the years; if I get a chance this weekend, I'll try to dig up some old webcase code showing how to create one out of two normal IBUF{G}DS's as a work around.
These can be used on regular IOB inputs as well as global clock inputs, but you've generally needed to LOC the global input buffer and bufg's to allowed sites to get this to work.
search for ibufgds_diff_out ibufds_diff_out
--
--
-- diff_out buffer example
--
-- shows how to create complementary internal clocks using
-- IBUF{G}DS's with neither a DCM nor local inversion required
--
-- forwards a global clock input to output, output/2
--
-- substitutes two ibuf{g}ds's for ibuf{g}ds_diff_out component;
-- various tool revs have choked when using attributes on those
--
-- intended for V2-ish family members
--
-- !!! example LOC constraints specific to XC3S200-FG256 !!!
--
-- COMPLETELY UNTESTED; SYNTHESIZED WITH 6.3 & EXAMINED IN FPGA_EDITOR
--
-- Input Clocking:
-- this example doesn't use the resulting clock for DDR inputs,
-- but best (or at least easier to analyze) DDR input timing may
-- result when using CLB registers rather than DDR IOB input regs
--
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
library unisim; use unisim.vcomponents.all;
entity diff_out_test is port ( global_clk_in_p : in std_logic; global_clk_in_n : in std_logic;
gclk_out_p : out std_logic; gclk_out_n : out std_logic;
gclk_div2_p : out std_logic; gclk_div2_n : out std_logic
);
end diff_out_test;
architecture arch1 of diff_out_test is
-- -- signals -- signal gclk_iob_p : std_logic; signal gclk_iob_n : std_logic;
signal gclk : std_logic;
signal gclk_p : std_logic; signal gclk_n : std_logic;
signal gclk_out : std_logic; signal gclk_div2 : std_logic;
signal g_toggle : std_logic; signal g_toggle_not : std_logic;
-- -- LOC the components -- attribute LOC : string;
-- -- see Answer Record 17697 for script to find local clock sites -- (complementary clocks are trickier with local routing resources) --
-- -- inputs have an IBUFDS comp in both DIFFM and DIFFS pin sites -- to create the diff_out buffer variant -- attribute LOC of GC1P : label is "D9"; attribute LOC of GC1N : label is "C9";
-- -- outputs need to LOC one OBUFDS to the P pin site -- attribute LOC of FGC1 : label is "E10";
attribute LOC of FGC2 : label is "C12";
-- -- Note : to use one BUFG for IOB DDR logic clocking, -- and another for internal logic clocking, intentionally -- LOC the BUFG's to the sites having the shared routing -- resources to the IBUFGDS ( may produce spurious ISE warning ) -- -- To locate the shared routing resources, see: -- Answer Record 19947 for S3 -- Answer Record 11756 for V2 -- attribute LOC of GCLK_BUFGMUX_LOGIC : label is "BUFGMUX4"; attribute LOC of GCLK_BUFGMUX_P : label is "BUFGMUX5"; attribute LOC of GCLK_BUFGMUX_N : label is "BUFGMUX6";
begin
-- -- global clock input -- two IBUFDS's with input nets swapped -- in place of IBUFGDS_DIFF_OUT -- GC1P : IBUFDS_LVDS_25 port map ( I => global_clk_in_p, IB => global_clk_in_n, O => gclk_iob_p );
GC1N : IBUFDS_LVDS_25 port map ( I => global_clk_in_n, IB => global_clk_in_p, O => gclk_iob_n );
-- -- note that the use of shared routing resources to two -- BUFGMUX's from the same internal clock source requires -- both LOCs and manual selection of the proper I0/I1 input -- ( see comments near LOCs above ) -- GCLK_BUFGMUX_LOGIC : BUFGMUX port map ( S => '1',
I0 => open, I1 => gclk_iob_p,
O => gclk );
GCLK_BUFGMUX_P : BUFGMUX port map ( S => '0',
I0 => gclk_iob_p, I1 => open,
O => gclk_p );
GCLK_BUFGMUX_N : BUFGMUX port map ( S => '0',
I0 => gclk_iob_n, I1 => open,
O => gclk_n );
-- -- clock divider -- gdiv2 : fd port map ( C => gclk, D => g_toggle_not, Q => g_toggle );
g_toggle_not gclk_out,
C0 => gclk_p, C1 => gclk_n,
CE => '1', R => '0', S => '0',
D0 => '1', D1 => '0' );
GCLK_DIV2_FWD : FDDRRSE port map ( Q => gclk_div2,
C0 => gclk_p, C1 => gclk_n,
CE => '1', R => '0', S => '0',
D0 => g_toggle, D1 => g_toggle );
-- -- Output buffers -- FGC1 : OBUFDS_LVDS_25 port map ( I => gclk_out,
O => gclk_out_p, OB => gclk_out_n );
FGC2 : OBUFDS_LVDS_25 port map ( I => gclk_div2,
O => gclk_div2_p, OB => gclk_div2_n );
end arch1;