基于DE10-Lite开发板的智能交通灯控制器实战指南十字路口的交通信号灯系统看似简单但背后蕴含的状态机设计和硬件实现技巧却非常值得FPGA初学者深入研究。本文将手把手教你如何用Verilog HDL在DE10-Lite开发板上实现一个带左转功能的交通灯控制器从代码编写到引脚分配从数码管驱动到实际调试完整呈现一个课程设计的实战过程。1. 系统架构设计与状态规划交通灯控制器的核心是一个复杂的状态机系统。我们需要为主干道和支干道分别设计四个基本状态绿灯通行、黄灯过渡、左转专用和红灯停止。每个状态的持续时间需要精确控制主干道时序绿灯40秒黄灯5秒左转15秒红灯55秒与支干道绿灯黄灯左转时间匹配支干道时序绿灯30秒黄灯5秒左转15秒红灯65秒与主干道绿灯黄灯左转时间匹配状态转换关系可以用以下表格清晰表示道路类型状态顺序持续时间主干道绿灯 → 黄灯 → 左转 → 红灯40-5-15-55支干道红灯 → 绿灯 → 黄灯 → 左转65-30-5-152. Verilog核心模块实现2.1 顶层模块设计module traffic_light_controller ( input wire clk, // 50MHz主时钟 input wire reset_n, // 异步复位(低有效) output reg [3:0] main_leds, // 主干道灯控信号 output reg [3:0] side_leds, // 支干道灯控信号 output wire [6:0] main_seg1, // 主干道十位数码管 output wire [6:0] main_seg0, // 主干道个位数码管 output wire [6:0] side_seg1, // 支干道十位数码管 output wire [6:0] side_seg0 // 支干道个位数码管 ); // 内部信号定义 reg [25:0] counter; // 1秒计数器 reg [5:0] main_sec, side_sec; // 倒计时秒数 reg [2:0] main_state, side_state; // 状态寄存器 // 状态编码 localparam GREEN 3b000; localparam YELLOW 3b001; localparam LEFT 3b010; localparam RED 3b011;2.2 时钟分频与计时控制DE10-Lite开发板提供50MHz时钟我们需要将其分频为1Hz信号用于秒计时// 时钟分频模块 always (posedge clk or negedge reset_n) begin if (!reset_n) begin counter 0; end else begin if (counter 26d49_999_999) begin counter 0; // 每秒触发一次状态更新 update_timing(); end else begin counter counter 1; end end end2.3 状态机实现主干道和支干道的状态机需要严格同步// 主干道状态机 always (*) begin case (main_state) GREEN: begin main_leds 4b1000; // 绿灯亮 if (main_sec 0) begin next_main_state YELLOW; next_main_sec 5; // 黄灯5秒 end end YELLOW: begin main_leds 4b0100; // 黄灯亮 if (main_sec 0) begin next_main_state LEFT; next_main_sec 15; // 左转15秒 end end // 其他状态类似... endcase end3. DE10-Lite硬件适配实战3.1 引脚分配技巧在Quartus Prime中配置引脚时需要注意DE10-Lite的特殊引脚布局信号名称FPGA引脚开发板对应元件clkPIN_P1150MHz时钟reset_nPIN_C10KEY0按键main_leds[0]PIN_A8LEDR0(红)main_leds[1]PIN_A9LEDR1(黄)main_leds[2]PIN_A10LEDR2(绿)main_leds[3]PIN_B10LEDR3(左转)提示使用Tcl脚本可以批量分配引脚提高效率set_location_assignment PIN_A8 -to main_leds[0] set_location_assignment PIN_A9 -to main_leds[1]3.2 数码管驱动实现DE10-Lite采用共阳极数码管需要特别注意段码的极性// 数码管译码模块 function [6:0] seg7_decode; input [3:0] num; begin case (num) 4d0: seg7_decode 7b1000000; 4d1: seg7_decode 7b1111001; 4d2: seg7_decode 7b0100100; // 其他数字编码... default: seg7_decode 7b1111111; endcase end endfunction assign main_seg1 seg7_decode(main_sec / 10); assign main_seg0 seg7_decode(main_sec % 10);4. 调试技巧与常见问题解决4.1 按键消抖处理机械按键在DE10-Lite上会产生抖动需要添加消抖逻辑// 按键消抖模块 reg [19:0] debounce_cnt; reg reset_db; always (posedge clk) begin if (~reset_n) begin debounce_cnt 20hFFFFF; reset_db 1b0; end else begin if (debounce_cnt ! 0) begin debounce_cnt debounce_cnt - 1; end else begin reset_db 1b1; end end end4.2 时序约束设置在SDC文件中添加以下约束确保时序正确create_clock -name clk -period 20 [get_ports clk] set_input_delay -clock clk 2 [get_ports reset_n] set_output_delay -clock clk 1 [get_ports {main_leds[*]}]4.3 常见问题排查表现象可能原因解决方案数码管显示乱码段码极性配置错误检查共阳/共阴配置灯状态不变化状态机未正确触发添加SignalTap观察状态寄存器计时速度异常时钟分频计算错误重新计算分频系数部分LED不亮引脚分配冲突检查Pin Planner中的分配5. 功能扩展与进阶优化基础功能实现后可以考虑以下增强功能紧急车辆优先模式reg emergency_mode; always (posedge clk) begin if (emergency_btn_pressed) begin emergency_mode 1b1; main_leds 4b1000; // 主干道绿灯 side_leds 4b0001; // 支干道红灯 end end夜间模式所有路口切换为黄灯闪烁使用PWM控制亮度倒计时动态调整// 根据交通流量动态调整绿灯时间 if (traffic_sensor_high) begin green_extend 1b1; main_sec main_sec 10; end在DE10-Lite上实际部署时建议先用ModelSim进行充分仿真再逐步移植到硬件。第一次上电测试时可以先用单个状态进行验证确保基本功能正常后再测试完整状态转换。