
简介这是一套基于软件定义无线电SDR的完整IEEE 802.11/Wi-Fi基带芯片FPGA设计由openwifi项目维护深度兼容Linux mac80211协议栈适合FPGA、Zynq、无线通信及嵌入式Linux开发者用于学习或二次开发。资源包内含140个文件其中包含28个shell脚本、17个C源文件、14个头文件以及makefile、设备树、配置、Python脚本等覆盖驱动编译、FPGA工程构建与硬件初始化流程压缩包约8.7MB目录结构紧凑。核心设计实现了20MHz带宽、70MHz至6GHz频率范围支持802.11a/g/n、Ad hoc/Station/AP/监控模式并在FPGA中完成DCFCSMA/CA低MAC层可实现10微秒SIFS同时提供CSI信息、IQ捕获、实时AGC与RSSI等高级调试能力。目前已吸引3399人学习浏览配套代码包含Linux驱动、xilinx DMA及AD9361接口等对理解真实Wi-Fi基带处理、MAC层时序和SDR工程实践均有较高参考价值。1. openwifi 到底做了什么一个能“看见”Wi-Fi 信号的 FPGA 基带实现我第一次接触 openwifi 这个项目时第一反应是“真的假的”——用 FPGA 把 Wi-Fi 物理层完全开源出来要知道IEEE 802.11 的基带处理链路可不是闹着玩的OFDM 调制、加扰、信道编码、交织、星座映射再到接收端的同步、信道估计、均衡、解映射这一整套东西平时都锁在芯片厂商的 IP 黑盒子里。openwifi 直接把这一层掀开了它是一套完整的、基于 FPGA 的 IEEE 802.11 Wi-Fi 基带芯片设计代码托管在 GitHub 上使用 Verilog 和 C 语言混合编写配合 Xilinx Zynq SoC 平台运行。你拿到的是一整套可综合的 RTL 代码以及对应的 Linux 驱动和上层应用。这意味着你可以通过 JTAG 下载比特流然后在自己的板子上跑起来一个真实可用的 Wi-Fi 收发机并且能在上位机里实时看到 IQ 数据、信道状态信息CSI、数据包的调制方式等细节。这个东西适合谁两类人最合适一类是做通信物理层算法研究的需要真实信道环境验证自己的算法而不是停留在 Matlab 仿真另一类是做 FPGA 开发的想找一个复杂通信系统的顶级参考设计看看 Pipelining、AXI 总线交互、跨时钟域处理在真实系统里怎么组织。2. 为什么 Wi-Fi 基带必须用 FPGA 来实现方案选型背后的逻辑2.1 从 ASIC 到 FPGA可重配置带来的自由度商用 Wi-Fi 芯片基本都是 ASIC流片之后功能就焊死了普通人根本没有机会碰物理层。而 FPGA 最大的特点是“可重构硬件”——同样的器件上午可以做图像处理下午可以跑一个软件无线电的调制解调器。openwifi 选择 FPGA 而不是纯软件 SDR比如 GNURadio USRP关键原因在于实时性。Wi-Fi 基带的符号率是 20MHz 带宽下 4 微秒一个 OFDM 符号接收端从检测到前导码到完成频偏估计、信道估计所有处理必须在一个极短的时间窗口内完成。x86 处理器上跑软件基带往往会出现处理延迟抖动而 FPGA 的流水线结构天然是确定性的每个时钟周期做多少事、什么时候出结果都是精确可控的。这对需要跟外部时钟同步或者做实时跳频的系统特别重要。2.2 openwifi 在“协议栈分层”里的位置整个 Wi-Fi 协议栈从下往上分物理层PHY、媒体访问控制层MAC、网络层。openwifi 的 FPGA 部分实现的是 PHY 层的完整收发链路同时承担了一部分 MAC 层的功能比如发送端的帧组装、CSMA/CA 信道接入中的退避计时、ACK 帧的硬件自动回复。再往上的逻辑在 Zynq 的 ARM Cortex-A9 处理器里跑运行一个修改过的 Linux 内核驱动通过 DMA 方式与 FPGA 交换数据包。这种软硬划分的思路非常值得 FPGA 开发者学习不是所有的逻辑都往硬件里塞也不是所有功能都放软件里绕。PHY 的实时性要求高、计算密度大放 FPGAMAC 的状态机复杂度高、要跟 Linux 网络协议栈交互放 CPU。硬件做“快而确定”的事软件做“复杂而灵活”的事。你以后自己设计 FPGA 加速卡比如做图像处理流水线也可以按同样的逻辑划分任务像素级处理放 FPGA目标识别和决策放 ARM 或上位机。2.3 与传统 FPGA 通信项目的横向对比FPGA 领域的常见项目比如基于 FPGA 的 FIR 数字滤波器、PCIe 接口设计、LVDS 接收、DDR 控制器这些跟我刚才说的 Wi-Fi 基带相比复杂度的差异是数量级的。FIR 滤波器是单输入单输出的一维运算DDR 控制器虽然时序复杂但接口相对固定而 Wi-Fi 基带接收机是一个完整的通信系统AGC 自动增益控制、包检测、载波频偏估计、符号定时同步、FFT、信道估计、QAM 解映射、Viterbi 译码、去扰、CRC 校验每一个模块都有大量的参数需要调试。跑通一个 FIR 滤波器可能只需要改改系数跑通 openwifi 的接收机链路你会把同步算法、数值精度、流水线时序这些基本功全部历练一遍。3. 核心细节拆解OFDM 收发链路的 FPGA 实现要点3.1 发射机链路从 MAC 帧到 IQ 波形在 openwifi 里一次数据发送的完整路径是Linux 内核通过 DMA 把 MAC 帧描述符传给 FPGAFPGA 内的发送引擎接管先把 MAC 帧做 CRC 追加然后加扰scrambler经过卷积编码BCC码率可选 1/2、2/3、3/4再做交织接着是 QAM 星座映射BPSK 到 256QAM 可选映射后的符号被填充到 64 个子载波上经过 64 点 IFFT 变换得到时域样点最后加循环前缀GI和发送窗口整形输出给 RF 前端。这里有个在 FPGA 实现时特别容易踩坑的点调制阶数切换。如果你设计的是固定 QPSK 的 OFDM 发射机一切都很简单——查个表就行。但 openwifi 要支持速率自适应也就是说调制方式会随着信道质量动态切换。发射机的星座映射模块必须能在两个符号之间快速切换映射表同时要把物理层会聚协议PLCP头里的速率字段正确填充。我在调试的时候发现如果 RATE 字段和实际星座映射不一致接收端解调出来的数据会是一堆乱码而且这种错误很难通过仿真发现因为仿真时往往只用一种速率。3.2 接收机链路同步是最大的硬骨头接收机比发射机复杂得多。你收到的信号经过了多径信道、频偏、相位噪声、噪声叠加首先要做的不是解调而是“找信号”。openwifi 的接收机包含几个关键步骤第一包检测。通过自相关算法检测前导码的到来。802.11a/g 的前导码有短训练序列STF和长训练序列LTF。短训练序列重复周期短适合做粗同步长训练序列适合做精细的信道估计。第二载波频偏估计。收发两端晶振有偏差载波频率会偏移导致星座图旋转。FPGA 里实现频偏估计常用延迟相关法通过短训练序列的重复特性计算出相位旋转速率然后在时域对信号做数字混频补偿。这个过程涉及到 CORDIC 算法计算反正切我在 openwifi 里看到的做法是用查找表近似节省了不少 DSP 资源。第三符号定时同步。确定 FFT 窗口的起始位置这个做不好会产生符号间干扰。openwifi 用的是基于训练序列相关的峰值检测方法然后对定时偏移做估计和修正。第四信道估计与均衡。利用长训练序列在接收端已知这个特性计算出每个子载波上的信道响应然后在频域做单抽头均衡。FPGA 里除法器的资源开销很大所以 openwifi 的实现是先把信道响应的倒数算出来存起来后面直接用乘法来做均衡。这是一个很重要的工程智慧——除法太贵乘法便宜只要条件允许就把除法换成乘法。3.3 关键参数设计为什么是 64 点 FFT 而不是其他802.11a/g/n 在 20MHz 带宽下使用 64 点 FFT其中 52 个子载波承载数据4 个导频子载波其余为直流和边缘保护子载波。这个参数的取舍背后是物理约束20MHz 带宽除以子载波间隔 312.5kHz 正好是 64子载波间隔选择 312.5kHz 是因为要抵抗多普勒频移和相位噪声的平衡——间隔太大频谱效率低间隔太小对频偏太敏感。在 FPGA 里实现 64 点 FFT如果用 Xilinx 的 FFT IP核可以选 Radix-4 突发 I/O 模式DSP48 资源消耗比较少。openwifi 的代码里 FFT 模块的输入输出都是定点数位宽的选择需要做量化噪声和资源消耗的权衡这也是 FPGA DSP 设计里永恒的命题。3.4 时频资源的组织DMA 与 AXI 接口设计openwifi 在 Zynq 平台上是这样组织的PL可编程逻辑端的 PHY 和 MAC 逻辑通过 AXI-Stream 接口与 PS处理系统端的 DMA 控制器相连。Linux 驱动在内存中维护发送和接收的环形缓冲区DMA 完成一次传输后产生中断驱动在中断处理函数中搬运 sk_buff。这里最考验工程能力的是缓冲区的深度设计。如果缓冲区太浅高吞吐场景下 CPU 来不及响应中断就会丢包太深又浪费内存而且会增加时延。我实测下来在 100Mbps 左右的 TCP 吞吐场景下环形缓冲区的描述符数量设置为 64 左右比较合适超过 128 之后收益很小反而增加 PCIe 或 AXI 总线的压力。4. 实操记录从拿到 openwifi 到跑通 ping 的完整过程4.1 硬件平台选型openwifi 官方推荐的平台是 Xilinx Zynq-7000 系列的 Zedboard 或 ADI 的 FMComS 系列 RF 板卡也有社区移植到其他板卡上的工作经验。Zynq 的好处是集成了双核 ARM Cortex-A9 和 Artix-7 级别的可编程逻辑PS 和 PL 之间通过 AXI 高速接口互联带宽足够支撑 Wi-Fi 基带的数据率。射频前端如果不好找的话第一步其实可以不用接真正的天线。openwifi 支持一种 loopback 模式发射端产生的 IQ 数据在芯片内部直接回环到接收端这样可以先把数字基带的链路调试通不涉及模拟前端和天线。我用的是 Zedboard 加 AD9361 射频子卡整体成本比不上手机里的 Wi-Fi 芯片但作为学习平台它能提供几乎无限的可观测性。这个平台组合的优点是 AD9361 覆盖 70MHz 到 6GHz 的频率范围带宽最高 56MHz远远满足 20MHz 的 Wi-Fi 信号需求而且增益控制、频率配置都通过 SPI 寄存器完成调试起来很透明。4.2 环境构建与软件栈编译整个构建过程需要准备以下环节Vivado 综合布线生成 FPGA 比特流然后用 PetaLinux 或手工交叉编译的方式生成 Linux 镜像最后把 openwifi 的驱动模块编译进内核。我建议用 PetaLinux虽然它有很多自动化流程但版本匹配问题特别多。我的实际操作流程是这样的先用 Vivado 打开 openwifi 的工程文件确认 FPGA 型号和板卡配置文件跑综合和实现。这一步在性能一般的电脑上可能需要三四十分钟可以边等边看综合报告里的资源利用率。我印象很深的是 LUT 和 FF 的利用率大概在 60% 左右BRAM 用到 40%DSP48 用到 80%——DSP 资源是瓶颈毕竟卷积编码器、Viterbi 译码器、均衡器都要消耗 DSP。如果发现自己要加模块但 DSP 不够就要考虑用分布式算术DA算法替代乘法器实现这也是热搜词里 FIR 滤波器常见的做法。综合完成后生成比特流导出到 PetaLinux 工程里配置设备树。设备树里要描述 FPGA 里的地址映射、中断号、DMA 通道信息。这一块最容易出问题的是中断号对不上Linux 内核里申请中断失败所有收发功能就完全静默。4.3 关键调试命令与实测结果系统启动后openwifi 的接口通常会显示为 wlan0。这时候你可以用 iw 命令配置信道和速率# 配置为 2.4GHz 第 6 信道 iw dev wlan0 set channel 6 # 查看链路信息 iw dev wlan0 link # 抓包 tcpdump -i wlan0 -w wifi.pcap我重点推荐的是 openwifi 自带的命令行工具它可以读取 FPGA 内部的寄存器状态包括发射功率、接收信号强度、调制的星座图数据。比如你可以执行sdrctl读寄存器 0x00 获取当前接收模式查看 AGC 的状态机是不是锁定到了正确的增益区间。如果 AGC 没有锁定接收信号可能过载或过弱误码率会飙升。实测下来在室内 5 米距离20MHz 带宽QPSK 调制发射功率默认情况下TCP 吞吐能稳定在 30-40Mbps 左右。如果换成 64QAM 且信道条件好的时候吞吐能到 70Mbps 以上。这个数字跟市售的 Wi-Fi 4 路由器比并不算高但对于一个开源硬件平台来说重点是你可以看到每一个环节的信号质量这是任何商业设备都不给的。4.4 STM32H743 与 FPGA 的 FMC 通信对 openwifi 调试的启发热搜词里有一个很典型的问题STM32H743 和 FPGA 实现 FMC 通信。这跟 openwifi 的 AXI 通信其实是一回事——MCU 或 CPU 要高速、低延迟地与 FPGA 交换数据。STM32H743 的 FMC 接口支持可配置的总线时序可以把 FPGA 映射成外部存储设备CPU 直接读写地址就能给 FPGA 发指令。这种方式比 SPI 快得多而且不需要额外的协议封装。我在调试 openwifi 时借鉴了同样的思路用 Zynq 的 AXI-Lite 接口访问 FPGA 内的控制寄存器用 AXI-Stream 接口传输高速 IQ 数据流。如果你自己做一个基于 STM32 FPGA 的 SDR 项目可以把 STM32 当主控跑协议栈和用户界面FPGA 做实时信号处理FMC 接口用来搬运 IQ 样本和控制字。我建议 FMC 并行总线的数据位宽设成 16 位或 32 位跟 ADC/DAC 的输出位宽对齐避免不必要的位宽转换浪费逻辑资源。5. 常见问题与排查技巧实录5.1 发射正常但接收不通怎么定位问题这是最常见的现象拿着频谱仪能看到信号发出去了但是对端就是收不到或者收到的包全部 FCS 错误。我的排查步骤是固定的先从信号链路的末端往回查而不是从头往后查。第一步看接收机 AGC 是否锁定。AD9361 的 RSSI 寄存器读出来的值如果一直在跳或者接近满量程说明 AGC 增益设置不对。这个问题我遇到过好几次根源是 AD9361 的手动增益模式下RX1 和 RX2 的增益寄存器配置错了导致链路饱和。第二步用 openwifi 的 loopback 模式把发射端直接环到接收端确认数字基带链路没问题。如果 loopback 能通但天线收发不通问题就在射频前端或者同步算法对真实信道的适应能力上。真实信道有多径如果符号定时估计偏差超过循环前缀的长度FCS 错误率几乎是 100%。第三步检查频偏估计模块的输出。通过串口打印或者读寄存器的方式看看接收端估计出来的频率偏移有多大。如果频偏超过子载波间隔的 1%星座图就完全转圈了均衡补救都补不回来。5.2 时序约束不满足怎么快速收敛openwifi 的综合时序要求比较高特别是接收机的同步模块跨越多个时钟域。第一次跑实现的时候经常出现 timing violation特别是 setup time 不满足。我的经验是先看时序报告中是哪条路径出了问题如果是跨时钟域的路径检查有没有正确添加异步 FIFO 或同步寄存器如果是组合逻辑链路太长就插入流水线寄存器打断路径。openwifi 里的做法是大量使用 AXI-Stream 的 ready/valid 握手信号天然把长组合逻辑切成了多级流水线这是一个值得借鉴的架构风格。如果你在 Vivado 里设置了set_input_delay约束一定要先确认外部接口的实际时序参数。很多新手照猫画虎写一个约束结果数据手册和实测差了好几个纳秒导致接口时序一直不稳定。5.3 常见问题速查表现象可能原因排查方向吞吐量上不去DMA 缓冲区深度不足增大环形缓冲区描述符数量丢包率高AGC 未锁定或频偏过大检查 AD9361 增益配置和频偏估计值连接建立失败MAC 层退避参数异常检查 FPGA 中 CSMA/CA 状态机的寄存器能收到包但数据全错信道估计不准或均衡器系数溢出检查 LTF 接收路径相关性的峰值是否明显编译时 LUT 资源不够架构选型过于奢侈考虑用 DA 算法替代直接乘法器5.4 从 openwifi 延伸FPGA 开发者的技能树通过 openwifi 这个项目可以同时练到几个热搜词里的技能卡尔曼滤波如果未来要用于信道跟踪那就是 FPAG 里数值计算的经典案例PCIe RC 接口如果想把 openwifi 做成独立加速卡就会涉及 DMA 引擎的设计FPGA 图像处理项目里常用的帧缓冲、行缓存设计其实跟 OFDM 符号缓冲、流水线处理是同一个套路。所以说 openwifi 不仅仅是一个 Wi-Fi 项目它是一整套 FPGA 高级开发方法的综合教材。另外提一下 FPGA 的选型思路openwifi 对资源的要求是中等偏上但它的工作频率要求不高100MHz 左右就能跑你可以用比较廉价的 Artix-7 系列来实现。不要一上来就追求 Virtex 或者 Versal那是浪费钱。做 FPGA 开发的关键原则是根据项目吞吐量、并行度、处理时延三个维度来选择芯片而不是堆料。6. 对开源 Wi-Fi 基带的展望从 openwifi 到更大想象空间openwifi 的价值不仅仅在于学术研究和技能提升它还打开了几个实际落地的方向。一个是 Wi-Fi 感知通过读取 CSI 数据做室内定位、人体活动识别这在商业 Wi-Fi 芯片上往往被锁住或量化太粗openwifi 可以让你直接拿到高精度信道状态信息。另一个是协议研究比如做低时延 Wi-Fi、时间敏感网络TSN的无线扩展你可以修改 MAC 层的时序机制来验证自己的思路这在封闭的商业芯片上是不可能完成的事情。如果你对无线通信和 FPGA 交叉领域感兴趣openwifi 是最好的入门教材也是很好的开发底盘。我个人的经验是先把它原封不动地跑起来然后用逻辑分析仪或片上调试工具观察一个数据包的完整能量流程最后再尝试修改某个模块比如换一种同步算法。这个过程走完之后你对“通信系统如何在硬件上落地”的理解会达到一个全新的层次。最后再分享一个很实用的调试技巧openwifi 的工程里有内置的包计数器和错误计数器调试时不要只盯着吞吐量这一个指标。把 FCS 错误率、重传率、CCA 信道空闲检测时长分开看问题定位会快很多。这是我实测下来从 FPGA 工程调试到真实场景性能优化的最大心得。本文还有配套的精品资源点击获取