基于PYNQ的AD采集系统

本文介绍了如何使用PYNQ-Z2开发板控制AN706AD进行数据采集,通过SPI协议从SPARTAN-6 FPGA传输数据,并通过AXI4-LITE总线将数据传递给ARM核。详细讲解了AN706的控制、SPI通讯的修改、AXI4-LITE总线的理解,以及IP核打包和SDK程序编写的过程。
摘要由CSDN通过智能技术生成

系统概述

打算用PYNQ-Z2开发板做MMC变化器的控制,遇到的第一个问题就是做MMC控制需要采集大量的电容电压、电流信号。但是考虑到XILINX官方的PYNQ-Z2开发板管脚很少,所以使用另一块XLINX的FPGA(SPANTAN-6)接两片黑金的AN706AD进行数据采集,通过SPI协议把采集到的数据从SPI从机传输到位于PYNQ开发板上的SPI主机上。最后通过AXI4-Lite总线传输到ARM核上。系统的总图如下:
在这里插入图片描述

AN706的控制

关于AN706AD的控制,这里直接使用黑金官方的例程就可以了,就是注意去理解其时序,如下图所示:
在这里插入图片描述
直接上代码:

module ad7606(
	input          clk,
	input          rst_n,
        input [15:0]   ad_data,    
        input          ad_busy,    
        input          first_dat
        output [2:0]   ad_os,      
        output reg     ad_cs,      
        output reg     ad_rd,      
        output reg     ad_reset,   
        output reg     ad_convstab,
        output reg [15:0] ad_ch1,
        output reg [15:0] ad_ch2,
        output reg [15:0] ad_ch3,
        output reg [15:0] ad_ch4,
        output reg [15:0] ad_ch5,
        output reg [15:0] ad_ch6,
        output reg [15:0] ad_ch7,
        output reg [15:0] ad_ch8,
        output reg ad_finish
        );
reg [15:0]  cnt;           
reg [5:0] i;               
reg [3:0] state;           
                           
parameter IDLE=4'd0;       
parameter AD_CONV=4'd1;    
parameter Wait_1=4'd2;     
parameter Wait_busy=4'd3;  
parameter READ_CH1=4'd4;   
parameter READ_CH2=4'd5;   
parameter READ_CH3=4'd6;   
parameter READ_CH4=4'd7;   
parameter READ_CH5=4'd8;   
parameter READ_CH6=4'd9;   
parameter READ_CH7=4'd10;  
parameter READ_CH8=4'd11;  
parameter READ_DONE=4'd12; 
                           
assign ad_os=3'b000;
always@(posedge clk)      
 begin                    
    if(cnt<16'hffff) begin
        cnt<=cnt+1;       
        ad_reset<=1'b1;   
      end                 
      else                
        ad_reset<=1'b0;   
   end
always @(posedge clk)                       
 begin                                      
  if (ad_reset==1'b1) begin                 
    state<=IDLE;                            
    ad_ch1<=0;                              
    ad_ch2<=0;                              
    ad_ch3<=0;                              
    ad_ch4<=0;                              
    ad_ch5<=0;                              
    ad_ch6<=0;                              
    ad_ch7<=0;                              
    ad_ch8<=0;                              
    ad_cs<=1'b1;                            
    ad_rd<=1'b1;                            
    ad_convstab<=1'b1;                      
    i<=0;                                   
    ad_finish<=1'b0;                        
  end                                       
  else begin                                
    case(state)                             
    IDLE: begin                             
     ad_cs<=1'b1;                           
     ad_rd<=1'b1;                           
     ad_convstab<=1'b1;                     
     if(i==20) begin                        
      i<=0;                                 
      state<=AD_CONV;                       
     end                                    
     else                                   
      i<=i+1'b1;                            
    end                                     
    AD_CONV: begin                          
     if(i==2) begin                       
      i<=0;                                 
      state<=Wait_1;                        
      ad_convstab<=1'b1;                    
      ad_finish<=1'b0;                      
     end                                    
     else begin                             
      i<=i+1'b1;                            
      ad_convstab<=1'b0;                    
     end                                    
    end                                     
    Wait_1: begin                           
     if(i==5) begin                         
      i<=0;                                 
      state<=Wait_busy;                     
     end                                    
     else                                   
      i<=i+1'b1;                            
    end                                     
    Wait_busy: begin                        
     if(ad_busy==1'b0) begin                
      i<=0;                                 
      state<=READ_CH1;                      
     end                                    
    end                                     
    READ_CH1: begin                         
     ad_cs<=1'b0;                           
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch1<=ad_data;                      
      state<=READ_CH2;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH2: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch2<=ad_data;                      
      state<=READ_CH3;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH3: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch3<=ad_data;                      
      state<=READ_CH4;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH4: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch4<=ad_data;                      
      state<=READ_CH5;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH5: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch5<=ad_data;                      
      state<=READ_CH6;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH6: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch6<=ad_data;                      
      state<=READ_CH7;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH7: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch7<=ad_data;                      
      state<=READ_CH8;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH8: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch8<=ad_data;                      
      state<=READ_DONE;                     
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_DONE:begin                         
      ad_rd<=1'b1;                          
      ad_cs<=1'b1;                          
      state<=IDLE;                          
      ad_finish<=1'b1;                      
    end                                     
    default: state<=IDLE;                   
    endcase                                 
    end                                     
                                            
 end                                        
                                            
endmodule                                                       
       

这里在黑金官方的代码的基础上加入了ad_finish这个输出信号,目的是每次AD读完8个通道的值后告知SPI从机可以进行数据传输了。

SPI通讯

在两个FPGA之间的通讯,准备采用SPI模式,但是因为数据的流动方向只是从SPANTAN-6流向PYNQ-Z2,所以在这里对SPI通讯协议进行了修改。首先在传统的4线SPI模式中,去掉MOSI这根线,其次为了在传输时加大传输速度,把MISO的数据位宽改为16位,与AD输出的位宽相同。传输时遵从在时钟的下降沿从机准备好需要传输的数据,在时钟的上升沿主机采集数据。
下面直接上代码:

从机
//下降沿发送数据                                                                 
module SPI_SLAVE                                                          
(                                                                         
    input clk,                                                            
    input rst_n,                                                          
    input CS_N,                                                           
    input SCK,                                                            
    input tx_en,   //                                                     
    output reg [15:0]MISO,                                                
    input [16*16-1:0] txd_data                                            
);                                                                        
//---------------------spi_slaver send data---------------------------    
reg [3:0] txd_state;                                                      
always@(negedge SCK or negedge rst_n)                                     
begin                                                                     
    if(!rst_n)                                                            
        begin                                                             
            txd_state <= 1'b0;                                            
            MISO<=0;                                                      
        end                                                               
    else if(!CS_N)                                                        
        begin                                                             
            case(txd_state)                                               
                4'd0:begin                                                
                        MISO <= txd_data[255:240];                        
                        txd_state <= 4'd1;                                
                      end                                                 
                
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值