简介:本资源为基于Xilinx ZC706开发板与ADI ADRV9009高性能接收器的完整工程包,面向FPGA开发者、嵌入式工程师及高速信号处理方向的研究人员,提供从HDL硬件设计到no-os裸机SDK软件实现的端到端参考案例,可用于无线通信、雷达、测试测量等场景的原型验证。压缩包共约2000个文件,整体201.1MB,以Verilog源码、Tcl脚本、XDC约束、Makefile、C头文件与源文件、XCI IP核配置为主,另含VHDL、SystemVerilog、SDC时序约束及日志报告等,覆盖时钟管理、数据同步、JESD204接口、DMA读写与寄存器映射等模块。目前已有3842人学习下载。工程同时包含HDL与SDK两部分,读者可借此理解FPGA与高速ADC协同工作的接口逻辑、无操作系统下的任务调度与驱动编写方法,并参考现有目录结构快速搭建低延迟、高实时性的信号采集与处理原型系统。
1. 拿到 zc706_adrv9009.rar 之后:这套 HDL + SDK 工程到底能跑出什么
如果你手头正好有一块 ZC706 开发板和一块 ADRV9009 射频收发芯片,又不想从零去啃 ADI 那套庞大的参考设计,那这个 zc706_adrv9009.rar 大概率就是你要找的东西。它把 FPGA 侧的 HDL 工程和处理器侧的 SDK 软件工程打包在一起,走的是 no-os 路线——也就是说,ARM 核上不跑 Linux,直接裸机操作 ADRV9009 的寄存器、配置收发通道、跑 JESD204B 链路。这种组合在快速验证射频链路、做原型收发测试的时候特别省事,不用折腾设备树和内核驱动,上电就能对着寄存器读写。适合谁?一类是做射频前端验证的 FPGA 工程师,另一类是想拿 ADRV9009 做教学或预研的嵌入式开发者。下面我就按“这工程长什么样 → 怎么把它跑起来 → 想改的时候从哪下手”的顺序,把这份资源拆开讲一遍。
2. 工程结构拆解:HDL 顶层、JESD204B 链路和 SDK 裸机驱动怎么串起来
2.1 HDL 侧:从顶层文件看数据通路
拿到压缩包解压之后,HDL 部分通常是一个 Vivado 工程目录,里面最核心的是顶层文件,一般叫system_top.v或者zc706_adrv9009_top.v。这个顶层干的事不复杂,就是把 ADRV9009 的物理接口(LVDS 或者 JESD204B 的 SERDES lane)和 ZC706 上的 FMC 接口对接起来,再往内部挂上 ADI 的 IP 核。常见做法是直接调用 ADI 提供的axi_adrv9009IP,里面封装了 JESD204B 的 PHY、链路层和 ADC/DAC 的数据打包逻辑。
我一般会先看顶层里这几个信号:
// 顶层里典型的 JESD204B 接口信号 output [3:0] rx_data_p, // 接收数据差分对 output [3:0] rx_data_n, input [3:0] tx_data_p, // 发送数据差分对 input [3:0] tx_data_n, output rx_sysref, // SYSREF 同步信号 output tx_sysref, input rx_sync, // SYNC 信号,链路建立用 output tx_sync这些信号直接连到 FMC 连接器上,对应 ADRV9009 评估板的引脚。逻辑说明:rx_data_p/n和tx_data_p/n是高速 SERDES 差分对,JESD204B 用它们传 IQ 采样数据;sysref用来做多芯片同步,sync是链路握手信号。参数上,lane 数量取决于你配置的 JESD204B 模式(比如 2 lane 还是 4 lane),这个在 IP 核的配置界面里改,改完要重新生成 IP 并综合。
2.2 SDK 侧:no-os 驱动怎么初始化 ADRV9009
SDK 工程里通常有一个main.c和一个adrv9009.c驱动文件。no-os 的意思是没有操作系统,所有初始化都靠顺序调用。典型流程是:先初始化 SPI 和 GPIO,然后读 ADRV9009 的芯片 ID 确认通信正常,再加载 ADI 提供的talise固件(ADRV9009 内部叫 Talise),最后配置收发通道的采样率、本振频率、增益模式。
// main.c 里典型的初始化片段 spi_init(); // 初始化 SPI 控制器 gpio_init(); // 初始化复位和使能引脚 adrv9009_reset(); // 硬件复位 id = adrv9009_read_reg(0x0000); // 读芯片 ID,正常应该是 0x00AD if (id != 0x00AD) { printf("ADRV9009 not detected!\n"); while(1); } adrv9009_load_firmware(); // 加载 Talise 固件 adrv9009_setup_jesd204b(); // 配置 JESD204B 链路参数 adrv9009_set_rx_freq(2400000000); // 设置接收本振 2.4GHz adrv9009_set_tx_freq(2400000000); // 设置发送本振 2.4GHz逻辑说明:adrv9009_read_reg通过 SPI 读寄存器,芯片 ID 对不上后面全白搭;load_firmware是把 ADI 提供的二进制固件通过 SPI 写进芯片内部 RAM;setup_jesd204b配置 lane 数、帧格式、多帧长度,必须和 HDL 侧 IP 核的配置完全一致,否则链路起不来。参数上,set_rx_freq的单位是 Hz,实际能设的范围取决于 ADRV9009 的射频 PLL 范围,一般 70MHz 到 6GHz。
2.3 目录结构:文件放哪、编译顺序是什么
解压后典型的目录树长这样:
zc706_adrv9009/ ├── hdl/ # Vivado 工程 │ ├── projects/ │ │ └── zc706_adrv9009/ │ │ ├── system_top.v │ │ └── system_constr.xdc │ └── library/ # ADI IP 核源码 ├── sdk/ # Xilinx SDK 工作空间 │ ├── app/ │ │ ├── main.c │ │ └── adrv9009.c │ └── hw/ # 导出的硬件描述文件 └── scripts/ # 编译和下载脚本HDL 部分用 Vivado 打开projects/zc706_adrv9009下的工程文件,综合实现后导出xsa文件。SDK 部分新建一个空的应用工程,把app目录下的源文件加进去,然后指定hw目录里的xsa作为硬件平台。编译顺序是先 HDL 后 SDK,因为 SDK 的地址映射依赖 HDL 导出的硬件描述。
3. 跑通全流程:从 Vivado 综合到 SDK 裸机程序上板
3.1 Vivado 侧:综合、实现和导出硬件
打开 Vivado 工程后,第一步是确认 IP 核的配置。在 Block Design 里找到axi_adrv9009,双击进去看 JESD204B 的 lane 数和采样率。常见配置是 4 lane、采样率 245.76MSPS,这个要和 ADRV9009 评估板上的拨码开关一致。确认完直接点 Generate Bitstream,Vivado 会自动跑综合、实现、生成比特流。这一步耗时取决于机器性能,一般 20 到 40 分钟。
跑完之后,菜单里选 File → Export → Export Hardware,勾选 Include Bitstream,导出xsa文件。这个文件是 SDK 用来识别硬件平台的,里面包含了寄存器地址映射和比特流。
注意:导出
xsa之前一定要确认没有时序违例,尤其是 JESD204B 的 SERDES 时钟,时序不过链路肯定起不来。
3.2 SDK 侧:新建工程、导入源码、编译
打开 Xilinx SDK,指定一个工作空间目录,然后 File → New → Application Project。在硬件平台那一页选刚刚导出的xsa,处理器选ps7_cortexa9_0,工程模板选 Empty Application。建完之后,把app目录下的main.c、adrv9009.c、adrv9009.h复制到工程的src目录里。
接下来要改的是链接脚本和堆栈大小。no-os 程序里会用到比较大的数组来存 IQ 数据,默认的堆栈可能不够。在lscript.ld里把Heap Size改成0x100000,Stack Size改成0x10000。然后右键工程 → Build Project,编译通过后会生成.elf文件。
# 如果习惯用命令行,也可以用 xsct 脚本编译 xsct create_project.tcl # 脚本里会调用 exec vitis -source build.tcl逻辑说明:xsct是 Xilinx 的命令行工具,适合做自动化构建。参数上,create_project.tcl里要指定xsa路径和源文件目录,编译完的elf可以直接用program_fpga和dow命令下载。
3.3 上板验证:JTAG 下载和串口打印
把 ZC706 的 JTAG 和串口都连上电脑,先给板子上电,然后打开 SDK 的 Terminal 视图,新建一个串口终端,波特率 115200。接着在 SDK 里点 Program FPGA,选比特流文件,下载完成后右键应用工程 → Run As → Launch on Hardware。程序跑起来后,串口会打印初始化日志:
ADRV9009 detected, ID = 0x00AD Loading Talise firmware... JESD204B link status: 0x01 (SYNC asserted) RX LO locked at 2400 MHz TX LO locked at 2400 MHz如果看到JESD204B link status一直是 0,说明链路没建立,先检查 HDL 侧和 SDK 侧的 lane 配置是否一致,再查 SYSREF 有没有接对。如果 LO 没锁,多半是参考时钟没给对,ADRV9009 需要外部提供 30.72MHz 或 122.88MHz 的参考时钟。
4. 避坑与排查:JESD204B 链路起不来、SPI 读不到 ID 怎么办
4.1 现象:串口打印 “ADRV9009 not detected”
原因:SPI 通信失败。常见的是 SPI 片选接错、时钟极性配反,或者 ADRV9009 的复位引脚没释放。解决:先用示波器量 SPI 的 SCLK 和 MOSI,看有没有波形;再确认adrv9009_reset()里拉低复位后有没有延时足够时间(一般至少 10ms)再拉高。
4.2 现象:JESD204B link status 一直是 0
原因:HDL 侧和 SDK 侧的 JESD204B 参数不匹配。比如 HDL 配的是 4 lane,SDK 里配的是 2 lane;或者多帧长度(K 值)对不上。解决:两边都打开配置界面,逐项核对 lane 数、帧长度、多帧长度、子类模式(Subclass 1)。改完 HDL 要重新综合,改完 SDK 要重新编译。
4.3 现象:RX 能收到数据但全是噪声
原因:ADRV9009 的增益模式没配对,或者本振频率设到了芯片不支持的范围。解决:检查adrv9009_set_rx_freq的参数是否在 70MHz 到 6GHz 之间;如果是手动增益模式,确认增益索引有没有写对寄存器。
4.4 现象:程序跑一会儿就挂死
原因:no-os 程序里没有中断处理,如果 JESD204B 链路断了,程序可能卡在轮询循环里。解决:在轮询链路状态的地方加超时计数,超时就打印错误并重新初始化,别死等。
提示:上板调试时先把串口终端打开再下载程序,否则可能错过最开始的打印信息。
5. 二次开发怎么改:换采样率、加自定义逻辑、做自动化构建
5.1 改采样率:HDL 和 SDK 要同步动
想换采样率,比如从 245.76MSPS 改成 122.88MSPS,不能只改一边。HDL 侧要在axi_adrv9009IP 核里改采样率参数,然后重新生成 IP、综合、实现、导出xsa。SDK 侧要在adrv9009_setup_jesd204b里改对应的时钟分频和 JESD204B 参数。两边都改完再编译下载。我一般会拿个表格把两边参数列清楚,改完逐项打勾,避免漏改。
| 参数 | HDL 侧位置 | SDK 侧位置 |
|---|---|---|
| 采样率 | IP 核配置界面 | adrv9009_setup_jesd204b |
| Lane 数 | IP 核配置界面 | adrv9009_setup_jesd204b |
| 多帧长度 | IP 核配置界面 | adrv9009_setup_jesd204b |
| 参考时钟 | 顶层约束文件 | adrv9009_load_firmware前 |
5.2 加自定义逻辑:在 HDL 里挂 AXI 外设
如果想在 FPGA 侧加自己的数据处理逻辑,比如做个简单的数字下变频,可以在 Block Design 里加一个 AXI 外设,把 ADRV9009 的 RX 数据流引出来。常见做法是用 AXI-Stream 接口,把axi_adrv9009的 RX 输出接到自己的 IP 上,处理完再写回 DDR 或者通过 AXI-Lite 给 ARM 读。改完 HDL 同样要重新导出xsa,SDK 侧用Xil_Out32和Xil_In32读写自定义寄存器。
5.3 自动化构建:用 xsct 脚本一键编译
手动点 SDK 编译容易漏步骤,我习惯写个build.tcl脚本,把创建工程、导入源码、编译全串起来。这样每次改完代码,命令行跑一下就行,不用来回点界面。
# build.tcl 片段 setws ./workspace createhw -name hw_design -hwspec ./hw/system.xsa createapp -name adrv9009_app -hwproject hw_design -proc ps7_cortexa9_0 -os standalone -lang C importsources -name adrv9009_app -path ./app projects -build逻辑说明:createhw用xsa建硬件平台,createapp建空应用工程,importsources把源码拷进去,projects -build触发编译。参数上,-proc指定处理器核,-os指定 standalone 表示裸机。跑完脚本直接生成elf,省去手动操作。
从那以后我每次改完 HDL 或者 SDK 代码,都强制走一遍脚本编译加串口验证,确认链路状态和 LO 锁定再往下做。希望帮到你。
本文还有配套的精品资源,点击获取