Вопрос или проблема
У меня есть три варианта кода. Я не хочу обсуждать логику, а именно синтаксис.
module top_module(
input clk,
input areset, // асинхронный активный высокий сброс на ноль
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk or posedge areset)
begin
if(areset)
q<=0;
if(load | ena)
begin
q[3]<=(0 & (~load) & ena) | (load & data[3]) ;
q[2]<=(q[3]& (~load) & ena) | (load & data[2]) ;
q[1]<=(q[2]& (~load) & ena) | (load & data[1]) ;
q[0]<=(q[1]& (~load) & ena) | (load & data[0]) ;
end
else
q<=q;
end
endmodule
Этот код выше вызвал ошибку.
module top_module(
input clk,
input areset, // асинхронный активный высокий сброс на ноль
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk)
begin
if(areset)
q<=0;
if(load | ena)
begin
q[3]<=(0 & (~load) & ena) | (load & data[3]) ;
q[2]<=(q[3]& (~load) & ena) | (load & data[2]) ;
q[1]<=(q[2]& (~load) & ena) | (load & data[1]) ;
q[0]<=(q[1]& (~load) & ena) | (load & data[0]) ;
end
else
q<=q;
end
endmodule
Этот код выше не вызывает ошибки.
module top_module(
input clk,
input areset, // асинхронный активный высокий сброс на ноль
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk or posedge areset)
begin
if(areset)
q<=0;
else if(load | ena)
begin
q[3]<=(0 & (~load) & ena) | (load & data[3]) ;
q[2]<=(q[3]& (~load) & ena) | (load & data[2]) ;
q[1]<=(q[2]& (~load) & ena) | (load & data[1]) ;
q[0]<=(q[1]& (~load) & ena) | (load & data[0]) ;
end
else
q<=q;
end
endmodule
И этот код тоже не вызывает ошибки.
С точки зрения языка Verilog нет синтаксической ошибки в первом примере кода.
Однако с точки зрения синтеза есть ошибка. Требование синтеза заключается в том, что ваш код должен соответствовать определенным шаблонам, чтобы инструмент синтеза мог сопоставить поведенческий код с поддерживаемыми логическими элементами. Следующий шаблон не соответствует ничему, что сопоставляется вашим инструментом синтеза:
always@(posedge clk or posedge areset)
begin
if(areset)
q<=0;
if(load | ena)
Второй пример кода поддерживается, потому что вы убрали posedge areset
из списка чувствительности:
always@(posedge clk)
Третий пример кода также поддерживается, потому что вы изменили if
на else if
:
else if(load | ena)
Смотрите синтезируемые конструкции для обсуждения. Документация вашего инструмента синтеза также должна обсуждать поддерживаемый синтаксис.
Ответ или решение
Ошибка (10200): ошибка условного оператора Verilog HDL в файле top_module.v(12): невозможно сопоставить операнды
Представленный вами код Verilog имеет несколько версий, и причина возникновения ошибки в синтаксисе первой версии кода, которая использует конструкцию условного оператора в блоке always
. Давайте разберем каждый из представленных вами примеров:
-
Первый код вызывает ошибку, поскольку в конструкции
always
используется чувствительность к сигнальным изменениям как по фронту сигналаclk
, так и по фронту сигналаareset
:always@(posedge clk or posedge areset)
В этом случае, если
areset
активен, код обнуляетq
, но не учитывает, что при активномareset
дальнейшие операторы в блоке не должны выполняться. А именно, используется второй условный операторif
, что создает неопределенное поведение в синтезируемом коде. В синтезе необходимо явно указывать, что дальнейшие действия должны зависеть от состояния сигналаareset
, в противном случае происходят конфликты в поведении вашего устройства. -
Второй код:
always@(posedge clk)
Здесь вы убрали
posedge areset
из списка чувствительности. Это исправляет ошибку, так как дальнейшая логика теперь зависит только отclk
. Однако для обработки асинхронного сброса необходимо добавить дополнительную логику для обработкиareset
внутри блока. Поскольку приareset
значенияq
не изменятся, это решение является правильным с точки зрения синтезируемости, но редуцирует поведение. -
Третий код исправляет условие, заменив его на
else if
, как показано ниже:else if(load | ena)
Поскольку управление потоком теперь явно определяется, если
areset
активно, дальнейшие условные проверки (наload
иena
) низвергнутся. Это позволило избежать логических конфликтов и работает чисто с точки зрения синтезируемого кода. Версия кода теперь соблюдает правила синтезируемости.
На основе представленного кода можно сделать вывод, что важно следить за последовательностью выполнения операторов в блоке always
и уделять внимание асинхронным сбросам. Конструкция с else if
более предпочтительна, так как обеспечивает четкое управление логикой на основе условий, исключая неявные или неопределенные случаи, которые могут привести к несоответствиям в синтезируемом коде.
Важно ознакомиться с документацией вашего синтезирующего инструмента и прочитать о поддерживаемых конструкциях, чтобы обеспечить корректность написанного кода в Verilog.