Перейти к содержанию
    

Vivado source-synchronous output констрейны

Добрый вечер уважаемые участники форума.

Прошу Вашей помощи с констрейнами.

Имеется простейшая схема. Берем клок с входной ножки, заводим на глобальный тактовый буфер.

С буфера клок подается на пользовательскую логику и на PLL.

С выхода PLL клок подается на выходной пин, подключенный к устройству-назначению.

Модуль приёмник должен по клоку, который я ему генерирую, корректно принять генерируемые мной данные.

Казалось бы простейшая задача обычный source-synchronous output интерфейс.

Однако когда я запросил значения T_setup и T_hold у приёмника и мне ответили, что T_setup = 6 ns, T_hold = 4 ns, при периоде клока в 10 ns я понял, что все не так просто ))))

Очевидно, что разработчики приёмника "немного" ошибаются, и такие значения T_setup и T_hold не имеют смысла, поэтому я решил взять за основу T_setup = 5.9 ns, T_hold -3.900.

Собрал проект, зашил FPGA - и не работает. Поигравшись с различными значениями T_setup и T_hold (менял в разных пределах, перепробовал всё что можно) я так и не добился работоспособности, которую определяю косвенно - когда приемник правильно принял данные, он формирует ответ. Но ответа я так и не получил, при любых значений таймингов.

Почесав голову, я решил перестать угадывать тайминги и добавил к PLL динамический сдвиг фазы и начал вручную двигать фазу выходного клока относительно данных. И таки заработало. Я начал получать ответы от приемника.

Поскольку руками крутить фазу утомительно - сделал простой автомат, который умеет крутить фазу.  Автомат умеет определять примерные границы( количество сдвигов частоты) зоны jitter, где прием не устойчивый, умеет определять размер окна устойчивого приема данных.

Таким образом, зная размеры всех зон очень легко скорректировать констрйны для корректной передачи данных.

Однако все не так просто оказалось. Каждый раз, какие бы я констрейны не указывал - у меня приемник не отвечает на запрос. И каждый раз после прошивки FPGA у меня зона устойчивого приема появляется только после примерно 40 сдвигов фазы.

Вот тут я призадумался. А работают ли вообще мои констрейны ? Или же приемник сам после того, как захватил частоту от меня производит какие-то манипуляции с частотой ?

Очень странно выглядит то, что как бы я констрейны не описывал - результат примерно один и тоже. После прошивки FPGA - надо примерно 40 раз сдвинуть фазу, чтобы прием заработал.

Порошу поделиться советом,  в какую сторону копать. С разработчиками приёмника общаться бесполезно. Их ответ простой – у них все работает, это вы что-то делаете не так.

# Констрейн входного клока. По-умолчанию он создается внутри IP PLL, и явно его описывать не надо. 
# Я его описал для примера
create_clock -period 10.000 -name input_clk [get_ports input_clk]

# Выход с PLL подключается на выходной порт плис (data_out_clk). Никаких манипуляций с клоком не произвожу.
create_generated_clock -name PLL_clk -multiply_by 1 -source [get_pins PLL_comp/inst/mmcme4_adv_inst/CLKOUT0] [get_ports data_out_clk]

# вообще явно мне не сказали какой Setup и Hold у приёмника,
# Мне написали что Hold = 4 ns,  Setup = 6 ns, что звучит очень сомнительно, т.к период клока 10 нс...
# Поэтому я решил задал выходные тайминги вот так:
set_output_delay -clock [get_clocks -of_objects [get_pins PLL_comp/inst/mmcme4_adv_inst/CLKOUT0]] -max  5.900  [get_ports data_out]
set_output_delay -clock [get_clocks -of_objects [get_pins PLL_comp/inst/mmcme4_adv_inst/CLKOUT0]] -min -3.900  [get_ports data_out]

 

Фрагмент.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

3 hours ago, Flip-fl0p said:

Очень странно выглядит то, что как бы я констрейны не описывал - результат примерно один и тоже. После прошивки FPGA - надо примерно 40 раз сдвинуть фазу, чтобы прием заработал.

Увы - констрейны  не двигают вам фазу выходного сигнала.  Они  лишь указывают в каком ограничении P&R волен  размещать логику.  Вы пишете 

3 hours ago, Flip-fl0p said:

set_output_delay -clock [get_clocks -of_objects [get_pins PLL_comp/inst/mmcme4_adv_inst/CLKOUT0]] -max 5.900 [get_ports data_out]

Это значит  что  P&R должен так разместить/развести  сигналы чтобы data_out появился на выходе  не позже чем  5.900 ns  от фронта внутреннего сигнала CLKOUT0!  А на сколько это "не позже"? на 1 нс или на 3 нс? 


К тому же  как выбранная вами схема вывода клока не по мне очень удачна. Было проще если бы один  выход PLL через BUFG тактировал  выход клока, но не напрямую, а через ODDR регистр на выходе.  А второй выход PLL  (опят же через BUFG) уже тактировал логику и выходные регистры в user_logic. Тогда можно быть почти уверенным что задержки клок->pad ~одинаковы и соответственно  можно легко рассчитать требуемую разницу фаз между выходами PLL.

 

Удачи!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы действительно что-то делаете не так. Слишком сложная схема для такой простой задачи.

Подобные констрейны вам не нужны. Проектируете так, чтобы на выходе шины данных был триггер, тактируемый частотой выходящего клока. Clock forward в любом случае делается через ODDR2, т.к. иначе клок наружу на пин не вывести. Точно так же поступаем и с данными, т.е. явно пропускаем их через ODDR2, тактируя от клока с PLL, который хотим посылать наружу. Все ODDR2 пакуются в IOB, в смысле они там и располагаются. Если внутри ПЛИС все тайминги сходятся, то итого получаем идеально выровненные к выходящему тактовому сигналу данные и никаких лишних констрейнтов set_output_delay. И да, на выходе шины данных должен быть именно триггер, но не лут, т.к. иначе это хозяйство вместе с ODDR2 в IOB не засунется, это архитектурная особенность, но это нормально, т.к. по-хорошему выходы нужно регистрировать всегда.
 

И да, согласен с RobFPGA, тактировать логику клоком до PLL - очень странно. Для чего вы вообще используете PLL?

Учтите, так же то, что выходной клок скорее всего нужно будет инвертировать, чтобы принимающее устройство по активному фронту считывало значение на шине данных ровно посередине длительности бита. Инверсия легко делается на том же ODDR2, даже PLL не нужно использовать для этого. Работать будет железно, проверено много раз.

Изменено пользователем Inanity

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И все равно придется разговаривать с разработчиками приемника, потому что "T_setup = 6 ns, T_hold = 4 ns, при периоде клока в 10 ns" оставляют ровно 0 на окно валидных данных. Это невозможно даже теоретически.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 minutes ago, dvlwork said:

И все равно придется разговаривать с разработчиками приемника, потому что "T_setup = 6 ns, T_hold = 4 ns, при периоде клока в 10 ns" оставляют ровно 0 на окно валидных данных. Это невозможно даже теоретически.

да легко, чип приемника на 50МГц, а они занимаются оверклокнигом)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

30 minutes ago, dvlwork said:

И все равно придется разговаривать с разработчиками приемника, потому что "T_setup = 6 ns, T_hold = 4 ns, при периоде клока в 10 ns" оставляют ровно 0 на окно валидных данных. Это невозможно даже теоретически.

Что-то какие-то слишком большие значения для такого клока, неправдоподобно.

Вот полезная картинка для source synchronous интерфейсов, чтобы setup/hold в рамках приличия держать:
clk_forward.png

Изменено пользователем Inanity

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, Flip-fl0p said:

Берем клок с входной ножки, заводим на глобальный тактовый буфер.

С буфера клок подается на пользовательскую логику и на PLL.

С выхода PLL клок подается на выходной пин, подключенный к устройству-назначению.

Судя по констрейну у Вас PLL умножает на 1.

В этом есть какой-то тайный смысл?

Я бы или всё тактировал от вх.буфера или всё с выхода PLL.

У устройства-назначения DDR интерфейс?

 

В любом случае я бы в output констрейн добавил -reference_pin [get_ports ...] поскольку 

"клок подается на выходной пин, подключенный к устройству-назначению"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, des00 сказал:

да легко, чип приемника на 50МГц

Что легко? Частоту приемника вдвое снизить?

У ТС период вроде 10нс. При этих условиях констрейны невыполнимы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Огромное спасибо всем ответившим. Вы мне очень сильно помогли. Извиняюсь, что раньше не ответил, но на работе нет интернета :cray:

16 часов назад, RobFPGA сказал:

Увы - констрейны  не двигают вам фазу выходного сигнала.  Они  лишь указывают в каком ограничении P&R волен  размещать логику.  Вы пишете 

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

 

16 часов назад, Inanity сказал:

Clock forward в любом случае делается через ODDR2, т.к. иначе клок наружу на пин не вывести.

Странно. Вроде же выводится... Или Вы имеете ввиду, что у клока, который выводится через обычный пин будет большой jitter ?

16 часов назад, Inanity сказал:

Подобные констрейны вам не нужны.

Тогда возникает резонный вопрос. А как тогда обконстрейнить выходные данные ? Игнорировать предупреждения Vivado об этих таймингах ?

16 часов назад, Inanity сказал:

И да, согласен с RobFPGA, тактировать логику клоком до PLL - очень странно. Для чего вы вообще используете PLL?

Просто я решил сделать отдельный клок для выхода данных, чтобы можно было динамически подвигать фазу, для того чтобы найти середину окна данных, и померять это окно. Ибо из-за моего направильного понимания констерйна  set_output_delay я не понимал, почему не работает.

16 часов назад, Inanity сказал:

Вы действительно что-то делаете не так. Слишком сложная схема для такой простой задачи.
Clock forward в любом случае делается через ODDR2, т.к. иначе клок наружу на пин не вывести. Точно так же поступаем и с данными, т.е. явно пропускаем их через ODDR2, тактируя от клока с PLL, который хотим посылать наружу.
Инверсия легко делается на том же ODDR2, даже PLL не нужно использовать для этого. Работать будет железно, проверено много раз.

Я именно так и сделал. Опытным путем установил, что если на PLL сгенерировать клок, сдвинутый на минус 90 градусов относительно клока, защёлкивающего данные(которые тоже вывожу через ODDR) и его подать на  ODDR, где сформировать его инверсию, то фронт клока точно устанавливается в центр окна данных.

6 часов назад, zombi сказал:

Судя по констрейну у Вас PLL умножает на 1.

В этом есть какой-то тайный смысл?

Я бы или всё тактировал от вх.буфера или всё с выхода PLL.

У устройства-назначения DDR интерфейс?

Смысл в том, что если это не указать, Vivado ругается на констрейн create_generated_clock

Устройство назначения SDR Интерфейс.

 

8 часов назад, Inanity сказал:

Что-то какие-то слишком большие значения для такого клока, неправдоподобно.

Вот полезная картинка для source synchronous интерфейсов, чтобы setup/hold в рамках приличия держать:

Спасибо. Но возникает вопрос, зная Ts и Th приёмного устройства как мне задавать выходные констрейны. Я ведь не знаю, какие манипуляции с клоком производят на приемной стороне. Может быть они сразу же тактируют приемный регистры инверсным клоком и от меня ничего не требуется... В общем где-то в моих знаниях пробелы, которые надо заполнить правильной информцией. Буду думать

Спасибо всем !

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Касательно констрейнтов в первом посте. Сразу вижу ошибку. Как должно быть: интерфейс констрейнится относительно клока на выводе микросхемы (а не выходе pll или другой внутренней логики). Соотвественно, пропущен этот выходной клок, объявленный как generated на выходном пине плис. Пропущен констрейнт емкости (set_load), приложенной к этому выводу - он влияет на задержку выходного пада и как следствие - на летенси клока. И наконец, set_output_delay должен быть указан относительно этого выходного клока, который пропущен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, Flip-fl0p said:

Устройство назначения SDR Интерфейс.

Тоже совсем недавно мучался с констрейнами set_output_delay для SDRAM.

Как только не игрался c -min -max - ничего толком не работало.

Фазу PLL двигал - вроде начинало оживать но как-то не устойчиво.

Пока не оставил только один кострейн set_output_delay без -max и без -min, а просто с одной цифрой 1.5 нс. А tHold получается выполняется автоматически в моём случае.

Ну и -reference_pin обязательно.

Теперь работает устойчиво сутками напролёт на частоте 150MHz! "сломать" хочу - не могу )

Спасибо Yuri124 помог в этой теме Отчёт TimeQuest как понять ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, dvlwork said:

Что легко? Частоту приемника вдвое снизить?

У ТС период вроде 10нс. При этих условиях констрейны невыполнимы.

вы фразу из контекста не вырывайте, я указал как может получится что при таких параметрах приемника, требуют такую тактовую частоту

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

27.08.2020 в 22:26, Aleх сказал:

Касательно констрейнтов в первом посте. Сразу вижу ошибку. Как должно быть: интерфейс констрейнится относительно клока на выводе микросхемы (а не выходе pll или другой внутренней логики). Соотвественно, пропущен этот выходной клок, объявленный как generated на выходном пине плис. Пропущен констрейнт емкости (set_load), приложенной к этому выводу - он влияет на задержку выходного пада и как следствие - на летенси клока. И наконец, set_output_delay должен быть указан относительно этого выходного клока, который пропущен.

 

Я правильно понимаю, что выходной клок надо создавать на входе ODDR буффера на котором я формирую forward клок ?

Т.е примерно так:

create_generated_clock -name FWD_data_out_clk -multiply_by 1 -source [get_pins ODDR_BUFF/C] [get_ports data_out_clk]
set_output_delay -clock FWD_data_out_clk  -max  x.xxx  [get_ports data_out]
set_output_delay -clock FWD_data_out_clk  -min -x.xxx  [get_ports data_out]

А разве не правильно ли констрейны задавать не относительно выходного порта data_out, а относительно входа ODDR буфера, через которые я данные вывожу на выходной порт.

Констрейны что-то типа:

create_generated_clock -name FWD_data_out_clk -multiply_by 1 -source [get_pins ODDR_BUFF/C] [get_ports data_out_clk]
set_output_delay -clock FWD_data_out_clk  -max  x.xxx  [get_pins DATA_OUT_ODDR_BUFF/D0]
set_output_delay -clock FWD_data_out_clk  -max  x.xxx  [get_pins DATA_OUT_ODDR_BUFF/D1]
set_output_delay -clock FWD_data_out_clk  -min -x.xxx  [get_pins DATA_OUT_ODDR_BUFF/D0]
set_output_delay -clock FWD_data_out_clk  -min -x.xxx  [get_pins DATA_OUT_ODDR_BUFF/D1]

Можно же предположить что задержки на всех ODDR примерно одинаковые, и нет смысла их как-то учитывать при расчете таймингов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

@Flip-fl0p

Сорри, я пропустил, что дженерейтед клок у вас уже правильно описан в первом посте

create_generated_clock -name FWD_data_out_clk -multiply_by 1 -source [get_pins PLL_comp/inst/mmcme4_adv_inst/CLKOUT0] [get_ports data_out_clk]

Суть этого клока - мастером является выход pll, а вершиной - внешний вывод data_out_clk, поскольку в source-synchronous интерфейсе тайминг (в спецификациях) задается относительно клока вне микросхемы-источника, а не внутри нее.

И дальше надо просто set_output_delay указать относительно этого клока, как в вашем последнем посте

set_output_delay -clock FWD_data_out_clk  -max  x.xxx  [get_ports data_out]
set_output_delay -clock FWD_data_out_clk  -min -x.xxx  [get_ports data_out]

если есть входные сигналы этого интерфейса, то set_input_delay тоже делается относительно FWD_data_out_clk.

Плюс, надо учесть, что от паразитной емкости вывода data_out_clk зависит задержка выходного пада микросхемы (фактически - влияет на летенси клока FWD_data_out_clk). Паразитная емкость складывается из емкости дорожки на плате, а так же входной емкости выводов микросхем-приемников сигнала. Эту емкость надо учитывать в синтезе, ее констрейнят с помощью set_load. Не знаю, пождерживает ли этот констрейнт ваш тул, почитайте про него в хелпе.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По поводу set_load и Vivado:

Quote

Sets the load capacitance on output ports to the  specified  value. The load capacitance is used during power analysis when running the  report_power  command, but is not used during t iming  analysis.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...