«Разблокированная» выборка и защелки в VHDL - PullRequest
5 голосов
/ 01 ноября 2011

Я почти всегда сталкиваюсь с этой проблемой в VHDL, и это, вероятно, связано с моим мышлением; поэтому я надеюсь, что кто-то может указать правильный способ думать об этом.

В любом случае, более чем часто, я начинаю нуждаться в переменной (или, скорее, в «регистре»), которая в основном копирует значение входного сигнала, если сигнал разрешения, скажем, низкий, и сохраняет его «последнее» значение если сигнал разрешения высокий. ( Теперь, когда я написал это, я вижу, что неявно, выборка здесь будет происходить при повышении фронта - переходе от низкого к высокому - сигнала разрешения; поскольку, пока разрешение активно, низкий уровень, то для любого маленькая дельта, изменение ввода распространяется на регистр, и поэтому «перезаписывает» значение, установленное из «предыдущего» времени дельты ).

Итак, моя первая попытка, как правило, самая простая - поместить что-то подобное в мой VHDL-файл:

wdata_reg <= wdata_in when (en_n = '0');  

... что подразумевает разомкнутую / асинхронную схему - и хотя я получаю в результатах моделирования то, что ожидаю, синтезатор ISE WebPack xst, например, barfs с:

WARNING:Xst:737 - Found 8-bit latch for signal <wdata_reg>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

Опять же, я думаю, что то, что я только что описал (разогнанный / асинхронный регистр "выборки") - по определению, защелка? Так что я никогда не уверен, хочу ли я этого там или нет.

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

...
IF en_n = '0' THEN
  wdata_reg <= wdata_in;
END IF;
...

... и, я полагаю, компилятор на это не жаловался (и работал как положено).

Итак, я полагаю, мой вопрос можно сформулировать так: всякий раз, когда мне нужно «сэмплировать» в регистр, всегда ли я должен делать это из конечного автомата (или синхронизированной схемы) - или есть альтернатива? Например, я могу попытаться обмануть « неполное ... if заявления », например:

wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;

... (другими словами: ... еще назначьте себя себе) - но компилятор видит мой нуберизм и все равно выплевывает оле WARNING:Xst:737 :)

Я был бы признателен за некоторые советы о том, как думать об этом, поэтому я не сталкиваюсь с этой дилеммой каждый раз, когда мне нужна регистрация :) Ура!

Ответы [ 3 ]

5 голосов
/ 02 ноября 2011

Итак, моя первая попытка, как правило, самая простая - поместить что-то подобное в мой VHDL-файл:

  wdata_reg <= wdata_in when (en_n = '0');  

Да, это классическая защелка. Это провод, когда en_n равен нулю, и когда он равен одному, wdata_reg будет хранить его значение, поскольку ничто не управляет им.

Опять же, я думаю, что то, что я только что описал (разогнанный / асинхронный регистр "выборки") - по определению, защелка? Поэтому я никогда не уверен, хочу ли я этого там или нет.

Защелки действительно полезны только при пересечении часовых доменов, чтобы избежать сбоев. В общем, вы их не хотите.

Версия внутри синхронизированного процесса сгенерирует регистр, потому что он синхронизирован (сюрприз!). Теперь у вас есть два сигнала: часы и включение. Разница в том, что касается VHDL, состоит в том, что одно присвоение происходит непрерывно (защелка), а одно происходит только по фронту тактовой частоты (регистр)

Итак, я полагаю, мой вопрос можно сформулировать так: всякий раз, когда мне нужно «сэмплировать» в регистр, я должен всегда делать это из конечного автомата (или синхронизированной схемы) - или есть альтернатива?

Это должно быть в синхронизированном процессе. Регистру нужны часы.

Например, я могу попытаться обмануть «неполные ... если утверждения», например так:

wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;

Это точно такое же утверждение, как и раньше. Предложение else выведено в предыдущей версии. Важным моментом является то, что когда wrd_n равен нулю, любые переходы на d_io будут происходить на wd_read_o, это не поведение регистра. Это защелка.

Я был бы признателен за некоторые советы о том, как думать об этом, поэтому я не сталкиваюсь с этой дилеммой каждый раз, когда мне нужна регистрация :) Ура!

В регистрах есть часы, поэтому они должны быть синхронизированы. Просто. (Прости повторение)


Другой распространенный способ вывести защелки без какого-либо значения, если у вас есть асинхронный процесс, через который проходит путь, который не обновляет сигнал.

p_async : process (wibble, wobble)
begin
  if (wibble = '1' and wobble = '0') then
      next_reg_b <= data_in;
  end if;
end process;

Если оператор if не соответствует действительности, next_reg_b не будет обновлен и должен будет содержать его значение. Это создает защелку, поскольку она должна хранить значение, но не хочет защелки (или даже регистра), просто немного логики. Решение состоит в том, чтобы добавить назначение по умолчанию.

p_async : process (wibble, wobble, reg_b)
begin
  next_reg_b <= reg_b;
  if (wibble = '1' and wobble = '0') then
      next_reg_b <= data_in;
  end if;
end process;

Теперь next_reg_b назначается всегда, независимо от состояния wibble и wobble. Без защелки.

3 голосов
/ 02 ноября 2011

Сначала я хотел бы прочитать обзор защелок: Почему я должен заботиться о защелках?

Вы можете построить схему, которую вы описываете, с триггером, запускаемым по ребру, следующим образом. Это будет проходить input, когда enable активно, или последнее значение input, когда enable неактивно.

last_input_set <= input WHEN enable='1' ELSE
                  last_input_reg;
output <= last_input_set;

if rising_edge(clk) then
    last_input_reg <= last_input_set;
end if;
1 голос
/ 02 ноября 2011

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

Это может быть традиционный

process(clk)
begin
  if rising_edge(clk) then
    if en = '1' then
      latched <= raw;
     end if;
  end if;
end process;

Или аккуратнее (если это все, что вы делаете):

latched <= raw when rising_edge(clk) and en = '1';
...