Что такое «Текущее время моделирования» и «Очередь событий» в Verilog? - PullRequest
0 голосов
/ 09 июня 2019

Рассмотрим приведенный ниже пример:

module test;
 reg a;
 initial begin
  a = 1'b0;
  a <= 1'b1;
  $display(a);
 end
endmodule

В приведенном выше примере отображается 0. Моя причина в том, что неблокирующее назначение будет назначено на шаге 3 «Стратифицированной очереди событий», а блокирующее назначение и отображение $ выполнены на шаге 1. Если я изменю пример как :

module test;
 reg a;
 initial begin
  a = 1'b0;
  a <= 1'b1;
  $display(a);
  $monitor(a);
 end
endmodule

Затем печатаются 0 и 1, потому что, я предполагаю, что $ monitor выполняется на шаге 4 Очереди событий (?). Но если я изменю пример дальше:

module test;
 reg a;
 initial begin
  a = 1'b0;
  a <= 1'b1;
  $monitor(a);
  $display(a);
 end
endmodule

Снова вывод: 0 и 1 - чего я не ожидал. Я ожидал, что 1 и 1 будут напечатаны, потому что $ monitor будет оцениваться на шаге 4 Очереди событий, и к этому времени «a» уже равно 1. После этого у нас есть $ display, который должен вывести 1.

Ссылки Я мог бы поговорить о «текущем времени моделирования» и «стратифицированной очереди событий», но я не уверен, как это работает.

Я ценю ваше объяснение! Спасибо

Ответы [ 2 ]

1 голос
/ 10 июня 2019

Verilog симуляция, управляемая событиями. Событие - это изменение значения переменной verilog (или именованного события). Симуляция делается по шагам.

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

Сам шаг разделен на несколько зон, которые выполняются с использованием алгоритма, определенного в стандарте.

Для verilog 2K существует примерно 3 основных зоны:

  1. зона назначения блокировки. Verilog выполняет все процедурные блоки, запланированные очередью событий, и реагирует на новые события назначения блокировки. Он просто планирует события nbas, которые будут выполнены позже. Когда все события блокировки завершены, он попадает в следующую зону.

  2. Неблокирующая зона назначения. Здесь он выполняет все блоки, которые реагируют на события расписания nba. Он поместит в очередь событие ba и nba. Когда все nba выполнено, он может вернуться в зону '1', если есть событие ba, и выполнить все заново.

  3. зона монитора / строба - это зона, в которой работает $ monitor (и $ strob). Он запускается после выполнения зон ba и nba (больше никаких событий).

В вашем случае a = 1 выполняется в зоне назначения блокировки. это значение сохраняется до конца этой зоны. $display также будет выполнено в этой зоне. Таким образом, он увидит значение 'a == 0`.

a <= 1 будет запланировано выполнение в неблокирующей зоне после выполнения $ dislpay. $monitor выберет события в зоне мониторинга, после того как неблокирование выполнено. Таким образом, он покажет вам значение 1.

Ваши операторы выполняются в блоке initial. В результате отсутствует распространение событий. Только события выбираются с помощью операторов always и assign. Если вы поместите свой $display в блок всегда, вы увидите более интересные результаты. always @* $display(a);

Вы должны прочитать о стандартной семантике симуляции в verilog, чтобы получить больше информации.

1 голос
/ 10 июня 2019

Цикл симуляции verilog сложнее, чем описывает ваше текущее объяснение. Короткий ответ на ваш вопрос заключается в том, что $monitor не ожидает окончания текущего цикла, показывает свое сообщение, затем продолжает выполнение процесса (и, следовательно, вызывает $display впоследствии), а вместо этого просто планирует сообщение для отображения в конец любого цикла моделирования, в котором изменяется любая из зависимых переменных (в данном случае просто a); это очень особенный (и довольно устаревший) способ мониторинга изменений сигналов во время симуляции. $display, однако, выполняется немедленно, таким образом печатая все, что a в данный момент. Итак, другой способ думать об этом - это как неблокирующее присваивание (<=), $monitor просто настраивает что-то, что должно произойти позже, и выполнение продолжается до следующего оператора, а не происходит внутри строки.

Вам следует рассмотреть возможность изучения имитационной модели systemverilogs, принимая во внимание активные области, nba и отложить, поскольку это происходит при выполнении блокирующих назначений (=), неблокирующих назначений (<=) и $monitor соответственно.

...