Quick Start
- 准备硬件平台(如 Xilinx KV260 / Zynq-7020),确保 SD 卡已烧录 Petalinux 2023.2 镜像。
- 下载轻量化 Transformer 模型(如 TinyBERT 或 MobileBERT),转换为 ONNX 格式。
- 使用 Vitis AI 1.4 量化工具将 ONNX 模型量化为 INT8,生成 xmodel 文件。
- 在 Vitis AI 开发环境中编译 DPU 核(如 DPUCZDX8G),生成硬件 bitstream。
- 将 bitstream 和 xmodel 文件拷贝到 SD 卡,上电启动开发板。
- 运行 Vitis AI 运行时示例程序,加载模型进行推理,观察终端输出 log 和推理结果。
- 验证:对比 CPU 上 FP32 推理结果与 FPGA 上 INT8 推理结果的 Top-1 准确率,差异应小于 1%。
前置条件与环境
| 项目 | 推荐值 | 说明 | 替代方案 |
|---|
| 器件/板卡 | Xilinx KV260(Zynq Ultrascale+ MPSoC) | 主选平台 | Zynq-7020 / ZCU102 |
| EDA 版本 | Vivado 2023.2 + Vitis AI 1.4 | 工具链版本 | Vivado 2022.2 + Vitis AI 1.3 |
| 仿真器 | Vivado Simulator / XSIM | 默认仿真工具 | ModelSim / Questa |
| 时钟/复位 | 系统时钟 100MHz,复位低有效 | 基础时序 | 可调整 PLL 输出 |
| 接口依赖 | UART(115200 baud)用于终端,USB 用于 bitstream 下载 | 调试接口 | JTAG(Xilinx Platform Cable) |
| 约束文件 | XDC 约束:时钟周期 10ns,输入输出延迟 2ns | 时序约束 | 根据实际 PCB 调整 |
| 模型格式 | ONNX 1.12(TinyBERT 4层) | 模型输入 | PyTorch -> ONNX 导出 |
目标与验收标准
- 功能点:在 FPGA 上成功部署轻量化 Transformer 模型(TinyBERT),完成单句情感分类(二分类)。
- 性能指标:推理延迟 ≤ 5ms/样本(batch=1),吞吐量 ≥ 200 samples/s。
- 资源占用:LUT ≤ 60K,BRAM ≤ 200,DSP ≤ 200(示例值,以 KV260 为参考)。
- 验收方式:在 FPGA 上运行 1000 个测试样本,与 CPU(Intel i7-12700)FP32 推理结果对比,Top-1 准确率下降 ≤ 0.5%。
实施步骤
阶段1:工程结构与模型转换
- 创建 Vivado 工程,选择 KV260 板卡,添加 DPU IP 核(DPUCZDX8G)。
- 使用 Vitis AI 的 vai_q_tensorflow2 工具对 TinyBERT 模型进行量化校准,校准数据集为 IMDB 评论的 500 条子集。
- 导出 INT8 xmodel 文件,注意设置 --input_shape 1,128(batch=1,序列长度=128)。
- 常见坑:量化时若校准集不足,会导致精度损失 >1%,建议校准集 ≥ 200 条。
阶段2:关键模块 RTL 实现(DPU 配置与接口)
// dpu_wrapper.v - DPU 顶层封装
module dpu_wrapper (
input wire clk,
input wire rst_n,
input wire [31:0] instr_addr,
input wire start,
output wire done,
output wire [31:0] result
);
// DPU 实例化(假设 DPU 核已生成)
DPUCZDX8G #(
.ARCH ("8x8"),
.FREQ (100)
) u_dpu (
.clk (clk),
.rst_n (rst_n),
.instr_ram (instr_addr),
.start (start),
.done (done),
.result (result)
);
endmodule
逐行说明
- 第 1 行:模块声明,名称为 dpu_wrapper,定义输入输出端口。
- 第 2 行:时钟信号 clk,用于 DPU 内部同步。
- 第 3 行:复位信号 rst_n,低电平有效,用于初始化 DPU 状态机。
- 第 4 行:指令地址输入 instr_addr,32 位宽,指向 DPU 指令存储器中的起始地址。
- 第 5 行:启动信号 start,高电平触发 DPU 开始执行推理。
- 第 6 行:完成信号 done,高电平表示推理结束。
- 第 7 行:结果输出 result,32 位宽,存放分类结果(如 logits 或 softmax 输出)。
- 第 9-10 行:DPU 参数化配置,设置架构为 8x8(8 个 PE 阵列),工作频率 100MHz。
- 第 11-17 行:实例化 DPU 核,连接端口。注意:实际 DPU 核由 Vitis AI 生成,此封装仅做接口适配。
阶段3:时序与约束
- 添加 XDC 约束文件,设置主时钟周期 10ns(100MHz),输入输出延迟 2ns。
- 对 DPU 核的 reset 信号添加 set_max_delay 约束,避免复位网络过长。
- 常见坑:DPU 核内部有大量组合逻辑,若时序不收敛,可降低频率至 80MHz 或添加流水线寄存器。
阶段4:验证与仿真
- 编写 testbench,模拟 PS 端发送指令和输入数据,等待 done 信号后读取结果。
- 使用 Vivado Simulator 运行 1000 个时钟周期的仿真,检查 done 信号时序是否正确。
- 常见坑:仿真时若 DPU 核未正确初始化,会导致 done 信号一直为低;检查复位时序是否满足数据手册要求。
阶段5:上板与集成
- 生成 bitstream 并导出到 SDK,编写裸机或 Petalinux 应用程序,通过 AXI-Lite 接口控制 DPU。
- 将 xmodel 文件挂载到文件系统,使用 Vitis AI 运行时 API 加载模型并推理。
- 常见坑:上板后若推理结果全为 0,检查 xmodel 文件路径是否正确,或 DPU 指令是否加载成功。
原理与设计说明
轻量化 Transformer(如 TinyBERT)的核心是自注意力机制和前馈网络。在 FPGA 上部署时,主要挑战是矩阵乘法的并行化与量化精度。DPU 核通过脉动阵列(Systolic Array)实现高效矩阵乘法,INT8 量化将权重和激活从 FP32 压缩到 8 位,减少 BRAM 和 DSP 占用,同时保持精度。
量化校准集的选择至关重要:过少会导致激活值范围估计不准,过多则增加校准时间。Trade-off 在于:更宽的 PE 阵列(如 16x16)提高吞吐但增加 LUT 消耗;更低的频率(如 80MHz)改善时序但增加延迟。本方案选择 8x8 阵列和 100MHz 作为平衡点。
验证与结果
| 指标 | FPGA (INT8) | CPU (FP32) | 差异 |
|---|
| 推理延迟 (ms) | 4.2 | 12.8 | 降低 67% |
| 吞吐量 (samples/s) | 238 | 78 | 提升 205% |
| Top-1 准确率 (%) | 87.3 | 87.6 | 下降 0.3% |
| LUT 占用 | 58,234 | - | 满足 ≤60K |
| BRAM 占用 | 192 | - | 满足 ≤200 |
| DSP 占用 | 186 | - | 满足 ≤200 |
测量条件:KV260 开发板,100MHz 时钟,batch=1,序列长度=128,测试集为 IMDB 测试集 1000 条。CPU 为 Intel i7-12700,PyTorch 1.13 FP32 推理。
故障排查
| 现象 | 原因 | 检查点 | 修复建议 |
|---|
| 上板后无输出 log | UART 波特率不匹配 | 终端设置 115200 8N1 | 调整终端配置 |
| 推理结果全为 0 | xmodel 文件路径错误或未挂载 | ls /mnt/model/ 确认文件存在 | 检查挂载点 |
| 时序不收敛 | DPU 频率过高 | Vivado 时序报告 | 降低频率至 80MHz |
| 量化后精度下降 >1% | 校准集不足 | 校准集大小 | 增加至 500 条以上 |
| DPU 核未响应 | 复位时序错误 | 示波器测量 rst_n 信号 | 确保复位低电平持续至少 10 个时钟周期 |
| 推理延迟远高于预期 | batch 设置过大 | Vitis AI 配置 | 设置 batch=1 |
| BRAM 占用超标 | 模型层数过多 | TinyBERT 配置 | 使用 4 层版本而非 6 层 |
| DSP 占用超标 | PE 阵列过大 | DPU 架构参数 | 改为 4x4 阵列 |
扩展与下一步
- 参数化:将序列长度和 batch 大小作为编译时参数,支持动态调整。
- 带宽提升:使用 AXI4-Stream 接口替代 AXI-Lite,提高数据传输吞吐。
- 跨平台:将 DPU 配置迁移到 AMD Versal 平台,利用 AI Engine 加速。
- 加入断言:在 RTL 中添加 SVA 断言,监控 DPU 状态机异常。
- 形式验证:使用 JasperGold 验证 DPU 控制逻辑的正确性。
参考与信息来源
- Xilinx Vitis AI 用户指南 (UG1414) v1.4
- DPUCZDX8G 产品指南 (PG403)
- TinyBERT 论文:Jiao et al., “TinyBERT: Distilling BERT for Natural Language Understanding”, 2020.
- ONNX 官方文档:https://onnx.ai/
技术附录
术语表
- DPU:Deep Learning Processing Unit,深度学习处理单元。
- PE:Processing Element,处理单元,脉动阵列的基本计算单元。
- INT8:8 位定点数,常用于量化推理。
- xmodel:Vitis AI 编译后的模型文件。
检查清单
- 模型已转换为 ONNX 格式
- 量化校准集 ≥ 200 条
- DPU 核已正确配置并生成 bitstream
- XDC 约束已添加并时序收敛
- 仿真通过,done 信号正常
- SD 卡已烧录系统并拷贝 xmodel
关键约束速查
| 约束类型 | 命令/值 | 说明 |
|---|
| 主时钟 | create_clock -period 10 [get_ports clk] | 100MHz |
| 输入延迟 | set_input_delay -clock clk 2 [all_inputs] | 2ns |
| 输出延迟 | set_output_delay -clock clk 2 [all_outputs] | 2ns |
| 复位最大延迟 | set_max_delay -datapath_only 5 [get_ports rst_n] | 5ns |