Выводные защелки в 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
Другие вопросы по тегам