You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修复说明

  1. 添加必要端口:新增rst_n同步复位端口和start启动端口,解决原代码未声明端口的问题
  2. 合并时序逻辑:将所有对count和timer_enable的操作合并到一个always块,消除多驱动冲突
  3. 初始化与复位:通过同步复位初始化寄存器状态,避免未知值导致的逻辑异常
  4. 完善结束逻辑:倒计时到0后自动停止计数,确保timer_done信号仅在结束时有效
  5. 扩展测试覆盖:测试平台覆盖所有四个档位,新增中途重新加载功能测试,打印关键节点信息便于调试

内容的提问来源于stack exchange,提问作者oli bb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 09:35:39