временное ограничение для схем шинного синхронизатора

У меня есть схема шинного синхронизатора для передачи широкого регистра по тактовым доменам.

Я приведу упрощенное описание, опуская логику асинхронного сброса.

Данные генерируются за один такт. Обновления разнесены на много (по крайней мере, дюжину) тактов:

PROCESS (src_clk)
BEGIN
   IF RISING_EDGE(clock) THEN
      IF computation_done THEN
          data <= computation;
          ready_spin <= NOT ready_spin;
      END IF;
   END IF;
END PROCESS;

Управляющий сигнал для свежих данных в кодировке NRZI (поэтому действительное слово на шине соответствует переходу управляющего сигнала). Управляющий сигнал проходит через цепь DFF, выполняющую роль синхронизатора.

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      ready_spin_q3 <= ready_spin_q2;
      ready_spin_q2 <= ready_spin_q1;
      ready_spin_q1 <= ready_spin;
   END IF;
END PROCESS;

Схема синхронизатора вводит короткую задержку, что дает достаточно времени для стабилизации шины данных; шина данных дискретизируется напрямую без риска метастабильности:

PROCESS (dest_clk)
BEGIN
   IF RISING_EDGE(dest_clk) THEN
      IF ready_spin_q3 /= ready_spin_q2 THEN
         rx_data <= data;
      END IF;
   END IF;
END PROCESS;

Это компилируется и хорошо работает при синтезе в Cyclone II FPGA. Однако TimeQuest сообщает о нарушениях времени установки и удержания, поскольку не распознает синхронизатор. Хуже, как говорится в руководстве Quartus

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

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

Я почти уверен, что set_multicycle_pathэто правильная команда SDC (Synopsis Design Constraint), поскольку линии данных будут иметь несколько циклов часов назначения для стабилизации, но я не могу найти полных примеров использования этой команды для описания логики пересечения области часов. .

Я был бы очень признателен за некоторые рекомендации по написанию временных ограничений SDC для синхронизаторов. Если вы видите проблему с этим подходом, сообщите мне об этом.


Деталь часов:

Внешний тактовый генератор: два канала, refclk = 20 МГц, refclk2 = refclk/2 (10 МГц и т. д.).

PLL Altera: src_clk = refclk * 9/5 = 36 МГц

Altera PLL: dest_clk = refclk2 * 10 = 100 МГц

У меня также есть данные, идущие в другом направлении, с частотой 100 МГц src_clk и 36 МГц dest_clk.


TL;DR: Каковы правильные временные ограничения SDC для приведенного выше кода?

Это было бы лучше на предложенном сайте FPGA Design, но это предложение еще не достигло бета-версии.
Можете ли вы опубликовать определения часов для src_clk и dest_clk? Связаны ли они каким-либо образом (синхронные кратные)? Если это несвязанные часы, то в этой ситуации обычно используется set_false_path.
@Энди: я добавил некоторые детали. Спасибо, что помогли с этим.

Ответы (4)

У меня нет опыта работы с Quartus, так что относитесь к этому как к общему совету.

При работе с путями между доменами часов инструменты синхронизации расширяют часы до наименьшего общего кратного их периодов и выбирают ближайшую пару ребер.

Для путей от тактовой частоты 36 МГц (27,777 нс) к тактовой частоте 100 МГц (10 нс), если я правильно провел свои быстрые расчеты, ближайшая пара нарастающих фронтов составляет 138,888 нс на тактовой частоте источника и 140 нс на тактовой частоте назначения. Это фактически ограничение в 900 МГц для этих путей! В зависимости от округления (или для часов без отношения) может получиться хуже.

Есть по крайней мере три способа написать ограничения для этой структуры. Я собираюсь назвать часы , fast_clkи slow_clk, как я думаю, это понятнее для иллюстрации.

Вариант 1: отключить синхронизацию с помощьюset_false_path

Самое простое решение - set_false_pathотключить синхронизацию между часами:

set_false_path -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_false_path -from [get_clocks slow_clk] -to [get_clocks fast_clk]

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

Вариант 2: ослабить ограничение с помощьюset_multicycle_path

Вы можете выделить дополнительное время для определенных путей с помощью set_multicycle_path. Чаще используются многоцикловые пути с тесно связанными часами (например, взаимодействующие часы 1X и 2X), но и здесь это будет работать, если инструмент поддерживает это в достаточной степени.

set_multicycle_path 2 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -setup
set_multicycle_path 1 -from [get_clocks slow_clk] -to [get_clocks fast_clk] -end -hold

Отношение краев по умолчанию для настройки — один цикл, set_multicycle_path 1т.е. Эти команды разрешают еще один цикл конечной точки ( -end) для путей настройки. Корректировка -holdс номером, меньшим на единицу, чем ограничение настройки, почти всегда требуется при настройке многоцикловых путей, подробнее см. ниже.

Чтобы аналогичным образом ограничить пути в другом направлении (ослабив ограничение на один период более быстрых часов), измените -endна -start:

set_multicycle_path 2 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -setup
set_multicycle_path 1 -from [get_clocks fast_clk] -to [get_clocks slow_clk] -start -hold

Вариант 3: указать требование напрямую с помощьюset_max_delay

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

set_max_delay 10 -from [get_clocks fast_clk] -to [get_clocks slow_clk]
set_max_delay 10 -from [get_clocks slow_clk] -to [get_clocks fast_clk]

Вы можете соединить это с set_min_delayпроверками удержания или оставить проверку удержания по умолчанию на месте. Вы также можете set_false_path -holdотключить проверки удержания, если ваш инструмент поддерживает это.


Кровавые подробности выбора ребер для многоцикловых путей

Чтобы понять регулировку удержания, которая связана с каждой регулировкой установки, рассмотрим этот простой пример с отношением 3:2. Каждая цифра представляет нарастающий фронт тактового сигнала:

1     2     3
4   5   6   7

Проверка установки по умолчанию использует края 2 и 6. Проверка удержания по умолчанию использует края 1 и 4.

Применение ограничения на несколько циклов, равного 2 -end, настраивает проверки настройки и удержания по умолчанию, чтобы использовать следующее ребро после того, которое они использовали изначально, что означает, что проверка настройки теперь использует ребра 2 и 7, а проверка удержания использует ребра 1 и 5. Для двух тактируется на одной частоте, такая настройка имеет смысл — каждому запуску данных соответствует один захват данных, и если край захвата сдвинут на единицу, то и проверка удержания тоже должна сместиться на единицу. Такое ограничение может иметь смысл для двух ветвей одного тактового генератора, если одна из ветвей имеет большую задержку. Однако в данной ситуации проверка удержания с использованием ребер 1 и 5 нежелательна, поскольку единственный способ исправить это — добавить полный тактовый цикл задержки на пути.

Ограничение многоциклового удержания, равное 1 (для удержания, значение по умолчанию равно 0), сдвигает фронт тактового сигнала назначения uesd для проверок удержания назад на один фронт. Комбинация 2-тактной настройки MCP и 1-цикла удержания MCP приведет к проверке настройки с использованием ребер 2 и 7 и проверке удержания с использованием ребер 1 и 4.

Этот ответ превосходен. Добавлю совет. Используйте TimeQuest Timing Analyzer, чтобы создать новые правила для файла sdc. Может быть сложно правильно синтаксис, если вы просто следуете руководству sdc. Также: я настоятельно рекомендую прочитать этот документ: fpgawiki.intel.com/wiki/File:TimeQuest_User_Guide.pdf

Я не знаю ответа для Altera, но в Xilinx Land вы можете установить временную задержку от одного домена часов к другому. Вам придется поработать над математикой (это зависит от дизайна), но обычно это самый короткий из двух периодов тактов. Думайте об этом времени как о максимальном рассогласовании между любыми двумя сигналами (включая ваш сигнал управления), и вы можете решить, сможет ли ваша схема синхронизации справиться с этим.

set_mulicycle_path не является правильной вещью для использования, потому что это обычно имеет дело со случаями, когда и источник, и место назначения находятся в одном и том же часовом домене. Опять же, я основываюсь на своем опыте с Xilinx, поэтому ваш опыт может отличаться.

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

Разве это не set_multicycle_pathспособ сообщить синтезатору/анализатору времени, как часто могут изменяться исходные сигналы? И я не уверен, что вы подразумеваете под «автобусными часами», здесь есть сигнальная шина, пересекающая домены часов, так какие часы вы называете «автобусными часами»? Я думаю, вы правы в том, что все еще может быть метастабильность, если синтезатор вносит сбои в периоды, когда я не обновляюсь data. Думаю, я мог бы специально создавать блоки DFF там :(
@BenVoigt: я думаю, что «set_multicycle_path» чаще используется, чтобы сообщить валидатору времени, что цепочке комбинаторной логики между двумя точками фиксации должно быть разрешено принимать N (Tc) -Ts-Tp (время цикла N раз минус время выборки минус защелка время распространения) вместо просто Tc-Ts-Th. Я не знаю, как такая штука будет взаимодействовать с фиксацией по разным часам.

Я думаю, что безопасно поставить set_false_path над синхронизатором.

Также вы можете указать «set_global_assignment -name SYNCHRONIZER_IDENTIFICATION AUTO» в qsf, чтобы помочь Quartus обнаружить синхронизатор.

Как бы это выглядело? set_false_path -from ready_spin -to ready_spin_q2? И set_false_path -from data -to rx_data?
set_false_path -from src_clk -to ready_spinЯ не уверен, что уместно указать ложный путь к данным, поскольку вы не синхронизируете их.