Смешивание неблокирующих и блокирующих назначений в блоке always_ff арбитра

Я не могу понять пример 10-3 в Книга SystemVerilog For Design Стюарта Сазерленда (и компании).

См. строку 232:

https://code.google.com/p/vak-opensource/source/browse/trunk/hardware/systemverilog/utopia-example/squat.sv?r=185

Вот фрагмент кода. Мой вопрос последует.

  bit [0:NumRx-1] RoundRobin;

  always_ff @(posedge clk, posedge reset) begin: FSM
    bit breakVar;
    if (reset) begin: reset_logic
      Rxready <= '1;
      Txvalid <= '0;
      Txsel_out <= '0;
      SquatState <= wait_rx_valid;
      forward <= 0;
      RoundRobin = 1;
    end: reset_logic
    else begin: FSM_sequencer
      unique case (SquatState)

        wait_rx_valid: begin: rx_valid_state
          Rxready <= '1;
          breakVar = 1;
          for (int j=0; j<NumRx; j+=1) begin: loop1
            for (int i=0; i<NumRx; i+=1) begin: loop2
              if (Rxvalid[i] && RoundRobin[i] && breakVar)
                begin: match
                  ATMcell <= RxATMcell[i];
                  Rxready[i] <= 0;
                  SquatState <= wait_rx_not_valid;
                  breakVar = 0;
                end: match
            end: loop2
            if (breakVar)
              RoundRobin={RoundRobin[1:$bits(RoundRobin)-1],
                          RoundRobin[0]};
          end: loop1
        end: rx_valid_state

В частности, мой вопрос касается назначения блокировки для breakVar и RoundRobin. Я где-то читал, что переменные оцениваются локально, но я не могу представить в терминах вентилей, как синтезируется логика. Синтезируется ли RoundRobin в государственный реестр?

В большинстве руководств говорится, что нельзя смешивать блокирующие и неблокирующие назначения. Есть ли лучший способ представить что-то подобное? Можно ли теперь в проектах SystemVerilog смешивать оба типа назначений, учитывая, что они находятся в блоке always_ff?


person edc    schedule 13.06.2014    source источник


Ответы (2)


Вы никогда не должны смешивать блокирующие и неблокирующие назначения для одной и той же переменной. breakVar — это временная переменная, которая будет синтезирована в комбинаторной логике, поскольку она всегда сначала записывается, а затем считывается. Нет состояния для сохранения. RoundRobin — это локальная переменная, которая используется как промежуточная переменная и как переменная состояния. Но поскольку доступ к нему осуществляется только из блока always_ff, опасности возникновения состояния гонки нет.


Временная переменная — это просто символический способ представления части уравнения. Вот другой, но более простой пример:

always_ff @(posedge clock)
   begin
   full = (counter == 10);
   brimming = (counter > 7);
   hold <= brimming && !full;
   if (full) 
      counter <= counter + 1;
   else 
      counter < = 0;
end

Это эквивалентно написанию следующего (но может быть труднее понять)

always_ff @(posedge clock)
   begin
   hold <= (counter > 7) && !(counter == 10);
   if (counter == 10) 
      counter <= counter + 1;
   else 
      counter < = 0;
end

В двух приведенных выше примерах counter всегда будет синтезироваться как регистр, потому что он читается перед записью. Неважно, использовали ли мы блокирующее или неблокирующее присваивание, потому что мы никогда не читаем counter после его записи. В этом блоке always_ff нет состояния гонки, использующего присваивание блокировки, но оно могло бы быть, если бы другой блок always_ff пытался его прочитать. Поскольку full и brimming записываются перед чтением, их не нужно регистрировать.

Подводя итог, переменная синтезируется как регистр, если выполняется любое из этих условий.

  1. Переменная читается перед записью в том же блоке always. Обратите внимание, что даже если неблокирующий оператор присваивания появляется первым, чтение происходит первым, потому что запись запланирована на более позднее время.
  2. Из-за условных или циклических операторов переменная иногда читается без записи.
  3. Переменная записывается в блок always_ff и читается вне блока.
person dave_59    schedule 13.06.2014
comment
Я не уверен, что это правильно - RoundRobin в данном случае является регистром, действительно должно использоваться неблокирующее присваивание. - person Chiggs; 13.06.2014
comment
Я был наполовину прав - RoundRobin сохраняет состояние, но также считывается после записи в цикле и поэтому требует присваивания блокировки... Мой комментарий немного вводил в заблуждение, но вы заметили преднамеренную ошибку;) - person Chiggs; 13.06.2014
comment
Подход с 2 блоками всегда чище, хотя и требует немного больше ввода. Один always_comb для всех блокирующих назначений, включая значения next_state, и always_ff для неблокирующего присвоения состояний их next_state. Это позволяет увидеть вывод D в волне, которая полезна для отладки. Я считаю, что это упрощает выполнение и документирование ECO. Согласно статье Клиффа SNUG2003 по FSM, подход 2-always дает больше возможностей. и время, но я думаю, что это действительно зависит от инструмента/версии. - person Greg; 13.06.2014
comment
@ dave_59, не могли бы вы немного рассказать о том, как синтезируется временная переменная? - person Shashank V M; 14.10.2020
comment
Обновленный ответ. - person dave_59; 18.10.2020

Полностью согласен с ответом @jonathan.

Вы всегда должны разделять свои логические элементы в блоке always_comb и последовательные элементы в блоке always_ff.

  • Если вы пишете код, который так тесно сшит вместе (как комбинированные, так и последовательные элементы в одном блоке), даже если он правильный и соответствует спецификации системного Verilog, некоторые старые версии симулятора или новые разрабатываемые симуляторы могут вывести его неправильно.

  • Ваш код не будет чистым и понятным для других.

  • Кроме того, написав в вышеприведенном стиле, вы просто сжимаете строки кода, хотя логика остается прежней. Нет смысла писать компактный код, если он мешает читабельности кода.

Теперь, что касается использования блокирующих и неблокирующих операторов, я думаю, что дискуссия закрыта. Теперь использование блокирующих операторов в блоке always_comb и неблокирующих в блоке always_ff является скорее правилом, чем рекомендацией.

Однако ответы на все ваши вопросы объясняются в этой превосходной статье Клиффорда Каммингса Неблокирующие задания в синтезе Verilog, стили кодирования, которые убивают!

И если вы новичок в разработке Verilog/системы Verilog, я предлагаю вам прочитать все их документы, они очень полезны и создают хорошую базу для инженера-проектировщика RTL.

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

Названия сигналов сложно понять за один раз, но если присмотреться, то код очень аккуратен логически и ничего не оставляет на прихоти инструментов моделирования и синтеза.

person nincompoop_    schedule 17.10.2020
comment
Процитированная вами статья посвящена Verilog, а не SystemVerilog. - person Shashank V M; 17.10.2020
comment
@ShashankVM SystemVerilog - это надмножество Verilog, применяются те же концепции. - person nincompoop_; 17.10.2020