具有数组实例的 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;
。我有两个问题:
- 我在这里做错了什么,我该如何解决?该错误对我来说没有意义,因为两个分配方程式的左侧是子模块的输入,而不是
ripple_adder16
模块的参数。
- 我想用以下行
assign adders[15:1].cin = adders[14:0].cout;
理想地替换 for 循环,尽管这本身就是一个语法错误。有没有办法在不直接内联 full_adder
? 的情况下做这样的事情
谢谢!
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
我已经实现了一个(有效的)纹波进位加法器,使用生成来创建 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;
。我有两个问题:
- 我在这里做错了什么,我该如何解决?该错误对我来说没有意义,因为两个分配方程式的左侧是子模块的输入,而不是
ripple_adder16
模块的参数。 - 我想用以下行
assign adders[15:1].cin = adders[14:0].cout;
理想地替换 for 循环,尽管这本身就是一个语法错误。有没有办法在不直接内联full_adder
? 的情况下做这样的事情
谢谢!
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