2. 开发环境搭建:Vivado/Quartus安装、CPU端开发环境(C++/Python)、FPGA与CPU通信库(PCIe)准备
好,咱们正式开始动手了。
这一章,说白了就是「把家伙事儿备齐」。你想想看,做FPGA+CPU异构计算,光有想法不行,得让工具链跑起来。我见过太多人,代码写了一半发现环境没配好,回头折腾半天——嗯,这种坑咱们得提前填上。
2.1 FPGA开发工具:Vivado vs Quartus
先聊FPGA这边的IDE。目前主流就两家:Xilinx的Vivado,Intel的Quartus。我个人习惯是看项目选工具,但如果你刚开始学,我建议从Vivado入手——生态更成熟,文档也更全。
2.1.1 Vivado安装要点
Vivado的安装包很大,动辄几十个G。我第一次装的时候,下载了一整夜。这里有几个避坑点:
- 版本选择:别追最新版。我建议用2022.2或2023.1,稳定,坑少。最新版有时候会有一些奇怪的bug,社区还没踩完。
- 安装组件:勾选「Vivado HL Design Edition」就够了。如果你做HLS,记得勾上「Vitis HLS」。别全选,全选装完你硬盘就炸了。
- License:WebPACK版免费,够用。但如果你要用PCIe硬核,可能需要申请一个Node-Locked License。我曾经因为License没配好,折腾了两天才发现是MAC地址填错了——低级错误,但很常见。
C:\Xilinx\Vivado\2023.1 这种结构,清爽。
2.1.2 Quartus安装要点
如果你用的是Intel的FPGA(比如Arria 10或Stratix 10),那就得装Quartus。安装流程跟Vivado类似,但有几个不同:
- 版本:Quartus Prime Pro Edition适合高端器件,Standard Edition适合中低端。别搞混了。
- Device Support:安装时只勾选你用的器件系列。全选的话,安装包能到100G+。我见过有人把Cyclone、Arria、Stratix全勾上,结果装完C盘直接红了。
- ModelSim:Quartus自带ModelSim Starter版,够用。但如果你做PCIe仿真,我建议单独装个ModelSim SE或QuestaSim,功能更全。
D:\project\。
2.2 CPU端开发环境:C++与Python
FPGA这边搞定了,咱们再看CPU端。异构计算嘛,两边都得跑起来。
2.2.1 C++开发环境
我推荐用Visual Studio 2022,社区版免费。如果你在Linux下开发,那就用GCC + CMake。我个人习惯是Windows下写原型,Linux下部署。
需要安装的组件:
- MSVC编译器:VS安装时勾选「使用C++的桌面开发」
- CMake:跨平台构建工具,必装
- Vcpkg:C++包管理器,方便安装第三方库。我习惯用它来管理PCIe驱动库的依赖
验证环境:写个简单的Hello World,编译通过就行。别小看这一步,我遇到过有人装完VS发现没选C++组件,编译报错一脸懵。
2.2.2 Python开发环境
Python在量化交易里用得很多,主要是做策略回测和数据分析。我建议用Anaconda,省心。
- Python版本:3.9或3.10,别用3.12,有些库还没适配
- 必备库:numpy, pandas, pybind11(用于C++扩展),pynq(如果用的是Xilinx的PYNQ板卡)
- 虚拟环境:每个项目建一个虚拟环境,别混在一起。我曾经因为依赖冲突,debug了一整天——后来发现是numpy版本不对。
2.3 FPGA与CPU通信库:PCIe准备
这是最核心的部分。FPGA和CPU之间怎么传数据?PCIe是主流方案。说白了,就是把FPGA当成一个PCIe设备,CPU通过驱动去读写它。
2.3.1 Xilinx的XDMA驱动
Xilinx提供了XDMA IP核,配套有Linux和Windows驱动。我建议用Linux,驱动更成熟,调试也方便。
安装步骤:
- 在Vivado中例化XDMA IP核,配置好DMA通道数(一般2个就够了,一个读一个写)
- 生成bitstream,下载到FPGA
- 在Linux下编译XDMA驱动:
make,然后insmod xdma.ko - 验证:
lspci -v能看到Xilinx设备,说明驱动加载成功
我曾经踩过一个坑:XDMA的BAR空间地址没配好,导致CPU读到的全是0。后来发现是Vivado里地址分配冲突了——嗯,这种问题查起来很费时间。
2.3.2 Intel的DMA驱动
Intel这边,对应的是DMA IP Core,驱动叫intel-fpga-pci。安装流程类似:
- 在Quartus中例化DMA IP,配置好AXI接口
- 编译驱动:
make,insmod intel-fpga-pci.ko - 用户态程序通过
mmap映射BAR空间,或者通过read/write接口进行DMA传输
2.3.3 通信库封装
驱动装好了,但直接操作驱动API太原始。我习惯封装一层C++库,提供简洁的接口:
// fpga_comm.h
class FpgaComm {
public:
bool init(); // 打开设备,映射BAR空间
bool dma_write(void* buf, size_t len, uint64_t fpga_addr);
bool dma_read(void* buf, size_t len, uint64_t fpga_addr);
void close(); // 释放资源
};
Python端通过pybind11调用这个C++库,实现Python到FPGA的数据通路。这样,策略代码里只需要调用fpga.dma_write(data),底层细节全封装好了。
2.4 整体架构图
下面这张图,展示了整个开发环境的层次关系。我画的时候尽量简洁,你看一眼就能明白:
这张图从下往上看:最底层是开发工具,往上走是硬件板卡和FPGA逻辑,再往上是通过PCIe驱动和C++封装库构成的通信层,最顶层就是你的量化策略代码。每一层都独立,但层与层之间通过定义好的接口交互。
2.5 验证环境是否搭好
环境搭完,怎么知道对不对?我一般做三步验证:
- FPGA编译通过:随便建个工程,跑一下综合实现,不报错
- PCIe链路通:用
lspci能看到FPGA设备,用devmem能读写BAR空间 - DMA传输成功:写一个简单的测试程序,从CPU发一段数据到FPGA,再读回来,比对一致
这三步走完,你的开发环境就算正式搭好了。别急,慢慢来。我当年第一次搭PCIe环境,光驱动就折腾了一周——但一旦通了,后面就顺了。
公众号:蓝海资料掘金营,微信deep3321