前言
AD9361作为一款功能强大的射频收发器件,在通信领域被广泛采用。ADI官方提供的Demo主要基于ZYNQ的软件控制方式,这种控制方法的优点是将所有功能配置都封装为API函数,使用者不需要了解太多AD9361的具体细节,特别是其1024个寄存器的具体定义。这种方法适合于快速上手验证,但是在产品实现时有诸多不便,甚至某些场合根本无法使用。本连载基于实际的产品开发经验,介绍了如何用纯逻辑(verilog)的方式,实现AD9361从0到1的无线收发过程。
AD9361是干什么的?
以上这段摘自《AD9361_cn.pdf》
AD9361纯逻辑控制的开发方法
AD9361有1024个寄存器,要了解每个寄存器的功能再写代码,是个很费事费力的工作,并且不是每个寄存器都有文档支撑,完全靠阅读寄存器的文档,很难写出正确的初始化代码。好在ADI官方提供了AD936x Evaluation Software,用于生成初始化的脚本。这个脚本是ADI公司特有的脚本语法,不能直接拿过来用,这个时候就需要将这个脚本语言翻译成verilog语言,一条条执行每条命令,从而完成AD9361的初始化工作。在完成了初始化工作后,还需要配置射频频率、增益控制、发射衰减等参数、读PLL锁定标志等等。如果需要快速跳频工作,那还需要加入Profile的校准相关的代码。后面按照步骤一一介绍。
第一步:实现SPI通信
参考文件《AD9361 Interface Spec v2.5.pdf》
AD9361的控制接口是SPI的接口,属于串行控制总线,以下是SPI的时序图。
AD9361支持三线SPI和4线SPI接口,我这里用4线SPI接口。为了方便,首先要将其转换为并行总线,我这里转换成Avalon总线,下面贴出代码接口定义:
module ad9361_spi(
input clk,
input rst_n,
//avalon interface
input read,
input write,
input [9:0] address,
input [7:0] writedata,
output reg [7:0] readdata,
output reg waitrequest,
//SPI interface
output spi_clk,
output reg spi_csn,
output reg spi_sdo,
input spi_sdi
);
第二步:实现Avalon总线仲裁,方便多个主控控制AD9361的SPI接口
我的代码中,有4个主控,分别是初始化主控,跳频校准主控,调试主控,参数配置主控,4个主控分时访问SPI接口。这么做的目的是方便切割模块,不然所有的功能代码揉到一起,不利于功能切割。代码可读性就会很差,也不利于维护。后面会一一介绍每个主控的作用。主控切换代码端口定义如下:
module avalon_mux #(parameter ADDR_WIDTH=256,DATA_WIDTH=256)
(
input clk,
input rst_n,
input s0_read,
input s0_write,
input [ADDR_WIDTH-1:0] s0_address,
input [DATA_WIDTH-1:0] s0_writedata,
output reg [DATA_WIDTH-1:0] s0_readdata,
output reg s0_waitrequest,
input s1_read,
input s1_write,
input [ADDR_WIDTH-1:0] s1_address,
input [DATA_WIDTH-1:0] s1_writedata,
output reg [DATA_WIDTH-1:0] s1_readdata,
output reg s1_waitrequest,
input s2_read,
input s2_write,
input [ADDR_WIDTH-1:0] s2_address,
input [DATA_WIDTH-1:0] s2_writedata,
output reg [DATA_WIDTH-1:0] s2_readdata,
output reg s2_waitrequest,
input s3_read,
input s3_write,
input [ADDR_WIDTH-1:0] s3_address,
input [DATA_WIDTH-1:0] s3_writedata,
output reg [DATA_WIDTH-1:0] s3_readdata,
output reg s3_waitrequest,
output reg m_read,
output reg m_write,
output reg [ADDR_WIDTH-1:0] m_address,
output reg [DATA_WIDTH-1:0] m_writedata,
input [DATA_WIDTH-1:0] m_readdata,
input m_waitrequest
);
到这里,我们实现了SPI的驱动以及多主控切换的功能。下一章,我会讲解如何用AD936x Evaluation Software生成初始化AD9361的配置脚本