Menu
CoddyTech

设置转换时序

本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 81 课,共 90 课。

challenge icon

挑战

在本课中,你将添加用于控制每盏灯亮起时长的计数器逻辑。计数器从预设值开始倒数到 0,然后触发状态切换。

计时要求

状态持续时间计数器值
绿灯30 秒30
黄灯10 秒10
红灯40 秒40

计数器的工作方式

  1. 状态开始时,计数器会载入该状态的持续时间值
  2. 每次时钟跳变时,计数器减 1
  3. 计数器达到 0 时,就该切换到下一个状态了

你的任务是为状态机添加缺失的计数器逻辑。上一步中的 next 输入不再使用:现在由计数器决定何时切换状态,测试平台也不再驱动 next。

操作步骤:

  1. 从模块头部移除 input next,,并用下面的计数器逻辑替换 else if (next) 条件
  2. 添加 reg [5:0] counter 声明(如果你在第一步中已经声明过,就保留它)
  3. 复位时,将 counter 设为 0
  4. 当 counter == 0 时:
    • 将下一个状态的持续时间载入计数器
    • 切换到下一个状态
  5. 否则,每次时钟跳变时将计数器减 1

亲手试试

module traffic_light (
  input clk,
  input reset,
  output reg red,
  output reg yellow,
  output reg green
);

  reg [1:0] state;
  // TODO: 声明 counter 寄存器(6 位)
  

  // 输出赋值
  always @(*) begin
    case (state)
      0: begin green = 1; yellow = 0; red = 0; end
      1: begin green = 0; yellow = 1; red = 0; end
      2: begin green = 0; yellow = 0; red = 1; end
      default: begin green = 0; yellow = 0; red = 1; end
    endcase
  end

  // 带计时功能的状态机
  always @(posedge clk or posedge reset) begin
    if (reset) begin
      state <= 2;      // 从红灯开始
      // TODO: 将 counter 设为 0
      
    end else begin
      if (counter == 0) begin
        case (state)
          0: begin
            state <= 1;
            // TODO: 为黄灯加载 counter(10 秒)
            
          end
          1: begin
            state <= 2;
            // TODO: 为红灯加载 counter(40 秒)
            
          end
          2: begin
            state <= 0;
            // TODO: 为绿灯加载 counter(30 秒)
            
          end
        endcase
      end else begin
        // TODO: 将 counter 减 1
        
      end
    end
  end

endmodule

基础知识中的所有课

自己练习: Verilog 在线编译器