FPGA-基于SPI接口的ADC芯片功能和接口时序介绍

ADC: Analog-to-Digital Converter,模/数转换器。

通常是指一个将模拟信号转变为数字信号的电子元件。像我们生活中常见的温度、湿度、电压、电流这些能够用连续变化的物理量所表达的信息,都属于模拟信号;而数字信号,则是在模拟信号的基础上,经过采样、量化和编码而形成的,也就是由许多个0和1组成的信号。

ADC常见指标参数:

分辨率:指ADC能够分辨量化的最小信号的能力,用二进制位数表示。常见的有8位分辨率、12位分辨率、16位分辨率等等。例如, 8位分辨率,就是可以将模拟信号量化为一个8位的数据,数值范围就是0~255

采样范围: ADC作为模拟转数字的器件,其能够进行转换的模拟信号的范围总是有限的,而且一般不高。比如ADC0809,其能够进行转换的模拟电压范围就是0~5V,超出这个范围的模拟电压, ADC0809就不能将其转换为准确的数字信号。

采样速率:也就是这个ADC一秒钟内能够进行多少次模拟量到数字量的转换。高速ADC一秒钟内可以执行几十兆,甚至几百兆次的转换。但是这样的高速ADC,一般价格都非常贵,常用在雷达、无线通信,示波器等领域。普通的ADC,采样速率在几Hz~几Mhz之间。3

上述例子假设采样结果为x,则电压为  U=x*5/(2^8)

手册中的介绍

手册中数据量和模拟量的数据关系图(非线性)

ADC128S102时序图

ADC芯片连续不间断转换图

模块框图

实现单次转换时序

(至少34个时间段)

CS和SCLK的时间间隔(>=10ns)

SCLK : 8MHZ-16MHZ(16MHZ周期是61.5ns则半个周期就是31.25ns大于10ns)

进行一轮转换时刻表

设计思路

设计代码如下

module adc128s102(
    Clk,
    Reset_n,
    
    Conv_Go,
    Addr,
    
    Conv_Done,
    Data,
    
    ADC_SCLK,
    ADC_CS_N,
    ADC_DIN,
    ADC_DOUT
 );
    input Clk;
    input Reset_n;
    
    input Conv_Go;
    input [2:0]Addr;
    
    output reg Conv_Done;
    output reg [11:0]Data;
    
    output reg ADC_SCLK;
    output reg ADC_CS_N;
    output reg ADC_DIN;
    input ADC_DOUT;
    
    parameter CLOCK_FREQ = 50_000_000;
    parameter SCLK_FREQ = 12_500_000;
    parameter MCNT_DIV_CNT = CLOCK_FREQ /( SCLK_FREQ * 2) -1;
    
    reg[7:0]DIV_CNT;
    reg[5:0]LSM_CNT;
    reg[11:0]Data_r;
    reg[2:0]r_Addr;
    
    always@(posedge Clk)
    if(Conv_Go)
        r_Addr <= Addr;
    else
        r_Addr <= r_Addr;
        
    reg Conv_En;//转换使能
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
       Conv_En  <= 1'b0;
    else if(Conv_Go)
        Conv_En <= 1'b1;
    else if((LSM_CNT == 6'd34)&&(DIV_CNT == MCNT_DIV_CNT -1))
        Conv_En <= 1'd0;
    else
        Conv_En <= Conv_En;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)  
        DIV_CNT <=0;
    else if(Conv_En) begin
        if(DIV_CNT == MCNT_DIV_CNT)
            DIV_CNT <= 0;
        else
            DIV_CNT <= DIV_CNT + 1'd1;
    end  
    else
        DIV_CNT <= 0;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        LSM_CNT <= 0;
    else if(DIV_CNT == MCNT_DIV_CNT)begin
        if(LSM_CNT == 6'd34)
            LSM_CNT <= 0;
        else
            LSM_CNT <= LSM_CNT + 1'd1;
    end
    else
        LSM_CNT <= LSM_CNT;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)  begin
        Data_r <= 12'd0;
        ADC_SCLK <= 1'd1;
        ADC_CS_N <= 1'd1;
        ADC_DIN <= 1'd1;
    end
    else if (DIV_CNT == MCNT_DIV_CNT) begin
        case(LSM_CNT)
            0 : begin ADC_CS_N <= 1'D1; ADC_SCLK <= 1'D1; end 
            1 : begin ADC_CS_N <= 1'D0;  end
            2 : begin ADC_SCLK <= 1'D0; end
            3 : begin ADC_SCLK <= 1'D1; end
            4 : begin ADC_SCLK <= 1'D0; end
            5 : begin ADC_SCLK <= 1'D1; end
            6 : begin ADC_SCLK <= 1'D0; ADC_DIN <= r_Addr[2];end
            7 : begin ADC_SCLK <= 1'D1; end
            8 : begin ADC_SCLK <= 1'D0; ADC_DIN <= r_Addr[1];end
            9 : begin ADC_SCLK <= 1'D1; end
            10 : begin ADC_SCLK <= 1'D0; ADC_DIN <= r_Addr[0];end
            11 : begin ADC_SCLK <= 1'D1; Data_r[11] <= ADC_DOUT;end
            12 : begin ADC_SCLK <= 1'D0; end
            13 : begin ADC_SCLK <= 1'D1; Data_r[10] <= ADC_DOUT;end
            14 : begin ADC_SCLK <= 1'D0; end
            15 : begin ADC_SCLK <= 1'D1; Data_r[9] <= ADC_DOUT;end
            16 : begin ADC_SCLK <= 1'D0; end
            17 : begin ADC_SCLK <= 1'D1; Data_r[8] <= ADC_DOUT;end
            18 : begin ADC_SCLK <= 1'D0; end
            19 : begin ADC_SCLK <= 1'D1; Data_r[7] <= ADC_DOUT;end
            20 : begin ADC_SCLK <= 1'D0; end
            21 : begin ADC_SCLK <= 1'D1; Data_r[6] <= ADC_DOUT;end
            22 : begin ADC_SCLK <= 1'D0; end
            23 : begin ADC_SCLK <= 1'D1; Data_r[5] <= ADC_DOUT;end
            24 : begin ADC_SCLK <= 1'D0; end
            25 : begin ADC_SCLK <= 1'D1; Data_r[4] <= ADC_DOUT;end
            26 : begin ADC_SCLK <= 1'D0; end
            27 : begin ADC_SCLK <= 1'D1; Data_r[3] <= ADC_DOUT;end
            28 : begin ADC_SCLK <= 1'D0; end
            29 : begin ADC_SCLK <= 1'D1; Data_r[2] <= ADC_DOUT;end
            30 : begin ADC_SCLK <= 1'D0; end
            31 : begin ADC_SCLK <= 1'D1; Data_r[1] <= ADC_DOUT;end
            32 : begin ADC_SCLK <= 1'D0; end
            33 : begin ADC_SCLK <= 1'D1; Data_r[0] <= ADC_DOUT;end
            34 : begin ADC_SCLK <= 1'D1; ADC_CS_N <= 1'D1; end
            default : ADC_CS_N <= 1'D1; 
        
        endcase
    end
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)  begin   
        Conv_Done <= 0;
        Data <= 12'd0;
        end
    else if((LSM_CNT == 34)&&(DIV_CNT == MCNT_DIV_CNT))begin    
        Conv_Done <= 1'd1;
        Data <= Data_r;
    end
    else begin
        Conv_Done <= 1'd0;
        Data <= Data;
    end
       
    
endmodule

然后编写testbench测试文件 

代码如下

`timescale 1ns / 1ns
module adc128s102_tb;
    reg Clk;
    reg Reset_n;
    
    reg Conv_Go;
    reg [2:0]Addr;
    
    wire Conv_Done;
    wire [11:0]Data;
    
    wire ADC_SCLK;
    wire ADC_CS_N;
    wire ADC_DIN;
    reg ADC_DOUT;    
    
    adc128s102 adc128s102(
        .Clk(Clk),
        .Reset_n(Reset_n),
        
        .Conv_Go(Conv_Go),
        .Addr(Addr),
        
        .Conv_Done(Conv_Done),
        .Data(Data),
        
        .ADC_SCLK(ADC_SCLK),
        .ADC_CS_N(ADC_CS_N),
        .ADC_DIN(ADC_DIN),
        .ADC_DOUT(ADC_DOUT)
     );
     
     initial Clk =1;
     always #10 Clk = ~Clk;
     initial begin
        Reset_n = 0;
        Conv_Go = 0;
        Addr = 0;
        #201;
        Reset_n = 1;
        #200;
        Conv_Go = 1;
        Addr = 3;  
        #20;
        Conv_Go = 0;  
        wait(!ADC_CS_N );
        //16'h0A58
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB15
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB14
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB13
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB12
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB11
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB10
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB9
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB8
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB7
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB6
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB5
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB4
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB3
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB2
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB1
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB0
        wait (ADC_CS_N);
        #20000;
        
        Conv_Go = 1;
        Addr = 7;
        #20;
        Conv_Go = 0;
        wait(!ADC_CS_N );
        //16'h0893
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB15
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB14
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB13
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB12
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB11
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB10
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB9
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB8
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB7
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB6
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB5
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB4
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB3
        @(negedge ADC_SCLK);
        ADC_DOUT = 0; //DB2
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB1
        @(negedge ADC_SCLK);
        ADC_DOUT = 1; //DB0
        wait (ADC_CS_N);
        #200;
        #2000;
        $stop;
     end
endmodule

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA可以通过模拟SPI接口来驱动ADCSPI接口通常用于与Flash、ADC、LCD控制器等设备进行通信。在FPGA中,可以使用FPGA内部的逻辑电路来模拟SPI接口功能。通过控制FPGA的引脚和时序,可以实现与ADC的通信。 在模拟SPI接口时,需要定义时钟信号、复位信号、使能信号和数据信号等。时钟信号用于同步数据传输,复位信号用于初始化接口,使能信号用于控制数据传输的开始和结束,数据信号用于传输具体的数据。 具体实现时,可以使用FPGA的时钟模块来生成时钟信号,使用寄存器来存储和控制数据,使用逻辑门来实现SPI接口功能。通过编写Verilog或VHDL代码,可以描述FPGA的逻辑电路,并进行仿真和验证。 在模拟SPI接口驱动ADC的过程中,需要根据ADC的规格和时序要求来配置FPGA的引脚和时钟频率。通过发送控制信号和数据,可以实现与ADC的通信和数据采集。 总结来说,FPGA可以通过模拟SPI接口来驱动ADC,通过配置引脚和时序,控制数据传输和采集。这样可以实现FPGAADC之间的数据交互和通信。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [D2--FPGA SPI接口通信2022-08-03](https://blog.csdn.net/weixin_40615338/article/details/126145035)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [FPGA_SPI驱动设计](https://blog.csdn.net/qq_43485409/article/details/109138893)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值