Commit 820b073a authored by Dimitris Lampridis's avatar Dimitris Lampridis

hdl: add option to select between 2xBUFIO2 or PLL+BUFPLL for the ADC serdes.

The new scheme (2x BUFIO2) is causing some routing troubles on the SVEC when WR is also present, so
we provide a generic that allows to use the previous clocking scheme as well.
parent 49800b98
......@@ -33,7 +33,17 @@ library unisim;
use unisim.vcomponents.all;
entity ltc2174_2l16b_receiver is
generic (
-- There are two topologies available for the generation of the IO clock.
-- One is based on a BUFIO2+PLL+BUFPLL to generate a double frequency
-- (800MHz) IO clock which is fed to the SERDES in SDR. This is the default
-- (g_USE_PLL=TRUE). The other one uses two BUFIO2 to generate two 400MHz
-- clocks in 180 phase, which are fed to the SERDES in DDR. The second
-- option saves one PLL, which can be very helpful when dealing with FPGAs
-- with limited number of available PLLs, but it can be unroutable in some
-- corner cases. This is why the dual BUFIO2 solution is not the default
-- option.
g_USE_PLL : boolean := TRUE);
port (
-- ADC data clock
adc_dco_p_i : in std_logic;
......@@ -71,7 +81,7 @@ architecture arch of ltc2174_2l16b_receiver is
signal adc_outb : std_logic_vector(3 downto 0);
signal clk_serdes_p : std_logic;
signal clk_serdes_n : std_logic;
signal clk_div : std_logic;
signal bufpll_locked : std_logic;
signal clk_div_buf : std_logic;
signal serdes_strobe : std_logic := '0';
signal serdes_auto_bslip : std_logic := '0';
......@@ -87,6 +97,18 @@ architecture arch of ltc2174_2l16b_receiver is
type serdes_array is array (0 to 8) of std_logic_vector(7 downto 0);
signal serdes_parallel_out : serdes_array := (others => (others => '0'));
-- used to select the data rate of the ISERDES blocks
function f_data_rate_sel (
constant SDR : boolean)
return string is
begin
if SDR = TRUE then
return "SDR";
else
return "DDR";
end if;
end function f_data_rate_sel;
begin -- architecture arch
------------------------------------------------------------------------------
......@@ -94,7 +116,7 @@ begin -- architecture arch
------------------------------------------------------------------------------
-- ADC data clock
cmp_adc_dco_buf : IBUFDS
cmp_adc_dco_buf : IBUFGDS
generic map (
DIFF_TERM => TRUE,
IBUF_LOW_PWR => TRUE,
......@@ -142,37 +164,127 @@ begin -- architecture arch
------------------------------------------------------------------------------
-- Clock generation for deserializer
--
-- We use the scheme proposed in UG382, v1.10, page 32, Figure 1-15
-- We use two of the schemes proposed in XAPP1064, v1.2
------------------------------------------------------------------------------
cmp_dco_bufio_p : BUFIO2
generic map (
DIVIDE => 4,
DIVIDE_BYPASS => FALSE,
I_INVERT => FALSE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
IOCLK => clk_serdes_p,
DIVCLK => clk_div,
SERDESSTROBE => serdes_strobe);
-- XAPP1064, v1.2, page 4, figure 5, without calibration
gen_pll_bufpll : if g_USE_PLL = TRUE generate
cmp_dco_bufio_n : BUFIO2
generic map (
DIVIDE => 4,
DIVIDE_BYPASS => FALSE,
I_INVERT => TRUE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
IOCLK => clk_serdes_n,
DIVCLK => open,
SERDESSTROBE => open);
-- some signals for local interconnect,
-- not used outside of this if-gen
signal l_pll_clkin : std_logic;
signal l_pll_clkfbin : std_logic;
signal l_pll_locked : std_logic;
signal l_pll_clkout0 : std_logic;
signal l_pll_clkout1 : std_logic;
cmp_clk_div_buf : BUFG
port map (
I => clk_div,
O => clk_div_buf);
begin
-- Use the DIVCLK output which is connected to I when
-- DIVIDE_BYPASS=TRUE and which can be connected to a
-- PLL_BASE (as opposed to the IOCLK output which cannot).
cmp_dco_bufio : BUFIO2
generic map (
DIVIDE => 1,
DIVIDE_BYPASS => TRUE,
I_INVERT => FALSE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
IOCLK => open,
DIVCLK => l_pll_clkin,
SERDESSTROBE => open);
BUFIO2FB_inst : BUFIO2FB
generic map (
-- Should match the BUFIO2 setting
DIVIDE_BYPASS => TRUE)
port map (
O => l_pll_clkfbin,
I => clk_serdes_p);
cmp_dco_pll : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => 2,
CLKIN_PERIOD => 2.5,
CLKOUT0_DIVIDE => 1,
CLKOUT1_DIVIDE => 8,
CLK_FEEDBACK => "CLKOUT0",
COMPENSATION => "SOURCE_SYNCHRONOUS",
DIVCLK_DIVIDE => 1,
REF_JITTER => 0.01)
port map (
CLKOUT0 => l_pll_clkout0,
CLKOUT1 => l_pll_clkout1,
LOCKED => l_pll_locked,
CLKFBIN => l_pll_clkfbin,
CLKIN => l_pll_clkin,
RST => '0');
cmp_clk_div_buf : BUFG
port map (
I => l_pll_clkout1,
O => clk_div_buf);
cmp_dco_bufpll : BUFPLL
generic map (
DIVIDE => 8)
port map (
IOCLK => clk_serdes_p,
LOCK => bufpll_locked,
SERDESSTROBE => serdes_strobe,
GCLK => clk_div_buf,
LOCKED => l_pll_locked,
PLLIN => l_pll_clkout0);
-- not used in this case
clk_serdes_n <= '0';
end generate gen_pll_bufpll;
-- XAPP1064, v1.2, page 5, figure 6, without calibration
gen_dual_bufio2 : if g_USE_PLL = FALSE generate
-- some signals for local interconnect,
-- not used outside of this if-gen
signal l_clk_div : std_logic;
begin
cmp_dco_bufio_p : BUFIO2
generic map (
DIVIDE => 8,
DIVIDE_BYPASS => FALSE,
I_INVERT => FALSE,
USE_DOUBLER => TRUE)
port map (
I => adc_dco,
IOCLK => clk_serdes_p,
DIVCLK => l_clk_div,
SERDESSTROBE => serdes_strobe);
cmp_dco_bufio_n : BUFIO2
generic map (
DIVIDE => 8,
DIVIDE_BYPASS => FALSE,
I_INVERT => TRUE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
IOCLK => clk_serdes_n,
DIVCLK => open,
SERDESSTROBE => open);
cmp_clk_div_buf : BUFG
port map (
I => l_clk_div,
O => clk_div_buf);
-- not used in this case
bufpll_locked <= '1';
end generate gen_dual_bufio2;
-- drive out the divided clock, to be used by the FPGA logic
adc_clk_o <= clk_div_buf;
......@@ -189,7 +301,7 @@ begin -- architecture arch
-- Generate bitslip and synced signal
if(bitslip_sreg(bitslip_sreg'LEFT) = '1') then
-- use fr_n pattern (fr_p and fr_n are swapped on the adc mezzanine)
-- use fr_n pattern (fr_p and fr_n are swapped on the adc mezzanine)
if(serdes_out_fr /= "00001111") then
serdes_auto_bslip <= '1';
serdes_synced <= '0';
......@@ -204,7 +316,7 @@ begin -- architecture arch
end process p_auto_bitslip;
serdes_bitslip <= serdes_auto_bslip or serdes_bslip_i;
serdes_synced_o <= serdes_synced;
serdes_synced_o <= serdes_synced and bufpll_locked;
------------------------------------------------------------------------------
-- Data deserializer
......@@ -212,7 +324,6 @@ begin -- architecture arch
-- For the ISERDES, we use the template proposed in UG615, v14.7, pages
-- 138-139. Since DATA_WIDTH parameter is greater than four, we need two
-- ISERDES2 blocks, cascaded.
------------------------------------------------------------------------------
-- serdes inputs forming
......@@ -227,7 +338,7 @@ begin -- architecture arch
cmp_adc_iserdes_master : ISERDES2
generic map (
BITSLIP_ENABLE => TRUE,
DATA_RATE => "DDR",
DATA_RATE => f_data_rate_sel(g_USE_PLL),
DATA_WIDTH => 8,
INTERFACE_TYPE => "RETIMED",
SERDES_MODE => "MASTER")
......@@ -256,7 +367,7 @@ begin -- architecture arch
cmp_adc_iserdes_slave : ISERDES2
generic map (
BITSLIP_ENABLE => TRUE,
DATA_RATE => "DDR",
DATA_RATE => f_data_rate_sel(g_USE_PLL),
DATA_WIDTH => 8,
INTERFACE_TYPE => "RETIMED",
SERDES_MODE => "SLAVE")
......
......@@ -42,6 +42,8 @@ use work.fmc_adc_100Ms_csr_wbgen2_pkg.all;
entity fmc_adc_100Ms_core is
generic (
g_MULTISHOT_RAM_SIZE : natural := 2048;
-- Only used on Xilinx Spartan6 FPGAs
g_SPARTAN6_USE_PLL : boolean := TRUE;
g_WB_CSR_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_CSR_GRANULARITY : t_wishbone_address_granularity := BYTE);
port (
......@@ -436,7 +438,9 @@ begin
-- ADC SerDes
------------------------------------------------------------------------------
cmp_adc_serdes : entity work.ltc2174_2l16b_receiver
cmp_adc_serdes : entity work.ltc2174_2l16b_receiver
generic map (
g_USE_PLL => g_SPARTAN6_USE_PLL)
port map (
adc_dco_p_i => adc_dco_p_i,
adc_dco_n_i => adc_dco_n_i,
......
......@@ -51,6 +51,8 @@ package fmc_adc_100Ms_core_pkg is
component fmc_adc_100Ms_core
generic (
g_MULTISHOT_RAM_SIZE : natural := 2048;
-- Only used on Xilinx Spartan6 FPGAs
g_SPARTAN6_USE_PLL : boolean := TRUE;
g_WB_CSR_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_CSR_GRANULARITY : t_wishbone_address_granularity := BYTE);
port (
......
......@@ -40,6 +40,8 @@ use work.timetag_core_pkg.all;
entity fmc_adc_mezzanine is
generic (
g_MULTISHOT_RAM_SIZE : natural := 2048;
-- Only used on Xilinx Spartan6 FPGAs
g_SPARTAN6_USE_PLL : boolean := TRUE;
g_WB_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_GRANULARITY : t_wishbone_address_granularity := BYTE);
port (
......@@ -441,6 +443,7 @@ begin
generic map (
g_WB_CSR_MODE => CLASSIC,
g_WB_CSR_GRANULARITY => BYTE,
g_SPARTAN6_USE_PLL => g_SPARTAN6_USE_PLL,
g_MULTISHOT_RAM_SIZE => g_MULTISHOT_RAM_SIZE
)
port map(
......
......@@ -45,6 +45,8 @@ package fmc_adc_mezzanine_pkg is
component fmc_adc_mezzanine
generic (
g_MULTISHOT_RAM_SIZE : natural := 2048;
-- Only used on Xilinx Spartan6 FPGAs
g_SPARTAN6_USE_PLL : boolean := TRUE;
g_WB_MODE : t_wishbone_interface_mode := PIPELINED;
g_WB_GRANULARITY : t_wishbone_address_granularity := BYTE);
port (
......
......@@ -739,6 +739,7 @@ begin
cmp_fmc_adc_mezzanine : fmc_adc_mezzanine
generic map (
g_MULTISHOT_RAM_SIZE => g_MULTISHOT_RAM_SIZE,
g_SPARTAN6_USE_PLL => FALSE,
g_WB_MODE => PIPELINED,
g_WB_GRANULARITY => BYTE)
port map (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment