Выводные защелки в Verilog/SystemVerilog
Операторы в процедурных блоках выполняются последовательно, так почему ни один из блоков block1, block2 или block3 не выводит защелку?
module testing(
input logic a, b, c,
output logic x, y, z, v
);
logic tmp_ref, tmp1, tmp2, tmp3;
//reference
always_comb begin: ref_block
tmp_ref = a & b;
x = tmp_ref ^ c;
end
always_comb begin: block1
y = tmp1 ^ c;
tmp1 = a & b;
end
always @(*) begin: block2
tmp2 <= a & b;
z = tmp2 ^ c;
end
always @(c) begin: block3
tmp3 = a & b;
v = tmp3 ^ c;
end
endmodule: testing
В block1 y вычисляется с использованием назначения блокировки до того, как новое значение tmp1 станет доступным.
В блоке 2 tmp2 вычисляется с использованием неблокирующего назначения, которое должно отложить назначение до конца блока всегда. Между тем, z вычисляется с использованием назначения блокировки, а новое значение tmp2 пока недоступно.
В блоке 3 есть неполный список чувствительности и все еще нет защелки.
Вот результат синтеза из Quartus II 14.1:
Только когда я добавляю этот блок, вывод фиксируется:
//infers a latch
always @(*) begin: block4
if (c == 1'b1) begin
tmp4 = a & b;
w = tmp4 ^ c;
end
end
Может кто-нибудь объяснить, почему неполный список чувствительности или использование переменной до обновления значения не выводит защелку в комбинаторном блоке?
1 ответ
Тип назначения, используемый в комбинаторном блоке, не влияет на синтез. Использование неблокирующих (<=
) может привести к несоответствиям имитатора RTL (перед синтезом) и гейтов (после синтеза).
То же самое верно для списков чувствительности, синтез даст поведение автоматически сгенерированного или полного списка.
В синхронизированном процессе (@(posedge clk)
) использовать неблокирующую (<=
) чтобы получить симуляцию поведения триггера. Можно использовать блокировку (=
) также иметь комбинаторный код внутри синхронизированного процесса, но смешивание стилей считается плохой практикой кодирования. Код комбинаторной части просто перенести в отдельный комбинаторный блок (always @*
).
Защелка является основным элементом памяти, и если цепь не нуждается в памяти, она не будет выведена.
Например:
always @* begin:
v = (a & b) ^ c;
end
v
полностью определяется входами, память не задействована. По сравнению с:
always @* begin
if (c == 1'b1) begin
w = (a & b) ^ c;
end
end
когда c
Значение 0 w должно содержать свое значение, поэтому вывод защелки.
Стоит отметить, что, хотя защелки не плохие, необходимо соблюдать осторожность при выборе времени открытия и закрытия, чтобы убедиться, что они фиксируют правильные данные. Следовательно, предполагаемая защелка обычно считается плохой и имеет плохое кодирование.
SystemVerilog имеет следующий синтаксис для семантически подразумеваемых намерений проектирования:
always_latch begin
if (c == 1'b1) begin
w = (a & b) ^ c;
end
end