Bootstrap

A/D转换控制器的设计

目录

简介

   LTC2308

设计过程:

Verilog代码参考

   FPGA驱动LTC2308的接口电路


简介

A/D转换即模数转换,表示将模拟信号(Analog Signal)转换为数字信号(Digital Signal),A/D转换器是实现模数转换的器件(Analog to Digital Converter,简称ADC)。A/D转换控制器(ADC Controller)是控制A/D转换器进行模数转换的电路或者系统。

ADC应用:(1) 在工业控制领域,普遍采用数字化信息处理技术; (2) 在通信行业,数字信息便于传输和处理;(3) 在电子信息领域,应用数字技术提高系统的性能(精度和可靠性)。

数字系统的优点:(1) 抗干扰能力强; (2) 信息处理强;(3) 信息便于记录传输。

   传统的A/D转换是应用微控制器(Micro-Controller Unit,简称MCU),按照转换器的工作时序控制A/D转换器完成数据的采集。

   受MCU工作速度的限制,这种控制方式在实时性方面有很大的局限性,难以实现高速信号的采集。 若基于FPGA应用状态机控制A/D转换器,则不仅控制速度快,而且可靠性高,这是微控制器控制方法无法比拟的。    特点:  纯硬件控制,工作速度很高。

A/D转换器控制与数据接口:

(1) 并行接口;(2) I2C;(3) SPI;(4) ...

   LTC2308

是ADI(亚德诺)公司推出的8通道12位A/D转换器,内部电路结构如图所示,由8通道模拟开关、12位逐次渐近型A/D转换器、内置基准源和4线SPI兼容型串行接口组成。    特性:(1) 最高采样时钟500kHz;  (2) 转换速度2.0µs.

   LTC2308的8通道模拟量输入端CH0~CH7可配置为单端输入、差分输入和混合输入三种类型,如图所示。

单极性:0~4.096V, 转换为12位无符号二进制数

双极性:-2.048V~2.048V, 转换为12位有符号二进制数

   LTC2308提供了4线SPI兼容性串行接口,可应用MCU或者FPGA控制A/D转换过程和配置转换参数。CONVST(Conversion Start)为A/D转换启动信号,有长、短两种时序方式。短CONVST时序如图6-56所示,其中SDI为串行数字输入端,用于设置A/D转换控制字,SDO为串行数字输出端,用于输出A/D转换得到的数字量。SCK为串行数据时钟。

   LTC2308的转换通道配置如表所示,其中S/D(Single ended/Differntial Bit)用于设置单端输入模式还是差分输入模式。O/S(Odd/Sign bit)在差分输入模式时用于设置差分信号的极性,在单端输入时与(Address Select bit)S1和S0一起作为3位通道选择地址(S1,S0,O/S)。

设计过程:

设计60进制计数器,并设状态分别用0~59表示。定义状态为2时产生启动脉冲CONVST,定义状态为3时更新转换控制字以切换转换通道,定义状态为44~55时生成12个数据时钟SCK,定义状态为57时输出12位转换数据,定义状态为56和58时分别输出转换数据无效和有效标志。

Verilog代码参考

根据上述设计思路,描述LTC2308转换控制器的Verilog代码参考如下:

module LTC2308_controller(
    // 输入输出端口定义
    input          clk50M,      // 50M晶振信号     
    input          rst_n,            // 复位信号
    input [2:0]   iCHNo,           // 转换通道号输入
    input          iSDO,            // 串行转换数据输入
    output wire         CONVST, // 启动脉冲输出
    output wire         oSCK,     // 数据时钟输出
    output reg          oSDI,     // 转换控制字输出
    output wire [2:0]  oCHNo,    // 转换通道号输出
    output reg          oADrdy,  // 转换数据有效标志
    output reg [11:0]  oADdat   // 并行转换数据输出
    );
    // 控制参数定义
    parameter uni_mode = 1'b1,slp_mode = 1'b0;
    // 通道参数定义,单端单极性输入                       // UNI:UNIpolar/BIpolar bit
    localparam CH0 = {4'h8,uni_mode,slp_mode};       // SLP: SLEEP MODE Bit
    localparam CH1 = {4'hC,uni_mode,slp_mode};       //       =0/1:NAP/sleep mode
    localparam CH2 = {4'h9,uni_mode,slp_mode};
    localparam CH3 = {4'hD,uni_mode,slp_mode};
    localparam CH4 = {4'hA,uni_mode,slp_mode};
    localparam CH5 = {4'hE,uni_mode,slp_mode};
    localparam CH6 = {4'hB,uni_mode,slp_mode};
    localparam CH7 = {4'hF,uni_mode,slp_mode};
    // 内部变量定义
    reg         clk;           // 25MHz内部时钟
    reg [5:0]  cnt;           // 状态计数变量 
    reg [5:0]  CHtmp;       // 通道控制字寄存器 
    reg [11:0] SDO_reg;    // 转换数据寄存器   
    // 25MHz时钟生成  
    always @( posedge clk50M or negedge rst_n )   
        if ( !rst_n )   clk = 0;
           else   clk = clk + 1'b1;
    // 时序逻辑过程,描述60进制计数器
    always @( posedge clk or negedge rst_n )    
        if ( !rst_n )   cnt <= 6'd0;
        else if ( cnt == 6'd59 )   cnt <= 6'd0;
            else   cnt <= cnt + 1'b1;
    // CONVST脉冲生成逻辑
    assign CONVST = ( cnt == 6'd2 )? 1'b1 : 1'b0;
    always @( posedge clk )  // 通道控制字更新逻辑
       if ( cnt == 6'd3 )
          case ( iCHNo )
             3'b000: CHtmp = CH0;
             3'b001: CHtmp = CH1;
             3'b010: CHtmp = CH2;
             3'b011: CHtmp = CH3;
             3'b100: CHtmp = CH4;
             3'b101: CHtmp = CH5;
             3'b110: CHtmp = CH6;
             3'b111: CHtmp = CH7;
             default: CHtmp = CH0;
          endcase
     // 数据时钟生成逻辑
    assign oSCK = (( cnt >= 44 ) && ( cnt <= 55))? clk : 1'b0;    
    // 通道号输出逻辑
    assign oCHNo = iCHNo;
    // 转换控制字输出过程,比数据时钟SCK提前半个时钟周期
    always @( negedge clk )
        case ( cnt )
           6'd43: oSDI =  CHtmp[5];
           6'd44: oSDI =  CHtmp[4];
           6'd45: oSDI =  CHtmp[3];
           6'd46: oSDI =  CHtmp[2];
           6'd47: oSDI =  CHtmp[1];
           6'd48: oSDI =  CHtmp[0];
          default: oSDI = 1'b0;
          endcase
     // 在数据时钟的上升沿读取转换数据
     always @( posedge clk )
        case ( cnt )
           6'd44: SDO_reg[11] =  iSDO;
           6'd45: SDO_reg[10] =  iSDO;
           6'd46: SDO_reg[9]  =  iSDO;
           6'd47: SDO_reg[8]  =  iSDO;
           6'd48: SDO_reg[7]  =  iSDO;
           6'd49: SDO_reg[6]  =  iSDO;
           6'd50: SDO_reg[5]  =  iSDO;
           6'd51: SDO_reg[4]  =  iSDO;  
           6'd52: SDO_reg[3]  =  iSDO;
           6'd53: SDO_reg[2]  =  iSDO;         
           6'd54: SDO_reg[1]  =  iSDO;  
           6'd55: SDO_reg[0]  =  iSDO;
          default: SDO_reg  =  SDO_reg;
      endcase
    // 时序过程,转换数据输出
    always @( posedge clk )
        if ( cnt == 6'd57 )
             oADdat <= SDO_reg;
   // 转换数据标志输出过程
   always @( posedge clk ) begin
       if ( cnt == 6'd56 )  oADrdy <= 1'b0; // 无效
       if ( cnt == 6'd58 )  oADrdy <= 1'b1; // 有效
       end   
endmodule

  建立向量波形文件,设置仿真结束时间为2.6µs。若设置iSDO始终为高电平,启动Modelsim进行仿真,结果如图所示。从图中可以看出,LTC2308转换控制器时序正确。

   FPGA驱动LTC2308的接口电路

如图所示,由FPGA片内的软核或者硬核处理器系统驱动LTC2308_controller控制LTC2308的模拟量采集过程和转换数字量的读取。

   对于单端单极性输入,LTC2308采集的模拟电压vI与转换得到的数据D之间的关系为: vI =(D/1024)×4.096=D/1000 (V),其中4.096为LTC2308内部基准源的电压值,并且注意输入模拟电压vI应在0~4.096V之间。

   LTC2308具有多路模拟量输入通道以及较高的转换速率和分辨率,常用于信号的正交解调、医疗成像、高速数据采集、工业过程控制、仪表和自动测试设备等多种应用场合。

;