Vcm-based时序的SAR,matlab代码
已完成:Vcm-based时序,比较器噪声与失调,电容失配,kT/C噪声,建立时间
未完成:功耗计算,冗余校正,后端校准
留档自用,复制进matlab内可直接运行。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Set parameter %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameter
Resol = 12;
FFTN = 2^Resol; % FFT number,namely,least SamplePoints
Fs =40e6;
Fin = 61*Fs/2^Resol; % 31 can be replaced other 质数
%Conversion parameter
Vcm = 0.55;
VFS = 1.1;
Vrefp = 1.1;%VDD
Vrefn = 0;%GND
% Comp parameter
Vos = 500e-6;
CompNoise = 500e-6 * randn(1,Resol);
% Sample parameter
R = 0.5e3; %Switch Ron
C = 0.125e-12; %Cap total 2pF~14bit 125f~12bit C*4,bit+1
tau = R*C;
% Setting time
Tcomp = ((1/Fs)/(Resol+3+1)); %3是采样;1可改,代表多出来的时间取出digital code
Tcompset = Tcomp/2;%只有一半的时间周期建立
Tsampleset = 3*Tcomp; %同步时序一般是3*Tcomp
K_sampleset = Tsampleset/tau %对于10bit,建立系数7.6
K_compset = Tcompset/tau % 12bit,建立系数9
% 14bit,建立系数10.4
% Cap Noise parameter
k = 1.38*1e-23;
T = 300;
Noise_kT_C = (k*T/C)^0.5;
NoisePos = 0.5*Noise_kT_C * randn(1,FFTN);
NoiseNeg = 0.5*Noise_kT_C * randn(1,FFTN);
% CDAC_Weight parameter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Accoding Resol,generate CapWeight,<16bit %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CapWeight = [32768,16384,8192,4096,2048,1024,...
512,256,128,64,32,16,8,4,2,1,1];% last "1" is dummy
% can be delete
CapWeight = flip(CapWeight);
CapWeight = CapWeight(1:Resol+1);
CapWeight = flip(CapWeight);
C_totalWeight= sum(CapWeight);%总权重,10bit 2048
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CapMismatch = 0.00;
CapWeightPos = normrnd( CapWeight, sqrt( CapWeight ) * CapMismatch );
CapWeightNeg = normrnd( CapWeight, sqrt( CapWeight ) * CapMismatch );
C_totalPos = sum(CapWeightPos);
C_totalNeg = sum(CapWeightNeg);
% When Sample
t = 0:1/Fs:(FFTN-1)*(1/Fs);
Vip = Vcm+VFS/2*sin(2*pi*Fin*t)+NoisePos;
Vin = Vcm-VFS/2*sin(2*pi*Fin*t)+NoiseNeg;
%Trend Vp & Vn
Burst = 1; %第 burst 次的量化结果
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Vcm-based logic %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tic; % 记录开始时间
D_record = zeros(FFTN, Resol);
Vp_record = zeros(FFTN, Resol+1);
Vn_record = zeros(FFTN, Resol+1);
for SamPoint = 1:FFTN % certain Sample
Vp = Vip(SamPoint)*(1-exp(-Tsampleset/tau));
Vn = Vin(SamPoint)*(1-exp(-Tsampleset/tau));
Vp_record (SamPoint,1) = Vp;
Vn_record (SamPoint,1) = Vn;
D = zeros(1, Resol);
for bit = 1:Resol % quantitize
if Vp + CompNoise(bit) + Vos >= Vn
D(bit) = 1;
Vp = Vp - (VFS / 2 * CapWeightPos(bit) / C_totalPos) ...
* (1-exp(-Tcompset/tau));
Vn = Vn + (VFS / 2 * CapWeightNeg(bit) / C_totalNeg) ...
* (1-exp(-Tcompset/tau));
Vp_record (SamPoint,bit+1) = Vp;
Vn_record (SamPoint,bit+1) = Vn;
else
D(bit) = 0;
Vp = Vp + (VFS / 2 * CapWeightPos(bit) / C_totalPos) ...
* (1-exp(-Tcompset/tau));
Vn = Vn - (VFS / 2 * CapWeightNeg(bit) / C_totalNeg) ...
* (1-exp(-Tcompset/tau));
Vp_record (SamPoint,bit+1) = Vp;
Vn_record (SamPoint,bit+1) = Vn;
end
end
D_record(SamPoint,:) = D;
end
% ↑↑↑ D_record gets all sample points' quantitize digital code
DACWeight = CapWeight(1:Resol)';%注意转置
Dout = D_record*DACWeight;
Dout = Dout/2^(Resol)*2*VFS-VFS;
elapsed_time = toc; % 记录结束时间并计算经过的时间
disp(['Elapsed time: ' num2str(elapsed_time) ' seconds']);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plot Vip & Vin %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %绘制图像
% figure(1);
%
% plot(t, Vip);
% %title('Vip');
% xlabel('Time (s)');
% ylabel('Voltage (V)');
% hold on
% plot(t, Vin);
% %title('Vin');
% xlabel('Time (s)');
% ylabel('Voltage (V)');
% hold off
% %调整图像布局
% sgtitle('Vip and Vin Signals');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Trend of Vp & Vn %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(2)
% Vp_record = reshape(Vp_record',1,[]);
% Vn_record = reshape(Vn_record',1,[]);
% new_t = 1:1:(Resol+1)*4096;
% stairs(new_t,Vp_record,'r');
% hold on
% stairs(new_t,Vn_record,'b');
% hold off
new_t = 1:1:Resol+1;
stairs(new_t,Vp_record(Burst,:),'r');
hold on
stairs(new_t,Vn_record(Burst,:),'b');
hold off
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Energy consumption %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plot Vi & Dout %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 绘制图像
figure(3);
% 合并子图并绘制 Vip - Vin
subplot(1,1,1);
plot(t, Vip - Vin, 'r'); % 使用红色实线
hold on; % 开启 hold on 模式
% 延迟一个采样周期绘制 Dout
% 使用 plot 函数画阶梯状曲线
t_delay=t(2)-t(1);
stairs(t+t_delay, Dout, 'b'); % 使用蓝色阶梯状线,延迟一个时间步长
xlabel('Time (s)');
ylabel('Voltage (V)');
legend({'Vip - Vin', 'Dout'}, 'Location', 'best');% 添加图例
hold off;% 关闭 hold on 模式
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT calculate SNDR,ENOB %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Dout=reshape(Dout,'',1)';%注意转置
Dout=Dout-(max(Dout(1:end))+min(Dout(1:end)))/2;
% figure(4);
% hold on;
% stairs(Dout(1:FFTN));%权值量
numpt2=fix(FFTN/2);
Dout=Dout(1:FFTN);
Window=hann(FFTN)';%汉宁窗口,注意转置
span=5;
Doutw=Dout.*Window;
DoutFFT=fft(Doutw,FFTN);
SumPower=(abs(DoutFFT)).*(abs(DoutFFT));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%不归一化,则可以不计算最大功率并删除/maxPower %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
maxPower = max(SumPower);% 计算最大功率值
SumPower_dB=10*log10(SumPower/maxPower);%归一化
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[MaxdB,FinPoint]=max(SumPower_dB(1:numpt2));
spanh=3;
DcPower=sum(SumPower(1:span));
if FinPoint>span
SinglePower=sum(SumPower(FinPoint-span:FinPoint+span));
else
SinglePower=0;
end
SingleHarmonyNumber2=floor(FFTN/FinPoint);%或者为Fs/(Fin)
SingleHarmonyPower=zeros(SingleHarmonyNumber2);
SingleHarmonyPower(1)=SinglePower;
SingleHarmonyFrequency=zeros(SingleHarmonyNumber2);
SingleHarmonyFrequency(1)=Fs*(FinPoint)/FFTN;
SingleHarmonyStep=FinPoint;
for SingleHarmonyNumber=1:SingleHarmonyNumber2/2
if (SingleHarmonyStep<=0) break; end
HarmonyFrequencyPoint=SingleHarmonyStep*SingleHarmonyNumber+FinPoint;
if (HarmonyFrequencyPoint<=numpt2)
if SingleHarmonyNumber==1
BaseHarmonyFrequencyPoint=HarmonyFrequencyPoint;
end
SingleHarmonyPower(SingleHarmonyNumber+1)=sum(SumPower(HarmonyFrequencyPoint-spanh:HarmonyFrequencyPoint+spanh));
SingleHarmonyFrequency(SingleHarmonyNumber+1)=(HarmonyFrequencyPoint)*Fs/FFTN;
end
end
Fin=SingleHarmonyFrequency(1);
HarmonyPowerNumber=floor(FFTN/FinPoint)/2;%或者为Fs/(Fin)/2
HarmonyPower=sum(SingleHarmonyPower(1:HarmonyPowerNumber))-SingleHarmonyPower(1);
NoisePower=sum(SumPower(1:numpt2))-DcPower-SinglePower;
ss=sqrt((sum(Dout.^2)/sum(Doutw.^2))*NoisePower*2)/FFTN;%*sqrt(12);
HarmonyRange=floor(FFTN/FinPoint)/2;%或者为Fs/(Fin)/2
SNDR=10*log10(SinglePower/NoisePower);
THD=10*log10(HarmonyPower/SingleHarmonyPower(1));
SFDR=10*log10(SingleHarmonyPower(1)/max(SingleHarmonyPower(2:HarmonyRange)));
ENOBloc=(SNDR-1.76)/6.02;
figure(5);
hold on;
semilogx([0:numpt2-1] * Fs / FFTN, SumPower_dB(1:numpt2), '-');
text_handle = text(Fin * 5, -20, sprintf('SNDR = %4.1f dB \nENOB = %2.2f bits ', SNDR, ENOBloc), ...
'EdgeColor', 'red', 'LineWidth', 3, 'BackgroundColor', [1 1 1], 'Margin', 10);
title('FREQ DOMAIN');
xlabel('ADC FFT SPECTRUM');
ylabel('AMPLITUDE(dB)');
set(gca, 'XScale', 'log'); % 将当前坐标轴改为对数轴,去除该行则线性x轴坐标。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%