设置转换时序
本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 81 课,共 90 课。
挑战
在本课中,你将添加用于控制每盏灯亮起时长的计数器逻辑。计数器从预设值开始倒数到 0,然后触发状态切换。
计时要求
| 状态 | 持续时间 | 计数器值 |
|---|---|---|
| 绿灯 | 30 秒 | 30 |
| 黄灯 | 10 秒 | 10 |
| 红灯 | 40 秒 | 40 |
计数器的工作方式
- 状态开始时,计数器会载入该状态的持续时间值
- 每次时钟跳变时,计数器减 1
- 计数器达到 0 时,就该切换到下一个状态了
你的任务是为状态机添加缺失的计数器逻辑。上一步中的 next 输入不再使用:现在由计数器决定何时切换状态,测试平台也不再驱动 next。
操作步骤:
- 从模块头部移除
input next,,并用下面的计数器逻辑替换else if (next)条件 - 添加
reg [5:0] counter声明(如果你在第一步中已经声明过,就保留它) - 复位时,将
counter设为 0 - 当
counter == 0时:- 将下一个状态的持续时间载入计数器
- 切换到下一个状态
- 否则,每次时钟跳变时将计数器减 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 在线编译器