1.  今日摸鱼计划
 
|   今天来学习一下ADC的原理,然后把ADC给实现  ADC芯片:ADC128S102   | 
|   视频:  18A_基于SPI接口的ADC芯片功能和接口时序介绍_哔哩哔哩_bilibili  18B_使用线性序列机思路分析SPI接口的ADC芯片接口时序_哔哩哔哩_bilibili  18C_基于线性序列机的SPI接口ADC控制逻辑设计_哔哩哔哩_bilibili   | 
 
2. ADC指标参数
 

 
3. ADC128S102
 
        在 ACZ702 EDA 扩展板上使用的模数转换器为逐次逼近型的低功耗芯片ADC128S102,其具有 8 通道以及 12 位的分辨率。电源采用独立的模拟供电以及数字供电,其中模拟电源 VA输入范围为 2.7V~5.25V,数字电源 VD输入范围为 2.7V~VA。其与外部通信支持多种接口如:SPI、QSPI、MICROWIRE以及通用的 DSP 接口。转换速度在 500 kps~1 Mkps,典型情况下当 3V 供电时功耗为2.3mW,5V 供电时为 10.7mW,如下图为该 ADC 芯片的内部结构图。 
 

 
芯片引脚功能如下:
 

 
ADC128S102通过 SPI接口与控制器进行通信的时序图如下图所示:
 

 
四线SPI分析:
 
|   CS    |   片选信号(本摸鱼怪不会加横线)  CS拉低,表示通信的开始,CS拉高表示通信结束   | 
| SCLK |   CS 为高时 SCLK  默认高    一帧包含  16  个上升沿  SCLK    | 
| DIN |   SCLK的上升沿,DIN上的信号要保持稳定,此时ADC芯片会对DIN上的信号采样      | 
| DOUT |    当CS 为高时代表空闲状态,当为低时为传输状态    | 
 
4.  线性序列机实现ADC
 
|       | 
  | 
  | 
|   module adc128s102(                  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'd0;      else if(Conv_Go)          Conv_En <= 1'd1;      else if((LSM_CNT == 6'd34) && (DIV_CNT == MCNT_DIV_CNT))          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 <= 6'd0;      else if(DIV_CNT == MCNT_DIV_CNT)begin          if(LSM_CNT == 6'd34)              LSM_CNT <= 6'd0;          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_DIN <= 1'd1;          ADC_CS_N <= 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          Data <= 12'd0;          Conv_Done <= 0;      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   | 
 
5.  adc128s102_tb
 
|   `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);          #2000;                            Conv_Go = 1;          Addr = 7;          #20;          Conv_Go  = 0;                  wait(!ADC_CS_N);          //16'h0893          @(negedge ADC_SCLK);          ADC_DOUT = 0;          @(negedge ADC_SCLK);          ADC_DOUT = 0;          @(negedge ADC_SCLK);          ADC_DOUT = 0;                  @(negedge ADC_SCLK);          ADC_DOUT = 0;                  @(negedge ADC_SCLK);          ADC_DOUT = 1;                    @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 1;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 1;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 0;                   @(negedge ADC_SCLK);          ADC_DOUT = 1;                   @(negedge ADC_SCLK);          ADC_DOUT = 1;                 wait(ADC_CS_N);          #200;              #2000;          $stop;      end  endmodule   | 
 
