По умолчанию все работает в области Активный. Исключениями являются:
- Назначения блокировки №0 находятся в области Неактивно.
- Неблокирующие назначения относятся к региону NBA.
- $ monitor, $ strobe и PLI / VPI находятся в области Monitor.
Мы можем доказать, что @
происходит в активной области, выполнив следующее в любом существующем симуляторе:
int x;
initial begin
$monitor("From $monitor: x is %0d",x);
#0 x = 5; // inactive event
x = 3; // active event (after inactive event)
#1; // go to next time stamp
fork
#0 x = 7; // inactive event
x = 11; // active event
join
#0 fork // inactive region
#0 x = 2; // inactive event
x = 5; // active event
x <= 4; // NBA event
join
end
// active event region
always @* $display("From @* $display: x is %0d",x);
Выходы:
From @* $display: x is 3
From $monitor: x is 3
From @* $display: x is 11
From @* $display: x is 7
From @* $display: x is 5
From @* $display: x is 2
From @* $display: x is 4
From $monitor: x is 4
Отображайте отчеты больше раз, чем отслеживайте. Это исключает @
накопление в регионе Monitor или Future. Дисплей сообщает по каждому региону событий. Каждая область событий может возвращаться только в активную область. Поэтому @
должен обрабатываться в активной области, и каждая область, которая обновляет переменную x
, запускает новое событие активной области.
Это также можно доказать, зная, глядя на историю Verilog. К сожалению, это плохо документировано. Я узнал об этом через людей, которые использовали / разрабатывали Verilog в конце 80-х - начале 90-х годов. Общее объяснение таково: неактивные регионы и регионы NBA были добавлены в Verilog до IEEE Std 1364-1995, @
предшествует этим двум регионам. Области были добавлены, чтобы добавить детерминизма к недетерминированному симулятору.
always @(posedge clk) pipe0 = in;
always @(posedge clk) pipe1 = pipe0; // unpredictable, non-deterministic order
always @(posedge clk) #0 pipe0 = in; // Inactive region added some determinism
always @(posedge clk) pipe1 = pipe0;
always @(posedge clk) #0 pipe0 = in; // But was fragile
always @(posedge clk) #0 pipe1 = pipe0; // unpredictable order again
always @(posedge clk) pipe2 = pipe1;
always @(posedge clk) pipe0 <= in;
always @(posedge clk) pipe1 <= pipe0;
always @(posedge clk) pipe2 <= pipe1; // NBA region fixed it
...
always @(posedge clk) pipeN <= pipeM; // and made it scalable
разъяснение на основе отзывов из комментариев
Events are
activated, not
moved. Activated NBA events enter the true condition of
if (E is an update event)
, modified object and schedule new
evaluation events (handled the next time
Active region entered). Once all the
activated events are completed, the schedule goes back to the top of the while-loop. The
NBA region only assigns values, the evaluation was actually done in an earlier
Active region stage.
From your example:
module TEST;
reg test = 0;
reg test2 = 0;
reg clk = 0;
initial begin
clk <= 1;
test <= 1;
end
always @(posedge clk) begin
test2 <= test;
end
endmodule
Каждая итерация цикла while будет выглядеть примерно так:
Iteration:0
Active: <----- This is region is executing
clk$tmp = eval(1)
test$tmp = eval(1)
Inactive:
NBA:
clk = clk$tmp
test = test$tmp
Iteration:1
Active:
Inactive:
NBA: <----- This is region is executing
clk = clk$tmp
test = test$tmp
Active.schedule( eval( "@(posedge clk)" )
Iteration:2
Active: <----- This is region is executing
eval( "@(posedge clk)" )
Active.schedule( "test2$tmp = eval(test)" )
NBA.schedule( "test2 = test2$tmp" )
Inactive:
NBA:
Iteration:3
Active: <----- This is region is executing
test2$tmp = eval(test)
Inactive:
NBA:
test2 = test2$tmp
Iteration:4
Active:
Inactive:
NBA: <----- This is region is executing
test2 = test2$tmp
Iteration:5 --> next simulation cycle
person
Greg
schedule
03.04.2014