Использование непрерывного назначения в процедуре Verilog?

Возможно ли и / или полезно ли когда-либо использовать непрерывное назначение в процедуре Verilog? Например, будет ли когда-либо assign внутри always блок?

Например этот код:

always @(*) 
begin 
  assign data_in = Data;
end

Кроме того, было бы возможно генерировать последовательную логику с таким подходом?

always @(posedge clk) 
begin 
  assign data_in = Data;
end

1 ответ

Решение

Это называется процедурным непрерывным назначением. Это использование assign или же force (и их соответствующие аналоги deassign а также release) в пределах процессуального блока. Новый непрерывный процесс присваивания создается при достижении строки в процедурном блоке. assign может применяться к типам регистров, таким как reg, integer, а также real, force может применяться к регистрам и сетям (т.е. wireс). Он был частью LRM с 1364-1995.

  • Стандарт IEEE 1364-1995 § 9.3
  • Стандарт IEEE 1364-2001 § 9.3
  • Стандарт IEEE 1364-2005 § 9.3
  • Стандарт IEEE 1800-2005 § 25.3
  • Стандарт IEEE 1800-2009 § 10.6
  • Стандарт IEEE 1800-2012 § 10.6

Процедурные непрерывные назначения синтезируются большинством инструментов. Однако рекомендуется ограничить использование моделированием поведения аналогового блока, файлами тестового стенда или исправлением функциональных несоответствий RTL<->gate.

  • always @* assign data_in = Data;
    функционально так же, как
    always @* data_in = Data;

  • always @(posedge clk) assign data_in = Data;
    Функционально так же, как:
    always @(posedge clk)
      enable = 1;
    always @*
      if (enable==1) data_in = Data;

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

always @(posedge clk or negedge rst_n, negedge set_n) begin
   if (!rst_n)      q <= 1'b0;
   else if (!set_n) q <= 1'b1;
   else             q <= d;
end

Он синтезируется на флопе с асинхронным набором и сбрасывается с приоритетом сброса. Однако при моделировании модель является неточной, если rst_n а также set_n оба низкие тогда rst_n идет высоко q Если перейти к 1, асинхронный набор все еще включен, но в списке чувствительности ничего не активируется. Это хорошо задокументированная проблема с Verilog. Это единственный случай, когда процедурное непрерывное назначение разрешено в RTL при использовании с ключевым словом translate off вашего синтезатора. release/deassign позволяет назначить регистр / провод обычным способом.

// translate_off
always @(rst_n or set_n)
  if (rst_n && !set_n) force q = 1'b1;
  else                 release q;
// translate_on

ИЛИ (в настоящее время действует, но не рекомендуется)

// translate_off
always @(rst_n or set_n)
  if (rst_n && !set_n) assign q = 1'b1;
  else                 deassign q;
// translate_on

С помощью assign/deassign таким образом считается устаревшим в будущем выпуске IEEE 1800. IEEE Std 1800-2005 § 25.3, IEEE Std 1800-2009 § C.4.2 и IEEE Std 1800-2012 § C.4.2 признает assign Использование этого способа вызывает путаницу и является источником ошибок. использование force/release если процедурное непрерывное назначение по мере необходимости.

В генерации с использованием процедурного непрерывного присваивания (с force/release) следует использовать только в случае крайней необходимости. Альтернативные подходы более надежны.

Злоупотребление процедурным непрерывным назначением и решениями:

  • Комбинационная логика на reg:

    always @(sel)
      if (sel) assign reg1 = func1(x,y,z);
      else     assign reg1 = func2(a,b,c);
    
    • Решение:

      always @* // <- IEEE Std 1364-2001 construct
        if (sel) reg1 = func1(x,y,z);
        else     reg1 = func2(a,b,c);
      
  • Комбинационная логика на wire:

    always @(sel)
      if (sel) force wire1 = func1(x,y,z);
      else     force wire1 = func2(a,b,c);
    
    • Решение:

      assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
      
  • Последовательная логика:

    always @(posedge clk)
      if (sel) assign reg2 = func1(x,y,z);
      else     assign reg2 = func2(a,b,c);
    
    • Решение (если исходная функциональность неверна):

      always @(posedge clk)
        if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!!
        else     reg2 <= func2(a,b,c);
      
    • Решение (если исходная функциональность верна):

      reg flop_sel;
      always @(posedge clk)
        flop_sel <= sel; // Non-blocking assignment !!!
      always @*
        if (flop_sel) reg2 = func1(x,y,z); // Blocking assignment !!!
        else          reg2 = func2(a,b,c);
      
Другие вопросы по тегам