У меня есть схема шинного синхронизатора для передачи широкого регистра по тактовым доменам.
Я приведу упрощенное описание, опуская логику асинхронного сброса.
Данные генерируются за один такт. Обновления разнесены на много (по крайней мере, дюжину) тактов:
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 для приведенного выше кода?
У меня нет опыта работы с 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.
Я не знаю ответа для Altera, но в Xilinx Land вы можете установить временную задержку от одного домена часов к другому. Вам придется поработать над математикой (это зависит от дизайна), но обычно это самый короткий из двух периодов тактов. Думайте об этом времени как о максимальном рассогласовании между любыми двумя сигналами (включая ваш сигнал управления), и вы можете решить, сможет ли ваша схема синхронизации справиться с этим.
set_mulicycle_path не является правильной вещью для использования, потому что это обычно имеет дело со случаями, когда и источник, и место назначения находятся в одном и том же часовом домене. Опять же, я основываюсь на своем опыте с Xilinx, поэтому ваш опыт может отличаться.
Я подозреваю, что проблема в том, что, хотя вы можете знать, что сигналы шины не будут меняться нигде вблизи точки, где они зафиксированы, программное обеспечение этого не знает. Лучше всего, вероятно, явно указать программному обеспечению, что входящие сигналы шины синхронизируются с шинными часами, и отключить любые оптимизации до того места, где вы фактически зафиксируете их (оптимизатор теоретически мог бы заменить вашу схему на схему, которая была бы эквивалентна если бы входы действительно были синхронными, но которые могли бы быть брошены для цикла, если бы они менялись в тактовых циклах, о которых схема, которую вы нарисовали, не заботилась бы).
set_multicycle_path
способ сообщить синтезатору/анализатору времени, как часто могут изменяться исходные сигналы? И я не уверен, что вы подразумеваете под «автобусными часами», здесь есть сигнальная шина, пересекающая домены часов, так какие часы вы называете «автобусными часами»? Я думаю, вы правы в том, что все еще может быть метастабильность, если синтезатор вносит сбои в периоды, когда я не обновляюсь data
. Думаю, я мог бы специально создавать блоки DFF там :(Я думаю, что безопасно поставить 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
Я не уверен, что уместно указать ложный путь к данным, поскольку вы не синхронизируете их.
Бен Фойгт
Энди
Бен Фойгт