Jump to content

    
Sign in to follow this  
zvs

ADC DDR и TimeQuest

Recommended Posts

У верблюда два горба,
потому что жизнь - борьба!

Доброго времени суток!
Есть проект:
Аппаратно:
- отладочная плата Arria II GX Development Kit, кристалл EP2AGX125EF35C4ES;
- самопальная платка с AD9272 на борту, тактовая 65 МГц.
Quartus II version 11

AD9272 по LVDS отдаёт по последовательному каналу данные (s_adc_data). К данным прилагается: DCO (s_adc_clk) - тактовый сигнал (390 МГц) и FCO (s_adc_frame) - кадровая синхронизация (те же 65 МГц).

ad9272.jpg

1. Проект тестовый, простецкий, один канал (из восьми доступных в АЦП), используется altddio_in, сгенерённый Мегавизардом (ddr_rx_in в коде).
//altera message_off 10040
module adc_deserializer(s_adc_clk, s_adc_frame, s_adc_data, adc_data, en_adc_data);

parameter    WIDTH_ADC_DATA = 12;//ширина шины данных АЦП

input    s_adc_clk;
input    s_adc_frame;
input    s_adc_data;
output    [WIDTH_ADC_DATA-1:0]adc_data;
output    en_adc_data;

reg [WIDTH_ADC_DATA/2-1:0]pos_shift_reg, odd_data;
reg [WIDTH_ADC_DATA/2-1:0]neg_shift_reg, evn_data;
reg en_adc_frame, en_odd_data, en_evn_data;

wire en_adc_data, in_rx_p, in_rx_n;
wire [WIDTH_ADC_DATA-1:0]adc_data;

assign en_adc_data = en_evn_data;

ddr_rx_in ddr_rx_in(
    .datain(s_adc_data),
    .inclock(s_adc_clk),
    .dataout_h(in_rx_p),
    .dataout_l(in_rx_n));

genvar i;
generate for(i=0; i<WIDTH_ADC_DATA/2; i=i+1) begin: assign_adc_data
        assign adc_data[2*i+1:2*i] = {odd_data[i], evn_data[i]};
    end
endgenerate

always @(posedge s_adc_clk) begin
    pos_shift_reg <= {pos_shift_reg, in_rx_p};
    neg_shift_reg <= {neg_shift_reg, in_rx_n};
    en_adc_frame <= s_adc_frame;
    en_odd_data <= en_adc_frame;
    en_evn_data <= en_odd_data;
    if(en_adc_frame && !en_odd_data)
        odd_data <= pos_shift_reg;
    if(en_odd_data && !en_evn_data)
        evn_data <= neg_shift_reg;
end//always
endmodule


Ноги АЦП расставлены самостоятельно, s_adc_sclk заведены на dedicated clock, DIFFCLK, как положено. Выходные отданы на откуп Quartus'у.
SDC файл для такого случая "классический", как в "Constraining and Analyzing Source-Synchronous Interfaces", Example 56.
Собственно вот он, SDC файл:

set_time_format -unit ns -decimal_places 3

create_clock -name {clk_480MHz} -period 390MHz -waveform {0.641 1.923} [get_ports {s_adc_clk}]
create_clock -name {clk} -period 390MHz

derive_clock_uncertainty

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_data}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_data}]

set_input_delay -max -clock {clk} -clock_fall  0.300 [get_ports {s_adc_data}] -add_delay
set_input_delay -min -clock {clk} -clock_fall -0.300 [get_ports {s_adc_data}] -add_delay

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_frame}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_frame}]


В результате TQ заявляет, что шоколада по холду не будет:

tqf.JPG

2. Размножаем один канал так, чтобы работали все 8:

module adc_deserializers(s_adc_clk, s_adc_frame, s_adc_data, adc_data, en_adc_data);

parameter NUM_CHANNEL = 8;//Количество каналов
parameter WIDTH_ADC_DATA = 12;//Ширина шины данных АЦП

input    s_adc_clk;
input    s_adc_frame;
input    [NUM_CHANNEL-1:0]s_adc_data;
output    [WIDTH_ADC_DATA*NUM_CHANNEL-1:0]adc_data;
output    [NUM_CHANNEL-1:0]en_adc_data;

adc_deserializer #(
        .WIDTH_ADC_DATA(WIDTH_ADC_DATA))
    adc_deserializer[NUM_CHANNEL-1:0](
        .s_adc_clk(s_adc_clk),
        .s_adc_frame(s_adc_frame),
        .s_adc_data(s_adc_data),
        .adc_data(adc_data),
        .en_adc_data(en_adc_data));

endmodule



Правим SDC, с учётом размножения (показаны изменившие строки)

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_data[*]}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_data[*]}]

set_input_delay -max -clock {clk} -clock_fall  0.300 [get_ports {s_adc_data[*]}] -add_delay
set_input_delay -min -clock {clk} -clock_fall -0.300 [get_ports {s_adc_data[*]}] -add_delay



Понятное дело, лучше не стало, только теперь еще повылазили слаки для выхода ddio, который захлопывается передним фронтом :(
tq8.JPG

Понятное дело, что если задрать тактовую АЦП до 80 (а нам так и надо) выползают слаки и по сетапу для того же выхода ddio.

В реальном проекте, в железе, сигнал действительно рассыпается причудливым образом :(

Уважаемые гуру, расскажите, что мы делаем не так и куда, собственно, копать-то?
Есть еще идея поиспользовать altlvds в его синтезируемом виде, но уверенности в результате нет. Однако пробовать будем - о результатах отпишусь.

Share this post


Link to post
Share on other sites
...продолжение


Собрали проект с altlvds, поскольку данные АЦП 12 бит, в SERDES это добро уже не помещается, используем "circuity in logic cells", в качестве клока для altlvds используем сигнал FCO АЦП.

altlvds_rx1_cr.jpg
altlvds_rx2_cr.jpg

module adc_deserializer(s_adc_clk, s_adc_frame, s_adc_data, adc_data, en_adc_data);

parameter    WIDTH_ADC_DATA = 12;//ширина шины данных АЦП

//input    n_clr;
input    s_adc_clk;
input    s_adc_frame;
input    s_adc_data;
//output    s_adc_seal;
output    [WIDTH_ADC_DATA-1:0]adc_data;
output    en_adc_data;

altlvds_ser altlvds_ser (   .rx_in(s_adc_data),
                            .rx_inclock(s_adc_frame),
                            .rx_out(adc_data),
                            .rx_outclock(en_adc_data));

endmodule



Соответствующий SDC файл:

set_time_format -unit ns -decimal_places 3

create_clock -name {clk_65MHz} -period 65MHz [get_ports {s_adc_frame}]
create_clock -name {clk} -period 390MHz

derive_pll_clocks -create_base_clocks
derive_clock_uncertainty

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_data}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_data}]

set_input_delay -max -clock {clk} -clock_fall  0.300 [get_ports {s_adc_data}] -add_delay
set_input_delay -min -clock {clk} -clock_fall -0.300 [get_ports {s_adc_data}] -add_delay

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_frame}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_frame}]



И вуаля! Ничего хорошего так и не случилось:

tq_lvds.jpg
tq_lvds2.jpg

Неужели Arria II GX c таймингами "4" не может принять LVDS сигнал с частотой 390 МГц??? :smile3046:
Где мы неправильно задаём констрейны? :help:

Share this post


Link to post
Share on other sites
Неужели Arria II GX c таймингами "4" не может принять LVDS сигнал с частотой 390 МГц??? :smile3046:

Где мы неправильно задаём констрейны? :help:

 

Констрейны вроде правильно задаёте. Подобная ситуация уже обсуждалась. Клок пока бежит по дереву, отстаёт на 1-2наносекунды, отсюда ваш слак по холду. SERDES в данном случае вряд ли поможет, так как ПМСМ использовать FCO для тактирования хуже, чем DCO, а с DCO в качестве главного клока встроенный SERDES не увидит границ слов, поэтому лучше читать FCO через обычный входной DDR триггер, и десериализировать всё "вручную". В, общем, пропустите s_adc_clk через PLL, должно заработать, а может, и в констрейны уложитесь:).

Share this post


Link to post
Share on other sites

Timmy, во первых, спасибо!

Во вторых, по вашей ссылке сказано:

Приём данных на такой частоте требует заведения клока через PLL/DLL с внутренним фидбэком в режиме компенсации задержки на clock tree.

Не совсем понял терминологию.

alt_pll может работать в режимах

1) Normal mode—The PLL feedback path source is a global or regional clock

network, minimizing clock delay to registers for that clock type and specific PLL

output. You can specify PLL output that is compensated.

2) Source-Synchronous mode—The data and clock signals arrive at the same time at

the input pins. In this mode, the signals are guaranteed to have the same phase

relationship at the clock and data ports of any Input Output Enable (IOE) register.

3) Zero-Delay Buffer mode—The PLL feedback path is confined to the dedicated

PLL external output pin. The clock port driven off-chip is phase aligned with the

clock input for a minimal delay between the clock input and the external clock

output.

4) No Compensation mode—The PLL feedback path is confined to the PLL loop. It

has no clock network or other external source. A PLL in no-compensation mode

has no clock network compensation, but clock jitter is minimized.

5) External Feedback mode—The PLL compensates for the fbin feedback input to

the PLL. The delay between the input clock pin and the feedback clock pin is

minimized.

Согласно описанию 2-4 не подходят, не так ли?

5 в Arria II GX не поддерживается...

Share this post


Link to post
Share on other sites
Собрали проект с altlvds, поскольку данные АЦП 12 бит, в SERDES это добро уже не помещается, используем "circuity in logic cells", в качестве клока для altlvds используем сигнал FCO АЦП.

 

И вуаля! Ничего хорошего так и не случилось:

 

А в чем заключается неработоспособность и как она проявляется? Т.к. подобный АЦП заведен на самый дохлый по скорости Циклон 3 и все прекрасно работает. Правда частота ниже - клок для АЦП 40 МГц//выход 40 и 240МГц соответственно.

 

Share this post


Link to post
Share on other sites

to Гяук Почитайте блог des00 про Ваш случай, может что-то новое найдете...

Было бы проще Вам помочь, если бы были приведены временные диаграммы timequest анализатора на пути, не проходящему по холду/слэку со всеми временными задержками. А насчет 390 МГц это в даташит надо смотреть, чтоб DDR "могло" работать на 780МГц.

ЗЫ// И к посту 2 вопрос - почему Вы в altlvds_ser на вход тактовой подаете частоту 65МГц, тогда как данные туда поступают на 780МГц? Может я чето не понимаю...Там же DDR на входе должны стоять, которые щелкают по фронту/срезу по идее для этого случае на частоте 390МГц.

ЗЫ2//

Собрали проект с altlvds, поскольку данные АЦП 12 бит, в SERDES это добро уже не помещается, используем "circuity in logic cells"
Вот это скорее всего и не будет работать на такой частоте...
Edited by bogaev_roman

Share this post


Link to post
Share on other sites
А в чем заключается неработоспособность и как она проявляется?

Данные разваливаются. Совсем. Например биты 0 и 2 на выходе десериализатора повторяют друг друга от отсчёта к отсчёту. Бит 10 сбивается в случайные моменты.

...подобный АЦП заведен на самый дохлый по скорости Циклон 3 и все прекрасно работает. Правда частота ниже - клок для АЦП 40 МГц//выход 40 и 240МГц соответственно.

Охотно верю. И у меня на этих частотах все прекрасно. Запас слаков по сетапу 569, по холду 262 в самом плохом варианте.

Кстати, для самого быстрого Циклона все собирается (по мнению TQ) и для 65/390 МГц :(

to Гяук Почитайте блог des00 про Ваш случай, может что-то новое найдете...

Я с него начинал знакомство с TQ, проштудировал внимательно...

Было бы проще Вам помочь, если бы были приведены временные диаграммы timequest анализатора на пути, не проходящему по холду/слэку со всеми временными задержками.

Вы имеете ввиду вот это?

Кстати от компиляции к компиляции слаки меняются, так что тут они уже не те, что были вчера (в первом посте).

 

tq8_detail.JPG

 

А насчет 390 МГц это в даташит надо смотреть, чтоб DDR "могло" работать на 780МГц.

В datasheet написано вот так:

The minimum and maximum specification depends on the clock source (for example, PLL and clock pin) and the clock routing resource you use (global, regional, or local). The I/O differential buffer and input register do not have a minimum toggle rate. You are required to calculate the leftover timing margin in the receiver by performing link timing closure analysis. You must consider the board

skew margin, transmitter channel-to-channel skew, and the receiver sampling margin to determine the leftover timing margin.

То бишь, не признаются :(

ЗЫ// И к посту 2 вопрос - почему Вы в altlvds_ser на вход тактовой подаете частоту 65МГц, тогда как данные туда поступают на 780МГц? Может я чето не понимаю...Там же DDR на входе должны стоять, которые щелкают по фронту/срезу по идее для этого случае на частоте 390МГц.

ЗЫ2// Вот это скорее всего и не будет работать на такой частоте...

В altlvds я сказал какой у меня будет DataRate, какая частота клока, фазовое соотношение между клоком и данными. altlvds на основании этих данных должен завести PLL так, чтобы на ней сделать нужный для защёлкивания данных клок. И она это делает, Modelsim показывает, что данные собираются те, что были выставлены на линию данных...

Share this post


Link to post
Share on other sites
Вы имеете ввиду вот это?

У меня картинка не отображается...

В datasheet написано вот так

Да, я это уже нашел, но по идее там в даташите для rx на serdes вообще максимальная 1250 стоит. Так что 780 не так много для ddr.

В altlvds я сказал какой у меня будет DataRate, какая частота клока, фазовое соотношение между клоком и данными. altlvds на основании этих данных должен завести PLL так, чтобы на ней сделать нужный для защёлкивания данных клок. И она это делает, Modelsim показывает, что данные собираются те, что были выставлены на линию данных...

1. Modelsim на gate уровне показывает?

2. Вы уверены, что PLL формирует частоты как надо? У меня был случай, когда в мегафункции задавалась начальная фаза, но реально сдвига не было из-за особенностей реализации и quartus отчетливо в fitter report для ignored assignment говорил об этом...

ЗЫ// Попробуйте сделать как Timmy сказал если реально ничего не получится. Пропустите 390 через PLL и сдвиньте ее вправо на 90* (ну или меньше/больше в зависимости от начальной фазы), чтоб она в окно попадала. Пустите тактовую с данными на DDR и на их выходе получите 6 разрядов на частоте 390, дальше сериализацию делаете вручную с помощью мультиплексоров и обычных триггеров и на выходе получите Ваши 12 разрядов на частоте 65МГц. По частоте после определенных усилий должны пройти...

Share this post


Link to post
Share on other sites
Не совсем понял терминологию.

alt_pll может работать в режимах

1) Normal mode—The PLL feedback path source is a global or regional clock

network, minimizing clock delay to registers for that clock type and specific PLL

output. You can specify PLL output that is compensated.

2) Source-Synchronous mode—The data and clock signals arrive at the same time at

the input pins. In this mode, the signals are guaranteed to have the same phase

relationship at the clock and data ports of any Input Output Enable (IOE) register.

У меня терминология Латтиса, там это называется clock injection delay removal. В вашем случае должно подойти 1 или 2, скорее 2, из описания не совсем понятно. Проблема в том, что у PLL джиттер великоват, а DLL Альтера не признаёт. Кстати, фазу DCO сдвигать не надо, она уже установлена, как надо, в АЦП. Хотя, может быть, надо сдвинуть чуть-чуть для попадания в середину окна.

Share this post


Link to post
Share on other sites
У меня картинка не отображается...

Приаттачил к этому посту (TQ8_detail.jpg).

Да, я это уже нашел, но по идее там в даташите для rx на serdes вообще максимальная 1250 стоит. Так что 780 не так много для ddr.

Был всегда уверен, что serdes - это некий аппаратный блок и мешать его с обычным LVDS не стоит. В datasheet (p.1-68, table 1-53) сказано что fHSDR максимум 945 Mbps (для не DPA).

"For interfacing with non-DPA receivers, the maximum supported data rate is 945 Mbps. Beyond 840 Mbps, PCB trace compensation is required."

То бишь на 780 все равно работать должна.

1. Modelsim на gate уровне показывает?

Да

2. Вы уверены, что PLL формирует частоты как надо? У меня был случай, когда в мегафункции задавалась начальная фаза, но реально сдвига не было из-за особенностей реализации и quartus отчетливо в fitter report для ignored assignment говорил об этом...

ЗЫ// Попробуйте сделать как Timmy сказал ...

По крайней мере в Ignored assignments ничего жуткого не написано.

Вариант, предложенный Timmy я пробовал, но:

1) 390 никуда не двигал - она вроде как и так должна стоять как положено - первая картинка в первом посте, на всяк случай прикрепил её и к этому посту (AD9272.jpg).

2) Pll использовал в normal mode.

3) Проект с ddio для одного канала.

module adc_deserializer(s_adc_clk, s_adc_frame, s_adc_data, adc_data, en_adc_data);

parameter    WIDTH_ADC_DATA = 12;//ширина шины данных АЦП

input    s_adc_clk;
input    s_adc_frame;
input    s_adc_data;
output    [WIDTH_ADC_DATA-1:0]adc_data;
output    en_adc_data;

reg [WIDTH_ADC_DATA/2-1:0]pos_shift_reg, odd_data;
reg [WIDTH_ADC_DATA/2-1:0]neg_shift_reg, evn_data;
reg en_adc_frame, en_odd_data, en_evn_data;

wire en_adc_data, in_rx_p, in_rx_n;
wire [WIDTH_ADC_DATA-1:0]adc_data;

assign en_adc_data = en_evn_data;

align_pll align_pll (
                        .inclk0(s_adc_clk),
                        .c0(pll_adc_clk));

ddr_rx_in ddr_rx_in(
    .datain(s_adc_data),
    .inclock(pll_adc_clk),
    .dataout_h(in_rx_p),
    .dataout_l(in_rx_n));

genvar i;
generate for(i=0; i<WIDTH_ADC_DATA/2; i=i+1) begin: assign_adc_data
        assign adc_data[2*i+1:2*i] = {odd_data[i], evn_data[i]};
    end
endgenerate

always @(posedge pll_adc_clk) begin
    pos_shift_reg <= {pos_shift_reg, in_rx_p};
    neg_shift_reg <= {neg_shift_reg, in_rx_n};
    en_adc_frame <= s_adc_frame;
    en_odd_data <= en_adc_frame;
    en_evn_data <= en_odd_data;
    if(en_adc_frame && !en_odd_data)
        odd_data <= pos_shift_reg;
    if(en_odd_data && !en_evn_data)
        evn_data <= neg_shift_reg;
end//always
endmodule

4) sdc файл, практически такой же как и раньше (добавлена команда derive_pll_clocks -create_base_clocks) Поправил 12.08.2011 в 15:25

set_time_format -unit ns -decimal_places 3

create_clock -name {clk_480MHz} -period 390MHz -waveform {0.641 1.923} [get_ports {s_adc_clk}]
create_clock -name {clk} -period 390MHz

derive_clock_uncertainty
derive_pll_clocks -create_base_clocks

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_data}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_data}]

set_input_delay -max -clock {clk} -clock_fall  0.300 [get_ports {s_adc_data}] -add_delay
set_input_delay -min -clock {clk} -clock_fall -0.300 [get_ports {s_adc_data}] -add_delay

set_input_delay -max -clock {clk}  0.300 [get_ports {s_adc_frame}]
set_input_delay -min -clock {clk} -0.300 [get_ports {s_adc_frame}]

Итог неутешительный: (на всякий случай картинку приаттачил к посту TQ_pll_detail.jpg)

tq_pll_detail.JPG

Все слаки только по сетапу. Вообще мне совсем не понятно отчего ему так поплохело внезапно.

 

bogaev_roman, Timmy, спасибо за участие! :)

post-1346-1313123762_thumb.jpg

post-1346-1313124574_thumb.jpg

post-1346-1313126169_thumb.jpg

Share this post


Link to post
Share on other sites

Я попробовал собрать это для первой Арии(второй в моём допотопном Квартусе нет) и должен отменить рекомендацию про PLL. Всё и так хорошо, задержки во входных буферах данных достаточно для компенсации задерки клока, задержка автоматически настраивается, получается симметричный запас 170ps.

Share this post


Link to post
Share on other sites

Timmy, да, проверил на EP1AGX20CF484C6 - все прекрасно собирается... ArriaII - такая гадость??? :(

All, звиняюсь - в предыдущем посте версия без pll. pll я прикручивал на одноканальный вариант.

Share this post


Link to post
Share on other sites
Приаттачил к этому посту

Картинки теперь отображаются. Если время будет попробую загрузить Ваш проект. Есть пока пару вопросов

1. Модуль align_pll в нормальном режиме без всяких сдвигов?

2. Фронт входных частоты и первой посылки данных совпадает или изначально смещен и если смещен, то почему это не отображается в ограничениях и нет на временной диаграмме?

3. -clock_fall -это что за ограничение, забыл? :wacko:

4. На report patch, кстати, видно, что путь клока до DDR 600нс с чем-то, а данных 850нс, причем логически quartus может вставить delay chain от пина до ddr и увеличить эту задержку, а вот от пина до pll такой возможности нет (это к слову почему так все плохо стало), так что тут можно попробовать как-то влипить анализ через один период тактовой...

Edited by bogaev_roman

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this