[X]关闭
 专注集成电路FPGA应用生态推广
 微信公众号
米联客
米联客uisrc 首页 Xilinx课程 19版ZYNQ 2-ZYNQ入门 查看内容
0

S02-CH28 利用LWIP实现ADC DAQ7606数据采集

摘要: 软件版本:VIVADO2017.4操作系统:WIN10 64bit硬件平台:适用米联客 ZYNQ系列开发板米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!28.1 DAQ7606 采集卡图片28.2 项目要求 使用DAQ7606子卡 ...

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

28.1 DAQ7606 采集卡图片

28.2 项目要求

      使用DAQ7606子卡采集数据,通过DMA将数据传输到PS端DDR,PS端使用TCP协议将采集数据发送至PC端。本项目的教程编写参考《DMA_PL_LWIP以太网传输》课时。如果读者对于 ZYNQ 的 DMA 传输,以及 LWIP 的使用还有疑问请先阅读《DMA_PL_LWIP以太网传输》课程并且掌握后再来学习本节课。

28.2.1 功能要求

      PS 通过 AXI GPIO IP核启动 PL 不间断循环构造64bit 位宽的 01023 的数据,利用 AXI DMA IP 核,通过 PS Slave AXI GP 接口传输至 PS DDR3 的乒乓缓存中。PL 每发完一次 01023AXI DMA IP 核便会产生一个中断信号,PS 得到中断信号后将 DDR3 缓存的数据通过乒乓操作的方式由 TCP协议发 送至 PC 机。

28.2.2 控制协议

      以太网接收控制命令协议格式 

      启动:0xAA55FFA0

      停止:0xAA55FFB1

      复位:0xAA55FFC1

      串口接收控制命令协议格式 

      启动:0xAA55EEA0

      停止:0xAA55EEB1

      复位:0xAA55EEC1

28.3 方案构架

28.3.1 传输方案

      8  16bit 200K ADC 经过 PL 采集 送入 128bit  FIFO,之后通过 DMA 模块送入 DDR,PS 部分 接收到中断信号后,启动 LWIP  TCP 传输,把一包数据发送出去。控制信号,通过以太网口或者 串口发送给开发板,控制启停,复位。

28.3.2 数据包格式

      设计的数据包格式如上图所示,一包数据一共是 1024*128bit。其中包头部分 128bit(32bit*4)格 式,0XAA55AA55 0XAA55AA55 代表了数据包开始,Packet index 代表了数据包的序列号,length 代表了本包数据的长度。

28.4 FPGA 代码介绍

28.4.1 axidma_tcp_demo_wrapper.v

-------所有代码的顶层模块。作用是复制信号之间的连接。关键的信号为 adc_capture_en_reg2使能ADC 采集。 ad_data_valid 代表 ADC 数据有效。

关键代码如下:

always @(posedge  FCLK_CLK1 )//CS

begin

reset_reg1 <= ~peripheral_aresetn;

reset_reg2 <= reset_reg1;

end


assign reset = reset_reg2;


always @(posedge  FCLK_CLK1 )//CS

begin

if(reset) begin

adc_capture_en_reg1 <= 1'd0;

adc_capture_en_reg2 <= 1'd0;

end

else begin

adc_capture_en_reg1 <= gpio_tri_o_0;

adc_capture_en_reg2 <= adc_capture_en_reg1;

end

end


ad7606_ctrl ad7606_ctrl_inst

(

    .clk_i  (FCLK_CLK1),

    .reset_i             (reset),

    .ad_data             (ad_data),

    .ad_busy             (ad_busy),

    .first_data          (first_data),   

    .ad_os               (ad_os),

    .ad_cs               (ad_cs),

    .ad_rd               (ad_rd),

    .ad_reset            (ad_reset),

    .ad_convsta          (ad_convsta),

    .ad_convstb          (ad_convstb),

    .ad_range            (ad_range),

    .ad_ch1_o            (ad_ch1),

    .ad_ch2_o            (ad_ch2),

    .ad_ch3_o            (ad_ch3),

    .ad_ch4_o            (ad_ch4),

    .ad_ch5_o            (ad_ch5),

    .ad_ch6_o            (ad_ch6),

    .ad_ch7_o            (ad_ch7),

    .ad_ch8_o            (ad_ch8),

    .ad_data_valid_o     (ad_data_valid)

    

);  

    

adc_to_axistream   adc_to_axistream_inst

(

.clk_i  (FCLK_CLK1),

.reset_i  (reset),

.adc_capture_en_i  (adc_capture_en_reg2),

.adc_data_i  ({ad_ch1,ad_ch2,ad_ch3,ad_ch4,ad_ch5,ad_ch6,ad_ch7,ad_ch8}),

//.adc_data_i  (128'h0123456789abcdef0123456789abcdef),

.adc_data_valid_i    (1'b1),


.s_axis_adc_tready   (S_AXIS_tready),

.s_axis_adc_tvalid   (S_AXIS_tvalid),

.s_axis_adc_tdata    (S_AXIS_tdata),

.s_axis_adc_tkeep    (S_AXIS_tkeep),

.s_axis_adc_tlast    (S_AXIS_tlast)

    );


assign s_axis_aclk = FCLK_CLK1;

assign s_axis_aresetn = peripheral_aresetn;



axidma_tcp_demo axidma_tcp_demo_i

    (.DDR_addr(DDR_addr),

     .DDR_ba(DDR_ba),

     .DDR_cas_n(DDR_cas_n),

     .DDR_ck_n(DDR_ck_n),

     .DDR_ck_p(DDR_ck_p),

     .DDR_cke(DDR_cke),

     .DDR_cs_n(DDR_cs_n),

     .DDR_dm(DDR_dm),

     .DDR_dq(DDR_dq),

     .DDR_dqs_n(DDR_dqs_n),

     .DDR_dqs_p(DDR_dqs_p),

     .DDR_odt(DDR_odt),

     .DDR_ras_n(DDR_ras_n),

     .DDR_reset_n(DDR_reset_n),

     .DDR_we_n(DDR_we_n),

     .FCLK_CLK1(FCLK_CLK1),

     .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),

     .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),

     .FIXED_IO_mio(FIXED_IO_mio),

     .FIXED_IO_ps_clk(FIXED_IO_ps_clk),

     .FIXED_IO_ps_porb(FIXED_IO_ps_porb),

     .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),

     .gpio_rtl_tri_i(gpio_tri_i_0),

     .gpio_rtl_tri_o(gpio_tri_o_0),

     .gpio_rtl_tri_t(gpio_tri_t_0),

 .s_axis_aclk(s_axis_aclk),

     .s_axis_aresetn(s_axis_aresetn),

     .S_AXIS_tdata(S_AXIS_tdata),

     .S_AXIS_tkeep(S_AXIS_tkeep),

     .S_AXIS_tlast(S_AXIS_tlast),

     .S_AXIS_tready(S_AXIS_tready),

     .S_AXIS_tvalid(S_AXIS_tvalid),

     .peripheral_aresetn(peripheral_aresetn));

28.4.2 ad7606_ctrl.v

-------ADC7606                                 ad_data_valid通知外部数据完成了采集。

其中关键代码如下:

`timescale 1ns / 1ns

//////////////////////////////////////////////////////////////////////////////////

// Module Name:    ad7606

//////////////////////////////////////////////////////////////////////////////////

module ad7606_ctrl(

    input         clk_i,                  //50mhz

input               reset_i,

input[15:0] ad_data,            //ad7606 采样数据

input         ad_busy,            //ad7606 忙标志位

    input         first_data,         //ad7606 第一个数据标志位  

output[2:0] ad_os,              //ad7606 过采样倍率选择

output          ad_cs,              //ad7606 AD cs

output          ad_rd,              //ad7606 AD data read

output     reg ad_reset,           //ad7606 AD reset

output          ad_convsta,         //ad7606 AD convert start

output          ad_convstb,         //ad7606 AD convert start

output              ad_range,

output              ad_ch1_o,

output              ad_ch2_o,

output              ad_ch3_o,

output              ad_ch4_o,

output              ad_ch5_o,

output              ad_ch6_o,

output              ad_ch7_o,

output              ad_ch8_o,

output              ad_data_valid_o

    );


wire[15:0] ad_data;

wire       ad_busy;

wire       first_data;

wire[2:0]  ad_os;

reg        ad_cs;

reg        ad_rd;

reg        ad_convsta;

reg        ad_convstb;

wire       ad_range;

reg[15:0]  ad_ch1_o;

reg[15:0]  ad_ch2_o;

reg[15:0]  ad_ch3_o;

reg[15:0]  ad_ch4_o;

reg[15:0]  ad_ch5_o;

reg[15:0]  ad_ch6_o;

reg[15:0]  ad_ch7_o;

reg[15:0]  ad_ch8_o;

reg        ad_data_valid_o;


reg [7:0] cnt;

reg [7:0] i;

reg [15:0] cnt5us;

reg [7:0] ad_state;


assign ad_os=3'b000;  //无过采样

assign ad_range = 1'b1; //±10V真直流输入范围


//ad复位

always@(posedge clk_i)

begin        

    if(reset_i)   

        ad_reset<=1'b0;            

    if(cnt<4'hf)

    begin

        cnt<=cnt+1'b1;

        ad_reset<=1'b1;

    end

    else

        ad_reset<=1'b0;  //计数器停止,ad_reset拉低,复位结束     

end            


//设置采样频率

always@ (posedge clk_i)   //200k采样率

begin

        if(reset_i)

            cnt5us <= 16'd0;

        if((cnt5us < 16'd249)&&(cnt==8'hf))

            cnt5us <= cnt5us + 1'b1;

        else

            cnt5us <= 16'd0;

end


//状态循环

always @(posedge clk_i)

begin

    if(reset_i)

    begin

        ad_cs<=1'b1;

        ad_rd<=1'b1;

        ad_convsta<=1'b1;   

        ad_convstb<=1'b1;   

        i<=8'd0;   

        ad_ch1_o<=16'd0;

        ad_ch2_o<=16'd0;

        ad_ch3_o<=16'd0;

        ad_ch4_o<=16'd0;

        ad_ch5_o<=16'd0;

        ad_ch6_o<=16'd0;

        ad_ch7_o<=16'd0;

        ad_ch8_o<=16'd0;

        ad_data_valid_o <= 1'b0;

        ad_state<=8'd0;

    end

    else if(ad_reset)

    begin

        ad_cs<=1'b1;

        ad_rd<=1'b1;

        ad_convsta<=1'b1;   

        ad_convstb<=1'b1;   

        i<=8'd0;   

        ad_state<=8'd0;

    end

    else        

    begin

        case(ad_state)     

  8'd0: begin

                     ad_cs<=1'b1;

                     ad_rd<=1'b1;

                     ad_convsta<=1'b1;

                     ad_convstb<=1'b1;

                     ad_data_valid_o <= 1'b0;    

                     ad_state <= 8'd1;

  end

  

8'd1: begin

                          if(i == 8'd5)            

                          begin

                              i<=8'd0;             

                              ad_state<=8'd2;

                          end

                          else

                          begin

                              i<=i+1'b1;

                              ad_state<=8'd1;

                          end

                    end

                    

                    8'd2: begin       

                           if(i==8'd2)     

                           begin                        //等待2个lock,convstab的下降沿最少为25ns,故至少需要两个时钟

                               i<=8'd0;             

                               ad_convsta<=1'b1;

                               ad_convstb<=1'b1;

                               ad_state<=8'd3;                                          

                           end

                           else

                           begin

                               i<=i+1'b1;

                               ad_convsta<=1'b0;

                               ad_convstb<=1'b0;                     //启动AD转换

                               ad_state<=8'd2;

                           end

                    end

                    

                    8'd3: begin            

                           if(i==8'd5)

                           begin                           //等待5个clock, 等待busy信号为高(tconv)

                               i<=8'd0;

                               ad_state<=8'd4;

                           end

                           else

                           begin

                               i<=i+1'b1;

                               ad_state<=8'd3;

                           end

                    end        

                    

                    8'd4: begin            

                             if(!ad_busy)

                             begin                    //等待busy为低电平  即转换之后读取模式         

                                 ad_state<=8'd5;

                             end

                             else

                                 ad_state<=8'd4;

                    end    

                    

                    8'd5: begin

                            ad_cs<=1'b0;                              //cs信号有效  直到读取8通道结束  

                            ad_rd<=1'b0;                       

                            ad_state<=8'd6;  

                     end

                    

                    8'd6: begin            

                            ad_state<=8'd7;

                    end

                    

                    

                    8'd7: begin  

                            if(first_data)                       

                                ad_state<=8'd8;

                            else

                                ad_state<=8'd7;    

                     end

                     

                     8'd8: begin

                           if(i==8'd1)

                           begin

                               ad_rd<=1'b1;

                               ad_ch1_o<=ad_data;                        //读CH1               

                               i<=8'd0;

                               ad_state<=8'd9;                 

                           end

                           else

                           begin  

                               i<=i+1'b1;

                               ad_state<=8'd8;

                           end

                     end

                     8'd9: begin

                           if(i==8'd1)

                           begin

                               ad_rd<=1'b0;              

                               i<=8'd0;

                               ad_state<=8'd10;                 

                           end

                           else

                           begin  

                               i<=i+1'b1;

                               ad_state<=8'd9;

                           end

                     end

                     

                     8'd10: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch2_o<=ad_data;                        //读CH2

                                i<=8'd0;

                                ad_state<=8'd11;                 

                            end

                            else

                            begin

                                i<=i+1'b1;

                                ad_state<=8'd10;

                            end

                    end

                    8'd11: begin

                           if(i==8'd1)

                            begin

                                ad_rd<=1'b0;

                                i<=8'd0;

                                ad_state<=8'd12;                 

                            end

                            else

                            begin                           

                                i<=i+1'b1;

                                ad_state<=8'd11;  

                            end

                    end        

                      

                    8'd12: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch3_o<=ad_data;                        //读CH3

                                i<=8'd0;

                                ad_state<=8'd13;                 

                            end

                            else

                            begin    

                                i<=i+1'b1;

                                ad_state<=8'd12;

                            end

                    end

                    8'd13: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b0;

                                i<=8'd0;

                                ad_state<=8'd14;                 

                            end

                            else

                            begin                                 

                                i<=i+1'b1;

                                ad_state<=8'd13;

                            end

                    end

                    

                    8'd14: begin

                            if(i==8'd1)

                            begin

                                ad_rd<=1'b1;

                                ad_ch4_o<=ad_data;                        //读CH4

                                i<=8'd0;

                                ad_state<=8'd15;                 

                 &nb


路过

雷人

握手

鲜花

鸡蛋

说点什么...

已有0条评论

最新评论...

本文作者
2019-9-6 19:37
  • 6
    粉丝
  • 6210
    阅读
  • 0
    回复

关注米联客

扫描关注,了解最新资讯

联系人:汤经理
电话:0519-80699907
EMAIL:270682667@qq.com
地址:常州溧阳市天目云谷3号楼北楼201B
热门评论
排行榜

关注我们:微信订阅号

官方微信公众号

官方微信公众号

客服服务热线:

0519-80699907

常州-总部:常州溧阳市中关村吴潭渡路雅创高科智造谷10-1幢楼

南京-分部:南京市栖霞区仙林大道181号5幢2220/2221室

邮编:213300 Email:tjy@uisrc.com

Copyright   ©2020-2026 内容版权归©UISRC.COM    ( 苏ICP备19046771号-2 )