Imax9
NEWS   ARTICLES   MINIMIG   FILES   ABOUT

Демистификация временных ограничений.

Проблема временных ограничений начинает выползать, как только начинаешь переходить от мигания светодиодиками к чему-то серьезному. Данная статья является переводом Demystifying Timing Constraints с сайта уважаемого Alastair M. Robinson рассказывает о практическом применении проекта с SDRAM. Для начала советую почитать теорию "Статический временной анализ demystified" Часть 2, еще интересная про Метастабильность... и первая половина статьи общая для всех вендоров Временные ограничения...

При проектировании системы с различными виртуальными компонентами внутри FPGA передача данных от одного модуля к другому довольно проста. При условии, что два модуля используют один и тот же тактовый сигнал (clock), мы просто посылаем исходящие данные на фронте такта и отбираем их в приемном модуле на следующем фронте такта. Новые данные имеют в запасе целый тактовый цикл, в течение которого, они проходят от источника к месту назначения.

 internal

Однако все усложняется, когда модули не находятся в одном чипе. Типичным примером является создание FPGA проекта, взаимодействующего с SDRAM.

Так почему же все становится намного сложнее, когда одно из устройств является внешним? Короче говоря, задержки. Задержки маршрутизации, задержки из-за емкостной нагрузки, задержки установки и удержания (setup-and-hold), задержки наростания и спада (rise-and-fall). Каждая из этих задержек уменьшает окно возможностей для выборки достоверных данных, и чем уже это окно становится, тем тщательнее мы должны контролировать временные ограничения нашего проекта FPGA.

В приведенном выше примере заштрихованная область представляет собой временное окно, в течение которого получатель мог бы сделать выборку высокого уровеня исходного сигнала и получить достоверные данные. Это окно имеет почти полный тактовый цикл по ширине, и в примере мы выбрали его прямо в конце окна. Хотя может показаться, что это близко к комфортным значениям, небольшие задержки при пересылке данных от ячейки к ячейке в FPGA фактически слегка смещают данные во времени, и программное обеспечение синтеза FPGA автоматически заботится о перекосе тактового сигнала и вставке дополнительных задержек там, где это необходимо, чтобы обеспечить достоверность данных на фронте такта.

Теперь рассмотрим, что происходит, когда мы отправляем данные во внешнюю SDRAM. Из этого окна мы должны вычесть время установки (setup) принимающего устройства и время удержания (hold) принимающего устройства. Окно допустимых данных теперь намного уже, и наш фронт такта защелки (latch) теперь выходят за пределы этого окна, поэтому мы не можем полагаться на то, что выбранные данные являются допустимыми.

external1

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

Проблема решена?
      Хмм... нет!

Мы позаботились об отправке данных на внешнее устройство, но как насчет приема данных? При отправке данных в противоположном направлении тактовый сигнал SDRAM становятся сигналом запуска, а тактовый сигнал FPGA - защелки, что означает, что фазовый сдвиг теперь задерживает, а не опережает тактовый сигнал защелки. Нет никакого способа, чтобы данные, посланные на такте SDRAM, были готовы к следующему фронту тактового сигнала FPGA, так как они находятся очень близко друг к другу, поэтому мы должны выстрелить по тактовому фронту после этого. Но это больше, чем один полный такт. Можно ли достичь этой цели?
В случае записи в SDRAM нам не нужно было беспокоиться о задержках маршрутизации, потому что задержки на сигналах и задержка на часах должны быть примерно равны и, таким образом, должны в значительной степени компенсировать друг друга. Однако при пересылке с SDRAM в FPGA они уже не отменяются, а объединяются. Эта задержка действительно помогает нам, смещая действительные данные к тактовому фронту, к которому мы стремимся. Кроме того, в FPGA существуют входные задержки, и до тех пор, пока программное обеспечение синтеза получает достаточную информацию о требованиях к времени, оно будет вставлять дополнительные задержки, чтобы помочь выровнять тактовую частоту защелки с действительными данными.

Определение временных ограничений в Quartus - это своего рода черное искусство, и найти информацию по этому вопросу непросто. Ниже приводится мое собственное понимание того, как определить временные ограничения внутри Quartus – возможно, я неправильно понял некоторые из них, так что не воспринимайте это как Евангелие, но, похоже, это работает в моих собственных проектах.

Для начала создайте новый файл ограничений проектирования синопсиса, сохраните его, добавьте в проект и в диалоговом окне Assignments -> Settings dialog перейдите на страницу TimeQuest Timing Analyzer и добавьте вновь созданный файл в список файлов SDC для проекта.

Итак, давайте рассмотрим типичный файл .sdc построчно:

#**************************************************************
# Time Information
#**************************************************************

set_time_format -unit ns -decimal_places 3

#**************************************************************
# Create Clock
#**************************************************************

create_clock -name {clk_50} -period 20.000 -waveform { 0.000 0.500 } [get_ports {iSYS_CLK}]

Эта последовательность определяет тактовый сигнал 50 МГц (период 20ns), поступающие в проект на выводе верхнего уровня под названием iSYS_CLK. В большинстве моих проектов этот сигнал не используются ни для чего напрямую – они подаются в PLL, который генерирует реальный тактовый сигнал.

#**************************************************************
# Create Generated Clock
#**************************************************************

derive_pll_clocks

Вместо того чтобы указывать тактовые сигналы PLL по отдельности, мы можем автоматически анализировать и генерировать их.
Однако было бы полезно ссылаться на тактовый сигнал SDRAM по имени, поэтому далее мы создадим их явно.
Путь счетчика PLL будет зависеть от имени, которое вы дали PLL, а также от устройства, которое вы используете: этот пример взят из проекта, который создан для Cyclone II – путь потребуется настроить для других устройств:

create_generated_clock -name sd1clk_pin -source [get_pins {mySysClock|altpll_component|pll|clk[1]}] [get_ports {sdr_clk}]

(Если вы щелкните правой кнопкой мыши в текстовом редакторе Quartus во время редактирования файла SDC, пока TimeQuest в данный момент открыт, вы можете использовать пункт меню Insert-> Generated Clock, чтобы найти правильный путь.)

#**************************************************************
# Set Clock Uncertainty
#**************************************************************

derive_clock_uncertainty;

Добавляет некоторую погрешность к тактовому сигналу, определенному до настоящего времени.

Теперь мы переходим к более сложным вещам. Здесь нам нужно обратиться к спецификации нашей SDRAM. Нам также необходимо сделать приблизительную оценку задержек топологии наших печатных плат. Предполагая, что SDRAM и FPGA находятся рядом друг с другом и имеют только короткие дорожки между ними, 1 нс не будет необоснованной оценкой.

Я возьму следующие параметры для IS42S86400B.
      Параметры, которые нам нужно знать:

#**************************************************************
# Set Input Delay
#**************************************************************

set_input_delay -clock sd1clk_pin -max 6.4 [get_ports sdr_data*]
set_input_delay -clock sd1clk_pin -min 1.0 [get_ports sdr_data*]

Здесь мы говорим Quartus, сколько времени после тактового фронта SDRAM мы можем ожидать, прежде чем действительные данные поступят на ПЛИС.
Единственные контакты SDRAM, которые отправляют данные обратно в ПЛИС, - это контакты данных, поэтому подстановочный знак (*) в части get_ports отражают это.
Для максимальной задержки ввода мы берем наибольшее время вывода и добавляем расчетную задержку маршрутизации.
Для минимальной задержки мы берем наименьшее время вывода и снова добавляем задержку маршрутизации.

#**************************************************************
# Set Output Delay
#**************************************************************

set_output_delay -clock sd1clk_pin -max 1.5 [get_ports sdr_*]
set_output_delay -clock sd1clk_pin -min -0.8 [get_ports sdr_*]

Здесь мы говорим, что у нас должны быть действительные данные на линиях за 1,5 нс до тактового фронта SDRAM, и они должны оставаться действительными до 0,8 нс *после* тактового фронта, следовательно, 0,8 является отрицательным. Это относится ко всем сигналам, связанным с SDRAM, за исключением тактового сигнала, поэтому рекомендуется назвать вывод синхросигнала так, чтобы он не был пойман знаком (*). В качестве альтернативы вы можете указать эти линии для каждой группы сигналов индивидуально, вместо того чтобы использовать такой подстановочный знак с широким охватом сигналов.

И последнее, но не менее важное: нам нужно установить “multicycle path”, чтобы справиться с тем фактом, что мы пропускаем фронт тактовой частоты при чтении данных из SDRAM.

#**************************************************************
# Set Multicycle Path
#**************************************************************

set_multicycle_path -from [get_clocks {sd1clk_pin}] -to [get_clocks {mySysClock|altpll_component|pll|clk[0]}] -setup -end 2

И это в основном все. Указав этот файл, перекомпелируйте проект, а затем запустите TimeQuest.

Из TimeQuest запустите отчет “Report all IO timings” и посмотрите, не происходит ли какой-либо сбоя. Если это так, отрегулируйте фазовый сдвиг тактового сигнала SDRAM, который, вероятно, он окажется где-то между -0,5 нс и -2,5 нс.


Адрес для контактов : imax9@narod.ru

Если вам понравились мои работы и вы желаете поддержать сайт - сделайте дотацию.

При копировании статьи – обязательна ссылка на авторство и источник. Без разрешения автора копирование запрещено.

© Максим Ильин 2022г.

Яндекс.Метрика