Verilog 乘法器和除法器中加法器模块的不同实现之间的行为差异

问题描述 投票:0回答:1

我的 Verilog 代码遇到了一个涉及乘法器和除法器的令人费解的问题。我已经使用并行加法器组件实现了这两个模块,但是根据我使用的加法器的实现,我得到了不同的结果。

以下是问题的简要概述:

我有两种加法器模块的实现:一种名为parallel_adder,另一种名为FA。 当我在乘法器和除法器中使用parallel_adder 实现时,我得到了正确的结果。 然而,当我切换到在相同的乘法器和除法器模块中使用加法器的 CSelA32 实现时,我开始得到不正确的结果。 具体来说,当我使用 33 位数字(第 33 位用于乘法器和除法器中的运算符号)(例如 32'd4 和 32'd2)时,CSelA32 实现会生成不正确的结果,而 parallel_adder 实现会生成正确的结果输出。 我确保模块之间的输入和输出宽度匹配,并且检查了数据路径和控制信号。我还验证了模块实例化是正确的。

我正在寻求指导,了解为什么两种实现之间的行为不同,以及无论我使用哪种加法器实现,如何确保结果一致。

任何见解或建议将不胜感激。谢谢!

module parallel_adder #(parameter WIDTH=32)(
    input  wire [WIDTH:0] a, 
    input  wire [WIDTH:0] b,
    input                 cin,
    input                 load,
    output reg  [WIDTH:0] sum,
    output reg            cout
);
    always @* begin
        if(load) {cout, sum} = a+b+cin;
    end
endmodule

这里我使用进位选择加法器

module FA (
    output reg sum,
    output reg cout,
    input a,
    input b,
    input cin,
    input load
);
  
  always @* begin
    if (load) begin
      sum = a ^ b ^ cin;
      cout = (a & b) | (b & cin) | (cin & a);
    end
  end

endmodule

module MUX2to1_w1 (         //Mux 2to1 for 1 bit
    output reg y,
    input i0,
    i1,
    s
);
  always @(i0, i1, s) begin
    if (s == 1'b0) 
        y = i0;
    else 
        y = i1;
  end
endmodule

module MUX2to1_w4 (         //Mux 2to1 for 4 bits
    output reg [3:0] y,
    input [3:0] i0,
    i1,
    input s
);

  always @(i0, i1, s) begin
    if (s == 1'b0) begin
      y = i0;  
    end else begin
      y = i1;  
    end
  end
endmodule

module RCA4 #(parameter WIDTH=3)(               // Ripple Carry Adder with 4 bits
    input [WIDTH:0] a,
    b,
    input cin,
    input load,
    output [WIDTH:0] sum,
    output cout
);
  wire [WIDTH-1:0] c;

  FA fa0 ( .a(a[0]), .b(b[0]), .cin(cin), .sum(sum[0]), .cout(c[0]), .load(load) );
  FA fa1 ( .a(a[1]), .b(b[1]), .cin(c[0]), .sum(sum[1]), .cout(c[1]), .load(load) );
  FA fa2 ( .a(a[2]), .b(b[2]), .cin(c[1]), .sum(sum[2]), .cout(c[2]), .load(load) );
  FA fa3 ( .a(a[3]), .b(b[3]), .cin(c[2]), .sum(sum[3]), .cout(cout), .load(load) );

endmodule

module CSelA32 #(parameter WIDTH=32) (
    input [WIDTH:0] a,
    input [WIDTH:0] b,
    input cin,
    input load,
    output [WIDTH:0] sum,
    output cout
);

  wire [WIDTH:0] sum0, sum1;
  wire [7:0] c;
  wire [7:0] cout0, cout1;

  RCA4 rca0_0 ( .sum(sum[3:0]), .cout(cout0[0]), .a(a[3:0]), .b(b[3:0]), .cin(1'b0), .load(load) );

  RCA4 rca_other_0[6:1](.sum(sum0[27:4]), .cout(cout0[6:1]), .a(a[27:4]), .b(b[27:4]), .cin(1'b0), .load(load) );
  RCA4 rca_other_1[6:1](.sum(sum1[27:4]), .cout(cout1[6:1]), .a(a[27:4]), .b(b[27:4]), .cin(1'b1), .load(load) );
  MUX2to1_w4 mux_other_sum[6:1](.y(sum[27:4]), .i0(sum0[27:4]), .i1(sum1[27:4]), .s(c[5:0]));
  MUX2to1_w1 mux_other_cout[6:1](.y(c[6:1]), .i0(cout0[6:1]), .i1(cout1[6:1]), .s(c[5:0]));

  RCA4 rca7_0 (.sum(sum0[31:28]), .cout(cout0[7]), .a(a[31:28]), .b(b[31:28]), .cin(1'b0), .load(load)  );
  RCA4 rca7_1 ( .sum(sum1[31:28]), .cout(cout1[7]), .a(a[31:28]), .b(b[31:28]), .cin(1'b1), .load(load)  );
  MUX2to1_w4 mux6543210_sum ( .y (sum[31:28]), .i0(sum0[31:28]), .i1(sum1[31:28]), .s (c[6]) );
  MUX2to1_w1 mux6543210_cout ( .y (c[7]), .i0(cout0[7]), .i1(cout1[7]), .s (c[6]) );

  FA sign (.a(a[32]), .b(b[32]), .cin(c[7]), .sum(sum[32]), .cout(cout), .load(load));


endmodule
verilog system-verilog
1个回答
0
投票

这里的问题是2:

  1. 您忘记将CSelA32模块的输入信号cin连接到RCA的rca0_0实例的cin端口。
  2. 您不会将第一个 RCA rca0_0 之间的进位传播到前 2 个多路复用器 mux_other_sum[0] 和 mux_other_sum[0]。

这是一个工作解决方案,其中 cout0[0] 分配给 c[0],将第一个进位传播到 2 个多路复用器。

module CSelA32 #(parameter WIDTH=32) (
    input [WIDTH:0] a,
    input [WIDTH:0] b,
    input cin,
    input load,
    output [WIDTH:0] sum,
    output cout
);

  wire [WIDTH:0] sum0, sum1;
  wire [7:0] c;
  wire [7:0] cout0, cout1;

  RCA4 rca0_0 ( .sum(sum[3:0]), .cout(cout0[0]), .a(a[3:0]), .b(b[3:0]), .cin(cin), .load(load) );
  assign c[0] = cout0[0];
    
    
  RCA4 rca_other_0[6:1](.sum(sum0[27:4]), .cout(cout0[6:1]), .a(a[27:4]), .b(b[27:4]), .cin(1'b0), .load(load) );
  RCA4 rca_other_1[6:1](.sum(sum1[27:4]), .cout(cout1[6:1]), .a(a[27:4]), .b(b[27:4]), .cin(1'b1), .load(load) );
  MUX2to1_w4 mux_other_sum[6:1](.y(sum[27:4]), .i0(sum0[27:4]), .i1(sum1[27:4]), .s(c[5:0]));
  MUX2to1_w1 mux_other_cout[6:1](.y(c[6:1]), .i0(cout0[6:1]), .i1(cout1[6:1]), .s(c[5:0]));

  RCA4 rca7_0 (.sum(sum0[31:28]), .cout(cout0[7]), .a(a[31:28]), .b(b[31:28]), .cin(1'b0), .load(load)  );
  RCA4 rca7_1 ( .sum(sum1[31:28]), .cout(cout1[7]), .a(a[31:28]), .b(b[31:28]), .cin(1'b1), .load(load)  );
  MUX2to1_w4 mux6543210_sum ( .y (sum[31:28]), .i0(sum0[31:28]), .i1(sum1[31:28]), .s (c[6]) );
  MUX2to1_w1 mux6543210_cout ( .y (c[7]), .i0(cout0[7]), .i1(cout1[7]), .s (c[6]) );

  FA sign (.a(a[32]), .b(b[32]), .cin(c[7]), .sum(sum[32]), .cout(cout), .load(load));


endmodule

希望对你有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.