Блокирующие и неблокирующие назначения в Verilog: ключевые различия
Блокирующие назначения (=)
Блокирующие назначения выполняются с помощью = и выполняются последовательно внутри процедурного блока. Однако это не предотвращает выполнение операторов в параллельных блоках.
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a = 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b = 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c = 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d = 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e = 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
Обратите внимание: два блока initial выполняются параллельно при старте симуляции. Операторы выполняются последовательно в каждом блоке, и оба блока завершаются в 0 нс. Конкретно: a назначается первой, затем $display, затем остальные операторы. Это видно в выводе: в первом $display переменные b и c равны 8'hxx, так как их назначения еще не выполнились.
Simulation Log
ncsim> run [0] a=0xda b=0xx c=0xx [0] a=0xda b=0xf1 c=0xx [0] a=0xda b=0xf1 c=0x30 [0] d=0xaa e=0xx [0] d=0xaa e=0x55 ncsim: *W,RNQUIE: Simulation is complete.
В следующем примере добавим задержки, чтобы увидеть поведение.
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a = 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
#10 b = 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c = 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
#5 d = 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
#5 e = 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
Simulation Log
ncsim> run [0] a=0xda b=0xx c=0xx [5] d=0xaa e=0xx [10] a=0xda b=0xf1 c=0xx [10] a=0xda b=0xf1 c=0x30 [10] d=0xaa e=0x55 ncsim: *W,RNQUIE: Simulation is complete.
Неблокирующие назначения (<=)
Неблокирующие назначения позволяют планировать назначения без блокировки выполнения следующих операторов. Обозначаются символом <=. Тот же символ используется как оператор отношения в выражениях и как оператор неблокирующего назначения. Если в первом примере заменить все = на <=, вывод изменится.
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a <= 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b <= 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c <= 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d <= 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e <= 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
Все $display выводят 'h'x. Причина: RHS каждого неблокирующего оператора на данном временном шаге захватывается, затем выполняется следующий оператор. Захваченное значение присваивается LHS только в конце временного шага.
Simulation Log
ncsim> run [0] a=0xx b=0xx c=0xx [0] a=0xx b=0xx c=0xx [0] a=0xx b=0xx c=0xx [0] d=0xx e=0xx [0] d=0xx e=0xx ncsim: *W,RNQUIE: Simulation is complete.
Разбор потока выполнения:
|__ Блок 1: initial | |___ Время #0ns: a <= 8'DA — неблокирующее, запоминаем RHS (8'hDA), идем дальше | |___ Время #0ns: $display() — блокирующее, выполняем: a еще не получил значение, a=8'hx | |___ Время #0ns: b <= 8'F1 — запоминаем RHS (8'hF1), идем дальше | |___ Время #0ns: $display() — b еще не получил значение, b=8'hx | |___ Время #0ns: c <= 8'30 — запоминаем RHS (8'h30), идем дальше | |___ Время #0ns: $display() — c еще не получил значение, c=8'hx | |___ Конец временного шага: присваиваем захваченные значения a, b, c |__ Блок 2: initial | |___ Время #0ns: d <= 8'AA — запоминаем RHS (8'hAA), идем дальше | |___ Время #0ns: $display() — d еще не получил значение, d=8'hx | |___ Время #0ns: e <= 8'55 — запоминаем RHS (8'h55), идем дальше | |___ Время #0ns: $display() — e еще не получил значение, e=8'hx | |___ Конец временного шага: присваиваем захваченные значения d, e |__ Конец симуляции в #0ns
Теперь второй пример с задержками, но с неблокирующими назначениями.
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a <= 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
#10 b <= 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c <= 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
#5 d <= 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
#5 e <= 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
Вывод снова отличается от блокирующего варианта.
Simulation Log
ncsim> run [0] a=0xx b=0xx c=0xx [5] d=0xx e=0xx [10] a=0xda b=0xx c=0xx [10] a=0xda b=0xx c=0xx [10] d=0xaa e=0xx ncsim: *W,RNQUIE: Simulation is complete.
Разбор выполнения:
|__ Блок 1 в #0ns: initial | |___ Время #0ns: a <= 8'DA — запоминаем RHS (8'hDA), идем дальше | |___ Время #0ns: $display() — a еще не получил значение, a=8'hx | |___ Конец временного шага: присваиваем a = 8'hDA | |___ Ждем 10 единиц времени до #10ns | | |___ Время #10ns: b <= 8'F1 — запоминаем RHS (8'hF1), идем дальше | |___ Время #10ns: $display() — b еще не получил значение, b=8'hx | |___ Время #10ns: c <= 8'30 — запоминаем RHS (8'h30), идем дальше | |___ Время #10ns: $display() — c еще не получил значение, c=8'hx | |___ Конец временного шага и блока: присваиваем b, c |__ Блок 2 в #0ns: initial | |___ Ждем 5 единиц до #5ns | | |___ Время #5ns: d <= 8'AA — запоминаем RHS (8'hAA), идем дальше | |___ Время #5ns: $display() — d еще не получил значение, d=8'hx | |___ Конец временного шага: d = 8'hAA | |___ Ждем 5 единиц до #10ns | | |___ Время #10ns: e <= 8'55 — запоминаем RHS (8'h55), идем дальше | |___ Время #10ns: $display() — e еще не получил значение, e=8'hx | |___ Конец временного шага и блока: e = 8'h55 |__ Конец симуляции в #10ns
Verilog
- Освоение Verilog: полное руководство по проектированию цифровых схем
- Освоение конкатенации в Verilog: практическое руководство
- Мастерство функций в Verilog для эффективного RTL дизайна
- Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
- Генератор тактового сигнала в Verilog: проектирование и реализация
- Мастерство математических функций Verilog для эффективного аппаратного дизайна
- Мастерство $timeformat в Verilog: точность и контроль отображения времени
- Понимание и печать timescale в Verilog в любой области видимости
- Работа с файлами в Verilog: открытие, чтение, запись и закрытие
- Verilog для начинающих: пример Hello World