Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Verilog

Управление задержками в Verilog: техники таймингов и лучшие практики

В Verilog два типа таймингового управления: задержка (delay) и событие (event). Задержка — способ добавить задержку между моментом, когда симулятор встречает оператор, и моментом его фактического выполнения. Событийное выражение откладывает выполнение до возникновения события симуляции: изменения значения на net или переменной (неявное событие) или явно именованного события, инициированного в другой процедуре.

Время симуляции может продвигаться следующими способами. Гейты и nets с внутренними задержками также продвигают время симуляции.

Управление задержкой (Delay Control)

Если выражение задержки оценивается в неизвестное (X) или высокоомное (Z) значение, оно интерпретируется как нулевая задержка. Если отрицательное — как 2's complement беззнаковое целое того же размера, что и переменная time.

`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

Обратите внимание: точность timescale 1ps, поэтому для оператора с задержкой (a+b)*10ps требуется $realtime для отображения точности.

Simulation Log

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.

Управление событиями (Event Control)

Изменения значений на nets и переменных можно использовать как синхронизирующие события для запуска других процедурных операторов — это неявное событие. Событие также может основываться на направлении изменения: к 0 — negedge, к 1 — posedge.

Переход из состояния в то же состояние не считается фронтом. Фронт (posedge/negedge) детектируется только на младшем бите векторного сигнала или переменной. Если выражение оценивается в тот же результат, это не считается событием.

module tb;
  reg a, b;
  initial begin
    a <= 0;
    #10 a <= 1;
    #10 b <= 1;
    #10 a <= 0;
    #15 a <= 1;
  end

  // Блок, ждущий обновления сигналов из вышеуказанного блока
  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

Simulation Log

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.

Именованные события (Named Events)

Ключевое слово event объявляет именованное событие, которое можно инициировать явно. 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 используется для триггера и ожидания.

Simulation Log

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 позволяет ждать, пока сработает любое из перечисленных событий. Запятая , также допускается вместо 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
  // "or" между событиями
  always @ (posedge a or posedge b) $display ("T=%0t posedge of a or b found", $time);
  // Запятая между событиями
  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

Simulation Log

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.

Неявный список выражений событий (Implicit Event Expression List)

Список чувствительности (sensitivity list) — частая причина функциональных ошибок в RTL. Пользователь может забыть обновить его после добавления нового сигнала в процедурный блок.

module tb;
  reg a, b, c, d;
  reg x, y;
  // Список чувствительности: a, b, c, 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

Simulation Log

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;
  // Добавляем "e" в список чувствительности
  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

Simulation Log

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 позволяет заменить список чувствительности на * — удобный сокращенный синтаксис, автоматически включающий все nets и переменные, читаемые оператором.

module tb;
  reg a, b, c, d, e;
  reg x, y, z;
  // @* или @(*)
  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

Simulation Log

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.

Уровневое управление событиями (Level Sensitive Event Control)

Выполнение процедурного оператора можно задержать до истинности условия с помощью ключевого слова wait — это уровень-чувствительное управление.

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

Simulation Log

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

  1. Освоение Verilog: полное руководство по проектированию цифровых схем
  2. Освоение конкатенации в Verilog: практическое руководство
  3. Понимание назначений в Verilog: типы, синтаксис и лучшие практики
  4. Блокирующие и неблокирующие назначения в Verilog: ключевые различия
  5. Управление потоком в Verilog: IF-ELSE, Case, циклы и не только
  6. Мастерство функций в Verilog для эффективного RTL дизайна
  7. Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
  8. Межназначенные и внутриназначенные задержки в Verilog: понимание и применение
  9. Понимание задержек гейтов в Verilog: точное тайминг для надежных цифровых схем
  10. Генератор тактового сигнала в Verilog: проектирование и реализация