【问题标题】:Verilog HDL behavioral coding calling modules for ALU用于 ALU 的 Verilog HDL 行为编码调用模块
【发布时间】:2016-10-06 03:58:38
【问题描述】:

这是我第一次在 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 语句有关。

谢谢,希望能学到新东西!

【问题讨论】:

    标签: overflow verilog hdl alu


    【解决方案1】:

    主要问题是你想调用 module.模块不是你不能调用它们的函数或任务。您可以并且应该对模块执行的操作是在另一个模块(在本例中为 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
    

    还有一件事,您的模块具有定义其输入和输出大小的参数,但顾名思义,它固定为三个,这可能会造成混淆。

    【讨论】:

    • 您使用n & N 来识别相同的参数是非法的;选择一个或另一个。我建议使用大写来识别参数,因为这是行业和几种编程语言的常见做法
    • 感谢您的帮助。所以模块需要提前初始化。这一定意味着每次读取 always 块中模块的输出时,它都会根据 a 和 b 读取一个新输入?另外,是否允许使用单个输出线而不是声明两条线 sum 和 diff?
    • 模块更新它的输出,无论阅读它。让我们来看看你的加法器,你在里面写了一个 always 过程,可以这样读:每次,当 a 或 b 改变时做操作:{co, sum} = a + b;。您不能使用单线,因为两个输出始终包含有效数据。 Verilog 是一种硬件描述语言,它不像 C 或其他编程语言,它描述硬件。您已经创建了异步加法器和减法器,它们总是分别以 a+b 和 a-b 的结果驱动它们的输出。
    • 谢谢!!我觉得我开始更好地理解这门语言并且不再被代码吓到了。我现在看到它是如何代表硬件的,在我考虑得太抽象之前。非常感谢!
    【解决方案2】:

    您不能在 verilog 中的 always 块内实例化模块。相反,您可以将模块 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
    

    【讨论】:

    • 任务不能包含always块,也不能声明parameters。
    • 我没有深入挖掘语法树来看到该参数是 block_item_declaration 的子集,它本身是任务使用的 tf_item_declaration 的子集。然而,在重新审查 LRM 时,我确实看到 pure Verilog (IEEE 1364) 不支持在模块之外定义的任务/功能。它在 SystemVerilog (IEEE 1800) 中是合法的。所有现代 Verilog 模拟器都是 SystemVerilog 模拟器,但如果编译器标志设置为严格 Verilog,则在模块外部定义的任务应该是编译错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多