2025寒假一起练——交通控制系统项目报告
一、硬件介绍
这个项目是一个基于小脚丫FPGA STEP BaseBoard V4.0套件的交通灯控制系统。在本次项目中我使用了STEP-MXO2-LPC核心板(控制整个系统的逻辑与信号)和FPGA STEP BaseBoard V4.0拓展版(利用RPR_0521RS等传感器)、74HC595元器件(数码管驱动)、核心板上的数码管(用于显示红绿灯倒计时)、拓展板上的数码管(显示环境光强度)、核心板上的两个三色LED灯(一个用于显示红黄绿三色交通灯,另一个用于显示行人距离远近)、核心板上的8段单色LED灯(用于提示环境光强度)、拓展版上的蜂鸣器(用于黄灯警示报警)、拓展版上的接近传感器(用于检测行人接近)、拓展版上的环境光传感器(用于检测环境光强度并控制单色LED灯)。
二、框图流程图及设计思路
任务一二的设计框图:
这个系统含有四个状态,分别是状态一(parameter S1 = 2'b00)9秒(parameter time_s1 = 4'd9)的绿灯(parameter led_s1 = 6'b111101)、状态二5秒的黄灯、状态三9秒的红灯和状态四5秒的黄灯。四个状态用于模拟现实中的交通灯。其中在状态二(cur_state == S2)的黄灯中进行蜂鸣器(beeper=1)的报警,用于提醒行人红灯即将开始。
该思路形成的图形化框图如下:
任务三四的设计框图如下:
在任务三和四中,我的设计思路参考了例程中的lab8。首先,我使用了lab8中的rpr0521rs_driver
模块通过I2C协议与拓展板上的传感器通信,定期采集数据,并在数据有效时产生名为dat_valid的
信号。其次,我改动了lab8中的decoder
模块对采集到的数据进行解析,将光照数据转换为亮度信息,并输出到拓展板上的数码管中进行动态显示。为了直观地展示光照强度,segment_scan
模块使用74HC595移位寄存器驱动8位数码管。并且当光照强度大于100时,该亮度信息驱动核心板中的单色LED灯亮。
三、软件流程图和代码思路介绍
任务一二的软件流程图如下:

在trafficsystem这个自定义模块中,状态之间的切换在always @ (cur_state or rst_n or timecont)中实现。如果timecont == 1,则切换到下一个状态中,否则保持当前的状态继续倒计时。倒计时在 always @(posedge clk1hz or negedge rst_n)中实现,timecont每秒(1Hz时钟上升沿)递减,并将timecont的数值发送到out_reg参数中存储当前状态的灯光数据,并通过 assign out = out_reg; 输出,用于数码管显示。
我将蜂鸣器模块与交通灯模块合并,初始思路是使用enable变量,每当cur_state == S2,enable变为1,驱动蜂鸣器模块报警。在简化后我用一行代码beeper_reg <= (cur_state == S2) && (counter < 9'd150);进行表示,使用 clk1k变量(1kHz 时钟)控制 counter 进行计数,每 300 个时钟周期归零。当counter < 150时beeper=1,否则=0。这样可以在黄灯状态时,每秒钟响 0.15 秒,产生警示效果。由于图形化的input和output默认是wire类型,我在代码中设置了中间变量(后缀为_reg),先对中间变量进行操作,最终用assign将中间变量赋值给各个output。
任务三四的软件流程图如下:
任务三和四我使用的是lattice diamond软件进行编写,并且参考了例程中的lab8。其中,Rpr0521rs_driver模块我没有改动,这个模块的作用是把拓展版上环境光和接近传感器的光照和接近度数据发送出来。输出的重要的数据有i2c_scl(代表I2C 的400kHz的时钟信号)、ch0_dat(环境光的测量值)、ch1_dat(红外光的测量值)、prox_dat(接近传感器的测量值);在decoder模块中,我基于原始代码中对ch0_dat和ch1_dat计算产生的lux,对是否亮灯进行判断,当lux > 32'd100000(即拓展版上的数码管显示的光照数值大于100时)8段单色LED灯点亮,否则熄灭。在判断接近度时,我保留了always @(posedge dat_valid) begin部分,这个部分用于防止短时间内的接近度大幅度变动。Prox_dat是16位的数据,通过查阅资料,高位表示物体大致距离并且变化较大,低位受噪声影响大变化细微,所以原代码中的[11:9]可以有效代表距离信息。我通过8种case控制三色灯的输出(从远到近为 灭红绿黄蓝紫青白 8种等级的警报),case000代表没有物体接近,case111代表非常近。
四、功能展示图
任务一二:wedide项目链接:https://www.stepfpga.com/project/17193/gui?type=top
在四种状态中分别在数码管中显示倒计时并在三色LED灯中显示红黄绿三种颜色。
任务三四:(部分情况展示,完整视频在b站中)
接近传感器感应手指(行人)位置并显示不同等级的警报(灯色)。
环境光传感器在数码管中动态显示光照数值并且当数值大于100时点亮一排LED单色灯。
五、项目中遇到的难题及解决办法
由于是第一次接触fpga和verilog,本次项目我遇到的难点非常多,但是在学习了开源社区的入门教程和百度网盘的例程后也让我学习到了很多实用的知识,成功入门了FPGA。
首先在任务12中,我经常性的对wire、reg、=、<=报错。在查阅资料后,我明白了wire只能用assign赋值,wire只能在always语句中赋值。其中在always中我遇见了两种符号=和<=。阻塞赋值(=)使用的是即时的变量值,一般在always @(*)使用,而非阻塞赋值使用的是变量的旧值,一般在always @(posedge clk)使用。由于图形化的input和output默认使用的时wire,适用于组合逻辑而不适用于always语句,基于我的代码都是使用always语句进行赋值,所以我最终使用了reg型的中间变量解决类型不匹配的问题。
在任务34中,涉及到拓展版的功能,我借鉴了lab8的几个模块,在原代码的基础上进行了修改。一开始因为从百度网盘下载的文件夹带有中文导致我打不开文件,只能自己开new project把lab8中的.v文件拷贝到我的项目中。但是在管脚分配处不知道怎么分配涉及传感器和数码管的几个管脚。后来在群聊中通过其他同学的指导,我学会了查看baseboard手册,并找到了相应管脚的分配。
六、本次活动心得体会
这次活动使我入门了FPGA。由于之前没有了解过FPGA,开源社区上的各种入门教程使我对FPGA有了一定的了解。虽然之前学习过数字电路,但是对课堂中的内容仍然感觉十分抽象。在本次活动中对FSM和其他思路的实现,使我对课本中的内容有了更深的理解和认识,了解了如何实践这些方法在具体的实际问题中。
对于本次活动的意见就是,如果有webide图形化视频教程就好了。我比较早就编写好了代码,但是在图形化的过程中很多bug比如不能用ctrl+s和enter键,都是在被删模块中自己摸索和群聊中同学们的经验得来的,要是在网站上直接有避免所有bug的一镜到底的从创建项目到生成jed文件的视频教程应该会节省很多时间。