Использование непрерывного назначения в процедуре Verilog?
Возможно ли и / или полезно ли когда-либо использовать непрерывное назначение в процедуре Verilog? Например, будет ли когда-либо assign
внутри always
блок?
Например этот код:
always @(*)
begin
assign data_in = Data;
end
Кроме того, было бы возможно генерировать последовательную логику с таким подходом?
always @(posedge clk)
begin
assign data_in = Data;
end
1 ответ
Это называется процедурным непрерывным назначением. Это использование assign
или же force
(и их соответствующие аналоги deassign
а также release
) в пределах процессуального блока. Новый непрерывный процесс присваивания создается при достижении строки в процедурном блоке. assign
может применяться к типам регистров, таким как reg
, integer
, а также real
, force
может применяться к регистрам и сетям (т.е. wire
с). Он был частью LRM с 1364-1995.
- Стандарт IEEE 1364-1995 § 9.3
- Стандарт IEEE 1364-2001 § 9.3
- Стандарт IEEE 1364-2005 § 9.3
- Стандарт IEEE 1800-2005 § 25.3
- Стандарт IEEE 1800-2009 § 10.6
- Стандарт IEEE 1800-2012 § 10.6
Процедурные непрерывные назначения синтезируются большинством инструментов. Однако рекомендуется ограничить использование моделированием поведения аналогового блока, файлами тестового стенда или исправлением функциональных несоответствий RTL<->gate.
always @* assign data_in = Data;
функционально так же, какalways @* data_in = Data;
always @(posedge clk) assign data_in = Data;
Функционально так же, как:always @(posedge clk) enable = 1; always @* if (enable==1) data_in = Data;
Действительное непрерывное процессуальное присвоение должно применяться к следующему:
always @(posedge clk or negedge rst_n, negedge set_n) begin
if (!rst_n) q <= 1'b0;
else if (!set_n) q <= 1'b1;
else q <= d;
end
Он синтезируется на флопе с асинхронным набором и сбрасывается с приоритетом сброса. Однако при моделировании модель является неточной, если rst_n
а также set_n
оба низкие тогда rst_n
идет высоко q
Если перейти к 1, асинхронный набор все еще включен, но в списке чувствительности ничего не активируется. Это хорошо задокументированная проблема с Verilog. Это единственный случай, когда процедурное непрерывное назначение разрешено в RTL при использовании с ключевым словом translate off вашего синтезатора. release
/deassign
позволяет назначить регистр / провод обычным способом.
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) force q = 1'b1;
else release q;
// translate_on
ИЛИ (в настоящее время действует, но не рекомендуется)
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) assign q = 1'b1;
else deassign q;
// translate_on
С помощью assign
/deassign
таким образом считается устаревшим в будущем выпуске IEEE 1800. IEEE Std 1800-2005 § 25.3, IEEE Std 1800-2009 § C.4.2 и IEEE Std 1800-2012 § C.4.2 признает assign
Использование этого способа вызывает путаницу и является источником ошибок. использование force
/release
если процедурное непрерывное назначение по мере необходимости.
В генерации с использованием процедурного непрерывного присваивания (с force
/release
) следует использовать только в случае крайней необходимости. Альтернативные подходы более надежны.
Злоупотребление процедурным непрерывным назначением и решениями:
Комбинационная логика на
reg
:always @(sel) if (sel) assign reg1 = func1(x,y,z); else assign reg1 = func2(a,b,c);
Решение:
always @* // <- IEEE Std 1364-2001 construct if (sel) reg1 = func1(x,y,z); else reg1 = func2(a,b,c);
Комбинационная логика на
wire
:always @(sel) if (sel) force wire1 = func1(x,y,z); else force wire1 = func2(a,b,c);
Решение:
assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
Последовательная логика:
always @(posedge clk) if (sel) assign reg2 = func1(x,y,z); else assign reg2 = func2(a,b,c);
Решение (если исходная функциональность неверна):
always @(posedge clk) if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!! else reg2 <= func2(a,b,c);
Решение (если исходная функциональность верна):
reg flop_sel; always @(posedge clk) flop_sel <= sel; // Non-blocking assignment !!! always @* if (flop_sel) reg2 = func1(x,y,z); // Blocking assignment !!! else reg2 = func2(a,b,c);