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
 | 
 
