Контроль задержки Verilog
В Verilog есть два типа контроля времени:задержка и событие выражения. задержка управление — это просто способ добавить задержку между моментом, когда симулятор встречает оператор, и моментом его фактического выполнения. Выражение события позволяет отложить оператор до возникновения некоторого события моделирования, которое может быть изменением значения в цепи или переменной (неявное событие ) или событие с явным именем, которое запускается в другой процедуре.
Время моделирования можно увеличить одним из следующих способов.
Ворота и цепи, которые были смоделированы с учетом внутренних задержек, также увеличивают время моделирования.
Управление задержкой
Если выражение задержки оценивается как неизвестное или высокоимпедансное значение, оно будет интерпретировано как нулевая задержка. Если оно дает отрицательное значение, оно будет интерпретироваться как целое число без знака в дополнении до 2 того же размера, что и временная переменная.
`timescale 1ns/1ps
module tb;
reg [3:0] a, b;
initial begin
{a, b} <= 0;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10;
a <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10 b <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#(a) $display ("T=%0t After a delay of a=%0d units", $realtime, a);
#(a+b) $display ("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
#((a+b)*10ps) $display ("T=%0t After a delay of %0d * 10ps", $realtime, a+b);
#(b-a) $display ("T=%0t Expr evaluates to a negative delay", $realtime);
#('h10) $display ("T=%0t Delay in hex", $realtime);
a = 'hX;
#(a) $display ("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);
a = 'hZ;
#(a) $display ("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);
#1ps $display ("T=%0t Delay of 10ps", $realtime);
end
endmodule
Обратите внимание, что точность шкалы времени составляет 1 пс и, следовательно, $realtime
требуется для отображения значения точности оператора с выражением задержки (a+b)*10ps.
xcelium> run T=0 a=x b=x T=10000 a=0 b=0 T=20000 a=4 b=0 T=24000 After a delay of a=4 units T=29000 After a delay of a=4 + b=1 = 5 units T=29050 After a delay of 5 * 10ps T=42050 Expr evaluates to a negative delay T=58050 Delay in hex T=58050 Delay is unknown, taken as zero a=x T=58050 Delay is in high impedance, taken as zero a=z T=58051 Delay of 10ps xmsim: *W,RNQUIE: Simulation is complete.
Контроль событий
Изменения значений в цепях и переменных могут использоваться как событие синхронизации для запуска выполнения других процедурных операторов и являются неявными мероприятие. Событие также может быть основано на направлении изменения, например, к 0, что делает его negedge
и изменение в сторону 1 делает его posedge
.
- А
negedge
когда есть переход от 1 к X, Z или 0 и от X или Z к 0 - А
posedge
когда есть переход от 0 к X, Z или 1 и от X или Z к 1
Переход из того же состояния в то же состояние не считается ребром. Краевое событие, такое как posedge или negedge, может быть обнаружено только в LSB векторного сигнала или переменной. Если выражение дает один и тот же результат, оно не может рассматриваться как событие.
module tb;
reg a, b;
initial begin
a <= 0;
#10 a <= 1;
#10 b <= 1;
#10 a <= 0;
#15 a <= 1;
end
// Start another procedural block that waits for an update to
// signals made in the above procedural block
initial begin
@(posedge a);
$display ("T=%0t Posedge of a detected for 0->1", $time);
@(posedge b);
$display ("T=%0t Posedge of b detected for X->1", $time);
end
initial begin
@(posedge (a + b)) $display ("T=%0t Posedge of a+b", $time);
@(a) $display ("T=%0t Change in a found", $time);
end
endmodule
Журнал моделирования ncsim> run T=10 Posedge of a detected for 0->1 T=20 Posedge of b detected for X->1 T=30 Posedge of a+b T=45 Change in a found ncsim: *W,RNQUIE: Simulation is complete.
Именованные события
Ключевое слово event
может использоваться для объявления named событие, которое может быть вызвано явно. event
не может хранить какие-либо данные, не имеет временной длительности и может произойти в любое конкретное время. Именованное событие запускается с помощью ->
оператора, поставив перед ним префикс перед именованным дескриптором события. Именованное событие можно ожидать с помощью @
оператор, описанный выше.
module tb;
event a_event;
event b_event[5];
initial begin
#20 -> a_event;
#30;
->a_event;
#50 ->a_event;
#10 ->b_event[3];
end
always @ (a_event) $display ("T=%0t [always] a_event is triggered", $time);
initial begin
#25;
@(a_event) $display ("T=%0t [initial] a_event is triggered", $time);
#10 @(b_event[3]) $display ("T=%0t [initial] b_event is triggered", $time);
end
endmodule
Именованные события можно использовать для синхронизации двух или более одновременно запущенных процессов. Например, always
блок и второй initial
блок синхронизируется с помощью a_event. События могут быть объявлены как массивы, как в случае b_event, который представляет собой массив размером 5, а индекс 3 используется для запуска и ожидания.
ncsim> run T=20 [always] a_event is triggered T=50 [always] a_event is triggered T=50 [initial] a_event is triggered T=100 [always] a_event is triggered T=110 [initial] b_event is triggered ncsim: *W,RNQUIE: Simulation is complete.
Событие или оператор
or
оператор может использоваться для ожидания, пока любое из перечисленных событий не будет запущено в выражении. Запятая ,
также можно использовать вместо or
оператор.
module tb;
reg a, b;
initial begin
$monitor ("T=%0t a=%0d b=%0d", $time, a, b);
{a, b} <= 0;
#10 a <= 1;
#5 b <= 1;
#5 b <= 0;
end
// Use "or" between events
always @ (posedge a or posedge b)
$display ("T=%0t posedge of a or b found", $time);
// Use a comma between
always @ (posedge a, negedge b)
$display ("T=%0t posedge of a or negedge of b found", $time);
always @ (a, b)
$display ("T=%0t Any change on a or b", $time);
endmodule
Журнал моделирования ncsim> run T=0 posedge of a or negedge of b found T=0 Any change on a or b T=0 a=0 b=0 T=10 posedge of a or b found T=10 posedge of a or negedge of b found T=10 Any change on a or b T=10 a=1 b=0 T=15 posedge of a or b found T=15 Any change on a or b T=15 a=1 b=1 T=20 posedge of a or negedge of b found T=20 Any change on a or b T=20 a=1 b=0 ncsim: *W,RNQUIE: Simulation is complete.
Список неявных выражений событий
Список чувствительности или список выражений событий часто являются распространенной причиной множества функциональных ошибок в RTL. Это связано с тем, что пользователь может забыть обновить список чувствительности после добавления нового сигнала в процедурный блок.
module tb;
reg a, b, c, d;
reg x, y;
// Event expr/sensitivity list is formed by all the
// signals inside () after @ operator and in this case
// it is a, b, c or d
always @ (a, b, c, d) begin
x = a | b;
y = c ^ d;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b x=%0b y=%0b", $time, a, b, c, d, x, y);
{a, b, c, d} <= 0;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
end
endmodule
Журнал моделирования ncsim> run T=0 a=0 b=0 c=0 d=0 x=0 y=0 T=10 a=0 b=1 c=0 d=0 x=1 y=0 T=20 a=0 b=0 c=0 d=1 x=0 y=1 T=30 a=1 b=0 c=0 d=1 x=1 y=1 ncsim: *W,RNQUIE: Simulation is complete.
Если пользователь решит добавить новый сигнал e и зафиксировать обратный сигнал в z, необходимо проявить особую осторожность, чтобы добавить e также в список чувствительности.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Add "e" also into sensitivity list
always @ (a, b, c, d, e) begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
Журнал моделирования ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
Verilog теперь позволяет заменить список конфиденциальности на *
что является удобным сокращением, которое устраняет эти проблемы, добавляя все цепи и переменные, которые считываются оператором, как показано ниже.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Use @* or @(*)
always @ * begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
Журнал моделирования ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
Управление событиями, зависящими от уровня
Выполнение процедурного оператора также может быть отложено до тех пор, пока условие не станет истинным, и может быть выполнено с помощью wait
ключевое слово и является элементом управления, зависящим от уровня.
Оператор ожидания должен оценивать условие, и, если оно ложно, последующие процедурные операторы должны оставаться заблокированными до тех пор, пока условие не станет истинным.
module tb;
reg [3:0] ctr;
reg clk;
initial begin
{ctr, clk} <= 0;
wait (ctr);
$display ("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);
wait (ctr == 4) $display ("T=%0t Counter reached 0x%0h", $time, ctr);
$finish;
end
always #10 clk = ~clk;
always @ (posedge clk)
ctr <= ctr + 1;
endmodule
Журнал моделирования ncsim> run T=10 Counter reached non-zero value 0x1 T=70 Counter reached 0x4 T=90 Counter reached 0x5 T=170 Counter reached 0x9 Simulation complete via $finish(1) at time 170 NS + 1
Verilog