VHDL交通信号灯实战:从零搭建Quartus仿真环境(含完整代码解析)

张开发
2026/4/12 12:02:23 15 分钟阅读

分享文章

VHDL交通信号灯实战:从零搭建Quartus仿真环境(含完整代码解析)
VHDL交通信号灯实战从零搭建Quartus仿真环境含完整代码解析在数字电路设计领域FPGA开发已成为工程师必备的核心技能之一。而交通信号灯控制系统作为经典的时序逻辑设计案例不仅能帮助初学者理解状态机的工作原理还能全面掌握VHDL语言的基本语法和Quartus开发环境的使用流程。本文将带你从零开始逐步构建一个完整的交通信号灯仿真项目。1. 开发环境准备与项目创建工欲善其事必先利其器。在开始编码前我们需要搭建好开发环境。Intel Quartus Prime Lite Edition是FPGA开发的理想选择它提供了从设计输入到硬件编程的全套工具链。首先下载并安装Quartus Prime Lite 21.1版本约8GB安装时注意勾选以下组件Quartus Prime软件ModelSim-Intel FPGA Starter Edition仿真工具对应你FPGA开发板的器件支持包安装完成后按以下步骤创建新项目File New Project Wizard - 指定项目目录和名称如TrafficLight - 选择项目类型为Empty project - 添加设计文件可稍后创建 - 选择目标器件如Cyclone IV EP4CE6E22C8 - 完成向导提示初学者常犯的错误是器件选择不当。务必根据你的开发板型号选择正确器件否则后续无法进行硬件验证。创建项目后我们需要添加VHDL设计文件File New VHDL File - 保存为traffic_light.vhd此时项目结构应如下所示TrafficLight/ ├── traffic_light.vhd └── TrafficLight.qpf (项目文件)2. 交通信号灯系统架构设计一个典型的十字路口交通信号灯系统包含以下功能模块时钟分频模块将板载高频时钟如50MHz分频为1Hz信号状态控制模块实现交通灯状态转换逻辑计时器模块控制各状态持续时间显示模块驱动数码管显示倒计时系统RTL结构如下图所示文字描述--------------- | 时钟分频模块 | -------┬------- | -------▼------- | 状态控制模块 | -------┬------- | ----------------------▼------- --------------- | 数码管显示模块 |←| 计时器模块 |←| 参数配置模块 | ------------------------------ ---------------交通灯状态转换遵循以下时序主干道绿灯(40s) → 主干道黄灯(5s) → 支干道绿灯(20s) → 支干道黄灯(5s) → 循环3. VHDL核心代码实现3.1 实体声明与端口定义首先定义交通灯控制器的顶层实体明确输入输出端口LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY traffic_light IS PORT( clk_50MHz : IN STD_LOGIC; -- 50MHz时钟输入 reset : IN STD_LOGIC; -- 异步复位信号 -- 主干道信号灯 main_red : OUT STD_LOGIC; main_yellow : OUT STD_LOGIC; main_green : OUT STD_LOGIC; -- 支干道信号灯 branch_red : OUT STD_LOGIC; branch_yellow : OUT STD_LOGIC; branch_green : OUT STD_LOGIC; -- 数码管显示两位BCD码 seg_led : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END traffic_light;3.2 时钟分频模块实现将50MHz时钟分频为1Hz信号用于驱动状态机ARCHITECTURE rtl OF traffic_light IS SIGNAL clk_1Hz : STD_LOGIC; SIGNAL counter : INTEGER RANGE 0 TO 25000000 : 0; BEGIN -- 时钟分频进程 clock_divider: PROCESS(clk_50MHz, reset) BEGIN IF reset 1 THEN counter 0; clk_1Hz 0; ELSIF rising_edge(clk_50MHz) THEN IF counter 24999999 THEN -- 50MHz/50M1Hz counter 0; clk_1Hz NOT clk_1Hz; -- 翻转产生1Hz时钟 ELSE counter counter 1; END IF; END IF; END PROCESS;3.3 状态机控制模块使用有限状态机(FSM)实现交通灯状态转换-- 状态机定义 TYPE state_type IS ( MAIN_GREEN, -- 主干道绿灯 MAIN_YELLOW, -- 主干道黄灯 BRANCH_GREEN, -- 支干道绿灯 BRANCH_YELLOW -- 支干道黄灯 ); SIGNAL current_state : state_type : MAIN_GREEN; SIGNAL timer : INTEGER RANGE 0 TO 40 : 0; -- 最大40秒 -- 状态机进程 state_machine: PROCESS(clk_1Hz, reset) BEGIN IF reset 1 THEN current_state MAIN_GREEN; timer 0; ELSIF rising_edge(clk_1Hz) THEN CASE current_state IS WHEN MAIN_GREEN IF timer 39 THEN -- 40秒倒计时 current_state MAIN_YELLOW; timer 0; ELSE timer timer 1; END IF; WHEN MAIN_YELLOW IF timer 4 THEN -- 5秒倒计时 current_state BRANCH_GREEN; timer 0; ELSE timer timer 1; END IF; WHEN BRANCH_GREEN IF timer 19 THEN -- 20秒倒计时 current_state BRANCH_YELLOW; timer 0; ELSE timer timer 1; END IF; WHEN BRANCH_YELLOW IF timer 4 THEN -- 5秒倒计时 current_state MAIN_GREEN; timer 0; ELSE timer timer 1; END IF; END CASE; END IF; END PROCESS;3.4 输出控制逻辑根据当前状态控制信号灯输出-- 输出控制逻辑 main_red 1 WHEN (current_state BRANCH_GREEN OR current_state BRANCH_YELLOW) ELSE 0; main_yellow 1 WHEN (current_state MAIN_YELLOW AND clk_1Hz 1) ELSE 0; -- 黄灯闪烁 main_green 1 WHEN current_state MAIN_GREEN ELSE 0; branch_red 1 WHEN (current_state MAIN_GREEN OR current_state MAIN_YELLOW) ELSE 0; branch_yellow 1 WHEN (current_state BRANCH_YELLOW AND clk_1Hz 1) ELSE 0; branch_green 1 WHEN current_state BRANCH_GREEN ELSE 0; -- 数码管显示倒计时简化版 seg_led STD_LOGIC_VECTOR(TO_UNSIGNED(40 - timer, 8)) WHEN current_state MAIN_GREEN ELSE STD_LOGIC_VECTOR(TO_UNSIGNED(5 - timer, 8)) WHEN current_state MAIN_YELLOW ELSE STD_LOGIC_VECTOR(TO_UNSIGNED(20 - timer, 8)) WHEN current_state BRANCH_GREEN ELSE STD_LOGIC_VECTOR(TO_UNSIGNED(5 - timer, 8)); END rtl;4. 仿真测试与调试技巧4.1 创建Testbench文件在ModelSim中验证设计功能首先创建测试平台文件LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY traffic_light_tb IS END traffic_light_tb; ARCHITECTURE behavior OF traffic_light_tb IS -- 组件声明 COMPONENT traffic_light PORT( clk_50MHz : IN STD_LOGIC; reset : IN STD_LOGIC; main_red : OUT STD_LOGIC; main_yellow : OUT STD_LOGIC; main_green : OUT STD_LOGIC; branch_red : OUT STD_LOGIC; branch_yellow : OUT STD_LOGIC; branch_green : OUT STD_LOGIC; seg_led : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); END COMPONENT; -- 输入信号 SIGNAL clk_50MHz : STD_LOGIC : 0; SIGNAL reset : STD_LOGIC : 0; -- 输出信号 SIGNAL main_red : STD_LOGIC; SIGNAL main_yellow : STD_LOGIC; SIGNAL main_green : STD_LOGIC; SIGNAL branch_red : STD_LOGIC; SIGNAL branch_yellow : STD_LOGIC; SIGNAL branch_green : STD_LOGIC; SIGNAL seg_led : STD_LOGIC_VECTOR(7 DOWNTO 0); -- 时钟周期定义 CONSTANT clk_period : TIME : 20 ns; -- 50MHz BEGIN -- 实例化被测单元 uut: traffic_light PORT MAP ( clk_50MHz clk_50MHz, reset reset, main_red main_red, main_yellow main_yellow, main_green main_green, branch_red branch_red, branch_yellow branch_yellow, branch_green branch_green, seg_led seg_led ); -- 时钟生成 clk_process : PROCESS BEGIN clk_50MHz 0; WAIT FOR clk_period/2; clk_50MHz 1; WAIT FOR clk_period/2; END PROCESS; -- 激励过程 stim_proc: PROCESS BEGIN reset 1; WAIT FOR 100 ns; reset 0; WAIT; END PROCESS; END;4.2 仿真结果分析在ModelSim中运行仿真后重点关注以下信号时钟信号clk_50MHz和clk_1Hz状态转换current_state的变化输出信号各信号灯输出是否符合预期典型仿真波形应显示主干道绿灯亮40秒main_green1主干道黄灯闪烁5秒main_yellow1且1Hz闪烁支干道绿灯亮20秒branch_green1支干道黄灯闪烁5秒branch_yellow1且1Hz闪烁4.3 常见问题排查问题现象可能原因解决方案仿真无输出时钟未正确分频检查分频计数器设置状态不转换计时器条件判断错误检查状态机中的timer比较值黄灯不闪烁1Hz时钟未接入确保main_yellow使用clk_1Hz控制数码管显示错误BCD转换问题添加二进制转BCD模块5. 硬件验证与优化5.1 引脚分配策略在Quartus中完成引脚分配时建议采用以下策略时钟信号连接到专用时钟引脚复位信号使用开发板上的按键信号灯输出连接LED时串联220Ω电阻数码管信号根据开发板原理图连接示例引脚分配表DE2-115开发板信号名称引脚编号开发板对应器件clk_50MHzPIN_Y250MHz时钟resetPIN_M23KEY0按键main_redPIN_G19LEDR0main_greenPIN_F19LEDR1main_yellowPIN_E19LEDR25.2 时序约束设置为确保设计满足时序要求需添加适当的约束# 时钟约束 create_clock -name clk_50MHz -period 20 [get_ports clk_50MHz] # 输入输出延迟 set_input_delay -clock clk_50MHz 2 [get_ports reset] set_output_delay -clock clk_50MHz 1 [all_outputs]5.3 资源优化技巧状态编码优化使用one-hot编码可提高性能但增加寄存器用量分频器优化改用PLL生成低频时钟可节省逻辑资源显示模块优化使用时分复用驱动数码管减少引脚占用优化后的状态机示例-- 使用枚举类型定义状态 TYPE state_type IS ( S_MAIN_GREEN, -- 主干道绿灯 S_MAIN_YELLOW, -- 主干道黄灯 S_BRANCH_GREEN, -- 支干道绿灯 S_BRANCH_YELLOW -- 支干道黄灯 ); ATTRIBUTE enum_encoding : STRING; ATTRIBUTE enum_encoding OF state_type : TYPE IS one-hot; -- 指定one-hot编码6. 进阶功能扩展基础功能实现后可以考虑以下扩展功能6.1 紧急车辆优先模式添加紧急模式输入信号当激活时所有方向亮红灯-- 实体添加emergency输入 emergency : IN STD_LOGIC; -- 修改输出逻辑 main_red 1 WHEN (current_state BRANCH_GREEN OR current_state BRANCH_YELLOW OR emergency 1) ELSE 0; -- 其他信号类似修改6.2 动态时间调整通过拨码开关动态调整各状态持续时间-- 添加配置输入 config_main_green : IN STD_LOGIC_VECTOR(5 DOWNTO 0); -- 最大63秒 config_branch_green: IN STD_LOGIC_VECTOR(4 DOWNTO 0); -- 最大31秒 -- 修改状态机中的定时比较 WHEN MAIN_GREEN IF timer unsigned(config_main_green) - 1 THEN current_state MAIN_YELLOW; timer 0; ELSE timer timer 1; END IF;6.3 车辆检测传感器模拟真实交通灯添加车辆检测功能-- 添加传感器输入 vehicle_main : IN STD_LOGIC; -- 主干道有车 vehicle_branch : IN STD_LOGIC; -- 支干道有车 -- 修改状态转换逻辑 WHEN MAIN_GREEN IF (timer 39) OR (timer 20 AND vehicle_main 0 AND vehicle_branch 1) THEN current_state MAIN_YELLOW; timer 0; ELSE timer timer 1; END IF;7. 工程管理与版本控制专业开发需要良好的工程管理习惯目录结构规范/project /doc # 设计文档 /src # 源代码 /sim # 仿真文件 /constraint # 约束文件 /ip # IP核版本控制使用Git管理代码变更# 初始化仓库 git init git add . git commit -m Initial traffic light project # 创建开发分支 git checkout -b dev自动化脚本编写Tcl脚本自动化编译流程# build.tcl project_open TrafficLight execute_flow -compile8. 性能评估与优化完成设计后需要评估关键性能指标资源利用率查看编译报告的Logic Utilization时序性能检查Timing Analyzer中的时钟频率功耗估算使用PowerPlay Power Analyzer典型优化手段包括流水线设计状态机编码优化资源共享使用DSP块实现计算通过本文的详细讲解你应该已经掌握了使用VHDL设计交通信号灯控制系统的完整流程。从环境搭建到代码实现从仿真验证到硬件测试每个环节都有其技术要点和最佳实践。

更多文章