FPGA学习(自用)

1. 核心架构:异构计算模型 🧠

  • Host (主机端):运行在服务器 CPU 上,使用标准 C++ 和 XRT 库编写。负责数据准备、内存分配以及调度底层硬件。

  • Kernel (内核端):运行在 U280 FPGA 上,负责实际的并行加速计算。通过 Vitis HLS 工具,可以用 C/C++ 来描述硬件逻辑。

2. Kernel 端开发 (硬件接口映射) ⚡

为了让 C++ 循环变成 U280 上的真实电路,我们使用了 #pragma 编译指示:

  • m_axi (高带宽内存接口) :负责海量数据传输。我们将数组绑定到不同的物理通道(如 gmem0, gmem1),让 FPGA 能够同时从 HBM 内存中读写不同数据,实现并行。

  • s_axilite (轻量级控制接口) :负责控制信号和参数传递。我们将指针基地址、标量(如长度 N)以及启动/停止信号统一绑定到 control 寄存器上,供 CPU 读写。

3. Host 端开发 (XRT 控制逻辑) 💻

主机程序扮演着"指挥官"的角色,核心数据流转包括四个步骤:

  1. 创建 Buffer 📦:在 U280 的 HBM 内存中按字节数分配缓冲区,为数据"占座"。

  2. H2D 传输 (Host to Device):通过 PCIe 总线,将待计算的数据从 CPU 内存搬运到 FPGA 的 HBM 中。

  3. 触发执行 :传递参数并下达执行指令,CPU 通过 wait() 指令等待 FPGA 闪电般的计算完成。

  4. D2H 传输 (Device to Host):将计算结果从 FPGA 的 HBM 搬运回 CPU 内存,供后续打印或保存。

4. 编译与仿真工作流 🛠️

  • 编译产物 :Host 代码被编译为普通的可执行文件(如 host_app),Kernel 代码被编译为硬件配置压缩包(.xclbin )。在终端运行时,将 .xclbin 作为参数传给 host_app 来启动整个系统。

  • 平台 (Platform) :编译时必须指定目标平台(如 xilinx_u280_...),它包含了板卡的底层硬件拓扑结构。

  • 阶梯式开发:

    • sw_emu (软件仿真):秒级编译,完全在 CPU 上运行,专用于快速验证算法逻辑的正确性。

    • hw_emu (硬件仿真):模拟底层硬件时序,用于评估周期和通道拥堵情况。

    • hw (纯硬件):耗时数小时进行综合与布线,生成最终部署到 U280 物理板卡上的文件。

异构计算(简单了解)
异构编程生态

学习 XRT (Xilinx Runtime) Native C++ API 是非常明智的选择,它是 AMD/Xilinx

官方目前主推的、比 OpenCL 更轻量且更符合现代 C++ 规范的接口。

以下是系统学习 XRT Native API 的路径和核心知识点:

1. 核心概念对比(从 OpenCL 迁移)

理解 XRT Native API 最快的方法是将其与你当前工程中的 OpenCL 概念进行对比: ┌────────────┬────────────────────────────┬─────────────────────────────────┐

│ 功能 │ OpenCL API (旧) │ XRT Native API (新) │

├────────────┼────────────────────────────┼─────────────────────────────────┤

│ 设备对象 │ cl::Device │ `xrt::device`

│

│ **加载硬... │ cl::Program │ `xrt::uuid` (通过 `device.load_x...

│

│ 内核对象 │ cl::Kernel │ `xrt::kernel`

│

│ 内存缓冲区 │ cl::Buffer │ `xrt::bo` (Buffer Object)

│

│ 数据同步 │ enqueueMigrateMemObjects │ `bo.sync()`

│

│ 执行内核 │ `cl::CommandQueue::enqueu... │ `kernel()` (像函数一样直接调用)

│

└────────────┴────────────────────────────┴─────────────────────────────────┘

2. 最小代码框架 (Hello World)

一个典型的 XRT Native C++ 主机端程序逻辑如下:

cpp 复制代码
// ==========================================
// 传统 OpenCL API 主机端代码示例 (极度简化版)
// ==========================================

// 1. 获取平台和设备
cl_platform_id platform;
clGetPlatformIDs(1, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ACCELERATOR, 1, &device, NULL);

// 2. 创建上下文和命令队列 (繁琐的初始化)
cl_context context = clCreateContext(0, 1, &device, NULL, NULL, NULL);
cl_command_queue q = clCreateCommandQueue(context, device, 0, NULL);

// 3. 加载 xclbin 硬件比特流并创建 Program (省略了读取文件的几十行代码)
cl_program program = clCreateProgramWithBinary(context, 1, &device, &fileBufSize, (const unsigned char**)&fileBuf, NULL, NULL);

// 4. 创建内核
cl_kernel kernel = clCreateKernel(program, "vadd", NULL);

// 5. 在 FPGA 显存中分配 Buffer
cl_mem buffer_in1 = clCreateBuffer(context, CL_MEM_READ_ONLY, size_in_bytes, NULL, NULL);
cl_mem buffer_in2 = clCreateBuffer(context, CL_MEM_READ_ONLY, size_in_bytes, NULL, NULL);
cl_mem buffer_out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, size_in_bytes, NULL, NULL);

// 6. 逐个设置内核参数 (非常容易出错,写错索引直接崩溃)
clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer_in1);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer_in2);
clSetKernelArg(kernel, 2, sizeof(cl_mem), &buffer_out);
clSetKernelArg(kernel, 3, sizeof(int), &size);

// 7. 将数据从主机拷贝到 FPGA,并排队执行内核
clEnqueueWriteBuffer(q, buffer_in1, CL_TRUE, 0, size_in_bytes, host_in1, 0, NULL, NULL);
clEnqueueWriteBuffer(q, buffer_in2, CL_TRUE, 0, size_in_bytes, host_in2, 0, NULL, NULL);
clEnqueueTask(q, kernel, 0, NULL, NULL); // 触发执行

// 8. 等待执行完毕并读回结果
clEnqueueReadBuffer(q, buffer_out, CL_TRUE, 0, size_in_bytes, host_out, 0, NULL, NULL);
clFinish(q);

// 9. 手动清理所有资源 (如果中途报错退出,这里没执行就会内存泄漏)
clReleaseMemObject(buffer_in1);
clReleaseMemObject(buffer_in2);
clReleaseMemObject(buffer_out);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(q);
clReleaseContext(context);

3. 核心学习资源 (必读)

  1. 官方文档 UG1393 (Vitis 用户指南):

* 重点阅读 "XRT Native API" 章节。这是最权威的参考资料。

  1. XRT 入门示例 (GitHub):

* 访问 Xilinx/Vitis_Accel_Examples

(https://github.com/Xilinx/Vitis_Accel_Examples)。

* 搜索标注有 xrt_native 的示例(通常在 host/ 目录下可以看到使用了

xrt_kernel.h 而非 xcl2.hpp 的代码)。

  1. XRT 官方 API 文档:

* 访问 xilinx.github.io/XRT/

(https://xilinx.github.io/XRT/master/html/index.html),查看完整的 C++

API 引用手册。

4. 实践建议

* 环境准备:确保你的系统中安装了 xrt-dev 包。在代码中包含头文件

<xrt/xrt_device.h>。

* 编译设置:在 Makefile 中,你需要链接 xrt_coreutil 库。

* 编译选项添加:-I$(XILINX_XRT)/include

* 链接选项添加:-L$(XILINX_XRT)/lib -lxrt_coreutil

* 从模仿开始:你可以试着把你现在工程里

Vitis_workflow/examples/vadd_vmul/host/host.cpp 的 OpenCL 代码改写成 XRT

Native 版本。你会发现代码量会减少 30% 以上,逻辑更清晰。

总结

学习 XRT Native API 的门槛比 OpenCL

低得多,因为它隐藏了大量底层的样板代码。如果你已经理解了"内存申请 -> 数据搬运

-> 启动内核 -> 传回结果"这个流程,只需花 1-2 天 熟悉 xrt::device、xrt::bo 和

xrt::kernel 这几个类即可上手。

相关推荐
女神下凡1 天前
芯参谋(37):EEPROM_电路设计指南
arm开发·单片机·嵌入式硬件·fpga开发·设计规范
szxinmai主板定制专家2 天前
工业视觉新思路:FPGA图像预处理+RK NPU推理,实现高速缺陷检测
人工智能·嵌入式硬件·fpga开发·rk3576+codesys
FPGA小徐2 天前
【硬件实战】立创 EDA 绘制 TF/SD 卡模块电路|SPI 模式原理图 + 阻抗匹配 + PCB 布局布线全教程
单片机·嵌入式硬件·fpga开发
狂奔蜗牛(bradley)2 天前
EtherCAT DC 分布式时钟同步的 ModelSim 仿真:从帧模板到从站行为建模
人工智能·嵌入式硬件·fpga开发·架构
ALINX技术博客3 天前
8 通道同步采样 ADC!AN706 波形显示实验 【FPGA黑金云课堂】
fpga开发
szxinmai主板定制专家3 天前
RK3568+FPGA+CODESYS异构控制方案:赋能半导体设备与工业自动化升级
人工智能·fpga开发·自动化·rk3576·半导体设备
辰丁电子3 天前
allegro入门教程-菜单栏Logic
fpga开发·pcb设计·pcb工艺·layout·pcb layout
FPGA小徐4 天前
数字IC/FPGA设计基础_ILA原理与使用
fpga开发
FPGA小徐4 天前
FPGA 部署 YOLO 完整指南:从模型量化到 Zynq PS+PL 硬件加速
yolo·fpga开发
dadaobusi4 天前
学习:chiesel,scala
学习·fpga开发·scala