【问题标题】:SystemVerilog Dataflow Modeling Ripple-Adder with array instancesSystemVerilog Dataflow Modeling Ripple-Adder 与数组实例
【发布时间】:2022-01-09 13:45:48
【问题描述】:

我已经使用生成实现了一个(工作的)波纹进位加法器,以创建 16 个不同的 full_adder 实例(full_adder 按预期工作):

module ripple_adder16 (a, b, cin, sum, cout);

input [15:0] a, b; input cin;
output [15:0] sum; output cout;
wire [15:0] a, b; wire [15:0] sum; wire cout;

// intermediate nets.
// Since the carries cascade, we have to tell
// verilator that it can't "flatten" or whatever.
/* verilator lint_off UNOPTFLAT */
wire [16:0] carries;
/* verilator lint_on UNOPTFLAT */

assign carries[0] = cin;
assign cout = carries[16]; // output.

genvar i;
generate for(i=0; i < 16; i = i + 1)
  begin
    full_adder adder (
      .a(a[i]),
      .b(b[i]),
      .sum(sum[i]),
      .cin(carries[i]),
      .cout(carries[i+1])
    );
  end
endgenerate

endmodule

现在我正在尝试修改加法器,以便保留一个加法器数组。下面是我正在尝试使用的代码示例:


input [15:0] a, b; input cin;
output [15:0] sum; output cout;
wire [15:0] a, b; wire [15:0] sum; wire cout;

full_adder adders [15:0] (
  .a(a),
  .b(b),
  .cin(),
  .sum(sum), // output.
  .cout()
);

// DIFFERENCES START HERE
assign adders[0].cin = cin;
assign cout = adders[15].cout; // output.

genvar i;
generate
for(i=0; i < 15; i = i + 1)
  assign adders[i+1].cin = adders[i].cout;
endgenerate
// DIFFERENCES END HERE

endmodule

但是,我在 assign adders[0].cin = cin; 和 @987654326 行上收到了来自 Verilator 的 ASSIGNIN 错误(文档显示“正在对输入信号进行分配错误。这几乎可以肯定是一个错误,尽管在技术上是合法的。”) @。我有两个问题:

  1. 我在这里做错了什么,我该如何解决?该错误对我来说没有意义,因为两个分配方程的左侧都是子模块的输入,而不是 ripple_adder16 模块的参数。
  2. 我想用下面的行assign adders[15:1].cin = adders[14:0].cout; 替换for 循环,尽管这本身就是一个语法错误。有没有办法在不直接内联full_adder 的情况下做这样的事情?

谢谢!

PS。如果相关,full_adder 完全用电线实现。

【问题讨论】:

    标签: system-verilog verilator


    【解决方案1】:

    @Serge 的回答对于弄清楚 Verilog 不喜欢什么以及如何解决它非常有帮助。我认为 Verilog 不喜欢当您“内部”查看实例化对象时(例如 adders[2].cin)。相反,如果你想暴露一个模块的内部,你必须在实例化它时连接它。这是有效的代码:

    module ripple_adder16 (a, b, cin, sum, cout);
    
    input [15:0] a, b; input cin;
    output [15:0] sum; output cout;
    
    wire [15:0] a, b; wire [15:0] sum; wire cout;
    /* verilator lint_off UNOPTFLAT */
    wire [16:0] carries;
    /* verilator lint_on UNOPTFLAT */
    
    full_adder adders [15:0] (
      .a(a),
      .b(b),
      .cin(carries[15:0]),
      .sum(sum), // output.
      .cout(carries[16:1])
    );
    
    assign carries[0] = cin;
    
    assign cout = carries[16]; // output.
    
    endmodule
    

    【讨论】:

      【解决方案2】:

      verilog 中的实例数组是generate 块的一种类型,它多次实例化一个模块,在其名称中添加数组索引并使用端口做一些工作。实例数组通常不是很好理解,也很少用于行为 verilog。

      因为它是一个生成块,所以不能在数组实例上使用范围。 'adders[15:1]' 是非法的。您需要使用生成循环逐个实例地访问它们。此外,'assign adders[15:1].cin' 表示与子模块实例的 internal 信号的连接,而不是与它的 输入端口 的连接。所以,编译器是绝对正确的。

      您未连接模块实例的端口并试图访问它们的内部信号。首先,这是一个不好的做法。要修复它,您应该弄清楚如何使用端口连接。需要额外的代码来重新分配向量以满足您的算法,至少在“carries”附近。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多