У вас уже есть ответы с решением («использовать неблокирующие присваивания»), но вот попытка понять, почему вам нужно это сделать.
Оба ваших оператора always
имеют одно и то же событие, поэтому они могут выполняться в любом порядке. Кажется, что происходит то, что первый запускается первым. Когда очередь...
done_buf_1 = done;
... попадет, он будет блокироваться до тех пор, пока задание не будет завершено (это «блокирующее» задание). Поэтому done_buf_1 немедленно принимает новое значение. Это отличается от неблокирующей версии...
done_buf_1 <= done;
... который говорит: «дайте done_buf_1 значение done (которое я сейчас оценю) в конце временного интервала».
Теперь идем дальше, и присваивается done_buf_2.
done_buf_2 = done_buf_1;
Теперь, если done_buf_1
был обновлен блокирующим назначением, он уже имеет текущее значение done
, и вы увидите, что оба сигнала возрастают одновременно. Если это было неблокирующее назначение, то done_buf_1
по-прежнему имеет предыдущее значение done
, поскольку оно не будет обновляться до конца временного интервала, в результате чего для done_buf_2
будет задержка в 2 цикла.
Хотя есть и другая проблема. Помните, я говорил, что операторы always можно запускать в любом порядке, потому что события одинаковы? Что ж, если бы второй был выполнен первым, код работал бы так, как предполагалось (db2 = db1; db1 = done;
Нет проблем). Поэтому стоит знать, что использование блокирующих назначений, подобных этому, дает неустойчивые результаты, особенно между инструментами. Это может привести к некоторым тонким ошибкам.
person
Paul S
schedule
18.06.2012