Блокировка и неблокировка 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 назначается первым, за ним следует оператор отображения, за которым следуют все остальные операторы. Это видно в выводе, где переменная b и с равны 8'hxx в первом операторе отображения. Это потому, что переменная b и с назначения еще не были выполнены, когда первый $display
называется.
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
Журнал моделирования 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 каждого неблокирующего оператора определенного временного шага фиксируется и переходит к следующему оператору. Захваченное значение RHS присваивается переменной LHS только в конце временного шага.
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.
Итак, если мы разберем поток выполнения приведенного выше примера, мы получим что-то вроде того, что показано ниже.
|__ Spawn Block1: initial | |___ Time #0ns : a <= 8'DA, is non-blocking so note value of RHS (8'hDA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But a hasn't received new values so a=8'hx | |___ Time #0ns : b <= 8'F1, is non-blocking so note value of RHS (8'hF1) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But b hasn't received new values so b=8'hx | |___ Time #0ns : c <= 8'30, is non-blocking so note value of RHS (8'h30) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But c hasn't received new values so c=8'hx | |___ End of time-step and initial block, assign captured values into variables a, b, c | |__ Spawn Block2: initial | |___ Time #0ns : d <= 8'AA, is non-blocking so note value of RHS (8'hAA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But d hasn't received new values so d=8'hx | |___ Time #0ns : e <= 8'55, is non-blocking so note value of RHS (8'h55) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement. But e hasn't received new values so e=8'hx | |___ End of time-step and initial block, assign captured values into variables d and e | |__ End of simulation at #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
Мы снова видим, что результат отличается от того, что мы получили раньше.
Журнал моделирования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.
Если мы разберем поток выполнения, мы получим что-то вроде того, что показано ниже.
|__ Spawn Block1 at #0ns: initial | |___ Time #0ns : a <= 8'DA, is non-blocking so note value of RHS (8'hDA) and execute next step | |___ Time #0ns : $display() is blocking, so execute this statement: But a hasn't received new values so a=8'hx | |___ End of time-step : Assign captured value to variable a, and a is now 8'hDA | |___ Wait until time advances by 10 time-units to #10ns | | |___ Time #10ns : b <= 8'F1, is non-blocking so note value of RHS (8'hF1) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But b hasn't received new values so b=8'hx | |___ Time #10ns : c <= 8'30, is non-blocking so note value of RHS (8'h30) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But c hasn't received new values so c=8'hx | |___ End of time-step and initial block, assign captured values into variables b, c | |__ Spawn Block2 at #0ns: initial | |___ Wait until time advances by 5 time-units to #5ns | | |___ Time #5ns : d <= 8'AA, is non-blocking so note value of RHS (8'hAA) and execute next step | |___ Time #5ns : $display() is blocking, so execute this statement: But d hasn't received new values so d=8'hx | |___ End of time-step : Assign captured value to variable d, and d is now 8'hAA | |___ Wait until time advances by 5 time-units to #5ns | | |___ Time #10ns : e <= 8'55, is non-blocking so note value of RHS (8'h55) and execute next step | |___ Time #10ns : $display() is blocking, so execute this statement. But e hasn't received new values so e=8'hx | |___ End of time-step and initial block, assign captured values to variable e, and e is now 8'h55 | |__ End of simulation at #10ns
Verilog