> 技术文档 > 基于ZYNQ7000的AD9226采集卡实现(1、采集数据到PL)_zynq dma adc

基于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驱动

本章节实现第一个小目标:

硬件:

主控板

在这里插入图片描述

采集模块

基于ZYNQ7000的AD9226采集卡实现(1、采集数据到PL)_zynq dma adc

模块引脚功能:

  • D0-D11:并口数据

  • CLK:时钟

  • OTR:输入超量程

AD时序
基于ZYNQ7000的AD9226采集卡实现(1、采集数据到PL)_zynq dma adc
可以发现,此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

仿真结果如下:
基于ZYNQ7000的AD9226采集卡实现(1、采集数据到PL)_zynq dma adc

  • AD数据值是递增的
  • AXIS是32位的,每个时钟周期传输2次AD采样的数据
  • 每个AXIS包,包含16帧AD采样数据
  • AXIS帧首先传输的是帧计数

漳州理工网