Шлепанцы и защелка приводят к дилемме

Может ли кто-нибудь объяснить мне, почему вместо триггера следует выводить защелку?

always_ff @ (posedge clk, negedge rst) 
begin
  if (!rst)
    a <= '0;
end

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

Этот вопрос исходит из выбранного лучшего ответа из этого вопроса о стеке:
System Verilog always_latch против always_ff

===========================================================================

Я поделюсь здесь тем, что узнал до сих пор. Причина, по которой это синтезируется в защелку, а не в триггер, заключается в том, что с правой стороны назначения находится КОНСТАНТА. В этом случае поведение защелки и триггера ЭКВИВАЛЕНТНО, потому что не имеет значения, захватывает ли он входное значение на фронте сигнала (триггер) или при включенной фиксации входа (защелка) так как ввод не меняется. Таким образом, инструмент синтеза выбирает элемент, который требует меньше ресурсов, то есть защелку.

С другой стороны, если бы в правой части присваивания была ПЕРЕМЕННАЯ, синтез должен был бы вывести триггер, потому что будет иметь значение, будет ли входной сигнал дискретизирован по краю (триггер) или во время включения фиксации входа (защелкивания), это означает, что два логических элемента НЕ ЭКВИВАЛЕНТНЫ.

Вот пример. Первые два блока всегда будут синтезироваться в защелку (в Quartus 14), что нормально, поскольку они эквивалентны из-за константы. Но блоки 3. и 4. always также будут синтезированы в защелку, что не является предполагаемым поведением, и эти блоки не эквивалентны! Блок 3. выдаст предупреждение, а блок 4. - нет.

 module ff_latch(
   input logic clk,
   input logic nrst,
   input logic a,
   output logic t, x, y, z
 );

    always_ff @(posedge clk, negedge nrst) 
       begin
          if (!nrst)
           t <= 0;
       end

    always_latch
       begin
          if (!nrst)
           x <= 0;
       end

    always_ff @(posedge clk, negedge nrst) 
       begin
          if (!nrst)
           y <= a;
       end

    always_latch
       begin
          if (!nrst)
           z <= a;
       end

endmodule: ff_latch

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

введите описание изображения здесь

Блок 3. (tb_y) ведет себя как асинхронный триггер, а блок 4. (tb_z) ведет себя как защелка. Но инструмент синтеза предполагает фиксацию в обоих случаях.

Если кто-то может пролить свет на это или прокомментировать код или форму волны, это будет очень полезно.


person evilpascal    schedule 01.06.2016    source источник


Ответы (2)


Синтезатор определит защелку, потому что этот код ведет себя как защелка. Он не ведет себя как триггер. Это так просто.

Подумайте, как ведет себя этот код: изначально значение a будет 'x. Когда для rst установлено низкое значение, тогда a станет '0. a останется на '0 навсегда. Таким образом, состояние a зависит не только от текущего состояния входов, но и от прошлого состояния. Следовательно, у нас есть последовательная логика, а не комбинационная логика. Триггеры изменяют состояние по фронту тактового сигнала; a нет. Тот факт, что блок Always чувствителен к фронту сигнала, не имеет значения. Это просто означает, что код внутри выполняется на этом фронте сигнала - положительном фронте clk. Но когда это происходит, ничего не происходит, поэтому этот код ведет себя как защелка.

person Matthew Taylor    schedule 01.06.2016
comment
Хорошо, но мне кажется, что он тоже может вести себя как триггер. При отрицательном сбросе сбросьте триггер, в противном случае при положительном фронте clk сохраните предыдущее значение. Это было бы эквивалентно: [ссылка] (imgur.com/htuPVsC) Кроме того, оборудование не может иметь состояние x. Это может быть 0, 1 или Z, поэтому в обоих случаях (с защелкой или триггером) при включении питания будет установлено какое-то произвольное значение (0 или 1). Мне кажется, что код может вести себя как оба, но инструменты синтеза выбирают тот, который требует меньше ресурсов. - person evilpascal; 01.06.2016
comment
@evilpascal Выбор схемы, которая потребляет меньше ресурсов, в значительной степени является хлебом для синтезатора. - person Matthew Taylor; 02.06.2016

Потому что вы не указали, что происходит при постановке часов. Как будто a вообще не зависит от clk или его позиции. Все ваше описание говорит, что a установлен на 0, когда rst=0. Более того, он говорит (неявно), что a сохраняет свое предыдущее значение во всех других случаях. Это может быть реализовано с помощью защелки.

Обратите внимание, что только то, что у вас @posedge clk, не означает, что каждая переменная внутри этого блока будет синтезирована как флоп. Вам также потребуется неблокирующее назначение для a, когда блок активируется при нажатии clk. См. здесь.

Если вы настаиваете на провале для реализации той же функции, вы можете попробовать следующее:

always_ff @ (posedge clk or negedge rst) 
begin
  if (!rst)
    a <= '0;
  else 
    a <= a;  //Here, we are specifying what happens @posedge of clk
end
person Ari    schedule 01.06.2016
comment
Но первый код в моем сообщении должен вести себя как триггер с асинхронным сбросом, а не с защелкой, поскольку он должен выполнять выборку только на заднем фронте сброса, а не все время, пока сброс не выполняется. См. Мой анализ в отредактированном вопросе. - person evilpascal; 02.06.2016
comment
То, что может сделать флоп, чего не может защелкнуть, - это выборка сигналов на границе clk. При сбросе выходное значение устанавливается на постоянное значение. Это может быть реализовано с помощью защелки, которую предпочитают инструменты синтеза из-за ее более низкой площади. Сигнал y в вашем примере действует как флоп, потому что теперь nrst действует как тактовый сигнал и производит выборку входного значения по его краю. Это невозможно сделать с помощью одной защелки. Обратите внимание, что хотя вы указываете @negedge rst, поскольку выход назначен константе, он не должен быть чувствительным к краям для rst. Достаточно модуля, чувствительного к первому уровню. - person Ari; 02.06.2016
comment
Когда константа находится справа от присваивания, поведение защелки и триггера эквивалентно. Это не проблема. Вы упоминаете сигнал y, и здесь все становится странно, потому что и y, и z синтезируются как защелки, и я утверждаю, что это не может быть правдой. Поскольку в правой части назначения находится переменная (сигнал), функциональность двух последних блоков always (y и z) не может быть эквивалентной (см. Мой прилагаемый анализ и форму волны). - person evilpascal; 02.06.2016