项目总结报告
北京理工大学 姚韧翔
1. 项目介绍:
本项目旨在使用FPGA板子,结合图形化编程与Verilog硬件描述语言,构建一个完整的交通灯控制系统。该系统将集成数码管显示、蜂鸣器报警、接近传感器检测以及环境光感知等功能,以实现智能化的交通灯控制。
交通灯控制:使用74系列元器件搭建交通灯控制逻辑,通过设置不同的状态来控制交通灯的显示。将利用时序逻辑电路来实现状态的切换,以模拟现实中的交通灯工作周期。
数码管显示:通过WebIDE的图形化编程,配置数码管驱动电路,实现计时信息的显示。数码管将显示剩余时间等关键信息,以便行人和车辆了解交通灯状态。
蜂鸣器报警:同样采用图形化编程配置蜂鸣器驱动电路,在特定情况下(如红灯即将变绿或绿灯即将变红)发出警报声,提醒行人和车辆注意交通灯的变化。
接近传感器检测:利用Verilog编写接近传感器的控制逻辑,检测人员是否走近。当传感器检测到有人靠近时,将触发交通灯控制逻辑,使灯进入相应的状态。
环境光感知:通过Verilog实现环境光传感器的控制逻辑,根据环境光的强度自动点亮路灯(使用小脚丫核心板上的单色LED模拟)。当环境光较暗时,路灯将自动点亮,提高夜间交通安全性。
2. 硬件介绍:
FPGA板子:选用小脚丫核心板,其具有丰富的外设接口和强大的处理能力,能够满足项目的需求。
74系列元器件:用于构建交通灯控制逻辑电路。
LED灯:点亮或熄灭
数码管:用于显示计时信息,采用共阳极数码管,通过74系列元器件驱动。
蜂鸣器:用于发出报警声,通过FPGA的GPIO口直接控制。
接近和环境光传感器(RPR0521RS)是一款结合了环境光(ALS,Ambient Light Sensing)和接近检测(Proximity Detection)功能的传感器。它通过测量反射红外光的强度来判断附近是否有物体(接近检测),并通过测量环境光强度来提供照度数据(ALS)。
通过74HC595 移位寄存器驱动数码管,用于显示传感器数据(如环境光强度)。
3. 方案框图和项目设计思路介绍:
任务一二:
任务三四:
任务1数码管显示计时信息设计思路:
时钟分频:系统需要一个较低频率的时钟信号来驱动计时功能。通过使用任意整数分频器,将输入的主时钟信号(CLK)分频为所需的低频时钟信号。
计数器模块:使用74HC290计数器模块来实现计时功能。74HC290是一个二进制计数器,可以用于实现从0到15的计数,它被用来对分频后的时钟信号进行计数,从而实现定时功能。
译码器模块:将计数器的输出通过译码器转换为数码管可以显示的段码信号。译码器根据计数器的输出值,选择对应的字符在数码管上显示。例如,当计数器输出为0时,译码器将输出对应的段码,使数码管显示“0”。
亮度控制:通过一个简单的控制模块,将计数器的输出值的一部分作为亮度控制信号,驱动RGB灯的亮度变化。这里使用了一个简单的逻辑门组合,将计数器的输出信号进行处理,以控制RGB灯的亮度。
任务2蜂鸣器报警:
时钟分频:同样,这里也需要一个较低频率的时钟信号来驱动蜂鸣器的报警功能。通过使用任意整数分频器,驱动蜂鸣器的报警声。
报警控制逻辑:使用一个简单的逻辑门组合,将分频后的时钟信号和一个控制信号进行逻辑运算,以产生蜂鸣器的驱动信号。当满足一定条件时,控制信号将触发蜂鸣器发出报警声。
报警信号输出:将逻辑门的输出连接到蜂鸣器的驱动端,使蜂鸣器能够根据控制逻辑发出报警声。这里使用了一个与门来实现对报警信号的控制,确保只有在特定条件下蜂鸣器才会发出声音。
任务3接近传感器检测:
阈值设定:定义了一个接近检测的阈值(THRESHOLD),用于判断是否有物体靠近传感器。
数据采样:在每个dat_valid信号的上升沿,对prox_dat信号进行采样,并将采样值存储在prox_dat0和prox_dat1寄存器中。
差分检测:通过比较prox_dat1和prox_dat0的差值,判断传感器信号的变化是否超过一定阈值(0x800)。如果变化超过阈值,则认为传感器信号发生了显著变化,可能是有物体靠近或远离。
状态更新:根据差分检测的结果,更新prox_dat2的值。如果差值超过阈值,则保持prox_dat2的值不变;否则,将prox_dat2更新为prox_dat0的值。
输出控制:根据prox_dat2的值与THRESHOLD的比较结果,控制Y_out的输出。当prox_dat2大于等于THR
任务4环境光感知:
1环境光计算逻辑:
通过传感器获取环境光(ALS)与红外(IR)数据,利用分段线性模型(根据IR/ALS比值动态选择校准系数)计算实际照度,经滑动窗口均值滤波抑制噪声后,与预设阈值比较:若低于阈值则点亮后4位LED(模拟路灯),并通过BCD编码输出照度值。设计核心为 动态校准抗干扰(分段系数) + 数据平滑降噪(四阶滤波) + 阈值响应控制(低照度触发)。
2滤波逻辑:
缓冲区定义:定义了一个长度为4的缓冲区lux_buffer,用于存储最近四次的lux值。
数据更新:在每个dat_valid信号的上升沿,将当前的lux值依次移入缓冲区,并更新缓冲区中的数据。
滤波计算:通过对缓冲区中的四个值进行求和,并将结果右移2位(相当于除以4),实现了简单的滑动平均滤波。滤波后的结果存储在lux_filtered中。
3 BCD转码:
调用子模块:实例化了一个bin_to_bcd模块,用于将滤波后的环境光强度数据(lux_filtered)转换为BCD格式。这样可以方便后续在数码管上显示环境光强度。
输出连接:将bin_to_bcd模块的输出bcd_code连接到模块的lux_data输出端口,使得最终的环境光强度数据以BCD格式输出。
4. 软件流程图和关键代码介绍:
任务一任务二:
图形化链接:stepfpga
Decoder:
wire [3:0] code;
reg [6:0] q;
reg ch;
assign code[0] = A0;
assign code[1] = A1;
assign code[2] = A2;
assign code[3] = A3;
assign Y[0] = q[0];
assign Y[1] = q[1];
assign Y[2] = q[2];
assign Y[3] = q[3];
assign Y[4] = q[4];
assign Y[5] = q[5];
assign Y[6] = q[6];
always@(code) begin
case(code)
4'b0000: q = 7'b110_1111;//9
4'b0001: q = 7'b110_0110;//4
4'b0010: q = 7'b100_1111;//3
4'b0011: q = 7'b111_1111;//8
4'b0100: q = 7'b000_0111;//7
4'b0101: q = 7'b101_1011;//2
4'b0110: q = 7'b000_0110;//1
4'b0111: q = 7'b111_1101;//6
4'b1000: q = 7'b110_1101;//5
4'b1001: q = 7'b011_1111;//0
endcase
ch <= code[0]&code[3]&(~code[1])&(~code[2]);
end
主要功能是实现一个4位二进制编码到7段数码管显示信号的转换。通过case语句,根据输入的4位二进制编码,选择对应的7段数码管显示信号,并将其赋值给q寄存器。Y输出信号直接连接到q寄存器的各位,用于驱动数码管的7个段。ch信号则用于数码管的选通控制。
注意:是在计数器为0时的下降沿触发颜色改变的信号,ch <= code[0]&code[3]&(~code[1])&(~code[2]);,也就是倒计时0结束时改变颜色信号。
颜色改变:
wire ch;
reg [1:0] count;
assign ch = color_change;
assign RGB0 = count[0];
assign RGB1 = count[1];
always@(negedge ch)begin
if(count==2'b10)
count<=2'b00;
else
count<=count+2'b01;
end
RGB0和RGB1:用于控制交通灯颜色的输出信号,它们的值由计数器count的当前值决定。
每当color_change信号的上升沿到来时,计数器count的值会加1。如果count的值达到2'b10(即十进制的2),它会在下一次加1时被重置为0,从而实现循环计数。
颜色控制:
wire [1:0] RGB2;
reg [5:0] RGB;
assign RGB2[0] = RGB0;
assign RGB2[1] = RGB1;
always @(*) begin
case (RGB2)
2'b00: RGB = 6'b00_11_11; // 红色:R满,G/B关闭
2'b01: RGB = 6'b11_00_11; // 绿色:G满,R/B关闭
2'b10: RGB = 6'b00_00_11; // 黄色:R/G满,B关闭
default: RGB = 6'b11_11_11;
endcase
end
RGB2:将RGB0和RGB1拼接成一个2位的信号,用于控制RGB灯的颜色。
RGB:6位的寄存器,用于存储RGB灯的颜色值。每个颜色通道(红、绿、黄)由两位表示。
case语句:根据RGB2的值,设置RGB灯的颜色。每个case分支对应一种颜色配置。
任务三任务四:
decoder:
module decoder(
input rst_n, // 异步复位信号(低电平有效)
input dat_valid, // 数据有效时钟(用于同步采样)
input [15:0] prox_dat, // 接近传感器原始数据(16位)
input [15:0] ch0_dat, // 环境光传感器通道0数据(ALS)
input [15:0] ch1_dat, // 环境光传感器通道1数据(IR)
output [31:0] lux_data, // BCD编码的照度值(数码管显示)
output reg [7:0] Y_out // LED控制信号(前4位接近检测,后4位环境光)
);
// --- 接近检测逻辑(三级滤波消除噪声)---
parameter THRESHOLD = 16'h0400; // 接近检测阈值(0x0400)
reg [15:0] prox_dat0, prox_dat1, prox_dat2; // 三级滤波寄存器
always @(posedge dat_valid) begin
prox_dat0 <= prox_dat; // 当前数据存入prox_dat0
prox_dat1 <= prox_dat0; // 前一次数据存入prox_dat1
// 若相邻数据差值≥0x800,保持prox_dat2不变;否则更新为最新值
if ( ( (prox_dat1 > prox_dat0) ? (prox_dat1 - prox_dat0) : (prox_dat0 - prox_dat1) ) >= 16'h800 )
prox_dat2 <= prox_dat2; // 抑制突变噪声
else
prox_dat2 <= prox_dat0; // 正常更新
end
// --- LED控制逻辑(低电平点亮)---
reg [3:0] prox_leds; // 前4位LED(接近检测结果)
reg [3:0] lux_leds; // 后4位LED(环境光亮度指示)
always @(*) begin
prox_leds = (prox_dat2 >= THRESHOLD) ? 4'b0000 : 4'b1111; // 接近时全亮
lux_leds = (lux_filtered < LUX_THRESHOLD) ? 4'b0000 : 4'b1111; // 亮度不足时全亮
Y_out = {prox_leds, lux_leds}; // 拼接输出8位LED信号
end
// --- 环境光计算逻辑(动态分段线性校准)---
// 校准参数(基于IR/ALS比值分段)
parameter RATIO_1 = 595; // 分段阈值0.595(Q16.16格式)
parameter COEFF_A1 = 1682; // ALS校准系数(0.1682 * 10000)
parameter COEFF_B1 = 1877; // IR校准系数(0.1877 * 10000)
parameter RATIO_2 = 1015; // 分段阈值1.015
parameter COEFF_A2 = 644; // 0.0644 * 10000
parameter COEFF_B2 = 132; // 0.0132 * 10000
parameter RATIO_3 = 1352; // 分段阈值1.352
parameter COEFF_A3 = 756; // 0.0756 * 10000
parameter COEFF_B3 = 243; // 0.0243 * 10000
parameter RATIO_4 = 3053; // 分段阈值3.053
parameter COEFF_A4 = 766; // 0.0766 * 10000
parameter COEFF_B4 = 25; // 0.0025 * 10000
localparam Q16 = 16; // 定点数小数位(Q16.16)
wire [31:0] data0 = ch0_dat; // 环境光数据扩展为32位
wire [31:0] data1 = ch1_dat; // 红外数据扩展为32位
reg signed [31:0] lux; // 计算的照度值
reg signed [31:0] calc_als, calc_ir; // 中间变量(Q16.16格式)
always @(*) begin
calc_als = data0 * (1 << Q16); // 转换为Q16.16格式
calc_ir = data1 * (1 << Q16);
// 根据IR/ALS比值选择校准系数
if (calc_ir < ((calc_als * RATIO_1) >> Q16)) begin
lux = (calc_als * COEFF_A1 + calc_ir * COEFF_B1) >> Q16;
end else if (calc_ir < ((calc_als * RATIO_2) >> Q16)) begin
lux = (calc_als * COEFF_A2 + calc_ir * COEFF_B2) >> Q16;
end else if (calc_ir < ((calc_als * RATIO_3) >> Q16)) begin
lux = (calc_als * COEFF_A3 + calc_ir * COEFF_B3) >> Q16;
end else if (calc_ir < ((calc_als * RATIO_4) >> Q16)) begin
lux = (calc_als * COEFF_A4 + calc_ir * COEFF_B4) >> Q16;
end else begin
lux = 0; // 异常情况输出0
end
end
// --- 滑动窗口均值滤波(抑制噪声)---
parameter LUX_THRESHOLD = 32'h00001000; // 环境光亮度阈值(需校准)
reg [31:0] lux_buffer [0:3]; // 4级缓冲区(存储最近4次数据)
reg [31:0] lux_filtered; // 滤波后的照度值
always @(posedge dat_valid or negedge rst_n) begin
if (!rst_n) begin // 复位时清空缓冲区
lux_filtered <= 32'h0;
lux_buffer[0] <= 32'h0;
lux_buffer[1] <= 32'h0;
lux_buffer[2] <= 32'h0;
lux_buffer[3] <= 32'h0;
end else begin
lux_buffer[0] <= lux; // 新数据插入队列头部
lux_buffer[1] <= lux_buffer[0]; // 旧数据依次后移
lux_buffer[2] <= lux_buffer[1];
lux_buffer[3] <= lux_buffer[2];
// 计算均值:4次数据求和后右移2位(等效除以4)
lux_filtered <= (lux_buffer[0] + lux_buffer[1] + lux_buffer[2] + lux_buffer[3]) >> 2;
end
end
// --- BCD编码模块(驱动数码管)---
wire [31:0] T_data_bcd; // BCD编码结果
bin_to_bcd u1(
.rst_n(rst_n), // 复位信号
.bin_code(lux_filtered), // 输入滤波后的照度值
.bcd_code(T_data_bcd) // 输出32位BCD码
);
assign lux_data = T_data_bcd; // 最终输出
endmodule
- 接近检测
- 三级滤波:通过移位寄存器链(
prox_dat0→prox_dat2
)消除数据突变噪声,仅当相邻数据差值小于0x800
时更新有效值。 - 阈值控制:滤波后数据与
THRESHOLD (0x0400)
比较,控制前4位LED(低电平点亮表示接近目标)。
- 三级滤波:通过移位寄存器链(
- 环境光感知
- 分段线性模型:根据IR/ALS比值动态选择校准系数(共4段),通过公式
lux = (ALS * A + IR * B) >> 16
计算实际照度。 - 抗干扰设计:
- 输入扩展:16位原始数据扩展为32位,避免计算溢出。
- 均值滤波:4级滑动窗口对历史数据求均值,抑制瞬时噪声。
- 阈值响应:当滤波后照度低于
LUX_THRESHOLD (0x1000)
时,点亮后4位LED(模拟路灯自动开启)。
- 分段线性模型:根据IR/ALS比值动态选择校准系数(共4段),通过公式
- 数据输出
- BCD编码:将滤波后的二进制照度值转换为BCD码,驱动数码管显示。
- 实时性:所有逻辑由
dat_valid
时钟同步,确保数据更新与传感器采样同步。
- 复位支持
- 复位信号 (
rst_n
) 清空所有寄存器,确保系统从稳定状态启动
- 复位信号 (
5. 功能展示图及说明
任务一、二:
倒计时设置为9秒,九秒红灯结束后变为绿灯,绿灯结束后变为黄灯同时蜂鸣器报警响起,黄灯结束后重新变为红灯。
任务三、四(修改后):
任务三:当传感器检测到有人靠近时,将触发交通灯控制逻辑,低于阈值时使下面四个灯亮起。
任务四:中间的数字随环境光亮暗进行变化,越亮数字越大,越暗数字越小,小于3.36时上面四个灯亮起。
环境亮度大于3.36,没有人员接近时,显示环境光亮度,不亮灯:
环境亮度小于3.36,没有人员接近时,显示环境光亮度,亮上面四个灯:
环境亮度大于3.36,有人员接近时,显示环境光亮度,亮下面四个灯:
环境亮度小于3.36,且有人员接近时,显示环境光亮度,亮下面下面8个灯,全部亮起:
资源占用:
任务一二:
任务三四:
6. 项目中遇到的难题和解决方法
难题1:时钟分频不准确导致计时错误
问题描述:
在交通灯控制系统中,需要精确的时钟信号来控制交通灯的计时。然而,在实际运行中发现计时会出现偏差,导致交通灯状态切换不准确。
解决方法:
重新设计时钟分频器:检查时钟分频器的逻辑,确保分频后的时钟信号频率准确。使用更精确的分频算法,例如基于计数器的分频方法。
增加时钟校准逻辑:在系统初始化时,增加时钟校准逻辑,确保时钟信号的稳定性。
使用高质量的晶振:更换更高精度的晶振,减少时钟信号的抖动和偏差。
难题2:接近传感器数据不稳定导致误触发
问题描述:
接近传感器在检测人员靠近时会出现数据不稳定的情况,导致交通灯状态误触发,影响系统的可靠性。
解决方法:
增加数据滤波逻辑:在接近传感器的数据处理模块中增加滤波逻辑,例如滑动平均滤波或中值滤波,以减少数据波动。
调整阈值检测逻辑:优化阈值检测逻辑,增加检测的灵敏度和稳定性。例如,使用动态阈值而不是固定阈值。
增加传感器校准步骤:在系统初始化时,增加传感器校准步骤,确保传感器在不同环境下的稳定性。
难题3:RGB灯控制逻辑复杂导致输出错误
问题描述:
在控制RGB灯的颜色变化时,逻辑复杂,容易出现输出错误,导致灯的颜色显示不正确。
解决方法:
简化控制逻辑:重新设计RGB灯的控制逻辑,使用更简洁的case语句或状态机来控制颜色变化。
增加中间变量:在逻辑中增加中间变量,逐步调试每个变量的值,确保逻辑的正确性。
使用仿真工具:利用仿真工具对RGB灯的控制逻辑进行仿真,提前发现和修正逻辑错误。
7.心得体会和意见
心得体会;
技术挑战与成长:
在项目开发过程中,我遇到了许多技术难题,例如时钟分频不准确、接近传感器数据不稳定和RGB灯控制逻辑复杂等问题。通过查阅资料、调试代码和优化设计,我逐渐克服了这些问题。这不仅让我在技术上有了很大的提升,也让我学会了如何在面对复杂问题时保持冷静和耐心。
时间管理与效率:
项目开发过程中,时间管理是一个重要的挑战。我们需要在有限的时间内完成设计、实现和测试等多个阶段。通过合理分配任务和设定优先级,我们能够有效地提高工作效率,确保项目按时完成。
意见和建议
网页稳定性:
在使用WebIDE进行开发时,网页的稳定性是一个大问题。频繁的卡顿和数据丢失严重影响了开发效率。希望平台能够优化服务器性能,提高网页的响应速度和稳定性。
自动保存功能:
建议增加自动保存功能,避免因意外断开连接或网页卡顿导致的代码丢失。可以设置定时保存或在用户进行操作时自动保存,以确保劳动成果得到保护。
优化开发环境:
提供更丰富的调试工具和仿真环境,帮助开发者更好地测试和验证代码。例如,增加波形仿真工具、逻辑分析仪等,以便开发者能够更直观地了解代码的运行情况。
通过这次项目开发,我不仅在技术上有了显著的提升,也在时间管理方面积累了宝贵的经验。希望未来能够有更多的机会参与类似的项目,进一步提升自己的能力。