Verilog可调倒计时计时器代码无法运行,请求修复及完善Testbench
修复后的可调倒计时计时器Verilog代码及测试平台
原代码问题分析
- 核心模块未声明
start输入端口,直接使用导致编译报错 count寄存器被两个时钟触发的always块同时赋值,产生多驱动冲突- 寄存器未初始化,初始状态为未知值(
x),逻辑行为不可预测 - 倒计时到0后未停止计数,无符号寄存器溢出会导致
timer_done信号异常 - 测试平台仅验证单一档位,未覆盖所有功能,缺乏过程验证
修复后的核心模块代码
module CountdownTimer( input wire clk, input wire rst_n, // 同步低复位 input wire start, // 新增:启动/重新加载倒计时信号 input wire [1:0] set_value, output wire [9:0] remaining_seconds, output wire timer_done ); reg [9:0] count; reg timer_enable; parameter [1:0] COUNT_1000 = 2'b00; parameter [1:0] COUNT_500 = 2'b01; parameter [1:0] COUNT_60 = 2'b10; parameter [1:0] COUNT_9 = 2'b11; // 合并所有时序逻辑,避免多驱动 always @(posedge clk) begin if (!rst_n) begin count <= 10'd0; timer_enable <= 1'b0; end else begin if (start) begin // 启动或重新加载计数值 case (set_value) COUNT_1000: count <= 10'd1000; COUNT_500: count <= 10'd500; COUNT_60: count <= 10'd60; COUNT_9: count <= 10'd9; default: count <= 10'd0; endcase timer_enable <= 1'b1; end else if (timer_enable) begin if (count > 10'd0) begin count <= count - 10'd1; end else begin // 倒计时结束,停止计数 timer_enable <= 1'b0; end end end end assign remaining_seconds = count; assign timer_done = (count == 10'd0) && !timer_enable; endmodule
完善后的测试平台代码
module CountdownTimer_tb; reg clk; reg rst_n; reg start; reg [1:0] set_value; wire [9:0] remaining_seconds; wire timer_done; // 例化待测试模块 CountdownTimer dut ( .clk(clk), .rst_n(rst_n), .start(start), .set_value(set_value), .remaining_seconds(remaining_seconds), .timer_done(timer_done) ); // 生成100MHz时钟(周期10ns) always begin #5 clk = ~clk; end // 测试流程 initial begin // 初始化信号 clk = 1'b0; rst_n = 1'b0; start = 1'b0; set_value = 2'b00; #20; rst_n = 1'b1; #10; // 测试档位1:1000秒倒计时 $display("=== Testing 1000s countdown ==="); set_value = 2'b00; start = 1'b1; #10; start = 1'b0; @(posedge timer_done); $display("1000s countdown done! Remaining: %d", remaining_seconds); #20; // 测试档位2:500秒倒计时 $display("\n=== Testing 500s countdown ==="); set_value = 2'b01; start = 1'b1; #10; start = 1'b0; @(posedge timer_done); $display("500s countdown done! Remaining: %d", remaining_seconds); #20; // 测试档位3:60秒倒计时 $display("\n=== Testing 60s countdown ==="); set_value = 2'b10; start = 1'b1; #10; start = 1'b0; @(posedge timer_done); $display("60s countdown done! Remaining: %d", remaining_seconds); #20; // 测试档位4:9秒倒计时 $display("\n=== Testing 9s countdown ==="); set_value = 2'b11; start = 1'b1; #10; start = 1'b0; @(posedge timer_done); $display("9s countdown done! Remaining: %d", remaining_seconds); #20; // 测试中途重新加载功能 $display("\n=== Testing reload during countdown ==="); set_value = 2'b00; start = 1'b1; #10; start = 1'b0; #50; // 等待5个时钟周期(模拟倒计时进行中) $display("Reloading to 9s when remaining: %d", remaining_seconds); set_value = 2'b11; start = 1'b1; #10; start = 1'b0; @(posedge timer_done); $display("Reloaded countdown done! Remaining: %d", remaining_seconds); $finish; end endmodule
关键修复说明
- 添加必要端口:新增
rst_n同步复位端口和start启动端口,解决原代码未声明端口的问题 - 合并时序逻辑:将所有对
count和timer_enable的操作合并到一个always块,消除多驱动冲突 - 初始化与复位:通过同步复位初始化寄存器状态,避免未知值导致的逻辑异常
- 完善结束逻辑:倒计时到0后自动停止计数,确保
timer_done信号仅在结束时有效 - 扩展测试覆盖:测试平台覆盖所有四个档位,新增中途重新加载功能测试,打印关键节点信息便于调试
内容的提问来源于stack exchange,提问作者oli bb
相关产品推荐
相关产品推荐

