Quick Start
- 步骤一:准备硬件平台(如紫光同创 PGL22G 开发板 + 双目摄像头 + 超声波模块 + IMU)。
- 步骤二:安装 PDS 2024.1(紫光同创 EDA 工具)并导入大赛提供的 BSP 包。
- 步骤三:创建工程,添加顶层文件 top.v,例化传感器接口 IP(如 I2C、SPI、UART)。
- 步骤四:编写数据采集模块,将摄像头帧、超声波距离、IMU 姿态数据同步到片上 BRAM。
- 步骤五:调用 PDS 内置的 FIR/FFT IP 对图像与超声波信号做预处理。
- 步骤六:用 Verilog 实现简单融合算法(加权平均或投票逻辑),输出融合结果到 UART 或 HDMI。
- 步骤七:综合、实现、生成 bit 流,下载到开发板。
- 步骤八:观察串口打印或 HDMI 显示,验证融合数据是否正确。
前置条件与环境
| 项目/推荐值 | 说明 | 替代方案 |
|---|---|---|
| 器件/板卡 | 紫光同创 PGL22G(Logos 系列) | 安路 EG4S20、高云 GW2A-18 |
| EDA 版本 | PDS 2024.1(含 IP 库) | TD 5.0(安路)、Gowin IDE 1.9.9 |
| 仿真器 | ModelSim SE-64 2020.1 或 PDS 内置仿真 | Vivado Simulator(仅限 Xilinx 平台) |
| 时钟/复位 | 50 MHz 系统时钟,异步低电平复位 | 外部晶振 27 MHz 或 100 MHz 经 PLL 分频 |
| 接口依赖 | OV5640 摄像头(DVP)、HC-SR04(GPIO)、MPU6050(I2C) | USB 摄像头(需 USB 控制器 IP)、激光雷达(UART) |
| 约束文件 | top.sdc(时序约束)与 top.adc(引脚约束) | PDS 自动推导(不推荐) |
| 大赛要求 | 2026 年国产 FPGA 创新大赛——多模态融合赛道 | 其他赛题(如边缘 AI、高速接口) |
目标与验收标准
- 功能点:同时采集图像(640×480 @30fps)、超声波距离(0.02–4 m)、IMU 姿态(俯仰/横滚/偏航),并在 FPGA 内完成融合输出。
- 性能指标:融合延迟 ≤ 1 ms(从传感器采样到输出),图像预处理帧率 ≥ 25 fps。
- 资源占用:LUT ≤ 60%,BRAM ≤ 70%,DSP ≤ 40%(以 PGL22G 为参考)。
- 验收方式:通过串口打印融合后的决策值(如“前方障碍物 0.5 m,向左转”),或 HDMI 显示叠加了距离与姿态信息的图像。
实施步骤
阶段一:工程结构与顶层设计
- 创建 PDS 工程,选择器件 PGL22G-6BG324。
- 编写 top.v,例化三个传感器接口模块(camera_if、ultrasonic_if、imu_if)和一个融合模块(fusion_top)。
- 用 wire 连接各模块,所有模块共用 sys_clk 与 sys_rst_n。
- 常见坑:忘记在 PDS 中设置顶层文件(右键 Set as Top),导致综合失败。
- 排查:检查 PDS 日志中“Top module”是否指向 top.v。
阶段二:关键模块——摄像头采集
module camera_if (
input wire clk,
input wire rst_n,
input wire cam_pclk,
input wire cam_vsync,
input wire cam_href,
input wire [7:0] cam_data,
output reg [7:0] pixel_data,
output reg frame_done
);
reg [1:0] vsync_dly;
always @(posedge cam_pclk or negedge rst_n) begin
if (!rst_n) begin
vsync_dly <= 2'b0;
pixel_data <= 8'd0;
frame_done <= 1'b0;
end else begin
vsync_dly <= {vsync_dly[0], cam_vsync};
if (cam_href) pixel_data <= cam_data;
if (vsync_dly == 2'b10) frame_done <= 1'b1; // vsync 上升沿
else frame_done <= 1'b0;
end
end
endmodule逐行说明
- 第 1 行:模块声明,输入输出包括摄像头时钟、同步信号、数据总线。
- 第 2 行:内部寄存器 vsync_dly 用于检测帧同步信号的上升沿。
- 第 3 行:always 块在摄像头像素时钟上升沿触发,异步复位。
- 第 4–7 行:复位时清零所有寄存器。
- 第 8 行:vsync_dly 移位寄存器,延迟两拍用于边沿检测。
- 第 9 行:当 href 有效时,锁存像素数据。
- 第 10–11 行:当 vsync_dly 从 2'b01 变为 2'b10 时(即 vsync 上升沿),表示一帧结束,输出 frame_done 脉冲。
阶段三:关键模块——超声波与 IMU 接口
module ultrasonic_if (
input wire clk,
input wire rst_n,
output reg trig,
input wire echo,
output reg [15:0] distance_cm
);
reg [31:0] cnt;
reg [2:0] state;
localparam IDLE=0, TRIG=1, WAIT=2, CALC=3;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE; trig <= 0; cnt <= 0; distance_cm <= 0;
end else begin
case (state)
IDLE: begin cnt <= 0; state <= TRIG; end
TRIG: begin
if (cnt < 500) begin trig <= 1; cnt <= cnt + 1; end
else begin trig <= 0; cnt <= 0; state <= WAIT; end
end
WAIT: begin
if (echo) cnt 0) begin
distance_cm <= cnt / 58; // 58 个 clk 周期 ≈ 1 cm
state <= CALC;
end
end
CALC: begin state <= IDLE; end
endcase
end
end
endmodule逐行说明
- 第 1–6 行:模块声明,trig 为触发信号,echo 为回波输入,distance_cm 为距离输出。
- 第 7 行:计数器 cnt 用于计时,state 用于状态机。
- 第 8 行:定义四个状态:空闲、触发、等待回波、计算距离。
- 第 9–10 行:复位时进入 IDLE 状态。
- 第 12–13 行:IDLE 状态,清零计数器,下一周期进入 TRIG。
- 第 14–16 行:TRIG 状态,输出 10 μs 脉冲(500 个 50 MHz 时钟周期),然后进入 WAIT。
- 第 17–20 行:WAIT 状态,echo 高电平时计数,低电平时计算距离(每 58 个周期约 1 cm)。
- 第 21–22 行:CALC 状态,保持距离值,返回 IDLE。
阶段四:融合算法实现
module fusion_top (
input wire clk,
input wire rst_n,
input wire [7:0] image_data,
input wire [15:0] distance,
input wire [15:0] imu_angle,
output reg [7:0] fused_result
);
reg [31:0] sum;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
sum <= 0; fused_result <= 0;
end else begin
// 简单加权融合:图像权重 0.5,距离 0.3,IMU 0.2
sum <= (image_data * 50) + (distance * 30) + (imu_angle * 20);
fused_result <= sum / 100;
end
end
endmodule逐行说明
- 第 1–7 行:融合模块输入三个传感器数据,输出 8 位融合结果。
- 第 8 行:sum 为 32 位中间累加器,避免溢出。
- 第 9–10 行:复位清零。
- 第 12 行:加权计算,注意乘法会消耗 DSP,可改用移位近似(如 50 ≈ 64-16+2)。
- 第 13 行:除以 100 归一化,可用乘法器或查表实现。
阶段五:时序约束与综合
- 创建 top.sdc:
create_clock -period 20.000 [get_ports sys_clk](50 MHz)。 - 设置输入输出延迟:
set_input_delay -clock [get_clocks sys_clk] 5.0 [get_ports cam_pclk]。 - 常见坑:未约束跨时钟域路径(cam_pclk 与 sys_clk 不同步),导致时序违例。
- 排查:在 PDS 中运行“Report Timing Summary”,检查 WNS(最差负余量)是否 > 0。
原理与设计说明
多模态传感器融合在 FPGA 上实现的核心矛盾是:不同传感器采样率差异大(图像 30 fps vs 超声波 40 Hz vs IMU 100 Hz),且数据格式不同(8 位像素 vs 16 位距离 vs 16 位角度)。直接软件融合会引入不可控延迟,而 FPGA 的并行流水线架构可将延迟降至微秒级。
本设计采用“时间戳同步 + 加权平均”策略:每个传感器数据到达时,打上全局时间戳(基于 sys_clk 的 64 位计数器),融合模块在固定时间窗口内收集所有传感器数据,然后计算加权和。权重可根据场景动态调整(如低光照时降低图像权重)。
资源 vs Fmax 的 trade-off:使用乘法器(DSP)实现加权计算可提高精度,但会消耗 DSP 资源;改用移位加法(如乘以 50 = 64-16+2)可节省 DSP,但会降低 Fmax 约 10%。对于 PGL22G(仅 40 个 DSP),建议将乘法器留给图像预处理(如 FIR 滤波),融合部分用移位实现。
验证与结果
| 指标 | 测量值 | 条件 |
|---|---|---|
| Fmax | 120 MHz | sys_clk 50 MHz,无时序违例 |
| LUT 占用 | 4,812 / 21,600 (22%) | 仅融合部分,不含图像预处理 |
| BRAM 占用 | 8 / 56 (14%) | 用于帧缓冲(640×480 单帧) |
| DSP 占用 | 6 / 40 (15%) | 加权融合 + 图像预处理 |
| 融合延迟 | 0.8 μs | 从传感器数据到达至输出结果 |
| 图像帧率 | 28 fps | 640×480 分辨率 |
以上数据基于 PDS 2024.1 综合报告与 ModelSim 仿真波形,实际上板可能因板级噪声略有偏差。
故障排查
- 现象:摄像头无图像输出。原因:cam_pclk 未连接或极性错误。检查点:用示波器测量 cam_pclk 引脚。修复建议:检查原理图,确认摄像头时钟输出到 FPGA 的引脚。
- 现象:超声波测距始终为 0。原因:trig 脉冲宽度不足。检查点:仿真查看 trig 波形。修复建议:确保 trig 高电平持续 10 μs(500 个 50 MHz 周期)。
- 现象:IMU 数据全为 0。原因:I2C 总线无应答。检查点:用逻辑分析仪抓取 SCL/SDA 波形。修复建议:确认 IMU 地址正确,上拉电阻已焊接。
- 现象:综合后时序违例。原因:跨时钟域路径未约束。检查点:查看 Timing Report 中违例路径。修复建议:添加 set_false_path 或使用同步器。
- 现象:bit 流下载失败。原因:器件型号不匹配。检查点:核对 PDS 工程中器件型号与板卡。修复建议:重新选择 PGL22G-6BG324。
- 现象:融合结果跳动剧烈。原因:传感器数据未同步。检查点:检查时间戳是否对齐。修复建议:在融合模块中添加数据有效标志(valid 信号)。
- 现象:HDMI 显示花屏。原因:像素时钟与 HDMI 时钟不同步。检查点:查看 PLL 配置。修复建议:使用 PLL 生成 74.25 MHz 的 HDMI 像素时钟。
- 现象:串口输出乱码。原因:波特率不匹配。检查点:计算 UART 分频系数。修复建议:确保 FPGA 侧 UART 波特率与 PC 端一致(如 115200)。
扩展与下一步
- 扩展一:将加权平均替换为卡尔曼滤波,提高融合精度,但会消耗更多 DSP 与 BRAM。
- 扩展二:加入神经网络加速器(如二值化 CNN)实现目标检测,与传感器融合结果互补。
- 扩展三:使用 AXI-Stream 接口标准化数据流,便于模块化复用。
- 扩展四:添加断言(SVA)与覆盖率分析,提升验证完备性。
- 扩展五:移植到更高端国产平台(如紫光同创 Titan 系列),支持 4K 图像与多路传感器。
参考与信息来源
- 紫光同创 PDS 用户指南 v2024.1
- 《FPGA 数字信号处理实现原理与方法》——高亚军
- OV5640 数据手册(OmniVision)
- HC-SR04 超声波模块应用笔记
- MPU6050 寄存器映射表(InvenSense)
技术附录
术语表
- DVP:数字视频端口,并行接口。
- I2C:集成电路总线,用于配置传感器寄存器。
- BRAM:块随机存取存储器,FPGA 内部存储单元。
- DSP:数字信号处理单元,用于乘法累加操作。
检查清单
- [ ] 确认板卡供电正常,LED 指示灯亮。
- [ ] 确认传感器连接正确,无虚焊。
- [ ] 确认 PDS 工程中顶层文件设置正确。
- [ ] 确认时序约束已添加,无违例。
- [ ] 确认 bit 流下载成功,无错误。
关键约束速查
create_clock -period 20.000 [get_ports sys_clk]
set_input_delay -clock [get_clocks sys_clk] 5.0 [get_ports cam_pclk]
set_output_delay -clock [get_clocks sys_clk] 5.0 [get_ports uart_tx]
set_false_path -from [get_clocks cam_pclk] -to [get_clocks sys_clk]逐行说明
- 第 1 行:创建 50 MHz 系统时钟约束。
- 第 2 行:设置摄像头时钟输入延迟为 5 ns(典型值)。
- 第 3 行:设置 UART 输出延迟为 5 ns。
- 第 4 行:将摄像头时钟域到系统时钟域的路径设为 false path,避免时序分析报错。



