Ошибка (10200): Ошибка условного оператора Verilog HDL в top_module.v(12): невозможно сопоставить операнды.

Вопрос или проблема

У меня есть три варианта кода. Я не хочу обсуждать логику, а именно синтаксис.

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. Давайте разберем каждый из представленных вами примеров:

  1. Первый код вызывает ошибку, поскольку в конструкции always используется чувствительность к сигнальным изменениям как по фронту сигнала clk, так и по фронту сигнала areset:

    always@(posedge clk or posedge areset)

    В этом случае, если areset активен, код обнуляет q, но не учитывает, что при активном areset дальнейшие операторы в блоке не должны выполняться. А именно, используется второй условный оператор if, что создает неопределенное поведение в синтезируемом коде. В синтезе необходимо явно указывать, что дальнейшие действия должны зависеть от состояния сигнала areset, в противном случае происходят конфликты в поведении вашего устройства.

  2. Второй код:

    always@(posedge clk)

    Здесь вы убрали posedge areset из списка чувствительности. Это исправляет ошибку, так как дальнейшая логика теперь зависит только от clk. Однако для обработки асинхронного сброса необходимо добавить дополнительную логику для обработки areset внутри блока. Поскольку при areset значения q не изменятся, это решение является правильным с точки зрения синтезируемости, но редуцирует поведение.

  3. Третий код исправляет условие, заменив его на else if, как показано ниже:

    else if(load | ena) 

    Поскольку управление потоком теперь явно определяется, если areset активно, дальнейшие условные проверки (на load и ena) низвергнутся. Это позволило избежать логических конфликтов и работает чисто с точки зрения синтезируемого кода. Версия кода теперь соблюдает правила синтезируемости.

На основе представленного кода можно сделать вывод, что важно следить за последовательностью выполнения операторов в блоке always и уделять внимание асинхронным сбросам. Конструкция с else if более предпочтительна, так как обеспечивает четкое управление логикой на основе условий, исключая неявные или неопределенные случаи, которые могут привести к несоответствиям в синтезируемом коде.

Важно ознакомиться с документацией вашего синтезирующего инструмента и прочитать о поддерживаемых конструкциях, чтобы обеспечить корректность написанного кода в Verilog.

Оцените материал
Добавить комментарий

Капча загружается...