这是很早之前用的一段SAR ADC行为模型,后面的部分是静态和动态参数的测试,算法原理就是产生斜波然后利用定义把每一个DNL和INL都计算出来,最后plot,但是ENOB那里可能不是特别准确。
代码写的比较简单,注释都标记好了,唯一的不足可能就是直接产生斜波有点太低效,感觉运行一次要卡很久,对16位来说更是如此,可能还有大改进的空间吧。
% 定义了以基准电压Vref,输入信号Vin和精度N作为变量的电荷再分配型SAR ADC sar_c
function Dout = sar_c(Vref,Vin,N)
sig_c = 1/128; % 定义单位电容的标准偏差
C_nor = [2.^[N-1:-1:0] 1]; % 定义理想电容阵列, 其中默认电位电容为1
C_dev = sig_c*sqrt(C_nor).*randn(1,N+1); % 电容阵列中各电容的标准偏差
C_act = C_nor + C_dev; % 定义实际电容由其均值和标准偏差组成
C_tot = sum(C_act); % 电容阵列的总电容值
Vs = -Vin; % 在采样保持结束时刻,Vx处的采样保持值Vs = -Vin
for i = 1:N
Vx = Vs + Vref*C_act(i)/C_tot; % 在逐次逼近阶段Vx处的电压值
if Vx < 0
D(i) = 1;
Vs = Vx;
else
D(i) = 0; % 根据比较结果得到正确的数字输出
end
end
Dout = 2.^[N-1:-1:0]*D'; % 将ADC的输出转换成了十进制值以方便处理
% 产生一个斜坡信号,进行A/D转换并对非线性误差进行分析
Vref = 2.5; % 定义基准电压为2.5V
N = 12; % 12-bit A/D转换器
% 产生斜坡信号,针对其中均匀分布的2N_in个电压值进行处理
M = 5; %定义每个转换台阶包含的点数为2^M
N_in = N + M;
Vin = [0:1:2^N_in-1]/2^N_in*Vref; % 产生斜坡输入
for i = 1:2^N_in
D(i) = sar_c(Vin(i),Vref,N); % 针对均匀分布的2N_in个电压值进行A/D转换
Do(i) = D(i)*Vref/(2^N);
end
for i = 1:2^N
A = (i-1)*ones(1,2^N_in);
E = D-A;
N(i) = 2^N_in - nnz(E);
DNL(i)=N(i)/2^M - 1;
INL(i) = sum(DNL(1,1:i)); % 计算A/D转换器的DNL和INL
DigOut(i) = i-1;
end
% 显示处理结果 subplot(2,1,1);
plot(DigOut,DNL);
xlabel('Digital Output');
ylabel('DNL(LSBs)');
grid on; subplot(2,1,2);
plot(DigOut,INL);
xlabel('Digital Output');
ylabel('INL(LSBs)'); % plot(Vin*2^N/Vref,(Vin-Do)*2^N/Vref-1/2);xlabel('Digital output'); ylabel('INL(LSBs)');
% 两种计算INL的方法,一种是对DNL进行累积,另外一种是实际曲线与理想曲线的偏差 grid on;
% 计算有效位数
sig2 = Vin*Vin'; % 计算输入信号能量
noi2 = (Vin-Do)*(Vin-Do)'; % 计算噪声能量,这里将输入和输出的差定义成了噪声
SNDR = 10*log10(sig2/noi2); % 计算信噪失真比
ENOB = SNDR/6.02 % 计算A/D转换器的有效位数
水平有限,仅供参考。