AD9361纯逻辑FPGA驱动,单音信号收发例程,可动态配置9361,verilog代码,Vi...
这时候拿频谱仪对着射频口,能扫到干净的单音信号——这时候千万别激动,先检查是不是本振泄露,把数字直流校正寄存器配置好再说。这里有个骚操作,把12bit的I/Q信号拼成24bit总线,后面接FIFO的时候能省一半带宽。AD9361纯逻辑FPGA驱动,单音信号收发例程,可动态配置9361,verilog代码,Vivado 2019.1工程。工程里最坑的是Vivado的时钟约束,必须给AD9361的da
AD9361纯逻辑FPGA驱动,单音信号收发例程,可动态配置9361,verilog代码,Vivado 2019.1工程。

搞AD9361纯FPGA驱动这事说难不难,但没点骚操作还真容易踩坑。咱今天不整那些虚的理论,直接撸起袖子干代码。先看收发链路的核心结构——这玩意儿就是个数据泵,得在FPGA里用Verilog硬怼出来。

收发通道的数据接口得跟紧AD9361的时钟节奏,上代码:
always @(posedge rx_clk or posedge reset) begin
if(reset) begin
rx_data_buffer <= 12'd0;
end else begin
rx_data_buffer <= {rx_data_Q, rx_data_I}; // I/Q拼成24bit
end
end
这里有个骚操作,把12bit的I/Q信号拼成24bit总线,后面接FIFO的时候能省一半带宽。注意rx_clk是从AD9361过来的随路时钟,时序不对齐分分钟丢数据。

动态配置这块必须上状态机,不然SPI时序搞死人。看这个配置状态机的骨架:
parameter IDLE = 3'd0;
parameter WRITE_CMD = 3'd1;
parameter WAIT_ACK = 3'd2;
always @(posedge spi_clk) begin
case(state)
IDLE:
if(config_en) begin
spi_csn <= 1'b0;
spi_mosi <= cmd_buffer[23];
bit_cnt <= 5'd23;
state <= WRITE_CMD;
end
WRITE_CMD:
if(bit_cnt > 0) begin
spi_mosi <= cmd_buffer[bit_cnt-1];
bit_cnt <= bit_cnt - 1;
end else begin
state <= WAIT_ACK;
end
// ...其他状态
endcase
end
注意cmd_buffer里塞的是[读写标志+7位地址+16位数据]的组合包。调试时用ILA抓这个信号,能看到配置参数像坐过山车一样在变化。

单音发生器模块是验证收发的关键,直接上DDS相位累加:
reg [31:0] phase_acc;
always @(posedge tx_clk) begin
phase_acc <= phase_acc + freq_ctrl_word;
tx_data_I <= $signed(2047 * $sin(phase_acc[31:24] * 2 * $PI / 256));
tx_data_Q <= $signed(2047 * $cos(phase_acc[31:24] * 2 * $PI / 256));
end
这里用相位截断法省资源,实际测试发现相位噪声完全在可接受范围。freqctrlword直接关联到前面SPI配置的频率寄存器,改个数值就能切频率。

工程里最坑的是Vivado的时钟约束,必须给AD9361的data clock加上creategeneratedclock约束,不然时序报告全飘红。记得在XDC文件里补上:
create_generated_clock -name rx_clk \
-source [get_pins ad9361_if/inst/clk] \
-divide_by 1 \
[get_ports rx_clk]
实测发现不这么搞的话,数据有效窗口会偏移超过1ns,直接导致收不到有效数据。

调通之后上SignalTap抓波形,能看到I/Q数据像心电图一样规律跳动。这时候拿频谱仪对着射频口,能扫到干净的单音信号——这时候千万别激动,先检查是不是本振泄露,把数字直流校正寄存器配置好再说。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐

所有评论(0)