Разработка 32-битного арифметико-логического устройства (АЛУ)

Я пишу этот кодер для ALU. Это ALU контролируется с ctrl сигналы и выполнять некоторые работы, такие как сложение, вычитание, и, или, ... Когда вывод равен нулю, oZero сигналы должны быть активными.

У меня есть некоторые ошибки в отмеченных строках. В чем моя ошибка?

module ALU_32 (iA, iB ,iCin ,ctrl, oCarry,oZero, out);    
input [31:0] iA,iB;
output [31:0] out;
input iCin,ctrl;
output oCarry,oZero;
reg [31:0] out;
reg oCarry;
reg oZero;
always@ (ctrl)
    begin 
        case(ctrl)
            4'b0: out<=iA&iB;
            4'b0001: out<=iA|iB;
            4'b0010: {oCarry ,out}<=iA+iB;
            4'b0011: out<=iA~|iB;    //error
            4'b0100: 
            begin 
                if(iA==iB)
                    out<=32'b1;
            end  
            4'b0101: out<=iA-iB;  //error
            4'b0110:    //error
            begin 
                if(iA<iB)
                    out<=32'b1;
                else
                    out<=32'b0;
                end
            4'b0111:   out<=iA*iB;     //error
            4'b1000: out<=iA/iB;        //error

        end
       always@(out)
           begin
               if(out==0)
                   oZero<=1;
               end

      endmodule

2 ответа

Решение

Как указал Цю, iA~|iB должно быть ~(iA|iB) и вам не хватает endcase, В дополнение к этому:

  1. ctrl должен быть шириной 4 бита. IE input [3:0] ctrl
  2. Комбинационный блок должен объявить все элементы в списке чувствительности или использовать авто-чувствительность. С always @(ctrl) симулятор не будет использовать увидеть изменения в iA или же iB, Вместо этого используйте always @* для авто-чувствительности. Вы всегда должны использовать авто-чувствительность для комбинационной логики, если только вы не ограничены версией IEEE Std 1364 1995 года (скорее всего, нет), в этом случае вам нужно always @(ctrl or iA or iB or iCin), Авто чувствительность (@* или же @(*)) был добавлен в стандарт в 2001 году.
  3. Вы не должны использовать неблокирующие назначения (<=) с комбинационной логикой, используйте блокирующие назначения (=). Неблокирование должно использоваться для назначения триггеров и защелок.
  4. out а также oCarry не присваивается известное значение в каждом условии, это делает их защелками. Конструкции логики защелки склонны к проблемам синхронизации и должны использоваться с осторожностью. Большинство FPGA имеют ограниченное количество защелок, а некоторые имеют некоторые. Изменение стиля кодирования может удалить защелку, и есть два основных способа сделать это.

    1. Назначьте выходы в каждом условии. Убедитесь, что в выражении case объявлено условие по умолчанию:

      always @* begin
        case(ctrl)
        4'b0000 :
          begin
            out = iA&iB;
            oCarry = 1'b0;
          end
        // conditions assigning both 'out' and 'oCarry'
        default:
          begin
            out = 32'0;
            oCarry = 1'b0;
          end
        endcase
      end
      
    2. Присвойте значения значению по умолчанию перед оператором case. Оператор case переопределяет значения по умолчанию.

      always @* begin
        // default value
        out = 32'd0;
        oCarry = 1'b0;
        // calculate value, override default
        case(ctrl)
          4'b0000 : out = iA&iB;
          // ...
          4'b0010: {oCarry ,out} = iA+iB;
          // ...
          4'b1000: out = iA/iB;
        endcase
      end
      
  5. oZero также является предполагаемой защелкой. Он может быть назначен только 1, нет пути к 0. Вы можете:

    • always @* oZero = (out==0);
    • Объединить блок всегда с oZero = (out==0); ниже endcase
    • assign oZero = (out==0); // Make sure 'oZero' is a wire (not reg)

Другие предложения (необязательно)

  1. Заголовок в стиле ANSI. Добавлен в IEEE Std 1364-2001 и поддерживается всеми современными симуляторами и синтезаторами. Он более компактен, чем не-ANSI стиль IEEE Std 1364-1995.

    module ALU_32 (    
      input [31:0] iA, iB,
      input        iCin,
      input [3:0]  ctrl,
      output reg  oCarry, oZero,
      output reg [31:0] out );
    
  2. Вы предположили там, где ошибки с iA*iB а также iA/iB, В verilog нет ничего плохого. У инструментов синтеза может быть проблема, потому что 32-разрядные на 32-разрядные умножители / делители, как правило, занимают много ресурсов. Возможно, вам придется разделить операции на отдельные модули. ПЛИС может иметь предопределенный модуль, поэтому проверьте данные.

~| оператор, который вы использовали в 4'b0011: out<=iA~|iB; Ваша IDE рассматривается как оператор сокращения, а не как операция NOR. Чтобы исправить это, вы можете использовать, например, следующую конструкцию:

out <= ~(iA | iB);

Вторая проблема в том, что вы забыли использовать endcase Ключевое слово в конце вашего case построить.

Проверьте edaplayground, чтобы увидеть эти изменения, примененные к вашему коду.

Другие вопросы по тегам