Неблокирующие операторы выполняются параллельно каждый раз, когда выполняется блок Always. Однако каждое назначение использует предыдущее значение правой стороны при назначении. Если мы смоделируем дизайн, мы увидим это поведение:
![enter image description here](https://i.stack.imgur.com/PZMSP.png)
Первоначально все сигналы имеют значение 0, однако на первом переднем фронте r_Test_1
принимает значение 1, в то время как два других регистра остаются равными 0. Это потому, что r_Test_2
присвоено значение r_Test_1
только перед фронтом тактового сигнала, а r_Test_1
равно 0 непосредственно перед нарастающим фронтом.
Подобное поведение происходит на втором переднем фронте, на этот раз с r_Test_2
и r_Test_3
. r_Test_2
становится 1 на втором переднем фронте, потому что на этот раз r_Test_1
имел значение 1 непосредственно перед фронтом часов, а потому что r_Test_2
был все еще 0 перед этим фронтом, r_Test_3
остается 0.
Давайте сопоставим это с поведением этого кода:
always @(posedge i_clock)
begin
r_Test_1 = 1'b1;
r_Test_2 = r_Test_1;
r_Test_3 = r_Test_2;
end
![enter image description here](https://i.stack.imgur.com/46Ntf.png)
Поскольку я использовал здесь блокирующие назначения, каждому регистру присваивается значение немедленно, а не назначение откладывается до конца блока Always. Из-за этого, когда присваивается r_Test_2
, r_Test_1
уже имеет значение 1, а также с r_Test_3
и r_Test_2
, поэтому все 3 сигнала принимают значение 1 в первом цикле.
Теперь, когда я использую блокирующие назначения, порядок стал важным. Поэтому, если я переставлю код так, чтобы он выглядел так:
always @(posedge i_clock)
begin
r_Test_1 = 1'b1;
r_Test_3 = r_Test_2;
r_Test_2 = r_Test_1;
end
Затем я получаю другой результат из второго моделирования:
![enter image description here](https://i.stack.imgur.com/cZydj.png)
Задача: почему это так?
Полный тестовый стенд:
`timescale 1ns/1ps
module test;
reg i_clock = 0;
reg r_Test_1 = 0;
reg r_Test_2 = 0;
reg r_Test_3 = 0;
initial begin
$dumpfile("dump.vcd");
$dumpvars;
#100 $finish;
end
always #5 i_clock <= ~i_clock;
always @(posedge i_clock)
begin
r_Test_1 <= 1'b1;
r_Test_2 <= r_Test_1;
r_Test_3 <= r_Test_2;
end
endmodule