Я пытаюсь понять, как симуляторы обрабатывают управление задержкой (с помощью #<delay>
), и не могу объяснить наблюдаемую разницу в следующих двух фрагментах:
(1)
module top ();
reg a,b;
initial begin
$monitor("At time %d a=%b b=%b", $time,a,b);
a = 1'b0;
b = 1'b0;
#10 a = 1'b1;
#10 b = 1'b1;
a <= #5 1'b0;
b <= #5 1'b0;
end
endmodule
(2)
module top ();
reg a,b;
initial begin
$monitor("At time %d a=%b b=%b", $time,a,b);
a = 1'b0;
b = 1'b0;
#10 a = 1'b1;
#10 b = 1'b1;
a = #5 1'b0;
b = #5 1'b0;
end
endmodule
Обратите внимание, что единственная разница заключается между двумя последними утверждениями в каждом фрагменте. Вывод таков, что в первом фрагменте оба значения a и b установлены в 0 при t=25, тогда как во втором мы имеем a=0 при t=25, а b=0 только при t=30. Почему это?
Основываясь на моем (явно ограниченном) понимании, я думал, что симулятор должен прийти к оператору a <= #5 1'b0;
, а затем тривиально оценить 1'b0
RHS, подождать 5 единиц времени, а затем обновить a
в области неблокирующего назначения (NBA). В частности, я думал, что это будет означать, что симулятор работает только с b <= #5 1'b0;
, начиная с t=25, как это явно имеет место в случае блокировки. Почему при неблокирующих заданиях симулятор переходит к b <= #5 1'b0;
, несмотря на то, что #5
присутствует в операторе перед ним? Я думал, что разница между блокирующими и неблокирующими назначениями заключается лишь в том, что NBA выполняется в области NBA многослойной очереди Verilog, тогда как блокирующее назначение выполняется в активной области данного временного интервала. Есть ли еще разница, о которой я не знаю?
Название «блокирующее назначение» означает, что следующий оператор в процессе блокируется до тех пор, пока не завершится обновление LHS. Неблокирующее назначение никогда не блокирует процесс, а только обновление LHS.
Оба неблокирующих назначения в вашем первом примере выполняются в момент 20 и планируют обновление в момент 25, не блокируя процесс.
Во втором примере последнее назначение блокировки не начинается до момента 25, а обновление происходит в LHS в момент 0. При обычном кодировании вы никогда не будете использовать задержку блокировки в назначении блокировки (называемую внутриназначением). задержка блокировки). Это остаток доисторического Verilog, существовавшего до того, как в 1989 году в язык были добавлены неблокирующие назначения. (Я знаю эту дату, потому что я сыграл важную роль в добавлении NBA в Verilog).
Я не в курсе и не вижу никакой пользы в наличии такой функции.
Большое спасибо, это очень информативно. Тогда для подтверждения: тогда различие между блокировкой и неблокировкой двоякое: (1) События оценки генерируются одинаково для обоих, но событие обновления для NBA откладывается до тех пор, пока регион NBA (2) Назначения блокировки блокируют любое дальнейшее выполнение операторов. в одном и том же блоке, тогда как неблокирующие назначения этого не делают. Рассматривалось ли когда-либо решение о разрешении типов назначения, которые обеспечивают только (1) или (2), но не оба (как это делают NBA)?