Конструкция синхронного сброса в fpga как ограничивающий фактор для временных ограничений

у меня есть дизайн fpga, который использует синхронные сбросы (я предпочитаю синхронные сбросы асинхронным по причинам, обсуждаемым в другом месте). У меня есть четыре разных домена часов в дизайне, и я использую одну кнопку для генерации сигнала сброса, который, конечно, полностью асинхронен ко всему (сохраните мой палец). Я дебатирую сигнал кнопки в каждом из четырех тактовых доменов, чтобы генерировать синхронные сбросы для четырех доменов из одного источника. Мой модуль debounce в основном подсчитывает N тактов утверждаемой кнопки сброса. Если с утвержденным сбросом прошло более N циклов, я генерирую сигнал сброса (код для этого модуля вставлен ниже).

первый вопрос -- есть ли лучшие способы создания сброса (ов), чем этот метод?

второй (более интересный вопрос): когда я смотрю на отчеты о синхронизации (с помощью инструментов xilinx), я вижу, что последовательно все ограничивающие сигналы связаны с сбросом. Например, предельный путь-от генератор сброса (debouncer) в государственный реестр некоторой государственной машины. Сигналы сброса очень высоки (они касаются всего в своих соответствующих тактовых доменах). Я немного удивлен, хотя моя скорость ограничена сбросом. Я нахожу, что я ограничен чем-то вроде 8.5 nS, где ~50% маршрутизации и ~50% это логика. Есть предложения, как сделать это немного лучше? Как вы идете о общаться с одновременным поколением возврата в конструкциях fpga?

вот код для генерации сброса. Обратите внимание, что сигнал сброса сигнала сродни выходу debounced (например, когда я создаю экземпляр модуля debounced output-сброс для этого конкретного домена часов).

module button_debouncer(/*AUTOARG*/
   // Outputs
   debounced,
   // Inputs
   clk, button
   );
   /* Parameters */
   parameter WIDTH = 1;
   parameter NUM_CLKS_HIGH = 12000000;
   parameter log2_NUM_CLKS = 24;

   /* Inputs */
   input clk;
   input [WIDTH-1:0] button;

   /* Outputs */
   output [WIDTH-1:0] debounced;

   /* Regs and Wires */
   reg [WIDTH-1:0]    b1, b2;
   reg [log2_NUM_CLKS-1:0] counter;

   /* Synched to clock domain */
   always @(posedge clk) begin
      b1 <= button;
      b2 <= b1;
   end

   /* Debounce the button */
   always @(posedge clk) begin
      if(~b2)
    counter <= 0;
      else if(counter < {log2_NUM_CLKS{1'b1}})
    counter <= counter + 1;
   end

   /* Assign the output */
   //wire [WIDTH-1:0] debounced = counter > NUM_CLKS_HIGH;
   reg [WIDTH-1:0] debounced;

   always @(posedge clk) begin
      debounced <= counter > NUM_CLKS_HIGH;
   end

endmodule //button_debouncer

2 ответов


очень хороший способ улучшить результаты синхронизации при работе со сбросами-закрыть максимальный разветвитель. затем инструменты буферизуют сигнал, чтобы не было ни одного lut, пытающегося маршрутизироваться и использоваться для управления каждым регистром. Это можно сделать следующим образом:--2-->

(* max_fanout = <arbitrary_value> *) 
wire reset; 

Итак, у нас есть ограничение, используемое инструментом синтезатора vivado (или если вы все еще используете ISE, то этот инструмент). Кроме того, если следует отметить, что это влияет только на следующее объявление сети, поэтому другие сети (провода, правила, ext), объявленные до или после этого, не затрагиваются.

на веб-сайте xilinx есть хорошее руководство пользователя ограничения. Есть еще несколько других, которые вы можете посмотреть, и они: IBUF или BUFG.


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

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