|
Использование ISERDES2 |
|
|
|
Jan 13 2015, 13:09
|
Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 26-07-09
Из: Нижний Новгород
Пользователь №: 51 578

|
Всем доброго дня! Посоветуйте пожалуйста по следующему вопросу. Есть плата с Xilinx Spartan-6 FPGA (XC6SLX100T-3FGG676C). Необходимо записать данные с АЦП (AD9434) в ОЗУ (тип DDR2). АЦП работает на частоте порядка 400 МГц. Тактовые частоты для ПЛИС и АЦП формируются с помощью микросхемы AD9518. Я хочу задействовать ISERDES2, для того чтобы в ПЛИС работать на меньшей частоте, но к сожалению пока не очень получается. Я делал как ug382 разными способами и через BUFIO2 и через PLL_BASE, но на этапе MAP вылетает ошибка (см. приложение). Через IP тоже не работает, также вылетает ошибка. Часть электрической схемы платы так же в приложении. Собственно вопрос в чем причина ошибки и как её можно исправить? Код: Формирование тактового сигнала CODE ---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 08:29:32 01/13/2015 -- Design Name: -- Module Name: CLK_Module - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all;
entity CLOCK is Port ( clk0_p : in STD_LOGIC; clk0_n : in STD_LOGIC; clk_in : in STD_LOGIC; clk_out : out STD_LOGIC; clk0_out : out STD_LOGIC; dclk0_out : out STD_LOGIC; SerDes_Strobe : out STD_LOGIC; SerDes_CLK : out STD_LOGIC); end CLOCK;
architecture Behavioral of CLOCK is
attribute IOSTANDARD : string; attribute DIFF_TERM : string; attribute IBUF_DELAY_VALUE : string; attribute IFD_DELAY_VALUE : string; attribute DIVIDE : string; attribute DIVIDE_BYPASS : string; attribute I_INVERT : string; attribute USE_DOUBLER : string; attribute ENABLE_SYNC : string; attribute COMPENSATION : string; attribute BANDWIDTH : string; attribute CLKOUT0_DIVIDE : string; attribute CLKOUT0_PHASE : string; attribute CLKOUT0_DUTY_CYCLE : string; attribute CLKOUT1_DIVIDE : string; attribute CLKOUT1_PHASE : string; attribute CLKOUT1_DUTY_CYCLE : string; attribute CLKOUT2_DIVIDE : string; attribute CLKOUT2_PHASE : string; attribute CLKOUT2_DUTY_CYCLE : string; attribute CLKOUT3_DIVIDE : string; attribute CLKOUT3_PHASE : string; attribute CLKOUT3_DUTY_CYCLE : string; attribute CLKOUT4_DIVIDE : string; attribute CLKOUT4_PHASE : string; attribute CLKOUT4_DUTY_CYCLE : string; attribute CLKOUT5_DIVIDE : string; attribute CLKOUT5_PHASE : string; attribute CLKOUT5_DUTY_CYCLE : string; attribute CLKFBOUT_MULT : string; attribute DIVCLK_DIVIDE : string; attribute CLKFBOUT_PHASE : string; attribute REF_JITTER : string; attribute CLKIN_PERIOD : string; attribute CLK_FEEDBACK : string; attribute RESET_ON_LOSS_OF_LOCK : string; attribute BOX_TYPE : string;
component IBUFGDS -- synopsys translate_off generic( DIFF_TERM : boolean := FALSE); -- synopsys translate_on port ( I : in std_logic; IB : in std_logic; O : out std_logic); end component; attribute IOSTANDARD of IBUFGDS : component is "DEFAULT"; -- attribute IOSTANDARD of IBUFGDS : component is "LVPECL_33"; attribute DIFF_TERM of IBUFGDS : component is "FALSE"; attribute IBUF_DELAY_VALUE of IBUFGDS : component is "0"; attribute BOX_TYPE of IBUFGDS : component is "BLACK_BOX";
component BUFIO2 port ( I : in std_logic; IOCLK : out std_logic; DIVCLK : out std_logic; SERDESSTROBE : out std_logic); end component; attribute DIVIDE of BUFIO2 : component is "4"; attribute DIVIDE_BYPASS of BUFIO2 : component is "FALSE"; attribute I_INVERT of BUFIO2 : component is "FALSE"; attribute USE_DOUBLER of BUFIO2 : component is "FALSE"; attribute BOX_TYPE of BUFIO2 : component is "BLACK_BOX";
component BUFG port (I : in std_logic; O : out std_logic); end component; attribute BOX_TYPE of BUFG : component is "BLACK_BOX"; component BUFPLL port ( PLLIN : in std_logic; GCLK : in std_logic; LOCKED : in std_logic; IOCLK : out std_logic; SERDESSTROBE : out std_logic; LOCK : out std_logic ); end component; attribute DIVIDE of BUFPLL : component is "4"; attribute ENABLE_SYNC of BUFPLL : component is "TRUE"; attribute BOX_TYPE of BUFPLL : component is "BLACK_BOX"; component PLL_BASE port ( CLKIN : in std_logic; CLKFBIN : in std_logic; RST : in std_logic; CLKOUT0 : out std_logic; CLKOUT1 : out std_logic; CLKOUT2 : out std_logic; CLKOUT3 : out std_logic; CLKOUT4 : out std_logic; CLKOUT5 : out std_logic; CLKFBOUT : out std_logic; LOCKED : out std_logic ); end component; attribute COMPENSATION of PLL_BASE : component is "SYSTEM_SYNCHRONOUS"; attribute BANDWIDTH of PLL_BASE : component is "OPTIMIZED"; attribute CLKOUT0_DIVIDE of PLL_BASE : component is "1"; attribute CLKOUT0_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT0_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKOUT1_DIVIDE of PLL_BASE : component is "4"; attribute CLKOUT1_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT1_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKOUT2_DIVIDE of PLL_BASE : component is "1"; attribute CLKOUT2_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT2_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKOUT3_DIVIDE of PLL_BASE : component is "1"; attribute CLKOUT3_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT3_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKOUT4_DIVIDE of PLL_BASE : component is "1"; attribute CLKOUT4_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT4_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKOUT5_DIVIDE of PLL_BASE : component is "1"; attribute CLKOUT5_PHASE of PLL_BASE : component is "0.0"; attribute CLKOUT5_DUTY_CYCLE of PLL_BASE : component is "0.5"; attribute CLKFBOUT_MULT of PLL_BASE : component is "1"; attribute CLKFBOUT_PHASE of PLL_BASE : component is "0.0"; attribute DIVCLK_DIVIDE of PLL_BASE : component is "1"; attribute REF_JITTER of PLL_BASE : component is "0.1"; attribute CLKIN_PERIOD of PLL_BASE : component is "2.5"; attribute RESET_ON_LOSS_OF_LOCK of PLL_BASE : component is "FALSE"; attribute BOX_TYPE of PLL_BASE : component is "BLACK_BOX";
component BUFIO2FB -- synopsys translate_off generic( DIVIDE_BYPASS : boolean := TRUE); -- synopsys translate_on port ( I : in std_logic; O : out std_logic); end component; attribute DIVIDE_BYPASS of BUFIO2FB : component is "TRUE"; attribute BOX_TYPE of BUFIO2FB : component is "BLACK_BOX";
signal clk0_pll:std_logic:='0'; signal clk0:std_logic:='0'; signal clk0fb:std_logic:='0'; signal dclk0:std_logic:='0'; signal LOCKED:std_logic:='0'; signal clk0_out0:std_logic:='0'; signal clk0_out1:std_logic:='0'; signal SD_CLK:std_logic:='0';
begin
CLK0_DIFF_BUF : IBUFGDS port map( I => clk0_p, IB => clk0_n, O => clk0);
CLK_BUF : BUFG port map( I => clk_in, O => clk_out); --CLK0_BUFIO2: BUFIO2 -- port map ( I => clk0, -- IOCLK => SerDes_CLK, -- DIVCLK => dclk0, -- SERDESSTROBE => SerDes_Strobe -- ); CLK0_BUFIO2: BUFIO2 port map ( I => clk0, IOCLK => open, DIVCLK => clk0_pll, SERDESSTROBE => open ); CLK0PLL:PLL_BASE port map ( CLKIN => clk0_pll, CLKFBIN => clk0fb, RST => '0', CLKOUT0 => clk0_out0, CLKOUT1 => clk0_out1, CLKOUT2 => open, CLKOUT3 => open, CLKOUT4 => open, CLKOUT5 => open, CLKFBOUT => open, LOCKED => LOCKED ); CLK0_BUFFPLL:BUFPLL port map ( PLLIN => clk0_out0, GCLK => dclk0, LOCKED => LOCKED, IOCLK => SD_CLK, SERDESSTROBE => SerDes_Strobe, LOCK => open ); CLK0_FB: BUFIO2FB port map( I => SD_CLK, O => clk0fb); DCLK0_BUF : BUFG port map( I => clk0_out1, O => dclk0);
SerDes_CLK<=SD_CLK; clk0_out<=clk0; dclk0_out<=dclk0; end Behavioral; Прием данных с АЦП CODE ---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 09:15:39 01/13/2015 -- Design Name: -- Module Name: Tochnost_FPGA_ADC_BUF - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all;
entity ADC_BUFFER is Port ( Divclk : in STD_LOGIC; SerDes_Strobe : in STD_LOGIC; SerDes_CLK : in STD_LOGIC; ADC1_D_P : in STD_LOGIC_VECTOR (11 downto 0); ADC1_D_N : in STD_LOGIC_VECTOR (11 downto 0); ADC1_OR_P : in STD_LOGIC; ADC1_OR_N : in STD_LOGIC; ADC1_DCO_P : in STD_LOGIC; ADC1_DCO_N : in STD_LOGIC; ADC2_D_P : in STD_LOGIC_VECTOR (11 downto 0); ADC2_D_N : in STD_LOGIC_VECTOR (11 downto 0); ADC2_OR_P : in STD_LOGIC; ADC2_OR_N : in STD_LOGIC; ADC2_DCO_P : in STD_LOGIC; ADC2_DCO_N : in STD_LOGIC; ADC1_DATA : out STD_LOGIC_VECTOR (47 downto 0); ADC2_DATA : out STD_LOGIC_VECTOR (47 downto 0)); end ADC_BUFFER;
architecture Behavioral of ADC_BUFFER is
attribute IOSTANDARD : string; attribute DIFF_TERM : string; attribute IBUF_DELAY_VALUE : string; attribute IFD_DELAY_VALUE : string; attribute DATA_RATE : string; attribute DATA_WIDTH : string; attribute BITSLIP_ENABLE : string; attribute SERDES_MODE : string; attribute INTERFACE_TYPE : string; attribute IDELAY_VALUE : string; attribute IDELAY2_VALUE : string; attribute IDELAY_MODE : string; attribute ODELAY_VALUE : string; attribute IDELAY_TYPE : string; attribute COUNTER_WRAPAROUND : string; attribute DELAY_SRC : string; -- attribute SERDES_MODE : string; attribute SIM_TAP_DELAY : string; -- attribute DATA_RATE : string; attribute BOX_TYPE : string; component IBUFDS -- synopsys translate_off generic( DIFF_TERM : boolean := FALSE); -- synopsys translate_on port ( I : in std_logic; IB : in std_logic; O : out std_logic); end component; attribute IOSTANDARD of IBUFDS : component is "DEFAULT"; -- attribute IOSTANDARD of IBUFGDS : component is "LVPECL_33"; attribute DIFF_TERM of IBUFDS : component is "FALSE"; attribute IBUF_DELAY_VALUE of IBUFDS : component is "0"; attribute BOX_TYPE of IBUFDS : component is "BLACK_BOX"; component IODELAY2 port ( IDATAIN : in std_logic; T : in std_logic; ODATAIN : in std_logic; CAL : in std_logic; IOCLK0 : in std_logic; IOCLK1 : in std_logic; CLK : in std_logic; INC : in std_logic; CE : in std_logic; RST : in std_logic; BUSY : out std_logic; DATAOUT : out std_logic; DATAOUT2 : out std_logic; TOUT : out std_logic; DOUT : out std_logic ); end component; attribute IDELAY_VALUE of IODELAY2 : component is "0"; attribute IDELAY2_VALUE of IODELAY2 : component is "0"; attribute IDELAY_MODE of IODELAY2 : component is "NORMAL"; attribute ODELAY_VALUE of IODELAY2 : component is "0"; attribute IDELAY_TYPE of IODELAY2 : component is "DEFAULT"; attribute COUNTER_WRAPAROUND of IODELAY2 : component is "STAY_AT_LIMIT"; attribute DELAY_SRC of IODELAY2 : component is "IDATAIN"; attribute SERDES_MODE of IODELAY2 : component is "NONE"; attribute SIM_TAP_DELAY of IODELAY2 : component is "50"; attribute DATA_RATE of IODELAY2 : component is "SDR"; attribute BOX_TYPE of IODELAY2 : component is "BLACK_BOX"; component ISERDES2 port ( CLK0 : in std_logic; CLK1 : in std_logic; CLKDIV : in std_logic; CE0 : in std_logic; BITSLIP : in std_logic; D : in std_logic; RST : in std_logic; IOCE : in std_logic; SHIFTIN : in std_logic; CFB0 : out std_logic; CFB1 : out std_logic; DFB : out std_logic; SHIFTOUT : out std_logic; FABRICOUT : out std_logic; Q4 : out std_logic; Q3 : out std_logic; Q2 : out std_logic; Q1 : out std_logic; VALID : out std_logic; INCDEC : out std_logic ); end component; attribute DATA_RATE of ISERDES2 : component is "SDR"; attribute DATA_WIDTH of ISERDES2 : component is "4"; attribute BITSLIP_ENABLE of ISERDES2 : component is "FALSE"; attribute SERDES_MODE of ISERDES2 : component is "NONE"; attribute INTERFACE_TYPE of ISERDES2 : component is "NETWORKING"; attribute BOX_TYPE of ISERDES2 : component is "BLACK_BOX"; signal ADC1_D:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC1_D1:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC1_D2:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC1_D3:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC1_D4:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC1_D_Delayed:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D1:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D2:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D3:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D4:std_logic_vector(11 downto 0):=(others=>'0'); signal ADC2_D_Delayed:std_logic_vector(11 downto 0):=(others=>'0'); begin
ADC1_DATA_BUFFERS: for i in 0 to 11 generate ADC1_D_BUF : IBUFDS port map( I => ADC1_D_p(i), IB => ADC1_D_n(i), O => ADC1_D(i)); ADC1_D_IODELAY : IODELAY2 port map( IDATAIN => ADC1_D(i), T => '1', ODATAIN => '0', CAL => '0', IOCLK0 => SerDes_CLK, IOCLK1 => '0', CLK => Divclk, INC => '1', CE => '1', RST => '0', BUSY => open, DATAOUT => ADC1_D_Delayed(i),-- to SERDES DATAOUT2 => open, -- to FPGA Logic TOUT => open, DOUT => open ); ADC1_D_SERDER : ISERDES2 port map( CLK0 => SerDes_CLK, CLK1 => '0', CLKDIV => Divclk, CE0 => '1', BITSLIP => '0', D => ADC1_D_Delayed(i), RST => '0', IOCE => SerDes_Strobe, SHIFTIN => '0', CFB0 => open, CFB1 => open, DFB => open, SHIFTOUT => open, FABRICOUT => open, -- to FPGA Logic Q4 => ADC1_D4(i), Q3 => ADC1_D3(i), Q2 => ADC1_D2(i), Q1 => ADC1_D1(i), VALID => open, INCDEC => open );
ADC1_DATA(i)<=ADC1_D1(i); ADC1_DATA(i+12)<=ADC1_D2(i); ADC1_DATA(i+24)<=ADC1_D3(i); ADC1_DATA(i+36)<=ADC1_D4(i); end generate ADC1_DATA_BUFFERS; ADC2_DATA_BUFFERS: for i in 0 to 11 generate ADC2_D_BUF : IBUFDS port map( I => ADC2_D_p(i), IB => ADC2_D_n(i), O => ADC2_D(i)); ADC2_D_IODELAY : IODELAY2 port map( IDATAIN => ADC2_D(i), T => '1', ODATAIN => '0', CAL => '0', IOCLK0 => SerDes_CLK, IOCLK1 => '0', CLK => Divclk, INC => '1', CE => '1', RST => '0', BUSY => open, DATAOUT => ADC2_D_Delayed(i),-- to SERDES DATAOUT2 => open, -- to FPGA Logic TOUT => open, DOUT => open ); ADC2_D_SERDER : ISERDES2 port map( CLK0 => SerDes_CLK, CLK1 => '0', CLKDIV => Divclk, CE0 => '1', BITSLIP => '0', D => ADC2_D_Delayed(i), RST => '0', IOCE => SerDes_Strobe, SHIFTIN => '0', CFB0 => open, CFB1 => open, DFB => open, SHIFTOUT => open, FABRICOUT => open, -- to FPGA Logic Q4 => ADC2_D4(i), Q3 => ADC2_D3(i), Q2 => ADC2_D2(i), Q1 => ADC2_D1(i), VALID => open, INCDEC => open );
ADC2_DATA(i)<=ADC2_D1(i); ADC2_DATA(i+12)<=ADC2_D2(i); ADC2_DATA(i+24)<=ADC2_D3(i); ADC2_DATA(i+36)<=ADC2_D4(i); end generate ADC2_DATA_BUFFERS; ADC1_OR_BUF : IBUFDS port map( I => ADC1_OR_p, IB => ADC1_OR_n, O => open); ADC1_DCO_BUF : IBUFDS port map( I => ADC1_DCO_p, IB => ADC1_DCO_n, O => open); ADC2_OR_BUF : IBUFDS port map( I => ADC2_OR_p, IB => ADC2_OR_n, O => open); ADC2_DCO_BUF : IBUFDS port map( I => ADC2_DCO_p, IB => ADC2_DCO_n, O => open);
end Behavioral;
Причина редактирования: Используйте codebox для оформления длинных кусков кода (с) модератор
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 14 2015, 06:33
|
Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 26-07-09
Из: Нижний Новгород
Пользователь №: 51 578

|
Цитата(serjj @ Jan 13 2015, 17:19)  У вас скорее всего BUFPLL и ножки входные в разных IO банках оказались, а компонент BUFPLL жёстко привязан к своему банку. Скидайте их констрейнами в один банк, можно через ГУИ прям, тогда должно развестись serjj, большое спасибо! Действительно они находятся в разных банках. Прописал позицию вручную через LOC для PLLBUF и BUFIO2 и все заработало. Единственное только пришлось упростить обратную связь убрав BUFIO2FB.
|
|
|
|
|
Jan 14 2015, 13:53
|
Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 26-07-09
Из: Нижний Новгород
Пользователь №: 51 578

|
Ну вот рано я обрадовался... Теперь тайминги никакие... Fmax 13 MHz Цитата(Bad0512 @ Jan 14 2015, 14:42)  Можно сделать проще, без PLL. Но для этого надо завести DCO с обеих АЦПеек на соответствующий клоковый вход. И чтобы все биты данных были в соответствующем банке. К сожалению так сделать нельзя. Плата физически уже есть, а DCO на клоковый вход не заведен  Я думаю тут надо попробовать 2 PLL поставить. Один в банке где, вход тактового сигнала, а другой в банке где входы данных с АЦП.
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 16 2015, 11:37
|
Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 26-07-09
Из: Нижний Новгород
Пользователь №: 51 578

|
Цитата(Timmy @ Jan 15 2015, 12:39)  На 400Msps это не проблема. Можно применить тактирование на 800МГц и динамическую подстройку фазы PLL по фронтам ADC_DCO с обычных пинов. Причём для каждого АЦП свою фазу, если получится подключить к разным АЦП разные выходы PLL. Данное решение получится более точным, чем непосредственное использование ADC_DCO с клокового входа. Что-то я не совсем понял... "если получится подключить к разным АЦП разные выходы PLL" - это как? Тактовый сигнал на АЦП не идет с FPGA, его формирует отдельная микросхема на плате - AD9518. Она же формирует тактовый сигнал на ПЛИС. Или имеется ввиду схема наподобии как в приложении?
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 16 2015, 12:23
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Вообще, DCO заводить на клоковый пин вредно. DCO надо рассматривать как вход данных, так как частота DCO может меняться в зависимости от настройки АЦП (его там делить можно, уменьшая частоту дискретизации). Поэтому, лучше всего, если на клоковый пин заведен входной клок АЦП, а там уже вполне себе четкие Tco(min) и Tco(max) прописаны у АЦП (в даташите на АЦП, Tpd/Tcpd), так что можно спокойно прописать констрейны на сетап и холд для FPGA по DCO и данным, там вилка получается достаточной, чтобы быть выдержанной. Ошибки по этим констрейнам можно исправлять как подстройкой фазы входного клока на PLL (фиксированное, на конкретное числовое значение), так и изменением задержки внутри I/O пада (если таковая доступна для конкретной FPGA)
Ну а DCO использовать совместно с данными - данное считается валидным только тогда, когда на DCO (с DDR-приемом) произошла смена уровня.
|
|
|
|
|
Jan 19 2015, 06:52
|

Знающий
   
Группа: Свой
Сообщений: 747
Регистрация: 11-04-07
Пользователь №: 26 933

|
Цитата(SM @ Jan 16 2015, 15:23)  Вообще, DCO заводить на клоковый пин вредно. DCO надо рассматривать как вход данных, так как частота DCO может меняться в зависимости от настройки АЦП (его там делить можно, уменьшая частоту дискретизации). Поэтому, лучше всего, если на клоковый пин заведен входной клок АЦП, а там уже вполне себе четкие Tco(min) и Tco(max) прописаны у АЦП (в даташите на АЦП, Tpd/Tcpd), так что можно спокойно прописать констрейны на сетап и холд для FPGA по DCO и данным, там вилка получается достаточной, чтобы быть выдержанной. Ошибки по этим констрейнам можно исправлять как подстройкой фазы входного клока на PLL (фиксированное, на конкретное числовое значение), так и изменением задержки внутри I/O пада (если таковая доступна для конкретной FPGA)
Ну а DCO использовать совместно с данными - данное считается валидным только тогда, когда на DCO (с DDR-приемом) произошла смена уровня. Интересно, для 1-3 ГГц АЦП тоже входной такт АЦП заводить на ПЛИС? По-моему лишнее это, все отлично работает с DCO, а то что он меняться может, обычно жестко завязано на режим работы преобразователя, с которым нужно заранее определиться. По топику, я бы поставил в IOB фазовый детектор, по которому подстраивал бы фазу сигнала с DCM.
--------------------
|
|
|
|
|
Jan 19 2015, 08:58
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(dm.pogrebnoy @ Jan 19 2015, 09:52)  Интересно, для 1-3 ГГц АЦП тоже входной такт АЦП заводить на ПЛИС? По-моему лишнее это, все отлично работает с DCO, а то что он меняться может, обычно жестко завязано на режим работы преобразователя, с которым нужно заранее определиться. Это, как сказать. У меня, к примеру, частотой DCO рулят программисты, как хотят. А система должна работать. Для 1-3 ГГц, я думаю, все будет по-другому, DCO надо будет уже заводить на DQS-входы и использовать примитивы приема сигнала и переноса ее на внутреннюю тактовую от DDR памяти. И, вообще, я не знаю таких ПЛИС, которые могут принять по LVDS 2-3 гигабита. Это уже прерогатива гигабитных трансиверов.
|
|
|
|
|
Jan 19 2015, 10:40
|

Знающий
   
Группа: Свой
Сообщений: 747
Регистрация: 11-04-07
Пользователь №: 26 933

|
Цитата(SM @ Jan 19 2015, 11:58)  Это, как сказать. У меня, к примеру, частотой DCO рулят программисты, как хотят. А система должна работать. Для 1-3 ГГц, я думаю, все будет по-другому, DCO надо будет уже заводить на DQS-входы и использовать примитивы приема сигнала и переноса ее на внутреннюю тактовую от DDR памяти. И, вообще, я не знаю таких ПЛИС, которые могут принять по LVDS 2-3 гигабита. Это уже прерогатива гигабитных трансиверов. Во всех устройствах, по моему опыту, DCO достаточно жестко задается конфигурацией аппаратной части, и просто так поменять не получится (не заработает). Хотя не исключаю возможности других вариантов использования DCO, надо смотреть конкретную м/сх. И обычно получается не 2-3 гигабита, а меньше. ADS5400 1 ГГц тактовая, 500 МБит LVDS, 250 МГц в DDR. Принимает Spartan-6. ADC08300 3 ГГц таковая, 700 Мбит LVDS, 350 МГц в DDR. Принимал когда-то даже Virtex-4, cейчас Virtex-6. Для более скоростных преобразователей JESD204 входит в моду. Там да, гигабитные приемо-передатчики.
--------------------
|
|
|
|
|
Jan 19 2015, 10:52
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(dm.pogrebnoy @ Jan 19 2015, 13:40)  и просто так поменять не получится (не заработает). Вот именно поэтому, я и описал, как сделать так, чтобы заработало. И заодно убить второго зайца, о котором тема. Сколько я видел АЦП от AD - там у всех (виденных) имеется регистр 0x0B - Clock divide (global) - которым можно менять частоту преобразования, и, соотв., DCO. Но, при этом, тайминги CLK->[DCO, DATA] не меняются. Только фронты на них реже становятся. Цитата(dm.pogrebnoy @ Jan 19 2015, 13:40)  250 МГц в DDR. Не думаю, что при 250 МГц будут проблемы с приемом DCO как DDR-бита данных. У меня DCO может быть от 125/16 (чуть больше 7) до 125 МГц, но запас в обе стороны по отчету STA - по холду 1.6 нс, по сетапу 0.866 нс, это значит, что Fmax в этом месте 325 МГц (с учетом, что это DDR, то есть, за период берется пол-периода). Хотя, тут еще надо учитывать, какая вилка у min <= Tpd <= max у конкретного АЦП
|
|
|
|
|
Jan 20 2015, 03:29
|
Знающий
   
Группа: Свой
Сообщений: 802
Регистрация: 11-05-07
Из: Томск
Пользователь №: 27 650

|
Клок с АЦП заводить на ПЛИС напрямую не рекомендуется по следующим причинам : В случае Схемы типа источник клока -> clock distributor с двумя выходами -> с его выходов один клок идёт на ПЛИС, а другой на АЦП. Здесь появляется в цепи клока клок дистрибьютор - это дополнительный источник джиттера, что ухудшает характеристики АЦП. Кроме этого ещё и дополнительное потребление плюс стоимость самого компонента. Кроме того в этом варианте разница в путях распространения distributor->ADC и distributor->FPGA неконтролируема и нигде не учитывается, на высоких частотах может быть критично. Как правило времянки выходных данных АЦП нормируются именно по отношению к DCO, а не к сэмплирующему клоку. И это неслучайно. Кроме того в продвинутых моделях АЦП-ЦАП есть механизм плавной подстройки DCO относительно данных, что практически исключает необходимость геморроя с IDELAY2 внутри ПЛИС - зачем плодить механизмы подстройки фазы если они уже есть? В общем, DCO как раз для этой цели и придуман чтобы сопровождать данные, и да, его частота в общем случае может и не совпадать с сэмплирующей (например если выход полифазный). Это не баг, это фича. Делается для большего удобства дизайна интерфейсов к ПЛИС. З Ы Для шустрых АЦП JESD204 - не единственный вариант, хотя и очень распространённый. Некоторые разбивают выход на несколько фаз, плюс фазы работают в DDR режиме. Для исключения зависящих от цифровых данных спурсов применяют скремблирование.
|
|
|
|
|
Jan 20 2015, 09:02
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(Bad0512 @ Jan 20 2015, 06:29)  Кроме того в этом варианте разница в путях распространения distributor->ADC и distributor->FPGA неконтролируема и нигде не учитывается, Ну это в корне неверно, она учитывается добавлением соответствующего пессимизма к setup и hold констрейнам (set_input_delay), равного джиттер + разница в путях. И отлично контролируема, так как все это хорощо документировано (для дистрибьютеров), или рассчитывается (для длин дорожек и емкостей нагрузок) - Смотрим отчет STA, и видим все как на ладони, сколько запаса по чему. Цитата(Bad0512 @ Jan 20 2015, 06:29)  Как правило времянки выходных данных АЦП нормируются именно по отношению к DCO, а не к сэмплирующему клоку. Как правило, они нормируются и к тому, и к другому. Для DCO определяют расхождение +- от данных, а для входного клока - время распространения от входного клока до DCO и до данных. PS. Офигенное удобство - делать переход с клока DCO на основной клок ПЛИС для каждого подключенного АЦП, когда еще и заранее неизвестно, какая частота на DCO придет, как ее вздумается пользователю поделить внутри АЦП, докучи, по-разному для нескольких АЦП... И еще. Пока не настроен АЦП, клок с DCO идет, как правило не в том виде - например, CMOS, вместо LVDS, который нужен ПЛИСе. Это еще одна причина не использовать его как основной клок ПЛИС, а брать с дистрибьютера отдельный. Нормальный дистрибьютер джиттера привносит так мало, что им пренебречь можно.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|