苏州市网站建设_网站建设公司_电商网站_seo优化
2025/12/25 6:32:52 网站建设 项目流程

用 ego1 开发板玩转交通灯:从状态机到硬件实现的完整实战

你有没有想过,每天路上看到的红绿灯,其实可以用一块小小的 FPGA 芯片自己做出来?这可不是什么遥不可及的工程难题——在 Xilinx 的ego1 开发板上,结合Vivado工具链,我们完全可以亲手搭建一个完整的交通灯控制系统。这个项目不仅是电子类课程的经典大作业,更是理解数字系统设计核心思想的绝佳入口。

今天,我们就以“ego1开发板大作业vivado”为背景,带你一步步拆解这个看似简单、实则内涵丰富的项目。不堆术语,不讲空话,只讲你真正需要知道的设计思路、关键技巧和避坑指南。


为什么选 FPGA 做交通灯?

传统交通灯多用单片机控制,写个循环延时就能搞定。但这种方式本质上是“顺序执行”:CPU 得一个任务接一个任务地处理,扩展性差,响应也不够快。

而 FPGA 不一样。它是并行工作的硬件逻辑,所有模块同时运行,互不干扰。比如你可以让状态机、倒计时、黄灯闪烁、紧急模式这些功能各自独立运作,通过信号联动协调。这种“硬连线”的方式不仅更稳定,也为后续升级留足了空间。

再加上ego1 开发板搭载的是 Xilinx Artix-7 系列的 XC7A50T 芯片,资源足够丰富,又有 6 颗用户 LED 和多个按键可用,简直是教学级项目的完美载体。

更重要的是,整个流程走一遍,你会完整经历:代码编写 → 仿真验证 → 综合实现 → 引脚约束 → 下载调试—— 这正是工业级 FPGA 开发的标准路径。


核心大脑:有限状态机怎么设计才靠谱?

交通灯的本质是什么?是一组有明确规则的状态切换:

  • 主路绿 → 黄 → 红
  • 支路红 → 绿 → 黄 → 红
  • 循环往复

这不就是典型的有限状态机(FSM)吗?

Moore 还是 Mealy?这里推荐 Moore

虽然两种都可以用,但我建议初学者优先使用Moore 型状态机,因为它的输出只依赖当前状态,不受输入影响,行为更可预测,也更容易避免毛刺问题。

我们定义三个核心状态:

状态名含义
IDLE初始状态,全灯灭
S1_GYR主路绿灯亮,支路红灯亮
S2_RGY主路红灯亮,支路绿灯亮

注意:黄灯可以作为独立状态加入,也可以在 S1/S2 切换前插入短暂延时处理。为了简化逻辑,我们先把它融合进主状态切换流程中。

下面是精简后的 Verilog 实现:

module traffic_fsm ( input clk, input rst_n, output reg [5:0] led_out ); // 状态编码:One-Hot 更适合 FPGA parameter IDLE = 6'b000001; parameter S1_GYR = 6'b000010; parameter S2_RGY = 6'b000100; reg [5:0] current_state, next_state; // 同步状态更新 always @(posedge clk) begin if (!rst_n) current_state <= IDLE; else current_state <= next_state; end // 组合逻辑决定下一状态 always @(*) begin case (current_state) IDLE: next_state = S1_GYR; S1_GYR: next_state = S2_RGY; S2_RGY: next_state = S1_GYR; default: next_state = IDLE; endcase end // 输出解码(Moore型) always @(posedge clk) begin case (current_state) IDLE: led_out <= 6'b111111; // 全灭(共阳极) S1_GYR: led_out <= 6'b110001; // G1=0,Y1=0,R1=1; G2=1,Y2=1,R2=0 S2_RGY: led_out <= 6'b001110; // G1=1,Y1=1,R1=0; G2=0,Y2=0,R2=1 default: led_out <= 6'b111111; endcase end endmodule

💡重点提醒
- 所有状态转移必须覆盖完全,default分支不能少;
- 使用非阻塞赋值<=更新寄存器;
- 输出与状态强绑定,不要掺杂组合逻辑判断。


时间基准:50MHz 怎么变成“一秒一跳”?

ego1 板载时钟是50MHz,也就是每秒震荡 5000 万次。而我们要控制绿灯亮 30 秒,显然不能靠数时钟边沿来计时。

所以必须做一个分频器,把高频时钟降下来,生成一个精准的 1Hz 脉冲信号,作为“秒计数”的使能信号。

分频原理很简单:数够了就翻转

要得到 1Hz 输出,我们需要对 50MHz 进行 25,000,000 分频(因为上升沿触发,半周期各计一次)。

也就是说,计数器从 0 数到 24,999,999,共 2500 万个时钟周期,刚好是 0.5 秒;再清零重新开始,下一个 0.5 秒后拉高输出,形成 1Hz 方波。

不过实际应用中,我们更希望它输出一个单周期脉冲,方便下游模块当作事件触发,而不是电平使能。

来看实现代码:

module clock_divider ( input clk_50m, input rst_n, output reg tick_1s ); reg [25:0] count; // 2^26 > 50M,安全起见用26位 always @(posedge clk_50m) begin if (!rst_n) begin count <= 26'd0; tick_1s <= 1'b0; end else if (count == 26'd24999999) begin count <= 26'd0; tick_1s <= 1'b1; // 仅在一个周期内为高 end else begin count <= count + 1; tick_1s <= 1'b0; end end endmodule

这个tick_1s就是我们后续驱动倒计时或状态切换的“心跳信号”。

⚠️ 注意事项:
- 计数器位宽别小了,log₂(25M) ≈ 24.58,至少 25 位,保险起见用 26;
- 输出脉冲宽度尽量窄,避免误触发;
- 若需支持动态调时(如白天/夜晚模式),可将阈值改为参数化输入。


如何连接真实世界?XDC 管脚约束详解

写完代码只是第一步。FPGA 是硬件芯片,每个信号都得对应到物理引脚上,否则烧进去也没法工作。

这就需要用到XDC 文件(Xilinx Design Constraints),它是 Vivado 中用来告诉工具“某个信号该接到哪个引脚”的配置文件。

ego1 的 LED 和按键都连在哪?

根据 Digilent 官方文档,ego1 上的关键 I/O 如下:

功能FPGA 引脚备注
主时钟E350MHz 有源晶振
用户复位D9低电平有效
LED[0]H5对应 G1(主路绿)
LED[1]J5Y1
LED[2]T9R1
LED[3]T8G2(支路绿)
LED[4]U8Y2
LED[5]R8R2

全部采用LVCMOS33标准(3.3V CMOS 电平)。

写好你的第一份 XDC 文件

## 时钟输入 set_property PACKAGE_PIN E3 [get_ports clk_50m] set_property IOSTANDARD LVCMOS33 [get_ports clk_50m] create_clock -period 20.000 -name sys_clk_pin [get_ports clk_50m] ## 复位按键 set_property PACKAGE_PIN D9 [get_ports rst_n] set_property IOSTANDARD LVCMOS33 [get_ports rst_n] set_property PULLUP true [get_ports rst_n] ;# 上拉防悬空 ## LED 输出 set_property PACKAGE_PIN H5 [get_ports {led_out[0]}] set_property PACKAGE_PIN J5 [get_ports {led_out[1]}] set_property PACKAGE_PIN T9 [get_ports {led_out[2]}] set_property PACKAGE_PIN T8 [get_ports {led_out[3]}] set_property PACKAGE_PIN U8 [get_ports {led_out[4]}] set_property PACKAGE_PIN R8 [get_ports {led_out[5]}] set_property IOSTANDARD LVCMOS33 [get_ports led_out[*]]

🔧 关键点:
-create_clock必须加,否则时序分析会报错;
- 按键引脚建议启用内部上拉,避免浮空误判;
- 引脚编号务必核对官方手册,错一个字母都不行!


系统整合:怎么让各个模块协同工作?

现在我们有两个核心模块:

  • clock_divider: 提供 1Hz 脉冲
  • traffic_fsm: 控制状态跳转

怎么把它们串起来?

最简单的做法是:用tick_1s作为状态机的“步进时钟”,每次脉冲到来就切换一次状态。

但这样太粗暴了——你想啊,如果绿灯要持续 30 秒,难道要等 30 个 tick 才跳?那岂不是要加个计数器?

没错!所以我们需要引入一个状态保持机制:只有当计数完成时,才允许进入下一个状态。

改进方案如下:

// 在 FSM 模块中新增: reg [5:0] timer; // 计数器,最大支持63秒 always @(posedge clk) begin if (!rst_n) begin timer <= 6'd0; end else if (tick_1s) begin case (current_state) S1_GYR: if (timer < 29) timer <= timer + 1; else timer <= 0; S2_RGY: if (timer < 29) timer <= timer + 1; else timer <= 0; default: timer <= 0; endcase end end // 修改 next_state 判断条件 always @(*) begin case (current_state) IDLE: next_state = S1_GYR; S1_GYR: next_state = (timer == 29) ? S2_RGY : S1_GYR; S2_RGY: next_state = (timer == 29) ? S1_GYR : S2_RGY; default: next_state = IDLE; endcase end

这样一来,每个状态都能维持整整 30 秒(第0秒到第29秒),第30个 tick 到来时自动切换。


调试经验分享:新手最容易踩的五个坑

我在带学生做这个项目时,总结出以下高频问题,提前规避能省下大把时间:

❌ 1. 忘记加create_clock约束

结果:综合通过,实现失败,提示“no timing constraint”。
✅ 解决:XDC 中必须为主时钟添加周期约束。

❌ 2. LED 接反了(共阳 vs 共阴)

结果:该亮的不亮,不该亮的常亮。
✅ 解决:查原理图!ego1 是共阳极连接,即输出低电平点亮。

❌ 3. 计数器溢出或位宽不够

结果:定时不准,有时快有时慢。
✅ 解决:确保计数器位数 ≥ ceil(log₂(N))。

❌ 4. 状态机卡死在某个状态

原因:缺少 default 分支,或复位信号未正确连接。
✅ 解决:always 加 default,复位信号全程同步处理。

❌ 5. 没做仿真就直接下载

结果:板子跑起来乱闪,根本看不出哪里错了。
✅ 解决:先写 Testbench,用 Vivado Simulator 看波形!

举个简单的测试平台片段:

initial begin clk_50m = 0; rst_n = 0; #100 rst_n = 1; end always #10 clk_50m = ~clk_50m; // 50MHz = 20ns 周期

跑完仿真能看到状态跳转、计数递增、输出变化全过程,比看实物调试高效十倍。


还能怎么升级?给你的项目加点料

基础版跑通之后,不妨尝试这些扩展功能,让你的大作业脱颖而出:

✅ 添加数码管显示剩余时间

用另一组 IO 驱动七段数码管,实时显示当前倒计时,直观又专业。

✅ 加入行人过街按钮

增加一个输入按键,按下后提前结束当前相位,进入黄灯过渡,保障行人安全。

✅ 实现车流量自适应调度

模拟接入传感器输入(可用拨码开关代替),根据车流密度动态调整红绿灯时长。

✅ 插入 ILA 逻辑分析仪

在 Vivado 中插入 Integrated Logic Analyzer 核,实时抓取内部信号,无需额外仪器即可深度调试。


写在最后:这不是作业,是通往系统的起点

当你第一次看到 ego1 上的 LED 按照预定节奏有序闪烁时,那种成就感远超写出一段能跑的代码。因为你已经不只是在“编程”,而是在“构建系统”。

这个交通灯项目虽小,却涵盖了现代数字系统设计的核心要素:

  • 状态机建模—— 抽象控制流程
  • 时钟管理—— 构建时间基准
  • 硬件映射—— 连接虚拟与现实
  • 模块化设计—— 提升可维护性

更重要的是,它为你打开了 FPGA 工程实践的大门。下一步,你可以尝试 VGA 显示、UART 通信、甚至软核处理器嵌入。每一个新技能,都是在这块小小开发板上生长出来的。

所以别再说“这只是个大作业”了。
你正在做的,是一个真正的控制系统原型。

如果你在实现过程中遇到了其他挑战,欢迎在评论区交流讨论。我们一起把想法变成看得见、摸得着的硬件行为。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询