SystemVerilog Layer模块输出为1而非11的问题排查与修正请求
SystemVerilog加权求和模块输出错误排查与修正
问题描述
编写实现输入与对应权重加权求和的Layer模块,测试时输出为1.0000而非预期的11.0000。使用Icarus Verilog仿真,编译命令为iverilog -g2012 -o output layer.sv main.sv,仿真命令为vvp output。
原模块代码
module Layer #(parameter num_inps=2)(out, inps, ws, clk, rst); output reg out; input real inps[num_inps]; input logic clk, rst; input real ws[num_inps]; real temp[num_inps]; genvar i; generate for(i=0; i<num_inps; i++) begin assign temp[i] = inps[i] * ws[i]; end endgenerate always @( posedge clk, posedge rst) begin : res if (rst==1) begin out = 0; end else begin out = 0; begin for(int j=0; j<num_inps; j++) begin out = out + temp[j]; end end end end endmodule
原测试平台代码
module main_tb(); real out; real inps[2], ws[2]; logic clk, rst; Layer l1(out, inps, ws, clk, rst); initial begin $dumpfile("ow.vcd"); $dumpvars(0, l1); inps[0] = 1.0; inps[1] = 2.0; ws[0] = 5.0; ws[1] = 3.0; rst = 0; clk = 0; #10 clk = 1; #10 clk = 0; $display(out); #10 $finish; end endmodule
错误原因
- 输出变量类型未明确声明:模块中
output reg out;未指定数据类型,默认是单bit的reg(等价于reg [0:0] out),无法存储实数类型的加权求和结果。当实数赋值给单bit变量时,会被截断为最低位二进制值(5.0和3.0的二进制最低位均为1),最终累加结果为1,测试平台中real类型的out读取到该值后显示为1.0000。 - 初始化值类型不匹配:always块中用整数
0初始化实数结果,虽然会隐式转换,但建议显式使用实数0.0以避免歧义。
修正后的代码
Layer模块
module Layer #(parameter num_inps=2)(out, inps, ws, clk, rst); output reg real out; // 明确声明为real类型的时序输出 input real inps[num_inps]; input logic clk, rst; input real ws[num_inps]; real temp[num_inps]; genvar i; generate for(i=0; i<num_inps; i++) begin assign temp[i] = inps[i] * ws[i]; end endgenerate always @( posedge clk, posedge rst) begin : res if (rst) begin out = 0.0; // 显式用实数初始化 end else begin out = 0.0; for(int j=0; j<num_inps; j++) begin out = out + temp[j]; end end end endmodule
测试平台(优化版)
module main_tb(); real out; real inps[2], ws[2]; logic clk, rst; // 使用命名端口连接,提升代码可读性与维护性 Layer #(.num_inps(2)) l1( .out(out), .inps(inps), .ws(ws), .clk(clk), .rst(rst) ); initial begin $dumpfile("ow.vcd"); $dumpvars(0, l1); inps[0] = 1.0; inps[1] = 2.0; ws[0] = 5.0; ws[1] = 3.0; rst = 0; clk = 0; #10 clk = 1; #10 clk = 0; $display("输出结果:%f", out); // 格式化输出,便于查看 #10 $finish; end endmodule
验证结果
执行原编译与仿真命令后,将输出预期的输出结果:11.000000。
内容的提问来源于stack exchange,提问作者kushurox TW
相关产品推荐
相关产品推荐

