Modelsim中4位Up/Down Counter波形异常:数值始终固定为0
解决4位上下计数器始终停留在0的问题
问题根源分析
- Testbench核心问题:
load信号在初始块中被设为1'b1后从未改变,且din赋值为4'b0000。由于RTL代码中load的优先级高于计数逻辑,每个时钟上升沿都会执行count <= din,导致计数器被持续重置为0,完全无法进入加/减计数流程。 - RTL复位逻辑命名不符:
resetn通常表示低电平复位(低有效),但当前RTL中是高电平触发复位,与行业命名习惯冲突,容易引发混淆。 - 打印格式错误:
$monitor中的%d/n应为%d\n,否则无法正确输出换行。
修正后的代码
修正后的RTL代码(调整复位逻辑为低有效,符合命名习惯)
module up_down_counter(clock, din, load, up_down, resetn, count); input clock; input [3:0]din; input resetn, up_down, load; output [3:0]count; reg [3:0]count; always@(posedge clock) begin if(resetn == 1'b0) // 修改为低电平复位,匹配resetn的命名 begin count <= 4'b0; end else if(load == 1'b1) begin count <= din; end else if(up_down == 1'b1) begin count <= count + 1; end else // 无需重复判断up_down==0,简化逻辑 begin count <= count - 1; end end endmodule
修正后的Testbench代码(调整load信号、复位时序,修复打印格式)
module up_down_test; reg clock; reg [3:0]din; reg resetn, up_down, load; wire [3:0]count; up_down_counter DUV(clock, din, load, up_down, resetn, count); always #8 clock = ~clock; initial begin clock = 1'b0; resetn = 1'b0; // 先拉低复位 load = 1'b0; up_down = 1'b0; din = 4'b0000; #16 resetn = 1'b1; // 释放复位 #32 load = 1'b1; // 触发load,赋值初始值 din = 4'b0100; #16 load = 1'b0; // 释放load,进入计数逻辑 #200 $finish; end always #80 up_down = ~up_down; // 每80ns切换一次计数方向 initial $monitor("%d\n", count); // 修复换行符 endmodule
关键修改说明
- Testbench中
load信号控制:添加了load信号的释放逻辑,让计数器在完成初始加载后能进入计数流程,同时给din设置了非零初始值,方便观察计数效果。 - RTL复位逻辑修正:将
resetn改为低有效,符合行业通用命名规则,避免歧义。 - 简化RTL计数逻辑:去掉了重复的
up_down == 1'b0判断,优化代码可读性。 - 修复打印格式:修正
$monitor的换行符错误,确保输出正常。
内容的提问来源于stack exchange,提问作者Avadhoot Sagrolikar
相关产品推荐
相关产品推荐

