AD9361 FPGA 纯 Verilog 驱动
AD9361 射频芯片驱动开发中,纯 Verilog 实现 LVDS 接口是常见难点。本方案提供无需 IP 核的驱动实现,代码结构清晰,便于移植。代码已在 ZYNQ、XILINX K7、Cyclone IV 等芯片中测试通过。
驱动核心架构
驱动核心分为三个模块:SPI 配置引擎、LVDS 数据接口、时钟同步电路。SPI 模块用状态机实现了自动化的寄存器配置。
SPI 时钟分频逻辑
always @(posedge clk_50m) begin
if(spi_busy) begin
clk_div <= clk_div + 1;
if(clk_div == SPI_CLK_DIV) begin
spi_sclk <= ~spi_sclk;
clk_div <= 0;
end
end else begin
spi_sclk <= 1'b0;
end
end
该自动分频机制让 SPI 时钟频率可以参数化配置,实测在 K7 平台上能稳定跑到 25MHz。寄存器写入时采用了 burst 模式,一次配置整个射频通道参数耗时不到 2ms,比传统的单寄存器写入方式快了近 20 倍。
LVDS 接口处理
LVDS 接口处理针对不同 FPGA 平台做了差异化处理。Altera 器件直接用 ALTDDIO 实现,Xilinx 平台则手动拼接 OSERDES:
// Xilinx LVDS 发送端实现
OSERDESE2 #( .DATA_RATE_OQ("DDR"), .DATA_WIDTH(4) ) oserdes_tx (
.OCE(1'b1),
.CLK(tx_clk),
.CLKDIV(clk_100m),
.D1(lvds_data[0]),
.D2(lvds_data[1]),
.D3(lvds_data[2]),
.D4(lvds_data[3]),
.OQ(tx_p),
.TCE(1'b0)
);
实测发现 Cyclone IV 的 LVDS 接收需要额外做相位补偿,在代码里留了动态调整参数 tx_delay_step,通过 SPI 可以实时调整数据对齐窗口。经过补偿后的稳定眼图中,数据跳变沿刚好落在时钟中心位置。
数据路径与 AGC
数据路径采用乒乓缓存结构,双口 RAM 配合状态机实现无缝切换。发送端 FIFO 深度可配置,实测在 DMA 突发传输时能保持 98% 以上的总线利用率。接收路径上的自动增益控制模块如下:
// 自动增益步进调整
always @(posedge rx_clk) begin
if(rssi > RSSI_THRESH_HIGH) begin
gain_step <= (gain_current > GAIN_MIN) ? (gain_current - 1) : GAIN_MIN;
end else if(rssi < RSSI_THRESH_LOW) begin
gain_step <= (gain_current < GAIN_MAX) ? (gain_current + 1) : GAIN_MAX;
end
end
该简易 AGC 方案在实测中表现不错,MATLAB 波形显示信号幅度始终维持在 -3dBFS 到 -6dBFS 之间。射频测试环节用频谱仪扫频时发现本振泄露比预期低了 8dB,后来发现是代码里 TX_LO 配置寄存器的校准参数没生效,加上手动校准流程后指标恢复正常。
移植说明
移植到不同平台主要改三个地方:PLL 配置脚本、LVDS 原语封装、跨时钟域处理。在 ZYNQ 上跑的时候发现 PS 端 DMA 传输会偶尔断流,最后在 AXI 总线仲裁模块里加了优先级权重参数才解决。


