基于ZYNQ7000的AD9226采集卡实现(1、采集数据到PL)_zynq dma adc
目标
AD9226为12位,65MHz采样率ADC。基于ZYNQ7010平台,PL端采集AD数据,通过内部AXI总线,将数据搬运到PS的DDR。
可以将如上目标分解为3个小目标
-
实现PL采集AD9226模块,采集后的数据为AXIS接口。
-
实现PL侧DMA可搬运AXIS数据到PS的DDR,可配置地址,帧长度,帧数量等。
-
实现PS侧DMA驱动
本章节实现第一个小目标:
硬件:
主控板
采集模块
模块引脚功能:
-
D0-D11:并口数据
-
CLK:时钟
-
OTR:输入超量程
AD时序
可以发现,此ADC的时序非常简单,只需给AD输入时钟,在时钟上升沿读取12位AD值
FPGA代码实现
AD9226 fpga驱动
`timescale 1ns / 1ps`default_nettype nonemodule ad9226_dri #( parameter TDATA_WIDTH = 32) ( input wire clk, input wire rstn, input wire[11:0] i_ad_data, input wire i_en, //ad使能 input wire[15:0] i_number, //一个axis报文包含多少次采样数据 output reg[TDATA_WIDTH-1:0] m_axis_fifo_tdata, output wire[(TDATA_WIDTH/8)-1:0] m_axis_fifo_tkeep, output reg m_axis_fifo_tlast, input wire m_axis_fifo_tready, output reg m_axis_fifo_tvalid);localparam BYTE_NUM = (TDATA_WIDTH / 8);reg[15:0] ad_cnt_reg;reg[15:0] seq_cnt_reg;wire[11:0] ad_data_conv;reg[11:0] ad_data_reg;assign ad_data_conv[0] = i_ad_data[11];assign ad_data_conv[1] = i_ad_data[10];assign ad_data_conv[2] = i_ad_data[9];assign ad_data_conv[3] = i_ad_data[8];assign ad_data_conv[4] = i_ad_data[7];assign ad_data_conv[5] = i_ad_data[6];assign ad_data_conv[6] = i_ad_data[5];assign ad_data_conv[7] = i_ad_data[4];assign ad_data_conv[8] = i_ad_data[3];assign ad_data_conv[9] = i_ad_data[2];assign ad_data_conv[10] = i_ad_data[1];assign ad_data_conv[11] = i_ad_data[0];// ila_0 ila_0_inst2(// .clk (clk ),// .probe0 ({// m_axis_fifo_tdata,// m_axis_fifo_tkeep,// m_axis_fifo_tlast,// m_axis_fifo_tready,// m_axis_fifo_tvalid,// i_en,// i_number,// ad_data_conv,// ad_cnt_reg// })// );always @(posedge clk or negedge rstn) begin if(rstn == 1\'b0) begin m_axis_fifo_tdata <= 0; m_axis_fifo_tlast <= 1\'b0; m_axis_fifo_tvalid <= 0; ad_cnt_reg <= 0; seq_cnt_reg <= 0; ad_data_reg <= 0; end else begin if (m_axis_fifo_tready && i_en) begin /* 偶数0\\2\\4 */ if (ad_cnt_reg[0] == 0) begin if (ad_cnt_reg == 0) begin m_axis_fifo_tdata <= seq_cnt_reg; m_axis_fifo_tvalid <= 1; m_axis_fifo_tlast <= 0; ad_cnt_reg <= ad_cnt_reg + 1; end else if (ad_cnt_reg == i_number) begin m_axis_fifo_tdata <= ad_data_conv; m_axis_fifo_tvalid <= 1; m_axis_fifo_tlast <= 1; ad_cnt_reg <= 0; seq_cnt_reg <= seq_cnt_reg + 1; end else begin m_axis_fifo_tvalid <= 0; m_axis_fifo_tlast <= 0; ad_cnt_reg <= ad_cnt_reg + 1; end ad_data_reg <= ad_data_conv; end /* 奇数1\\3\\5 */ else begin m_axis_fifo_tvalid <= 1; m_axis_fifo_tdata <= {4\'b0, ad_data_conv, 4\'b0, ad_data_reg}; if (ad_cnt_reg == i_number) begin m_axis_fifo_tlast <= 1; ad_cnt_reg <= 0; seq_cnt_reg <= seq_cnt_reg + 1; end else begin m_axis_fifo_tlast <= 0; ad_cnt_reg <= ad_cnt_reg + 1; end end end else m_axis_fifo_tvalid <= 0; endendassign m_axis_fifo_tkeep = {BYTE_NUM{1\'b1}};endmodule`default_nettype wire
仿真代码
`timescale 1ns / 1nsmodule ad9226_tb ();`include \"../../sources_1/new/inc/base.h\"reg clk, reset;reg[11:0] ad_data;always #(10) clk = ~clk; //50MHzinitial begin clk = 0; ad_data = 0;endinitialbegin reset = 1\'b1; #7; reset = 1\'b0; // 解复位 for (; ;) begin /* 读fifo */ ad_data = ad_data + 1; #20; end $stop;endad9226_dri #( .TDATA_WIDTH (32 )) ad9226_dri_inst0 ( .clk (clk ), .rstn (!reset ), .i_ad_data (ad_data ), .i_en (1 ), //ad使能 .i_number (16\'hf ), //一个axis报文包含多少次采样数据 .m_axis_fifo_tdata ( ), .m_axis_fifo_tkeep ( ), .m_axis_fifo_tlast ( ), .m_axis_fifo_tready (1 ), .m_axis_fifo_tvalid ( ));endmodule
仿真结果如下:
- AD数据值是递增的
- AXIS是32位的,每个时钟周期传输2次AD采样的数据
- 每个AXIS包,包含16帧AD采样数据
- AXIS帧首先传输的是帧计数