一、设计概述
本设计实现一个完整的交通灯控制系统,包含主干道和支干道两组信号灯,具有自动循环、行人请求、紧急模式等功能。系统采用有限状态机(FSM)实现,具有清晰的时序逻辑和状态转换。
二、系统设计
1. 系统框图
+-----------------+ +-----------------+ +-----------------+
| 时钟分频模块 | | 状态机控制 | | 输出控制 |
| (Clock Divider) |---->| (State Machine) |---->| (Output Logic) |
+-----------------+ +-----------------+ +-----------------+
| | |
v v v
+-----------------+ +-----------------+ +-----------------+
| 复位信号 | | 时间计数器 | | LED显示驱动 |
| (Reset Signal) | | (Time Counter) | | (LED Driver) |
+-----------------+ +-----------------+ +-----------------+
2. 功能规格
- 主干道绿灯时间:30秒
- 支干道绿灯时间:20秒
- 黄灯时间:3秒
- 支持行人请求按钮
- 支持紧急模式开关
- 倒计时显示功能
三、Verilog实现
1. 顶层模块 (traffic_light_top.v)
v
module traffic_light_top(
input clk, // 100MHz系统时钟
input reset, // 复位信号
input ped_request, // 行人请求按钮
input emergency, // 紧急模式开关
output [2:0] main_light, // 主干道灯 [红,黄,绿]
output [2:0] side_light, // 支干道灯 [红,黄,绿]
output [6:0] seg, // 7段数码管
output [3:0] an // 数码管位选
);
// 时钟分频
wire clk_1Hz;
clock_divider #(.DIVIDER(100_000_000)) u_clk_divider(
.clk(clk),
.reset(reset),
.clk_out(clk_1Hz)
);
// 状态机控制
wire [1:0] state;
wire [5:0] timer;
wire ped_wait;
state_machine u_state_machine(
.clk(clk_1Hz),
.reset(reset),
.ped_request(ped_request),
.emergency(emergency),
.state(state),
.timer(timer),
.ped_wait(ped_wait)
);
// 输出控制
output_logic u_output_logic(
.state(state),
.emergency(emergency),
.main_light(main_light),
.side_light(side_light)
);
// 倒计时显示
display_driver u_display_driver(
.clk(clk),
.reset(reset),
.state(state),
.timer(timer),
.ped_wait(ped_wait),
.seg(seg),
.an(an)
);
endmodule
2. 时钟分频模块 (clock_divider.v)
v
module clock_divider #(
parameter DIVIDER = 100_000_000 // 100MHz -> 1Hz
)(
input clk,
input reset,
output reg clk_out
);
reg [31:0] counter;
always @(posedge clk or posedge reset) begin
if (reset) begin
counter <= 0;
clk_out <= 0;
end else begin
if (counter == DIVIDER/2 - 1) begin
counter <= 0;
clk_out <= ~clk_out;
end else begin
counter <= counter + 1;
end
end
end
endmodule
3. 状态机控制 (state_machine.v)
v
module state_machine(
input clk,
input reset,
input ped_request,
input emergency,
output reg [1:0] state,
output reg [5:0] timer,
output reg ped_wait
);
// 状态定义
localparam MAIN_GREEN = 2'b00;
localparam MAIN_YELLOW = 2'b01;
localparam SIDE_GREEN = 2'b10;
localparam SIDE_YELLOW = 2'b11;
// 时间参数
localparam MAIN_GREEN_TIME = 6'd30;
localparam MAIN_YELLOW_TIME = 6'd3;
localparam SIDE_GREEN_TIME = 6'd20;
localparam SIDE_YELLOW_TIME = 6'd3;
// 状态转移逻辑
always @(posedge clk or posedge reset) begin
if (reset) begin
state <= MAIN_GREEN;
timer <= MAIN_GREEN_TIME;
ped_wait <= 0;
end else if (emergency) begin
// 紧急模式:所有方向红灯
state <= MAIN_GREEN; // 任意状态,实际输出会覆盖
timer <= 0;
end else begin
// 行人请求处理
if (ped_request && state == SIDE_GREEN && timer > 6'd5) begin
ped_wait <= 1;
end
// 状态转移
if (timer == 0) begin
case (state)
MAIN_GREEN: begin
state <= MAIN_YELLOW;
timer <= MAIN_YELLOW_TIME;
end
MAIN_YELLOW: begin
state <= SIDE_GREEN;
timer <= (ped_wait) ? 6'd5 : SIDE_GREEN_TIME;
ped_wait <= 0;
end
SIDE_GREEN: begin
state <= SIDE_YELLOW;
timer <= SIDE_YELLOW_TIME;
end
SIDE_YELLOW: begin
state <= MAIN_GREEN;
timer <= MAIN_GREEN_TIME;
end
endcase
end else begin
timer <= timer - 1;
end
end
end
endmodule
4. 输出逻辑 (output_logic.v)
v
module output_logic(
input [1:0] state,
input emergency,
output reg [2:0] main_light,
output reg [2:0] side_light
);
// 灯定义: [红, 黄, 绿]
localparam RED = 3'b100;
localparam YELLOW = 3'b010;
localparam GREEN = 3'b001;
always @(*) begin
if (emergency) begin
// 紧急模式:所有方向红灯
main_light = RED;
side_light = RED;
end else begin
case (state)
// 主干道绿灯,支干道红灯
2'b00: begin
main_light = GREEN;
side_light = RED;
end
// 主干道黄灯,支干道红灯
2'b01: begin
main_light = YELLOW;
side_light = RED;
end
// 主干道红灯,支干道绿灯
2'b10: begin
main_light = RED;
side_light = GREEN;
end
// 主干道红灯,支干道黄灯
2'b11: begin
main_light = RED;
side_light = YELLOW;
end
default: begin
main_light = RED;
side_light = RED;
end
endcase
end
end
endmodule
5. 显示驱动 (display_driver.v)
v
module display_driver(
input clk,
input reset,
input [1:0] state,
input [5:0] timer,
input ped_wait,
output reg [6:0] seg,
output reg [3:0] an
);
// 数码管显示值
reg [3:0] digit0, digit1;
reg [3:0] digit2, digit3;
// 数码管译码
always @(*) begin
case(digit0)
0: seg = 7'b1000000; 1: seg = 7'b1111001;
2: seg = 7'b0100100; 3: seg = 7'b0110000;
4: seg = 7'b0011001; 5: seg = 7'b0010010;
6: seg = 7'b0000010; 7: seg = 7'b1111000;
8: seg = 7'b0000000; 9: seg = 7'b0010000;
default: seg = 7'b1111111;
endcase
end
// 时间显示逻辑
always @(posedge clk or posedge reset) begin
if (reset) begin
digit0 <= 0; digit1 <= 0;
digit2 <= 0; digit3 <= 0;
an <= 4'b1110;
end else begin
// 根据状态选择显示内容
case(state)
2'b00: begin // 主干道绿灯
digit1 <= timer / 10;
digit0 <= timer % 10;
digit3 <= 4'hM; // M表示Main
digit2 <= 4'hG; // G表示Green
end
2'b01: begin // 主干道黄灯
digit1 <= timer / 10;
digit0 <= timer % 10;
digit3 <= 4'hM;
digit2 <= 4'hY; // Y表示Yellow
end
2'b10: begin // 支干道绿灯
digit1 <= timer / 10;
digit0 <= timer % 10;
digit3 <= 4'hS; // S表示Side
digit2 <= 4'hG;
end
2'b11: begin // 支干道黄灯
digit1 <= timer / 10;
digit0 <= timer % 10;
digit3 <= 4'hS;
digit2 <= 4'hY;
end
endcase
// 行人等待状态
if (ped_wait) begin
digit3 <= 4'hP; // P表示Pedestrian
digit2 <= 4'hW; // W表示Wait
end
end
end
endmodule
四、约束文件 (traffic_light.xdc)
v
# 时钟信号
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
# 复位按钮
set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports reset]
# 行人请求按钮
set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports ped_request]
# 紧急模式开关
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports emergency]
# 主干道信号灯
set_property -dict {PACKAGE_PIN F5 IOSTANDARD LVCMOS33} [get_ports {main_light[0]}] # 红
set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS33} [get_ports {main_light[1]}] # 黄
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {main_light[2]}] # 绿
# 支干道信号灯
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {side_light[0]}] # 红
set_property -dict {PACKAGE_PIN C3 IOSTANDARD LVCMOS33} [get_ports {side_light[1]}] # 黄
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {side_light[2]}] # 绿
# 数码管段选
set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS33} [get_ports {seg[0]}]
set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports {seg[1]}]
set_property -dict {PACKAGE_PIN J22 IOSTANDARD LVCMOS33} [get_ports {seg[2]}]
set_property -dict {PACKAGE_PIN K22 IOSTANDARD LVCMOS33} [get_ports {seg[3]}]
set_property -dict {PACKAGE_PIN K21 IOSTANDARD LVCMOS33} [get_ports {seg[4]}]
set_property -dict {PACKAGE_PIN H20 IOSTANDARD LVCMOS33} [get_ports {seg[5]}]
set_property -dict {PACKAGE_PIN H22 IOSTANDARD LVCMOS33} [get_ports {seg[6]}]
# 数码管位选
set_property -dict {PACKAGE_PIN F17 IOSTANDARD LVCMOS33} [get_ports {an[0]}]
set_property -dict {PACKAGE_PIN H18 IOSTANDARD LVCMOS33} [get_ports {an[1]}]
set_property -dict {PACKAGE_PIN C19 IOSTANDARD LVCMOS33} [get_ports {an[2]}]
set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {an[3]}]
参考代码 Vivado下verilog编写完整交通灯 www.youwenfan.com/contentcss/182616.html
五、仿真测试
1. 测试平台 (tb_traffic_light.sv)
v
`timescale 1ns / 1ps
module tb_traffic_light();
reg clk;
reg reset;
reg ped_request;
reg emergency;
wire [2:0] main_light;
wire [2:0] side_light;
// 实例化被测设计
traffic_light_top uut (
.clk(clk),
.reset(reset),
.ped_request(ped_request),
.emergency(emergency),
.main_light(main_light),
.side_light(side_light)
);
// 生成时钟
initial begin
clk = 0;
forever #5 clk = ~clk; // 100MHz时钟
end
// 测试序列
initial begin
// 初始化
reset = 1;
ped_request = 0;
emergency = 0;
#20;
// 释放复位
reset = 0;
#100;
// 测试行人请求
ped_request = 1;
#10;
ped_request = 0;
#200;
// 测试紧急模式
emergency = 1;
#100;
emergency = 0;
#100;
// 结束仿真
$finish;
end
// 波形记录
initial begin
$dumpfile("traffic_light.vcd");
$dumpvars(0, tb_traffic_light);
end
endmodule
2. 预期仿真结果
- 复位后系统进入主干道绿灯状态(30秒)
- 30秒后切换到主干道黄灯(3秒)
- 3秒后切换到支干道绿灯(20秒)
- 20秒后切换到支干道黄灯(3秒)
- 3秒后回到主干道绿灯状态
- 行人请求在支干道绿灯最后5秒有效
- 紧急模式时所有方向显示红灯
六、实现与综合
1. Vivado实现步骤
- 创建新项目,选择目标FPGA器件
- 添加所有Verilog源文件
- 添加约束文件
- 运行综合(Synthesis)
- 运行实现(Implementation)
- 生成比特流(Generate Bitstream)
- 下载到开发板
2. 资源占用预估
| 资源类型 | 使用量 | 可用量 | 利用率 |
|---|---|---|---|
| LUT | 约200 | 63400 | <1% |
| FF | 约100 | 126800 | <1% |
| IO | 约20 | 300 | <7% |
| BUFG | 1 | 32 | 3% |
七、扩展功能
1. 夜间模式
v
// 在状态机中添加夜间模式
localparam NIGHT_MODE = 2'b00; // 使用相同状态编码
// 添加夜间模式检测
always @(posedge clk or posedge reset) begin
if (night_mode_button) begin
night_mode <= ~night_mode;
end
end
// 修改状态转移
if (night_mode) begin
// 夜间模式:黄灯闪烁
main_light = (clk_1Hz) ? YELLOW : OFF;
side_light = (clk_1Hz) ? YELLOW : OFF;
end
2. 车流量检测
v
// 添加车流量传感器输入
input [3:0] car_flow_main;
input [3:0] car_flow_side;
// 在状态机中动态调整时间
if (car_flow_main > 8'h0A) begin
// 主干道车多,延长绿灯时间
main_green_time = 40;
end
八、项目总结
本设计实现了一个完整的交通灯控制系统,具有以下特点:
- 采用有限状态机实现清晰的交通灯状态转换
- 支持行人请求和紧急模式
- 提供倒计时显示功能
- 模块化设计,便于扩展和维护
- 资源占用少,适合在中小规模FPGA上实现