0

我已经使用生成实现了一个(工作的)波纹进位加法器来创建 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. 我想理想地用以下行替换 for 循环assign adders[15:1].cin = adders[14:0].cout;,尽管这本身就是一个语法错误。有没有办法在没有直接内联的情况下做这样的事情full_adder

谢谢!

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

4

2 回答 2

0

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

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

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

于 2021-12-03T12:05:21.000 回答
0

@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
于 2021-12-12T08:59:01.513 回答