Verilog可变时长积分模块故障排查:integral始终为0
问题排查与修复方案
核心问题分析
非阻塞赋值导致累加逻辑失效
在时钟触发的always块中,<=是非阻塞赋值,所有赋值操作会在块执行结束后统一更新。你写的for循环里反复执行integral <= integral + memory[i],实际上每次循环都使用当前时钟周期开始时的integral旧值,最终integral只会被赋值为旧integral + memory[duration-1],完全达不到累加所有memory元素的效果。积分前未初始化累加变量
你提到"每个时钟周期都会将integral初始化为0",但代码里除了reset阶段,else块中没有对integral做清零操作,加上非阻塞赋值的特性,导致累加逻辑彻底混乱。乘法操作覆盖累加结果
for循环后的integral <= integral * interval会直接覆盖前面的累加赋值(非阻塞赋值以最后一次为准),进一步导致输出异常。
修复后的代码
module VariableIntegrator ( input [15:0] x, input clk, reset, input [7:0] duration, interval, output reg [63:0] integral ); reg [15:0] memory [31:0]; reg [7:0] i; reg [63:0] temp_integral; // 临时累加变量 always @ (posedge clk) begin if (reset) begin integral <= 64'd0; // 用循环简化memory初始化 for(i=0; i<=31; i=i+1) begin memory[i] <= 16'd0; end end else begin // 循环实现移位寄存器,简化冗余代码 for(i=31; i>0; i=i-1) begin memory[i] <= memory[i-1]; end memory[0] <= x; // 初始化临时累加变量为0,保证每个周期独立计算 temp_integral = 64'd0; // 用阻塞赋值实现正确累加 for(i=0; i < duration; i=i+1) begin temp_integral = temp_integral + memory[i]; end // 最后将结果赋值给输出寄存器,包含乘法操作 integral <= temp_integral * interval; end end endmodule
关键修改点
- 引入临时变量
temp_integral,用阻塞赋值(=)完成累加,确保每一次循环都基于上一次的累加结果计算。 - 每次积分前将
temp_integral清零,保证每个时钟周期的积分都是独立计算的。 - 用循环简化memory的初始化和移位操作,避免冗余代码。
- 将累加和乘法合并为最后一次非阻塞赋值,确保结果正确更新到输出。
内容的提问来源于stack exchange,提问作者Riya_ofWhiteFang
相关产品推荐
相关产品推荐

