Понимание назначений в Verilog: типы, синтаксис и лучшие практики
Размещение значений на сигналах (nets) и переменных называется назначениями (assignments). Существует три основных типа:
- Процедурные (Procedural)
- Непрерывные (Continuous)
- Процедурные непрерывные (Procedural continuous)
Допустимые значения левой части (LHS)
Назначение состоит из двух частей: правой части (RHS) и левой части (LHS), разделенных символом равенства (=) или неблокирующего назначения (<=).
| Тип назначения | Левая часть (LHS) |
|---|---|
| Процедурное |
|
| Непрерывное |
|
| Процедурное непрерывное |
|
Правая часть (RHS) может содержать любое выражение, вычисляемое в итоговое значение, а левая часть (LHS) указывает сигнал или переменную, которой присваивается это значение.
module tb;
reg clk;
wire a, b, c, d, e, f;
reg z, y;
// clk в LHS, инверсия clk в RHS
always #10 clk = ~clk;
// y в LHS, константа 1 в RHS
assign y = 1;
// f в LHS, выражение a,b,d,e в RHS
assign f = (a | b) ^ (d & e);
always @ (posedge clk) begin
// z в LHS, выражение a,b,c,d в RHS
z <= a + b + c + d;
end
initial begin
// Переменные слева — LHS, 0 — RHS
a <= 0; b <= 0; c <= 0;
d <= 0; e <= 0; clk <= 0;
end
endmodule
Процедурное назначение
Процедурные назначения выполняются внутри процедур (always, initial, task, function) и используются для присваивания значений переменным. Переменная сохраняет значение до следующего назначения той же переменной.
Значение помещается в переменную в момент выполнения оператора во время симуляции. Порядок выполнения можно управлять с помощью операторов управления потоком: if-else-if, case и циклов.
reg [7:0] data;
integer count;
real period;
initial begin
data = 8'h3e;
period = 4.23;
count = 0;
end
always @ (posedge clk)
count++;
Назначение при объявлении переменной
Начальное значение можно задать при объявлении переменной. Назначение не имеет длительности и удерживает значение до следующего назначения той же переменной. Обратите внимание: назначение при объявлении массива не допускается.
module my_block;
reg [31:0] data = 32'hdead_cafe;
initial begin
#20 data = 32'h1234_5678;
// data будет dead_cafe с 0 до 20
// В момент 20 получит 12345678
end
endmodule
reg [3:0] a = 4'b4;
// эквивалентно
reg [3:0] a;
initial a = 4'b4;
Если переменная инициализируется при объявлении и в initial блоке в момент 0, порядок вычисления не гарантирован — результат может быть либо 8'h05, либо 8'hee.
module my_block;
reg [7:0] addr = 8'h05;
initial addr = 8'hee;
endmodule
reg [3:0] array [3:0] = 0; // недопустимо
integer i = 0, j; // объявляет i,j; i = 0
real r2 = 4.5, r3 = 8; // r2=4.5, r3=8
time startTime = 40; // time переменная со значением 40
Процедурные блоки и назначения рассматриваются подробнее в следующем разделе.
Непрерывное назначение
Нажмите здесь для пошагового примера симуляции!
Используется для присваивания значений скалярным и векторным сигналам (nets) и срабатывает при любом изменении RHS. Обеспечивает моделирование комбинационной логики без явного описания связей гейтов и упрощает управление сигналами логическими выражениями.
// Пример модели AND гейта
wire a, b, c;
assign a = b & c;
При изменении b или c выражение RHS пересчитывается, и a обновляется.
Назначение при объявлении net
Позволяет разместить непрерывное назначение в том же операторе, что и объявление net. Поскольку net можно объявить только один раз, возможно только одно такое назначение.
wire penable = 1;
Процедурное непрерывное назначение
Это процедурные операторы, позволяющие непрерывно назначать выражения на сигналы или переменные. Существует два типа:
assign...deassignforce...release
assign / deassign
Переопределяет все процедурные назначения переменной и отключается с помощью deassign для того же сигнала. Значение переменной остается неизменным до нового назначения через процедурное или процедурное непрерывное назначение. LHS в assign не может быть выбором бита, части или ссылкой на массив, но может быть переменной или конкатенацией переменных.
reg q;
initial begin
assign q = 0;
#10 deassign q;
end
force / release
Аналогичны assign - deassign, но применимы и к nets, и к переменным. LHS может быть выбором бита net, частью net, переменной или net, но не ссылкой на массив и не выбором бита/части переменной. force переопределяет все остальные назначения до release.
reg o, a, b;
initial begin
force o = a & b;
...
release o;
end
Verilog
- Освоение Verilog: полное руководство по проектированию цифровых схем
- Освоение конкатенации в Verilog: практическое руководство
- Мастерство функций в Verilog для эффективного RTL дизайна
- Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение
- Генератор тактового сигнала в Verilog: проектирование и реализация
- Мастерство математических функций Verilog для эффективного аппаратного дизайна
- Мастерство $timeformat в Verilog: точность и контроль отображения времени
- Понимание и печать timescale в Verilog в любой области видимости
- Работа с файлами в Verilog: открытие, чтение, запись и закрытие
- Verilog для начинающих: пример Hello World