具有数组实例的 SystemVerilog 数据流建模 Ripple-Adder

SystemVerilog Dataflow Modeling Ripple-Adder with array instances

我已经实现了一个(有效的)纹波进位加法器,使用生成来创建 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

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

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

谢谢!

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

verilog 中的实例数组是一种 generate 块,并多次实例化模块,将数组索引添加到其名称中 并使用端口做一些工作.实例数组通常没有被很好地理解并且很少在行为 verilog 中使用。

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

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

左右

@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