当前位置:首页 > 通信技术 > 通信技术
[导读]AD9361 是 ADI 的 2×2 RF Agile Transceiver,覆盖 70 MHz–6 GHz,单通道带宽最高 56 MHz,配 Zynq(ZedBoard + FMCOMMS3 或 ZCU102 + FMCOMMS5)是 SDR 原型验证的主流组合。Vivado 侧负责 PL 逻辑(AXI_AD9361 + DMA + FIFO),PS 侧跑 Linux(ADI 的 Kuiper Linux)或 No-OS 裸库配寄存器,数据从 AD9361 → DMA → DDR,再给用户态做 FFT/解调。下面以 ZedBoard + FMCOMMS3(2.4 GHz ISM 接收,20 MHz 带宽)为主线。

AD9361 是 ADI 的 2×2 RF Agile Transceiver,覆盖 70 MHz–6 GHz,单通道带宽最高 56 MHz,配 Zynq(ZedBoard + FMCOMMS3 或 ZCU102 + FMCOMMS5)是 SDR 原型验证的主流组合。Vivado 侧负责 PL 逻辑(AXI_AD9361 + DMA + FIFO),PS 侧跑 Linux(ADI 的 Kuiper Linux)或 No-OS 裸库配寄存器,数据从 AD9361 → DMA → DDR,再给用户态做 FFT/解调。下面以 ZedBoard + FMCOMMS3(2.4 GHz ISM 接收,20 MHz 带宽)为主线。

一、Vivado 工程:ADI 参考设计别自己撸

ADI 开源了 analogdevicesinc/hdl 仓库,FMCOMMS3 对应 projects/fmcomms2/zed,直接用 Tcl 生成:

# 在 hdl/projects/fmcomms2/zed/ 下

source ../../scripts/adi_make.tcl

adi_make fmcomms2_zed

生成后的关键 IP:

• axi_ad9361:AD9361 的 LVDS/CMOS 接口解串 + IQ 重组,输出 16-bit I/Q(I 低 16 + Q 高 16,拼 32-bit AXI-Stream)

• axi_dmac:ADI 的 DMA 控制器,把 AXI-Stream 搬去 DDR,支持 cyclic(循环播放)和 oneshot

• util_ad9361_divclk:AD9361 输出的 DATA_CLK 进 PL,做分频/对齐

⚠ AD9361 默认 LVDS 接口(DDR 双沿 2×12 bit),Vivado 里 I/O 规划要设 LVCMOS25_LVDS_25(Bank 13/14 接 2.5 V),且 DATA_CLK、FB_CLK 要走 P→N 对,组内 skew < 50 ps。

二、PS 驱动配置:No-OS 结构体最直观

量产调试或裸跑用 No-OS(analogdevicesinc/no-OS),关键结构体 ad9361_init_param:

struct ad9361_init_param default_ad9361_params = {

   .rx_lo_freq_hz = 2400000000ULL,    // 2.4 GHz

   .tx_lo_freq_hz = 2400000000ULL,

   .rx_bw_hz = 20000000,             // 20 MHz 接收带宽

   .tx_bw_hz = 20000000,

   .rx_sampl_freq_hz = 30720000,     // 30.72 MSps(LTE 1.4M 整数倍)

   .tx_sampl_freq_hz = 30720000,

   .gain_ctrl_rx1 = RF_GAIN_MGC,      // 手动增益,方便测 EVM

   .gain_rx1 = 45,                   // 45 dB

   .rf_port_rx = "A_BALANCED",       // RX1A 平衡口

};

int main() {

   struct ad9361_rf_phy *phy;

   ad9361_init(&phy, &default_ad9361_params);

   // 之后可以调 agc/校准

   return 0;

}

Linux 侧更简单,设备树 adi,ad9361 节点把上面参数填进去,开机 ifconfig 能看到 cf-ad9361 字符设备,用户态用 libiio 拿 IQ。

几个易错参数:

• rx_sampl_freq 必须是 bbpll_div / (2×HB_dec×FIR_dec),HB 是半带滤波器,FIR 是 AD9361 内可编程 FIR——30.72 M 是常见甜点(bbpll=983.04 M,÷32 再 HB3×HB2×HB1 三级半带 + FIR ÷2 → 30.72 M)

• 增益模式:AGC(快/慢)适合实网,MGC 适合实验室测 EVM;2.4 G + 20 MHz 下 AGC 能压到 NF≈2.5 dB

三、数据抓取:ILA + DMA 双轨

1. ILA 抓实时 IQ(调试用)

在 Vivado Block Design 里 axi_ad9361 的 adc_data_* 后插 ila_v6(深度 4096,抓 30.72 M 下 4096 点 ≈ 133 µs),触发条件设 adc_valid=1:

# HW Manager 里触发

set_property CONTROL.TRIGGER_CONDITION CHIPSCOPE_ILA_0 {BASIC=AND}

set_property CONTROL.DATA_DEPTH 4096 CHIPSCOPE_ILA_0

run_hw_ila [get_hw_ilas]

导出 CSV 后 Python 画频谱:

import numpy as np, matplotlib.pyplot as plt

iq = np.fromfile('ila_adc_iq.csv', sep=',')

I, Q = iq[::2], iq[1::2]

sig = (I + 1j*Q).astype(np.complex64)

fft = np.fft.fftshift(np.fft.fft(sig * np.hanning(len(sig))))

plt.plot(20*np.log10(np.abs(fft)))

plt.title("AD9361 RX Spectrum @2.4G, 30.72Msps")

2. DMA 搬 DDR(长期采集)

axi_dmac 配成 S2MM(Stream→Memory),每次搬 8192 样点(I+Q 拼 32-bit,8192×4=32 KB 一帧),PS 侧用 libiio 的 iio_buffer_refill() 循环读:

// libiio 简易采集

struct iio_context *ctx = iio_create_local_context();

struct iio_device *dev = iio_context_find_device(ctx, "cf-ad9361-lpc");

struct iio_channel *ch = iio_device_get_channel(dev, 0);

iio_channel_enable(ch);

struct iio_buffer *buf = iio_device_create_buffer(dev, 8192, false);

while (1) {

   iio_buffer_refill(buf);

   int16_t *ptr = (int16_t*)iio_buffer_start(buf);

   // ptr[2i]=I, ptr[2i+1]=Q

}

30.72 Msps × 4 字节 = 122.88 MB/s,ZedBoard 的 DDR3-533 能扛,ZCU102 跑 61.44 Msps(56 MHz BW)也稳。

四、三个翻车高发点

• DATA_CLK 和 BBPLL 没对齐:AD9361 的 rx_sampl_freq 改了,BBPLL 重锁,DATA_CLK 频率变,PL 侧 util_ad9361_divclk 的分频比要同步改,否则 ILA 抓到的 IQ 会"每几帧丢一段"——表现为频谱周期性毛刺。改采样率后必重跑 ad9361_set_rx_sampling_freq() 让驱动把 BBPLL + 接口时钟一起刷

• LVDS 模式 vs CMOS 模式搞混:FMCOMMS3 默认 LVDS,有些自制板走 CMOS(SDR 模式),Vivado 里 axi_ad9361 的 CMOS_LVDS_N=1(LVDS)还是 =0(CMOS)要跟硬件一致,错了 IQ 全 0 或乱码

• DMA 深度没对齐 AD9361 burst:AD9361 的 AXI-Stream 是 valid-not-ready 发,DMA 的 CYCLIC 和 ONE_SHOT 切换时机不对,会丢头尾 16 样点——第一次 refill 前先 iio_buffer_first() 扔掉前 16 样点,再进主循环

想抓 56 MHz 满带宽(61.44 Msps),ZedBoard 的 HP 口带宽不够(AXI 32-bit @150 MHz = 600 MB/s,61.44 M×4=245 MB/s 理论够但实际有瓶颈),建议换 ZCU102(HP 64-bit @333 MHz → 2.6 GB/s 稳跑)。

AD9361 + Zynq SDR 的真谛:Vivado 直接套 ADI fmcomms2 HDL 别自撸、No-OS/libiio 配 LO/采样率/带宽、ILA 抓 133 µs 看时域 IQ、DMA 搬 DDR 跑 libiio 长采;采样率改完记得同步 BBPLL 和 PL 分频,LVDS/CMOS 别焊错。这套走完 2.4 G/20 MHz 下 EVM < 2%,56 MHz 满带宽换 ZCU102 能扛,SDR 原型验证一周能出解调 demo。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

在大型FPGA项目中,靠鼠标点选"Generate Bitstream"既低效又不可复现。Tcl(Tool Command Language)是Vivado的原生脚本语言,一条命令即可完成工程创建、IP配置、综合与比特流...

关键字: Tcl脚本 Vivado

在Xilinx FPGA开发中,Vivado HLS(High-Level Synthesis) 是把C/C++/SystemC算法“翻译”成RTL(Verilog/VHDL)并封装为可重用IP核的利器。相比手写RTL,...

关键字: Vivado FPGA Xilinx

在FPGA设计中引入多个时钟(系统时钟、PLL输出、用户自定义时钟)后,SDC(Synopsys Design Constraints)书写错误是导致时序分析失真或违例误判的头号原因。本文归纳Vivado下多时钟约束最常...

关键字: Vivado 多时钟约束

在Xilinx FPGA设计中引入XDMA、Video DMA、AXI Interconnect等IP核后,IP输出与用户逻辑常处于不同频率或相位——这就是典型的时钟域交叉(Clock Domain Crossing,...

关键字: Vivado 时钟域交叉 CDC

在Xilinx FPGA开发中,综合与布局布线通过并不代表设计能正常工作。静态时序分析(STA)才是判定设计能否在目标频率下稳定运行的最终依据。本文以Vivado为例,带你走完从基础时钟约束、I/O约束到Setup/Ho...

关键字: Vivado 时序约束

在FPGA设计中,时序收敛是决定设计能否稳定上板的关键。Vivado工具通过WNS(Worst Negative Slack,最差负时序裕量)和TNS(Total Negative Slack,总负时序裕量)这两个核心指...

关键字: Vivado 时序约束

在复杂的FPGA系统设计中,算法验证与硬件实现之间往往存在巨大的鸿沟。本文将深入探讨如何利用Tcl脚本构建自动化桥梁,实现Matlab/Simulink算法仿真与Vivado硬件验证的无缝衔接。

关键字: EDA Tcl脚本 Vivado

在200MHz以上时钟频率的FPGA设计中,时序收敛已成为决定项目成败的关键。某5G前传单元项目曾因时序违例导致六轮迭代失败,最终通过系统化优化将开发周期缩短40%。本文将结合Vivado 2025最新特性,揭示解决建立...

关键字: 时序收敛 Vivado

在FPGA设计中,时序收敛是工程师面临的终/极挑战。当系统时钟频率突破200MHz时,建立时间(Setup Time)往往成为阻碍设计成功的"后一公里"难题。本文将深入解析Vivado和Quartus工具链中的物理优化策...

关键字: Vivado Quartus FPGA 时序收敛

在高速通信系统设计中,SERDES(串行器/解串器)接口的信号完整性直接影响数据传输的可靠性。Xilinx FPGA的IBERT(Integrated Bit Error Ratio Tester)工具通过眼图分析技术,...

关键字: Vivado 高速SERDES IBERT眼图
关闭