在 FPGA 里跑 SDR 和 FT8:一个 32 MHz 全频谱无线电的硬核实现

从 0--32 MHz 频谱显示,到 AM/SSB 解调,再到 FT8 数字通信,这一切竟然都在一块 FPGA 上完成。
在软件定义无线电(SDR)的世界里,我们已经习惯了「PC + USB SDR」的组合:RTL-SDR、HackRF、Airspy...... 但如果把 高速采样、频谱分析、数字下变频,甚至 FT8 数字模式 全部塞进 FPGA,会发生什么?
今天的项目,给出了非常漂亮的答案。
项目简介
本项目展示了一个完全基于 FPGA 的软件定义无线电(SDR)系统,其功能覆盖:
-
0--32 MHz 的完整频谱显示
-
AM / SSB(USB / LSB)解调
-
实时 FFT 频谱与瀑布图
-
FT8 数字通信模式(收发)
整个系统运行在一块低成本的 Zynq FPGA SoC 开发板上,不依赖外部 PC,即可完成从射频采样到解调、显示和数字通信的完整流程。
设计目标
本项目的主要目标包括:
-
使用 FPGA 实现完整的 SDR 信号链
-
覆盖 HF(短波)频段 0--32 MHz
-
支持传统模拟调制(AM / SSB)
-
支持现代数字通信模式 FT8
-
构建一个可独立运行的无线电系统
类似项目
KiwiSDR是一个非常好的基于 FPGA 的 0-30 MHz 宽带 SDR 接收器的例子,但它的价格为 450 欧元,并且需要一台 BeagleBone SBC。
Red Pitaya是一个很棒的项目,有很多可能性,而且它是开源的,但是电路板的价格在 600 欧元左右。
Panoradio (https://panoradio-sdr.de/panoradio-sdr/) 的功能远超我们想要构建的系统(100 MHz 频谱,16 位采样),而且它的组件(FPGA 板、A/D 板)也贵得多。
框图

ADC - 模数转换器 - AD9226
该电路板没有参考时钟(参见 AD9226 电路板原理图:https://hackaday.io/project/186329/gallery#d57ce9aa5e91eddf06783c34d0ca2dc4),因此 64MHz 时钟必须由 FPGA 提供。具体方法如下:
-
AD9226 在时钟信号的下降沿输出数据。
-
FPGA 在时钟上升沿进行采样
请看下图,更多详情请参阅 Analog Devices 的 AD9226 数据手册(https://www.analog.com/media/en/technical-documentation/data-sheets/ad9226.pdf)。

目前担心FPGA产生的时钟抖动会不会给接收信号增加噪声?
例如,在这个使用 ZYNQ 7000 的 ADC 转 DMA 转以太网项目中(https://github.com/Hamid-R-Tanhaei/ZYNQ_ADC_DMA_LWIP),采样时钟是在 FPGA 外部生成的。
FPGA
FPGA 中运行的功能如下。
-
它向 AD9226 提供 64MHz 时钟,并从中接收 12 位数据 + 1 位"超出范围"数据。
-
内部信号发生器 0.1 - 30 MHz AM,调制频率为 1KHz,可用于测试目的。
-
一个"捕获模块"一次可以捕获 16384 个样本(采样频率为 64MHz)。这些样本被发送到 FPGA PS,然后从 FPGA PS 发送到 sdr-app(一个运行在 Zynq PS 上的 QT5 C++ 应用程序),显示完整的 32 MHz 无线电频谱和瀑布图。
-
一个具有可选带宽(10 MHz、3 MHz、1 MHz、300KHz、100 KHz、30 KHz、10 KHz)的数字下变频器 (DDC) 将放大无线电频谱并提高分辨率。
-
另一台DDC可以调谐到特定频率,用于解调和解码例如80、40、20、15和10米波段的FT8频率,可选频率为(100KHz、30KHz、15KHz、8KHz、4KHz和2KHz)。
-
它生成 TMDS 信号以驱动 DVI 接口(HDMI 不带音频和控制功能)。
-
它生成I2S信号以驱动外部I2S DAC,从而收听AM广播和SSB业余无线电广播。
-
它可连接PS2鼠标
EBAZ4205 板入门
整个项目颇具挑战性,尤其是对于那些从未接触过 Xilinx Zynq 开发环境(Vivado、Vitis、Petalinux)的人来说。因此,强烈建议先从一个"入门"项目开始。 请参考 Hackaday 项目(https://hackaday.io/project/187351-ebaz4205-development-environment)。
模拟输入
AD9226 12 位 65MSPS 模数转换器板将输入信号衰减 -8.4 dB 的设计并不好。所以决定对其进行改造,以获得更大的放大倍数,并使用更宽的 12 位模数转换器范围。
设计一个这样的电路:

与原电路相比,增益约为 16.5 dB,而原电路的增益为 -8.4 dB:

修改后的电路板:

模拟输入动态范围
在设置的第一级放大倍数下,最大输入信号(在 VINA 和 VINB 之间产生 2 Vpp 的信号)约为 -6 dBm。
以太网
以太网端口连接到本地局域网,获取 IP 地址。
这样,使用外接电脑,可以:
-
使用 SSH 启动一个或多个终端会话。
-
使用 VNC 服务器从帧缓冲区读取数据来查看屏幕(不使用 X11)
-
使用 FileZilla 或类似软件通过 SFTP 查看/复制文件。
图形用户界面
决定将所有功能都集成到 Zynq-7010 中,所以用 QT5 C++ 编写了一个应用程序来查看频谱和调谐电台。它的图形用户界面如下图所示。
在这个例子中,频谱宽度为 100 kHz,调谐到了一个频率为 13.67 MHz 的电台(见图中绿色竖线)。另请注意图中红色的鼠标指针以及右侧的可用设置。

一个 32 MHz 宽的频谱,其中 13.67 MHz 的无线电台被调谐到(与上面相同)。

可以接收到一些广播电台和业余无线电台的信号
通过捕获采样输入脉冲串来显示频谱的方案显然不能用于接收无线电电台,因为:
-
它在短时间内(256us)接收一些样本(16384个),频率约为100-200HZ,具体频率取决于构建和显示频谱所需的时间(5-10ms)。而要收听广播电台,则需要连续的信号流。
-
这样一来,处理系统(即 Zynq-7010 CPU)就可以承担繁重的工作,而功能强大的 Zynq-7010 可编程逻辑芯片则无法得到充分利用。
因此,设计了:
-
数字下变频器 (DDC)
-
低通 CIC-FIR 滤波器和抽取器
-
AM/SSB/LSB解调器
-
I2S接口
从 Zynq-7000 输出后,以 48Ksamples/s的采样率听一些音频。
32 MHz 低通滤波器
(待办事项)
需要衰减进入频谱的强调频广播信号(88-108MHz),这些信号来自第三和第四奈奎斯特区,以及第二奈奎斯特区的一些商业中继器。(《奈奎斯特准则与采样数据系统设计》:https://www.analog.com/media/en/training-seminars/tutorials/MT-002.pdf)。
根据 crun 的建议,应该滤除 FM 广播频段(88-108 MHz)和 AM 频段(最高 1.6 MHz)。为了滤除 FM 广播信号,打算使用像这样的 9 阶椭圆滤波器。


但当时什么也没做,因为:
-
在此之前,我想接收并解调一些短波信号,以了解干扰程度;
-
打算使用 ADC 的"超出范围"位来诊断是否有强信号干扰我的接收,导致 ADC 超出 12 位范围。
DDC(数字下变频器)
它像往常一样由一个本振和一个复乘法器组成。

请注意,本地振荡器、其 AXI 控制和复数乘法器都使用 64 MHz 时钟 (CLK)。
本振

-
它输出一个32位复数(16位正弦+16位余弦)信号。
-
它的频率是通过一个普通的 ctrl AXi 界面设置的。
复数乘数

-
32 位复数(16 位正弦 + 16 位余弦)信号被分成两个 16 位信号。
-
12 位乘以 16 位(28 位)的运算结果被截断为前 16 个最高有效位。

测试信号发生器
为了在没有外部信号且不使用ADC的情况下测试电路逻辑和整个设计,很快意识到需要一个内部测试信号。使用Xilinx DDS编译器IP设计了以下模块:

它产生一个以 1 kHz 音调调制的载波 AM 信号。载波频率可以设置为 0 到 32 MHz(必要时还可以更高)。
CIC-FIR
我找到了两篇解释得非常清楚的文章:
- 级联积分梳状(CIC)滤波器入门指南
- 英特尔 - Altera:了解 CICO 补偿滤波器
关于 CIC-FIR
标准配置是设计一个或两个可编程的连续 CIC 滤波器/抽取器,然后接一个固定的 FIR 滤波器。
关于CIC
-
阶段数是固定的(N=8)
-
R 抽取率可以设置 CIC+FIR 滤波器的整体带宽。
-
在本设计中,R=4...8192 的带宽范围为 2MHz 至 1KHz(见下表)。

关于FIR
-
非常陡峭的过渡带宽(例如,2MHz 处为 -3dB,2.42MHz 处为 -120dB)
-
极高的阻带衰减(-120dB)
-
CIC滤波器轻微下降的补偿
它是使用 110 个系数的 FIR 滤波器获得的,该滤波器由 matlab 计算得出:
- CIC-FIR 设计(matlab .mlx 格式)
https://github.com/guido57/EBAZ4205_SDR/blob/main/matlab/myAN455quater.mlx
- CIC-FIR 设计(.pdf 格式)
https://github.com/guido57/EBAZ4205_SDR/blob/main/matlab/myAN455quater.pdf
它进一步将复杂度减半(仅使用一半的 DSP48),从而进一步降低一半。详情请参阅 《级联积分梳状 (CIC) 滤波器入门指南:https://www.dsprelated.com/showarticle/1337.php》。
在测试 CIC-FIR 双通道解决方案时,遇到了一个问题,并已将该问题提交给Xilinx/AMD 支持部门(https://support.xilinx.com/s/question/0D54U00007D2CXOSA3/dual-channel-cic-fir-problem?language=en_US)。
AM解调器
基本上是照搬了 K6JCA 的设计 ------一款基于 FPGA 的 SDR 高频收发器。
https://k6jca.blogspot.com/2017/03/an-fpga-sdr-hf-transceiver-part-2-fpga.html
AM解调器

这是一个经典的包络检波器,执行 sqrt ( I^2 + Q^2 )。
下图黄色部分为进入此 AM 解调器的测试信号(仅 I 分量),蓝色部分为解调后的 AM 信号。
无直流和信号电平表

为了从 AM 解调信号中去除直流分量,简单地使用了一个一阶 IIR 高通滤波器,该滤波器还可以使 AM 解调信号通过低通滤波后得到载波电平。
下图红色部分为经高通 IIR 滤波器滤除直流分量后的 AM 解调信号,绿色部分为载波电平。

这是在 Simulink 中使用的完整测试平台。

除了调幅解调器和高/低通滤波器之外,请注意使用的测试信号(最左侧的模块)。该测试信号旨在产生一个持续1s的调幅调制信号,随后是1s的无信号信号,以测试信号电平表的瞬态响应。
这是它的框图

其输出(仅 I 分量)以黄色显示。

绿色部分显示的是信号电平表的响应。
AGC
它作用于 AM/SSB 解调之后。
这是一种称为"前向"的自动增益控制,即它在不影响前级的情况下调整输出电平,而是直接放大/衰减信号本身。

使用 Simulink 进行仿真,并转换为 VHDL。
I2S 测试
为了测试 IP(I2S_Transmitter)和 I2S DAC(PCM5102),构建了这个 Vivado 模块:

一些事实:
-
dds_compiler 生成一个 16 位二进制补码正弦波和一个 16 位余弦波,采样频率为 1 KHz(采样频率为 100MHz,作为 AXI 流时钟 s00_axis_aclk)。
-
I2S_Transmitter IP 来自 http://www.harald-rosenfeldt.de/2017/12/30/zynq-create-an-i2s-transmitter-to-send-audio-signals/
-
SCLK、LRCLK 和 I2SDATA 是标准的 I2S 线。
-
mclk=10MHz,因此:
SCLK = 1.536MHz(参见 I2S_Transmitter.v)
音频采样率(LRCLK)为 1.536MHz/32 (16+16 位) = 48.000 Hz
这是I2S数据协议:

BCLK 即 SCLK,SDATA 即 I2SDATA,频率 fs = 48.000 Hz
DAC(PCM5102)和D类音频放大器(PAM8403)原理图。

请注意:
-
线性稳压器 5 转 3.3V(PCM5102 不能承受 5V)
-
虽然不需要立体声输出,但这两个声道可以用于不同的用途:
-
一个通道用于LSB音频,另一个通道用于FT8音频。
-
一个通道用于I数据,另一个通道用于Q数据(解调前)。
最后,这些是左侧和右侧的输出。

Zoom FFT接收器
从 Panoradio ( https://panoradio-sdr.de/panoradio-sdr/ )那里借鉴了这个想法。
事实上,如果需要查看调制信号的频谱细节,则需要放大频谱并采集其子频带。
例如,对 0-32MHz 频谱进行 8192 个时间采样,即可查看"定义"(频率区间跨度)为 32M/8192 = 3906.25 Hz 的频谱,这意味着可以在单个区间中看到完整的 FT8 7,074 MHz 频段。
因此,构建了一个独立的接收器(DDC + 中频滤波器 + AXI 频谱捕获器),以获取所需子频段的射频频谱及其定义。请参阅本文开头框图中的频谱 DDC(缩放 FFT)。
SSB解调器
显而易见的选择是构建一个韦弗解调器,这里有非常详细的描述: 韦弗 SSB 调制/解调 - Derek Rowell 的教程(https://forum.pjrc.com/attachment.php?attachmentid=9746\&d=1487439697)。
还应该阅读唐纳德·韦弗 (Donald Weaver) 的原文 《单边带信号生成与检测的第三种方法》,载于 IRE 会议论文集,1956 年 12 月。
这是本次设计。

集成
把所有电路板都放进了一个从旧调制解调器上拆下来的塑料盒里。


FT8 通联
现在整个项目作为接收机运行良好,包括FT8解码,是时候开始发送数据了。
MYJTDX 软件(由 JTDX 衍生而来,JTDX 又由 WSJT-X 衍生而来)解码效果良好,可以进行发射和管理 QSO。
-
调制 8FSK
-
调制其幅度以生成 FT8 的斜坡(升余弦初始幅度增加和最终幅度减少)。

Zynq-7010 - AD9851 接线

注意,RC 低通滤波器(R1-C1)用于从 2 MHz PWM 波形中滤除直流分量。如果衰减 2 MHz 信号不够,会将其更换为 LC 多极点低通滤波器。
代码
https://github.com/guido57/EBAZ4205_SDR_spectrum/blob/main/Vivado/Vivado.srcs/sources_1/new/ad9851gfsk.vhd
https://hackaday.io/project/186329-32mhz-spectrum-sdr-ft8-in-an-fpga/details
https://github.com/guido57/EBAZ4205_SDR_spectrum/tree/main
总结
从 0--32 MHz 的宽带频谱显示,到传统模拟解调,再到现代 FT8 数字通信,这个项目完整展示了 FPGA 在无线电领域的真实应用能力。
对于希望深入理解 SDR + FPGA + SoC 协同设计 的工程师来说,这是一个极具参考价值的实例。
