定义状态
本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 79 课,共 90 课。
挑战
交通信号灯控制器是一种有限状态机,会按照特定的时间间隔在不同的灯光状态(红灯、黄灯、绿灯)之间循环。有限状态机(FSM)是一种只能处于有限个状态之一的电路。它会根据输入或计时从一个状态切换到另一个状态。
在这个项目中,你将为一个简单的十字路口构建交通信号灯控制器。交通信号灯有三个输出:
| 灯光 | 输出 | 含义 |
|---|---|---|
| 红灯 | red = 1 | 停止 |
| 黄灯 | yellow = 1 | 注意 |
| 绿灯 | green = 1 | 通行 |
灯光按以下顺序循环:
Green → Yellow → Red → Green → …
计时顺序
| 状态 | 持续时间 | 下一个状态 |
|---|---|---|
| 绿灯 | 30 秒 | 黄灯 |
| 黄灯 | 10 秒 | 红灯 |
| 红灯 | 40 秒 | 绿灯 |
在本课中,你将定义交通信号灯控制器的状态。
交通信号灯有三种可能的状态:
| 状态 | 灯光 | 代码 |
|---|---|---|
| 绿灯 | 绿灯亮 | 2'b00 |
| 黄灯 | 黄灯亮 | 2'b01 |
| 红灯 | 红灯亮 | 2'b10 |
添加缺少的部分,完成这个模块。
操作步骤:
定义状态编码:0=绿灯,1=黄灯,2=红灯
- 声明一个名为
state的 2 位寄存器 - 声明一个名为
counter的 6 位寄存器(用于计时,最长可达 40 秒)。此步骤中不会用到它:使用该寄存器进行计数的计时逻辑将在本项目后续的“计时转换”步骤中实现 - 在组合 always 块中添加输出赋值,
always @(*) begin ... end,并在其中使用case (state)。red、yellow和green声明为output reg,而reg只能在这样的块中赋值。@(*)表示只要该块读取的任何内容发生变化,就会再次运行。这里读取的是state:- 当 state 为 0 时:
green = 1,yellow = 0,red = 0 - 当 state 为 1 时:
green = 0,yellow = 1,red = 0 - 当 state 为 2 时:
green = 0,yellow = 0,red = 1
- 当 state 为 0 时:
亲手试试
module traffic_light (
input clk,
input reset,
output reg red,
output reg yellow,
output reg green
);
// TODO:任务 1:声明状态寄存器(2 位)
// TODO:任务 2:声明计数器寄存器(6 位)
// TODO:任务 3:使用 case (state) 为输出赋值
// 状态 0:green=1,yellow=0,red=0
// 状态 1:green=0,yellow=1,red=0
// 状态 2:green=0,yellow=0,red=1
endmodule基础知识中的所有课
自己练习: Verilog 在线编译器