一、项目介绍
本项目基于STEP Baseboard4.0底板和STEP MXO2 LPC核心板,设计并实现了一个智能化的交通灯控制系统。系统功能包括:
- 数码管显示计时信息 :通过WebIDE图形化编程实现交通灯倒计时显示。
- 蜂鸣器报警功能 :当红灯亮起且检测到有人接近时,蜂鸣器发出警报声。
- 接近传感器检测人员走近 :使用Verilog语言编程实现传感器信号处理与报警逻辑。
- 环境光感知与路灯控制 :根据环境光强度自动点亮或关闭小脚丫核心板上的单色LED,模拟路灯功能。
该系统旨在模拟现实中的智能交通灯控制场景,结合多种传感器和输出设备,提升系统的交互性和实用性。
二、硬件介绍
1. STEP BaseBoard V4.0 扩展底板
STEP BaseBoard V4.0 是第4代小脚丫FPGA扩展底板,专为全系列小脚丫核心板设计,提供丰富的外设接口和功能模块。其主要特点如下:
- 尺寸与布局 :采用100mm x 161.8mm的黄金比例设计,便于实验操作。
- 板载资源 :
- 存储器 :E2PROM芯片AT24C02,用于存储配置数据。
- 传感器模块 :
- 温湿度传感器(SHT-20):监测环境温湿度。
- 环境光和接近式传感器:感知环境光强度及检测人员靠近。
- 气压计:测量气压值。
- 加速度计:支持运动检测。
- 输入设备 :
- 4×4矩阵键盘:提供用户交互界面。
- 旋转编码器和电位计:用于模拟信号输入。
- 显示设备 :
- RGB LCD液晶屏:支持图形化显示。
- 8位7段数码管:用于数字信息显示。
- 通信模块 :
- HDMI接口:支持高清视频输出。
- UART通信模块(CH340C):实现串口通信。
- WIFI功能模块(ESP8266-12F):支持无线通信。
- 模拟信号处理 :
- ADC模块(ADC081S101):模数转换。
- DAC模块(DAC081S101):数模转换。
- 其他接口 :
- PMOD接口:支持外部模块扩展。
- 蜂鸣器模块:用于报警提示。
该扩展底板集成了多种传感器和功能模块,能够满足数字逻辑、微机原理、可编程逻辑语言以及EDA设计工具等课程的实验需求,是理想的多功能实验平台。
2. STEP-MXO2-LPC 小脚丫FPGA核心板
STEP-MXO2-LPC 是基于Lattice MXO2系列FPGA的小脚丫核心板,专为初学者设计,兼具易用性和高性能。其主要特点如下:
- 核心器件 :
- Lattice LCMXO2-4000HC-4MG132 FPGA芯片:
- 132脚BGA封装,引脚间距0.5mm,芯片尺寸仅8mm x 8mm。
- 上电瞬时启动,启动时间小于1ms,无需外部重新配置。
- 提供4320个LUT资源、96Kbit用户闪存和92Kbit RAM。
- 支持2+2路PLL+DLL,增强时钟管理能力。
- 嵌入式硬核功能块:一路SPI、一路定时器、两路I2C。
- 支持DDR/DDR2/LPDDR存储器接口。
- 提供104个可热插拔I/O,内核电压范围2.5V-3.3V。
- 板载资源 :
- 显示设备 :
- 两位7段数码管:用于简单数字显示。
- 两个RGB三色LED:支持多色灯光效果。
- 8路用户LED:用于状态指示。
- 输入设备 :
- 4路拨码开关:提供简单的二进制输入。
- 4路按键:支持用户交互。
- 接口与扩展 :
- 36个用户可扩展I/O,包括一路SPI硬核接口和一路I2C硬核接口。
- USB Type-C接口:用于供电、FPGA配置文件下载和UART通信。
- 支持U盘模式下载:通过USB连接即可直接上传JED配置文件,兼容Windows、Mac OS和Linux系统,无需安装驱动程序。
- 开发工具支持 :
- 思德普Web IDE:基于浏览器的图形化开发环境,简化FPGA编程。
- Lattice Diamond:官方提供的专业开发工具。
- 支持MICO32/8软核处理器和RISC-V软核,便于嵌入式系统开发。
- 便携性 :
- 板卡尺寸仅为52mm x 18mm,兼容标准DIP40封装,便于携带和集成到其他电路中。
3. 硬件组合优势
将STEP BaseBoard V4.0扩展底板与STEP-MXO2-LPC核心板结合使用,可以充分发挥两者的性能优势:
- 强大的功能扩展 :扩展底板提供了丰富的传感器和外设接口,为核心板的功能扩展提供了广阔的空间。
- 灵活的开发方式 :核心板支持多种开发工具(如Web IDE和Diamond),降低了学习门槛,同时满足了从初学者到高级用户的多样化需求。
- 便捷的操作体验 :核心板的U盘模式下载和USB Type-C接口设计,使得开发过程更加高效和直观。
通过上述硬件的配合,本项目成功实现了交通灯控制系统的各项功能,展示了小脚丫FPGA学习平台在实际应用中的强大潜力和灵活性。
三、方案框图与设计思路
方案框图
设计思路
- 交通灯控制逻辑 :
- 使用WebIDE图形化编程实现交通灯的状态切换和倒计时功能。
- 定义绿灯、黄灯、红灯的持续时间,并在数码管上实时显示剩余时间。
- 接近传感器与蜂鸣器联动 :
- 使用Verilog语言编写逻辑,读取接近传感器信号。
- 当检测到人员接近且当前为红灯状态时,触发蜂鸣器报警。
- 环境光感知与路灯控制 :
- 使用Verilog语言编写逻辑,读取环境光传感器信号。
- 根据光强阈值判断是否点亮单色LED,模拟路灯功能。
四、 主要WebIDE图形化编程图与关键Verilog代码
1. WebIDE图形化编程(交通灯倒计时与数码管显示)
整体:
细节:
WebIDE图形化链接:https://www.stepfpga.com/project/17287/gui?type=top
简要说明:74LS48是BCD至七段解码器,用于显示以二进制编码的十进制格式解码的数字。组合逻辑3、4、5是由与门和非门构成的,3是输入00000001时输出1,4是输入00000000时输出1,5是高四位输入不为0且低四位输入为0时输出0。该工程中配置的模拟红绿灯循环倒计时是7秒-3秒-15秒。
2. 关键Verilog代码
基于i2c_driver的rpr0521rs的控制:(项目中i2c_driver改编自https://github.com/fangyzh26/IIC)
module rpr0521rs_ctrl(
input sys_clk,
input sys_rst_n,
input flag_done,//1:finish a process of writing or reading
input [7:0] data_read,
output reg start, //start=1 then begin writing or reading
output ctrl_w0_r1,// 0:write 1:read
output reg [7:0] addr,
output reg [7:0] data_write,
output reg dat_valid, //数据有效脉冲
output reg [15:0] ch0_dat, //ALS数据
output reg [15:0] ch1_dat, //IR数据
output reg [15:0] prox_dat //Prox数据
);
localparam WAIT_TIME = 19'd1200; // writing time interval:0.1ms, make sure that data write sucessfully
reg flag_write_over,flag_read_over;
reg flag_done_delay1, flag_done_delay2; // to find the posedge of flag_done
wire flag_done_posedge;
reg [23:0] cnt_delay;
reg [19:0] wait_cnt; //
reg [4:0] wr_addr_cnt,rd_addr_cnt;
//--------------------------- define the period of writing or reading, start=1 means working ---------------------------------------------------------
always @(posedge sys_clk, negedge sys_rst_n) begin
if (!sys_rst_n) begin
start <= 1'b0;
wait_cnt <= 10'd0;
end
else if((!flag_done_posedge) && !flag_read_over)begin
if (!ctrl_w0_r1) begin
if (wait_cnt == (WAIT_TIME-1)) begin //writing interval
wait_cnt <= wait_cnt;
start <= 1'b1;
end
else begin
wait_cnt <= wait_cnt + 1'b1;
start <= start;
end
end
else begin
if (wait_cnt == (WAIT_TIME/20-1)) begin //reading interval
wait_cnt <= wait_cnt;
start <= 1'b1;
end
else begin
wait_cnt <= wait_cnt + 1'b1;
start <= start;
end
end
end
else if (flag_read_over) begin
start <= 1'b0;
end
else begin
start <= 1'b0;
wait_cnt <= 10'd0;
end
end
//--------------------------- get flag_done's posedge ---------------------------------------------------------
always @(posedge sys_clk, negedge sys_rst_n) begin
if (!sys_rst_n) begin
flag_done_delay1 <= 1'b0;
flag_done_delay2 <= 1'b0;
end
else begin
flag_done_delay1 <= flag_done;
flag_done_delay2 <= flag_done_delay1;
end
end
assign flag_done_posedge = flag_done && (!flag_done_delay2);
assign ctrl_w0_r1 = flag_write_over; // 0:write 1:read
always @(posedge sys_clk, negedge sys_rst_n) begin
if (!sys_rst_n) begin
flag_write_over <= 1'b0;
addr <= 8'h40;
data_write <= 8'h0a;
wr_addr_cnt <= 4'd1;
rd_addr_cnt <= 4'd0;
flag_read_over <= 1'b0;
end
else if (!ctrl_w0_r1) begin //------------writing! the control of writing address and data need to be wrote
if (flag_done_posedge) begin
case (wr_addr_cnt)
4'd1: begin addr <= 8'h40; data_write <= 8'h0a; wr_addr_cnt <= 4'd2; flag_write_over <= flag_write_over; end
4'd2: begin addr <= 8'h41; data_write <= 8'hc6; wr_addr_cnt <= 4'd3; flag_write_over <= flag_write_over; end
4'd3: begin addr <= 8'h42; data_write <= 8'h02; wr_addr_cnt <= 4'd4; flag_write_over <= flag_write_over; end
4'd4: begin addr <= 8'h43; data_write <= 8'h01; wr_addr_cnt <= 4'd1; flag_write_over <= ~flag_write_over; end
default: begin addr <= 8'h40; data_write <= 8'h0a; wr_addr_cnt <= 4'd2; flag_write_over <= flag_write_over; end
endcase
end
else begin
addr <= addr; data_write <= data_write;
end
end
else begin //----------------reading! the control of reading address
if (flag_done_posedge) begin
case (rd_addr_cnt)
4'd0: begin flag_read_over <= 1'b0; dat_valid <= 1'b0; rd_addr_cnt <= 4'd1; end
4'd1: begin addr <= 8'h44; prox_dat[7:0] <= data_read; rd_addr_cnt <= 4'd2; end
4'd2: begin addr <= 8'h45; prox_dat[15:8] <= data_read; rd_addr_cnt <= 4'd3; end
4'd3: begin addr <= 8'h46; ch0_dat[7:0] <= data_read; rd_addr_cnt <= 4'd4; end
4'd4: begin addr <= 8'h47; ch0_dat[15:8] <= data_read; rd_addr_cnt <= 4'd5; end
4'd5: begin addr <= 8'h48; ch1_dat[7:0] <= data_read; rd_addr_cnt <= 4'd6; end
4'd6: begin addr <= 8'h49; ch1_dat[15:8] <= data_read; rd_addr_cnt <= 4'd7; end
4'd7: begin flag_read_over <= 1'b0; dat_valid <= 1'b1; rd_addr_cnt <= 4'd0; end
default: begin addr <= 8'h44; prox_dat[7:0] <= data_read; rd_addr_cnt <= 4'd2; end
endcase
end
else
addr <= addr;
end
end
endmodule
五、功能展示图及说明
- 数码管显示计时信息、RGBLED表示红灯、绿灯和黄灯
- 数码管配合RGBLED实时显示当前交通灯的剩余时间及当前交通灯状态。
- 蜂鸣器报警功能
- 当红灯亮起且有人接近时,蜂鸣器发出连续报警声。
- 环境光感知与路灯控制
- 在光线较暗时,单色LED点亮;光线充足时,LED熄灭。
六、项目中遇到的难题及解决方法
- 问题:倒计时归零才切换下一状态,实际情况中倒计时至一后直接进入下一状态
- 原因 :使用74HC190芯片的maxmin输出触发状态切换,maxmin只有当减至0时才输出高电平。
- 解决方法 :增加组合逻辑电路,判断当输出显示为1时,触发切换。
- 问题:蜂鸣器误报警
- 原因 :传感器误触发或逻辑判断不准确。
- 解决方法 :增加延时判断逻辑,确保只有在红灯状态下才触发报警。
七、心得体会
- 收获与成长
- 通过本项目,深入理解了FPGA开发流程以及硬件描述语言的应用。
- 学会了如何将多种传感器与输出设备整合到一个系统中,提升了综合设计能力。
- 意见与建议
- 希望进一步优化WebIDE,减少图形化编程时的BUG,例如管脚分配时找不到已定义引脚。
八、总结
本项目成功实现了交通灯控制系统的各项功能,涵盖了从硬件连接到软件编程的完整开发流程。通过实际动手实践,不仅巩固了理论知识,还积累了宝贵的工程经验。未来可以进一步扩展系统功能,例如加入无线通信模块,实现远程监控与控制。
FPGA资源占用:
Diamond:
WebIDE