Подождите, пока ‹signal›=1 никогда не будет истинным в симуляции VHDL

Ниже приведен код, который я запускаю. Мой вопрос: почему 3-й wait until не срабатывает в modelim? Вывод консоли просто GOT HERE. Он никогда не доходит до строки GOT HERE 2. Я бы подумал, что иметь одно и то же wait until <SIGNAL> = 1 дважды подряд было бы нормально, потому что условие верно оба раза. Я не добавлял туда событие, поэтому я не думаю, что симулятору нужно будет видеть край. Кто-нибудь может объяснить такое поведение?

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity example_wait_failure is
end example_wait_failure;

architecture behave of example_wait_failure is

  signal r_CLK_TB : std_logic := '0';

begin

  r_CLK_TB <= '1' after 20 ns, '0' after 40 ns, '1' after 60 ns;


  p_TEST : process
  begin

    wait until r_CLK_TB = '1';
    report "GOT HERE" severity note;

    wait until r_CLK_TB = '1';
    wait until r_CLK_TB = '1';
    report "GOT HERE 2 " severity note;

  end process p_TEST;

end behave;

person Russell    schedule 09.12.2013    source источник


Ответы (3)


Поведение находится в деталях оператора ожидания (детали ожидания, на которые ссылается Джим Льюис). Причина в том, что операторы wait состоят из трех частей:

wait
  [on sensitivity_list]
  [until condition]
  [for time_expression];  -- Only for timeout, and not relevant here

wait в соответствующем коде имеет только часть until, поэтому чувствительность_список создается в соответствии со стандартом VHDL: «Если пункт чувствительности не появляется, набор чувствительности создается в соответствии со следующим (рекурсивным) правилом: ...». В этом случае сгенерированный список чувствительности будет содержать r_CLK_TB.

В стандарте VHDL есть пример, который точно соответствует коду, и в нем говорится, что:

wait until r_CLK_TB = '1';

идентичен:

loop
  wait on r_CLK_TB;
  exit when r_CLK_TB = '1';
end loop;

Таким образом, хотя wait явно не содержит wait until r_CLK_TB'event (как написано в комментарии), выполнение приводит к ожиданию события r_CLK_TB, чтобы передать первое wait в wait on r_CLK_TB. Это интуитивно... судите сами ;-)

Так что, возможно, исходный код должен быть изменен так:

wait until r_CLK_TB = '1';

заменяется на:

if r_CLK_TB /= '1' then
  wait until r_CLK_TB = '1';
end if;

В этом случае и «ПОПАЛ ЗДЕСЬ», и «ПОПУСТИЛ ЗДЕСЬ 2» отображаются через 20 нс, поскольку здесь условие всех трех построений будет ИСТИНА.

person Morten Zilmer    schedule 10.12.2013
comment
Спасибо за объяснение. Мне интересно, что ожидание r_CLK_TB является частью ожидания до проверки r_CLK_TB = '1'. Позвольте мне задать последний вопрос, затем я поставлю галочку :) При поиске положительных фронтов часов у вас есть 2 варианта. Предполагая, что вы не используете ожидание до повышения_края (r_CLK_TB) в своем обычном коде RTL, которое вы используете, ожидание до события r_CLK_TB и r_CLK_TB='1'. Вы хотите сказать, что ждать, пока r_CLK_TB'event здесь совершенно бесполезно? - person Russell; 10.12.2013
comment
В wait until r_CLK_TB'event and r_CLK_TB='1' r_CLK_TB'event будет тривиальным TRUE после оценки r_CLK_TB'event and r_CLK_TB='1', поскольку это событие, которое запускает оценку, как вы подразумеваете, поэтому выражение можно сократить до r_CLK_TB='1'. - person Morten Zilmer; 10.12.2013
comment
АККУРАТНЫЙ. Я собираюсь начать писать весь свой код так, просто чтобы возиться с людьми :) - person Russell; 10.12.2013

Домашнее задание? Экзамен?

Вам нужно изучить детали того, как работает ожидание. Ожидание всегда приостанавливается как минимум на дельта-цикл. Ожидание до тех пор, пока возобновляется только тогда, когда сигнал в условии изменится и выражение станет истинным. Итак, сколько переходов к «1» вам нужно здесь, чтобы перейти ко второму оператору отчета?

Сколько переходов на «1» у вас есть с:

signal r_CLK_TB : std_logic := '0';
...
r_CLK_TB <= '1' after 20 ns, '0' after 40 ns, '1' after 60 ns; 

Вам нужно изучить детали того, как работает ожидание. Ожидание всегда приостанавливается как минимум на дельта-цикл. Подождите, пока возобновится только тогда, когда сигнал в условии изменится, а выражение станет истинным. Итак, сколько переходов на «1» вам нужно здесь?

Что произойдет, если вы измените r_CLK_TB на следующее?

r_CLK_TB <= not r_CLK_TB after 20 ns ; 
person Jim Lewis    schedule 09.12.2013
comment
Не домашнее задание или экзамен... нашел эту проблему на реальной работе! Почему сигнал в состоянии ожидания должен измениться? Если условие ожидания до тех пор, пока r_CLK_TB = '1' не станет истинным, ДО перехода к оператору ожидания, оно просто пройдет мимо него, не так ли? Я бы предположил, что ждать, пока r_CLK_TB'event будет искать какой-то переход. Боюсь, я еще не совсем понимаю... - person Russell; 10.12.2013
comment
Я также могу принять это, это то, как ведет себя Modelsim, но мне это НЕ ЧУВСТВУЕТСЯ правильным. :) - person Russell; 10.12.2013
comment
Это не только ModelSim, все симуляторы VHDL делают это, поскольку такое поведение является требованием языка. Другой способ думать об этом состоит в том, что сигналы в условии формируют неявный список чувствительности. Я понимаю ваши мысли, потому что многие ошибочно считают это проверкой уровня, но это проверка края. Язык был разработан таким образом, чтобы упростить проверку процесса, который никогда не приостанавливается (плохой бесконечный цикл) — если процесс содержит либо оператор ожидания, либо список чувствительности процесса, то он приостанавливается. Для тестовых стендов вам действительно нужно понимать детали того, как работает ожидание. - person Jim Lewis; 15.12.2013

Я зависаю над той же проблемой.
Мой возможный обходной путь — добавить глобальные часы в список конфиденциальности:

nClk <= NOT nClk AFTER 10 ns;

WAIT ON nClk UNTIL signalToCheck = '1';
person Christian Nienhaus    schedule 02.09.2020