如何从寄存器表达式中选择位段:Verilog实现8个8位寄存器求平均问题
问题原因与修复方案
1. 位段选择报错修复
报错的根本原因是Verilog语法不支持直接对未命名的临时运算结果做位段选择。你代码中8个8位数相加的结果是临时生成的未声明值,编译器没有为其分配11位的显式位宽,因此索引第10位时触发越界错误。
修复方式非常简单,先声明一个11位宽的线网存储求和结果,再对其做位段选择即可:
// 11位宽足够容纳8个8位最大值的求和结果:8*255=2040 < 2^11=2048 wire [10:0] sum_total; assign sum_total = registers[0] + registers[1] + registers[2] + registers[3] + registers[4] + registers[5] + registers[6] + registers[7]; // 取[10:3]等价于右移3位,即除以8取整得到平均值 assign ave8 = sum_total[10:3];
修改后即可解决编译报错问题。
2. 复位逻辑缺陷修复
你当前编写的复位逻辑存在功能错误:always块中if(rs)复位分支后的移位赋值没有添加else分支,会导致复位触发时,寄存器先被赋值为0,紧接着又会执行移位逻辑,复位操作直接失效。修改后的always块如下:
always @(posedge clk) begin if(rs) begin registers[0] <= 0; registers[1] <= 0; registers[2] <= 0; registers[3] <= 0; registers[4] <= 0; registers[5] <= 0; registers[6] <= 0; registers[7] <= 0; end else begin registers[0] <= num_in; registers[1] <= registers[0]; registers[2] <= registers[1]; registers[3] <= registers[2]; registers[4] <= registers[3]; registers[5] <= registers[4]; registers[6] <= registers[5]; registers[7] <= registers[6]; end end
更高效的实现方案
你之前手动通过结构级建模实现的加法器树,用上述行为级描述的话,现代FPGA/ASIC综合工具会自动将求和代码优化为和你手动实现完全一致的加法器树结构,不需要手动例化多个不同位宽的加法器,代码更简洁易维护,综合后的资源占用、时序性能和手动结构级实现完全一致。
如果场景对吞吐量要求不高,也可以采用串行累加方案:每输入一个新数据就做一次累加,8个周期输出一次平均值,这种方案可以大幅减少加法器资源占用,缺点是输出延迟更高。
内容的提问来源于stack exchange,提问作者bitbytten
相关产品推荐
相关产品推荐

