Вызывающие модули поведенческого кодирования Verilog HDL для ALU

Это мой первый раз, когда я программирую на verilog hdl, и мне сложно понять, что не так с моим кодом. Мне нужно разработать простой ALU в поведенческом коде.

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

У меня есть следующие модули в отдельных файлах .v в одном проекте (уверен, что это поведенческий?):

module adder3bit( sum, co, a, b);
parameter n = 2;
output reg [n:0] sum;
output reg co;
input [n:0] a;
input [n:0] b;

always @(a, b)
{co, sum} = a + b;

endmodule


module subtract3bit(diff, bo, a, b);
parameter n = 2;
output reg [n:0] diff;
output reg bo;
input [n:0] a;
input [n:0] b;

always @(a, b)
{bo, diff} = a - b;

endmodule

Я проверил их и убедился, что они работают.

Теперь пытаюсь вызвать их в основном модуле ALU:

module alu( out, overflow, a, b,sel);
input [2:0] a, b;
input sel;
output [2:0] out;
output overflow;
always @(a,b,sel)
begin
if(sel=='b0)
    adder3bit A1(out,overflow,a,b);
if(sel=='b1)
    subtract3bit S1( out, overflow, a, b);
end
endmodule

Мой синтаксис может быть неправильным, но он показывает ошибки. Я просто очень плохо знаком с Verilog. Я чувствую, что впервые почувствовал, изучая C. Помощь будет очень признательна.

Я знаю, что он правильно вызывает модули, но я думаю, что это как-то связано с операторами if.

Спасибо, надеюсь узнать что-то новое!


person Darklink9110    schedule 06.10.2016    source источник


Ответы (2)


Основная проблема в том, что вы хотите вызвать модуль. Модули - это не функции или задачи, которые вы не можете назвать. Что вы можете и должны делать с модулем, так это создать его экземпляр в другом модуле (в данном случае модуле ALU). Модули не могут быть созданы внутри процедурных блоков (например, всегда в вашем коде). И сумматор, и вычитатель будут давать новый результат при каждом изменении его входов, поэтому вам нужно только правильно управлять входами этих модулей и читать их выходы.

Советую объявить порт модуля более читаемым способом:

module adder3bit #(
    parameter N = 2
) ( 
   output reg [N:0] sum, 
   output reg co,
   input [N:0] a,
   input [N:0] b
);
    always @(a, b)
        {co, sum} = a + b;

endmodule

В ALU вы можете создать экземпляр adder3bit следующим образом:

module alu (
    input [2:0] a,
    input [2:0] b,
    input sel,
    output [2:0] out,
    output overflow
)
    localparam SIZE = 3;
    wire [SIZE - 1 : 0] diff;
    wire [SIZE - 1 : 0] sum;
    wire co;
    wire bo;

    adder3bit #( 
       .N(SIZE) 
    ) adder (
       .a(a),
       .b(b),
       .sum(sum),
       .co(co)
    );

    subtract3bit #( 
       .N(SIZE) 
    ) subtractor (
       .a(a),
       .b(b),
       .diff(diff),
       .bo(bo)
    );

    always @(*)
    begin
         if(sel=='b0)
             {out,overflow) = {sum, co};
         if(sel=='b1)
             {out,overflow) = {diff, bo};
    end
endmodule

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

person Kamil Rymarz    schedule 06.10.2016
comment
Вы используете n & N для идентификации того же параметра, который является недопустимым; выберите тот или иной. Я советую использовать верхний регистр для обозначения параметра, так как это обычная практика в отрасли и на нескольких языках программирования. - person Greg; 06.10.2016
comment
Спасибо за помощь. Таким образом, модули необходимо инициализировать заранее. Это должно означать, что каждый раз, когда считывается вывод модуля в блоке always, он читает новый ввод в зависимости от a и b? Кроме того, можно ли использовать одиночный провод вместо объявления двух проводов, sum и diff? - person Darklink9110; 07.10.2016
comment
Модуль обновляет свои выходные данные независимо от его чтения. Возьмем ваш сумматор, вы написали внутри него процедуру always, которую можно читать так: Каждый раз, когда изменяется a или b, выполняется операция: {co, sum} = a + b;. Вы не можете использовать одиночный провод, поскольку оба выхода всегда содержат действительные данные. Verilog - это язык описания оборудования, он не похож на C или другие языки программирования, он описывает оборудование. Вы создали асинхронный сумматор и вычитатель, они всегда управляют своими выходами с результатом a + b и a-b соответственно. - person Kamil Rymarz; 07.10.2016
comment
Спасибо!! Я чувствую, что начинаю лучше понимать язык и меньше боюсь кода. Теперь я понимаю, как он представляет оборудование, прежде чем я думал об этом слишком абстрактно. Очень признателен! - person Darklink9110; 07.10.2016

Вы не можете создать экземпляр модуля внутри блока always в verilog. Вместо этого вы можете преобразовать модули adder3bit и substract3bit в задачи и использовать код, как вы написали сейчас. решение будет таким

task adder3bit;
parameter n = 2;
input [n:0] a;
input [n:0] b;
output reg [n:0] sum;
output reg co;
begin
always @(*) {co, sum} = a + b;
endtask


task subtract3bit;
parameter n = 2;
input [n:0] a;
input [n:0] b;
output reg [n:0] diff;
output reg bo;
begin
always @(*) {bo, diff} = a - b;
endtask

module alu( out, overflow, a, b,sel);
input [2:0] a, b;
input sel;
output [2:0] out;
output overflow;
always @(a,b,sel)
begin
if(sel=='b0)
    adder3bit (a,b,out,overflow);
if(sel=='b1)
    subtract3bit ( a,b,out,overflow);
end
endmodule
person vlsi_user    schedule 06.10.2016
comment
Задачи не могут содержать always блоков и не могут объявлять parameters. - person Greg; 06.10.2016
comment
Я недостаточно копался в синтаксическом дереве, чтобы увидеть, что параметр является подмножеством block_item_declaration, которое само по себе является подмножеством tf_item_declaration, которое используется задачей. Однако при повторном просмотре LRM я обнаружил, что чистый Verilog (IEEE 1364) не поддерживает задачи / функции, определенные вне модуля. Это разрешено в SystemVerilog (IEEE 1800). Все современные симуляторы Verilog являются симуляторами SystemVerilog, но если флаг компилятора установлен на строгий Verilog, тогда задача, определенная вне модуля, должна быть ошибкой компиляции. - person Greg; 07.10.2016