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

发布于:2025-07-04 ⋅ 阅读:(16) ⋅ 点赞:(0)

目标

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 none

module 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;
    end
end

assign m_axis_fifo_tkeep = {BYTE_NUM{1'b1}};

endmodule
`default_nettype wire

仿真代码

`timescale 1ns / 1ns
module ad9226_tb (
);
`include "../../sources_1/new/inc/base.h"

reg clk, reset;
reg[11:0] ad_data;

always #(10) clk = ~clk;    //50MHz

initial begin
    clk = 0;
    ad_data = 0;
end

initial
begin
    reset = 1'b1;
    #7;
    reset = 1'b0;               // 解复位
    for (; ;) begin
        /* 读fifo */
        ad_data = ad_data + 1;
        #20;
    end
    $stop;
end

ad9226_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帧首先传输的是帧计数

网站公告

今日签到

点亮在社区的每一天
去签到