Jerome_Cool的模拟人生
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1、施密特触发器阈值电压计算方法
施密特触发器阈值电压计算方法
本文内容并非原创,均摘自I. M. Filanovsky and H. Bakes的“CMOS Schmitt Trigger Design”。
总结一下,以备不时之需。
近似的模型:
分析认为M2刚导通时触发器翻转,即l(m2)= 0,且此时M1和M3均处于饱和区。
根据上述分析,有(1)~(3),从而得到(4)。
相似的过程对M4~M6进行分析可以得到(5)。
公式(4)、(5)便可以用来指导触发器的各管宽长比设计。
更为精确的模型:
考虑触发器在翻转阈值附近时流过M2的电流,电路模型如图。
触发器翻转点为正反馈环路增益为1的临界点。
记流过M2的电流为ΔI,有(6)~(8)。
假定gm2*ro1>>1,ΔI<<I(m1),根据(6)~(8)可化简推导得到ΔI,进而得到阈值电压修正量ΔVH和ΔVL。
2、
怎样做一个电流镜?
对于高手而言,这是一个如吃饭走路般几乎无意识的行为,而对于吾等菜鸟,这真是个问题!我们关注的指标无外乎功耗、面积、失配、PSR等,一个优化的设计应该在这几项指标之间取得折衷。
一、功耗、面积、失配:
首先考虑如图所示的基本结构。
通常用作电流镜的MOS管都具有较大的L、W值,因此可以使用经典平方律模型来分析:
(A)如果给定的约束条件为电流、失配、最大Vgs电压,则至少需要的版图面积计算如下:由(2)式计算出L,进而由(1)式计算得到W。
(B)如果给定的约束条件为面积、失配,则可以根据(3)计算出所需的Vgs电压,而W/L 与Id解不唯一,确定其中一个变量后另一个变量也随之确定。
Note:一个有趣的现象是,根据(3),如果你的boss同时给定了面积、失配、Vgs三项约束条件,结果可能是——无解!
现在考虑稍微复杂一点的情况,如下图所示的两次镜像及多输出支路。
假定P支路数目与N支路数目之比为k,每个PMOS与NMOS面积分别为Ap和An,
根据上面的(3)式,(ΔId/Id)=2 * Avt / Vov / Area,可以得到
mis_tot^2 = ( Kc_p / Ap )^2 + ( Kc_n / An )^2, 其中Kc_p = 2 * Avt_p / Vov_p,Kc_n 类似。
且满足k*Ap + An = Area_tot
通过简单的数学推导,实现最小的mis_tot的条件是:
单个支路PMOS与NMOS的面积之比 Ap / An = [ (Kc_p / Kc_n )^2 / k ] ^ (1/3) PMOS与NMOS的总面积之比 (k*Ap) / An = ( k *Kc_p / Kc_n ) ^ (2/3)
二、noise、PSR,kickback:
从热噪声及闪烁噪声的产生角度看,我们应该尽可能使用大的Vdsat,Id,以及WL;然而从PSR角度看,我们通常期望更大的本征增益,即小的Vdsat,以及Id。
不过,对待noise、PSR,还有kickback,一致的是,我们都可以通过filtering来降低其影响。
对于多次镜像结构,总的原则是应该将LPF电容加到靠近输出级的gate节点以及impedance较大的gate 节点。
三、cacsode结构
在headroom足够的情况下,增加一层cascode管可以有效的提高PSR。
需要注意的是,cascode管的偏置电压需要trade-off:低温下,Vth_c较大,A点电压较低,迫使Ms趋向
于线性区;高温下,Vdsat_c增大而Vds_c通常会变小,从而使Mc趋向于线性区。
3、
matlab的代码效率调试工具profiler
matlab提供了一个非常有用的工具profiler,用来对matlab代码的运行效率进行分析,通
过profiler,我们可以了解每行代码的运行情况,包括运行时间和调用次数等,找出程序运
行时间瓶颈从而有针对性的进行改进。
1. 打开profiler.
打开方式有以下几种:
a,在matlab desktop下,Desktop->Profiler.
b,在M文件编辑器下,Tools->Open Profiler.
c,在命令行直接输入,frofile viewer
2. 运行profiler.
在Run this code后面的输入框里输入要运行的代码或者M文件名,点击Start Profiling或
者按回车。
3. 查看Profile Detail Report。
程序运行完成后,profile summary会以网页的形式显示,通过网页中的超链接可以查看到
代码所调用的所有方法中的任何一行代码的运行情况,并且能够标示耗用时间最多的代码行。
报告通过对这些代码行按照占用时间的比例使用不同的色温图的颜色作背景,可以非常清晰的分析代码效率。
4、一个INV的jitter PSR
所谓反相器(inverter)的jitter PSR,楼主指的是DVDD上的noise对反相器输出信号的jitter 的影响。
在低频段,DVDD噪声会调制INV的in-out delay;而在高频段,DVDD噪声可能直接在INV的输出造成glitch,或者,在输入端造成glitch,再由INV传递至输出。
影响INV jitter对DVDD敏感性的因素主要有:
1,Input swing & rising edge
一般来讲,INV的输入信号摆幅越小,则INV的in-out delay越大;而且,与此同时,INV 的∂(delay)/∂(dvdd)也会越大。
而当输入摆幅确定后,输入信号的rising edge同样会影响∂(delay)/∂(dvdd)……
不多废话,下图为根据某工艺的单个INV的∂(delay)/∂(dvdd),包含了TT,55c,DVDD、SS,-40c,-10%DVDD、FF,125,+10%DVDD,0.1~1V的输入摆幅,以及6种不同的rising edge 的情况,一图胜千言。
2,Device mismatch
这一点似乎不是那么的显而易见。
直观上笔者是这么理解的:在下图所示的offset情况下,PMOS的Vgs会增大,从而让PMOS在更多的时间内处于非饱和状态,这样会使DVDD的噪声更多的couple到INV输出,导致较差的jitter。
根据仿真,INV的threshold offset大约会额外贡献5~10%的∂(delay)/∂(dvdd)。
3,Input signal PSR
这一条主要从瞬态的角度来理解,如果输入信号的PSR较差,当DVDD上施加一个step时,input signal上也会同时产生一个step;类似的,如果INV的输出对DVDD有较大电容时,DVDD上的step也可能造成INV输出的glitch。
总结如下:
1,在实际应用中,某些场合下需要特别关注INV的jitter PSR:
A)AC level shift中,由于INV通常工作在非满摆幅状态,因此更容易受到DVDD noise的影响。
当jitter performance非常关键时,take care about the signal swing!
B)BUFER chain中,多级INV的∂(dly)/∂(dvdd)相叠加,有可能会在输出端产生相当可观的jitter。
2,进行仿真时,worst case的设定应该同时考虑input signal以及device mismatch。
5、Matlab辅助简单模拟电路的EDA优化程序(1)到(8)Matlab辅助简单模拟电路的EDA优化程序(1)
这套程序是在研究生阶段和一位很有才的师弟zhaow一起搞的,但工作以后就一直荒废在那儿了。
现在看来,当年的想法还是简单了一点,只考虑了everything is typical 的情况,现在知道了要cover corner。
看来,EDA的最终目标还任重道远~~
整套程序分为两部分,目录结构如下:
公共部分,位于/EDA/OptPlatform/ 下,包含
器件模型库建立、加载函数:loadLib.m,CreatTable.m
器件模型库查询、解析函数:P_getSize,N_getSize,P_parse,N_parse
优化算法函数(均为带约束条件的多变量优化函数),目前有:
质子群算法pso_min.m,
萤火虫算法ffa_min.m,
人工鱼算法afsa_min.m,
退火算法sa_min.m。
应用部分,位于/EDA/Apps/ 下,每一个优化应用都包含两个文件:
优化程序文件XXX_min.m,包含优化目标,优化变量取值范围,优化算法设置
电路描述文件XXX_Description.m,包含待优化电路的数学模型。
用户可以自己编写新的优化应用。
Matlab辅助简单模拟电路的EDA优化程序(2)
模型库建立程序CreatTable.m。
关于这个方法的说明请移步《应用于matlab辅助EDA的器件模型的查表法实现》
/jerome_cool/blog/item/23637e15b2721a6ccb80c46e.html
所谓的模型库其实就是若干张巨大的3维表格。
这次还需要说明的是,该方法在第一次建立某工艺的模型库时,需要从sw0文件中读取数据,速度较慢。
程序会将模型数据另存一份mat格式的数据,提高以后的加载速度。
=================================
global libSelect libSel FLAG;
tic;
FLAG = 0;
if nargin<1
FLAG = 0;
libSelect = 'null';
return;
end
libPath = '.';
switch libSel
case 'tsmc055lp'
libPath='..\tsmc_055lp';
case 'tsmc18'
libPath='..\tsmc18';
%------------------------------------
case 'chrt18'
libPath='..\CHRT018IC';
case 'smic18'
libPath='..\smic18mmrf';
%------------------------------------
case 'smic13'
libPath='..\smic13_1233';
case 'smic65'
libPath='..\smic65';
end
if libPath == '.'
FLAG = 0;
libSelect = 'null';
return;
end
%----------------------------------------
libSelect = libSel;
clear plen pgs pds pgm_id pgds_id pcgg_id pcgd_id pcdd_id pid_w;
clear nlen ngs nds ngm_id ngds_id ncgg_id ncgd_id ncdd_id nid_w;
%----------------------------------------
global plen pgs pds pgm_id pgds_id pcgg_id pcgd_id pcdd_id pid_w;
global nlen ngs nds ngm_id ngds_id ncgg_id ncgd_id ncdd_id nid_w;
%check for quick Loading
Lib_File_name = strcat('..\LibData\', libSelect, '.mat');
Mat_Lib_exist = exist(Lib_File_name,'file');
if Mat_Lib_exist ~= 0
disp('MAT file Lib exists, using stored MAT Lib ...');
pause(1);
load(Lib_File_name, 'FLAG', 'libSelect', ...
'plen', 'pgs', 'pds', 'pgm_id', 'pgds_id', 'pcgg_id', 'pcgd_id', 'pcdd_id', 'pid_w', ...
'nlen', 'ngs', 'nds', 'ngm_id', 'ngds_id', 'ncgg_id', 'ncgd_id', 'ncdd_id', 'nid_w'); else
disp('Loading PMOS Parameters ...');
FOM_MOS=loadsig(strcat(libPath,'\pmos.sw0'));
plen=evalsig(FOM_MOS,'sw_ll')';
pgs=evalsig(FOM_MOS,'gs');
pgs=pgs(:,1);
clear FOM_MOS;
%3-D look up table: [ Len Vgs Vds ]
len_step=max(size(plen));
gs_step=max(size(pgs));
ds_step=gs_step;
pgm_id = zeros ( len_step , gs_step , ds_step);
pgds_id = zeros ( len_step , gs_step , ds_step);
pcgg_id = zeros ( len_step , gs_step , ds_step);
pcgd_id = zeros ( len_step , gs_step , ds_step);
pcdd_id= zeros ( len_step , gs_step , ds_step);
pid_w= zeros ( len_step , gs_step , ds_step);
pds = zeros (ds_step , 1);
%Fill in the table
for ds = 1:ds_step
disp([num2str(ds/ds_step*100,'%1.4f') ' % ...']);
FOM_MOS=loadsig(strcat(libPath,'\pmos.sw',num2str(ds-1)));
pgm_id( :,:,ds) = evalsig(FOM_MOS,'gm_id')';
pgds_id( :,:,ds) = evalsig(FOM_MOS,'gds_id')';
pcgg_id( :,:,ds) = evalsig(FOM_MOS,'cgg_id')';
pcgd_id( :,:,ds) = evalsig(FOM_MOS,'cgd_id')';
pcdd_id( :,:,ds) = evalsig(FOM_MOS,'cdd_id')';
pid_w( :,:,ds) = evalsig(FOM_MOS,'id_w')';
pds(ds) = max(max(evalsig(FOM_MOS,'d')));
clear FOM_MOS;
end
%----------------------------------------
%----------------------------------------
disp('Loading NMOS Parameters ...');
FOM_MOS=loadsig(strcat(libPath,'\nmos.sw0'));
nlen=evalsig(FOM_MOS,'sw_ll')';
ngs=evalsig(FOM_MOS,'gs');
ngs=ngs(:,1);
clear FOM_MOS;
%3-D look up table: [ Len Vgs Vds ]
len_step=max(size(nlen));
gs_step=max(size(ngs));
ds_step=gs_step;
ngm_id = zeros ( len_step , gs_step , ds_step);
ngds_id = zeros ( len_step , gs_step , ds_step);
ncgg_id = zeros ( len_step , gs_step , ds_step);
ncgd_id = zeros ( len_step , gs_step , ds_step);
ncdd_id= zeros ( len_step , gs_step , ds_step);
nid_w= zeros ( len_step , gs_step , ds_step);
nds = zeros (ds_step , 1);
%Fill in the table
for ds = 1:ds_step
disp([num2str(ds/ds_step*100,'%1.4f') ' % ...']);
FOM_MOS=loadsig(strcat(libPath,'\nmos.sw',num2str(ds-1)));
ngm_id( :,:,ds) = evalsig(FOM_MOS,'gm_id')';
ngds_id( :,:,ds) = evalsig(FOM_MOS,'gds_id')';
ncgg_id( :,:,ds) = evalsig(FOM_MOS,'cgg_id')';
ncgd_id( :,:,ds) = evalsig(FOM_MOS,'cgd_id')';
ncdd_id( :,:,ds) = evalsig(FOM_MOS,'cdd_id')';
nid_w( :,:,ds) = evalsig(FOM_MOS,'id_w')';
nds(ds) = max(max(evalsig(FOM_MOS,'d')));
clear FOM_MOS;
end
%----------------------------------------
end
clear libPath;
disp(strcat(libSelect,' Library loaded.'));
clear ans ds
clear ds_step gs_step len_step libSel;
FLAG = 1;
toc;
Matlab辅助简单模拟电路的EDA优化程序(3)
模型库加载函数loadLib.m
使用方法:loadLib('smic13'); loadLib('smic13','f');
1、当workspace中已经存要加载的库时,什么都不做;
2、当workspace中不存在要加载的库时,
2.1、如果存在MAT格式的模型库,则从mat文件加载
2.2、如果不存在MAT格式的模型库,则从sw0文件加载,并在加载完成后令存一份mat格式模型库。
第二参数… F … 会强制从文件重新加载模型库到workspace
========================
function loadLib(libName,force)
global libSel libSelect FLAG
FLAG = 1;
disp(['Using Lib "' libName '" ...']);
if nargin == 2 && force == 'f'
disp('Force Reloading Lib ...');
clear FLAG libSelect;
libSel = libName;
CreatTable;
elseif ~strcmp(libSelect,libName)
disp('Loading New Lib ...');
clear FLAG libSelect;
libSel = libName;
CreatTable;
else
disp('Lib Already Loaded ...');
end
if FLAG == 0
disp('Loading ERROR!');
else
Dir_name = '..\LibData\';
Dir_exist = exist(Dir_name,'dir');
if Dir_exist == 0
mkdir('..\','LibData');
end
Lib_File_name = strcat('..\LibData\', libSelect, '.mat');
Mat_Lib_exist = exist(Lib_File_name,'file');
if Mat_Lib_exist == 0
disp('Saving Lib data to "..\LibData\" for quick loading in the future ...');
pause(1);
save(Lib_File_name, 'FLAG', 'libSelect', ...
'plen', 'pgs', 'pds', 'pgm_id', 'pgds_id', 'pcgg_id', 'pcgd_id', 'pcdd_id', 'pid_w', ...
'nlen', 'ngs', 'nds', 'ngm_id', 'ngds_id', 'ncgg_id', 'ncgd_id', 'ncdd_id', 'nid_w');
end
end
end
Matlab辅助简单模拟电路的EDA优化程序(4)
模型库解析函数(实现将器件的工作点参数L,Vgs,Vds转换为小信号参数gm/id,gds/id,cgg/id,cgd/id,cdd/id。
因为程序的优化变量为器件的工作点参数,而器件模型中使用的是小信号参数):
======================================
function [gm_id gds_id cgg_id cgd_id cdd_id] = N_parse(L , vgs , vds)
global nlen ngs nds ngm_id ngds_id ncgg_id ncgd_id ncdd_id
tmp=abs(L-nlen);
L_index=find(tmp==min(tmp),1);
tmp=abs(vgs-ngs);
vgs_index=find(tmp==min(tmp),1);
tmp=abs(vds-nds);
vds_index=find(tmp==min(tmp),1);
gm_id = ngm_id(L_index, vgs_index, vds_index);
gds_id = ngds_id(L_index, vgs_index, vds_index);
cgg_id = ncgg_id(L_index, vgs_index, vds_index);
cgd_id = ncgd_id(L_index, vgs_index, vds_index);
cdd_id = ncdd_id(L_index, vgs_index, vds_index);
end
======================================
function [gm_id gds_id cgg_id cgd_id cdd_id] = P_parse(L , vgs , vds)
global plen pgs pds pgm_id pgds_id pcgg_id pcgd_id pcdd_id
tmp=abs(L-plen);
L_index=find(tmp==min(tmp),1);
tmp=abs(vgs+pgs);
vgs_index=find(tmp==min(tmp),1);
tmp=abs(vds+pds);
vds_index=find(tmp==min(tmp),1);
gm_id = pgm_id(L_index, vgs_index, vds_index);
gds_id = pgds_id(L_index, vgs_index, vds_index);
cgg_id = pcgg_id(L_index, vgs_index, vds_index);
cgd_id = pcgd_id(L_index, vgs_index, vds_index);
cdd_id = pcdd_id(L_index, vgs_index, vds_index);
end
======================================
======================================
模型查询函数:(优化完成后,需要将工作点参数L,Vgs,Vds,以及电流I 转化为电路设计参数W,L)
注意:方法参数列表中,第一个参数ID为器件编号,仅用于最后的显示输出,最后一个参数I才是电流。
======================================
function [L_opt W_opt gmid_opt idw_opt] = N_getSize( ID, L, vgs, vds, I)
global nlen ngs nds ngm_id nid_w
tmp=abs(L-nlen);
L_index=find(tmp==min(tmp),1);
tmp=abs(vgs-ngs);
vgs_index=find(tmp==min(tmp),1);
tmp=abs(vds-nds);
vds_index=find(tmp==min(tmp),1);
gmid_opt = ngm_id(L_index, vgs_index, vds_index);
idw_opt = nid_w(L_index, vgs_index, vds_index);
L_opt = L*1e6;
W_opt = I / idw_opt * 1e6;
disp([ID ': nmos, L(um): ' num2str(L_opt,'%1.4g') ', W(um): ' num2str(W_opt,'%1.4g') ', gmid: ' num2str(gmid_opt,'%1.4g') ', idw: ' num2str(idw_opt,'%1.4g')]);
end
======================================
function [L_opt W_opt gmid_opt idw_opt] = P_getSize( ID, L, vgs, vds, I)
global plen pgs pds pgm_id pid_w
tmp=abs(L-plen);
L_index=find(tmp==min(tmp),1);
tmp=abs(vgs+pgs);
vgs_index=find(tmp==min(tmp),1);
tmp=abs(vds+pds);
vds_index=find(tmp==min(tmp),1);
gmid_opt = pgm_id(L_index, vgs_index, vds_index);
idw_opt = pid_w(L_index, vgs_index, vds_index);
L_opt = L*1e6;
W_opt = I / idw_opt * 1e6;
disp([ID ': pmos, L(um): ' num2str(L_opt,'%1.4g') ', W(um): ' num2str(W_opt,'%1.4g') ', gmid: ' num2str(gmid_opt,'%1.4g') ', idw: ' num2str(idw_opt,'%1.4g')]);
end
Matlab辅助简单模拟电路的EDA优化程序(5)
多变量优化算法,鉴于楼主在优化算法领域一知半解,这里只贴其中的一种实际应用中感觉还不错的粒子群算法(据说是模仿鸟群觅食行为写成的)?
有兴趣的同学完全可以再编写更为有效的优化算法,唯一的要求是,函数的输入输出参数列表保持一致:
function [gbest,fbest]=XXX_min(fhandle,seed,Lb,Ub,para)
输入参数:
fhandle,函数值句柄,可以是优化目标,例如功耗
seed,初始输入变量。
Lb,Ub,输入变量的下界、上界
para,优化算法控制变量
输出参数:
gbest:输入变量的全局最优值
fbest:输入变量的全局最优值对应的函数值
细心的朋友会发现,这里所使用的优化算法是无约束条件的,事实上,在我的程序中,约束条件被安排在电路描述文件XXX_Description.m中,大家以后将会看到~~
================================
%% === APSO Solver starts here ================================ % No need to modify the following, unless you want to improve
% the perfornance of this accelerated PSO.
function [gbest,fbest]=pso_min(fhandle,psoseed,Lb,Ub,para)
% fid = fopen('best.txt','wt');
if nargin<=4,
para=[50 500 0.95 0];
end
% Populazation size, time steps ,gamma ,pso_init(1:use psoseed as initial state;0:use random as initial state)
n=para(1); time=para(2); gamma=para(3); pso_init=para(4);
% -----------------------------------------------------------------
%% Scalings
scale=abs(Ub-Lb);
% Validation constraints
if abs(length(Lb)-length(Ub))>0,
disp('Constraints must have equal size');
return
end
% -----------------------------------------------------------
% Setting parameters alpha, beta
% Randomness amplitude of roaming particles alpha=[0,1]
% Speed of convergence (0->1)=(slow->fast); % beta=0.5
alpha=0.2; beta=0.5;
% A potential improvement of convergence is to use a variable
% alpha & beta. For example, to use a reduced alpha, we have
% gamma in [0.7, 1];
% -----------------------------------------------------------
%% ------------- Start Particle Swarm Optimization -----------
% generating the initial locations of n particles
best=init_pso(n,Lb,Ub,pso_init,psoseed);
if pso_init
gbest = psoseed;
else gbest = best(1,:);
end
fbest=fhandle(gbest);
pause_cnt=0;% count how long fbest has stucked
% ----- Iterations starts ------
for t=1:time,
% Find which particle is the global best
for i=1:n,
fval=fhandle(best(i,:));
% Update the best
if fval<=fbest,
gbest=best(i,:);
fbest=fval;
pause_cnt=0;
else
pause_cnt=pause_cnt+1;
end
end
% -----------------------------------------------------------
% Randomness reduction
if fbest>1e10
alpha = alpha;
beta = 0.6;
else
alpha = alpha*gamma;
if alpha < 1e-6
alpha = 0;
end
beta = 0.6;
end
% refresh the coe and thres according to pause_cnt
if pause_cnt>400
coe = 0.2;
thres = 0.5;
pause_cnt = pause_cnt-100;
elseif pause_cnt>n
coe = log10(pause_cnt)/24;
thres = 1.3-(log(pause_cnt/n))/10;
else
coe = 0.08;
thres = 0.8;
end
coe = min(coe,0.4); %coe<0.4
thres = max(thres,0.5); %thres>0.6
% Move all particles to new locations
best=pso_move(best,gbest,alpha,beta,Lb,Ub,thres,coe);
% Output the results to screen
% str=strcat('iteration=',num2str(t));
% str=strcat(str,' Best estimates: fbest=',num2str(fbest),' alpha=',num2str(alpha)); if rem(t,50)==0
disp(['itr=' num2str(t) ' fbest=' num2str(fbest) ...
' alpha=' num2str(alpha) ' pause_cnt=' num2str(pause_cnt) ' beta='
num2str(beta) ' coe=' num2str(coe) ' thres=' num2str(thres)]);
% fprintf(fid,'\t %f\t %2.15f\n',fbest,gbest);
end
end
%%%%% end of main program
% fclose(fid);
% -------------------------------------------------
% All subfunctions are listed here
%
% Intial locations of particles
function [guess]=init_pso(n,Lb,Ub,pso_init,psoseed)
ndim=length(Lb);
for i=1:n
if pso_init==1
guess(i,1:ndim)=psoseed+0.05*randn(1,ndim).*(Ub-Lb);
else
guess(i,1:ndim)=Lb+rand(1,ndim).*(Ub-Lb);
end
end
% Move all the particles toward (xo,yo)
function ns=pso_move(best,gbest,alpha,beta,Lb,Ub,thres,coe)
% This scale is important as it increases the mobility of particles
n=size(best,1); ndim=size(best,2);
scale=(Ub-Lb);
for i=1:n,
% ns(i,:)=best(i,:)+ beta*(gbest-best(i,:))+
coe*(randn(1,ndim)>thres).*randn(1,ndim).*scale;
ns(i,:)=best(i,:)+ beta*(gbest-best(i,:))+alpha.*randn(1,ndim).*scale+ ...
(1-alpha)*coe*(randn(1,ndim)>thres).*randn(1,ndim).*scale; % ns(i,:)=best(i,:)+ beta*(gbest-best(i,:))+alpha.*randn(1,ndim).*scale; end
ns=findrange(ns,Lb,Ub);
% Application of simple lower and upper bounds
function ns=findrange(ns,Lb,Ub)
n=length(ns);
for i=1:n,
% Apply the lower bound
ns_tmp=ns(i,:);
I=ns_tmp<Lb;
ns_tmp(I)=Lb(I);
% Apply the upper bounds
J=ns_tmp>Ub;
ns_tmp(J)=Ub(J);
% Update this new move
ns(i,:)=ns_tmp;
end
%% end of the program
Matlab辅助简单模拟电路的EDA优化程序(6)
在之前的《Matlab辅助简单模拟电路的EDA优化程序(2)》~《Matlab辅助简单模拟电路的EDA优化程序(5)》贴中,楼主已经将优化程序的公共部分,即位于
/EDA/OptPlatform/ 下的所有matlab方法全部公开了。
本帖将以一个二级运放为例说明如何使用楼主的优化平台创建一个具体的优化应用。
应用部分位于/EDA/Apps/ 下,每一个优化应用都包含两个文件:
1、优化程序文件twoStage_min.m
=============================
%2-stage OTA Design Program
%stage1
% Input_NMOS : M1, Loading_PMOS : M2 %我所使用的电路结构
%stage2
% Input_NMOS : M3, Loading_PMOS : M4
clc;
loadLib('smic13'); %加载使用的工艺模型库
tic;
%-----------circuits parameters----------
global GBW CS CF CL PM kp2 KT gamma Ccmax Ccmin VN AL scale myTITLE; %所有的设计变量都应设置为全局变量
myTITLE = '******** Optimization of Two-Stage Amplifier ********'; %TITLE,随便写
GBW = 100e6; %loop bandwidth
PM = 70;
AL_dB = 40; %loop gain, unit is dB
AL = 10^(AL_dB/20); %loop gain
VN = 800e-6; %total noise
CS = 1000e-15; %sampling capcitor,unit is F
CF = 1000e-15; %feedback capacitor
CL = 2e-12; %load capacitor %该OTA应用与pipeline ADC的MDAC中,使用电容反馈结构,故有Cs,Cf,Cl
VICM = 0.9; %input common voltage,unit is V
VOMAX = 1.3; %output maximum voltage
VOMIN = 0.6; %output minimum voltage %定义输出摆幅,会影响输出级的gds VTH = 0.50; %threshold voltage of nmos
KT = 4.14e-21;
gamma = 1; %MOS噪声公式中的那个r
Ccmin = 100e-15;
Ccmax = 10e-12; %补偿电容的允许取值范围,100fF~10pF
kp2 = tan(pi*PM/180); %极点分离系数
scale = 1.01; %放水系数?留一些裕量
% %-----------function options for PSO--------------------
Lb = [180e-9 0.35 180e-9 0.35 180e-9 0.35 180e-9 0.35 ];
Ub = [800e-9 0.8 1000e-9 1.1 800e-9 0.8 1000e-9 1.1 ];
%总共8个优化变量,每个优化变量的允许变化范围,显然某些指的是沟道长度,另外一些看上去像电压值。
x0 = (Lb+Ub)./2; %起始变量,具体值并不重要
structure = @twoStage_Description; %这边应该是对应的电路描述文件的文件名
disp(myTITLE); %显不显示自愿
para=[50 1000 0.95 0]; %pso优化算法的参数,从左至右大概是粒子群规模、迭代次数、@¥%、&#×!……
[gbest,fbest] = pso_min(structure,x0,Lb,Ub,para); %标准调用格式,一般不需要改structure(gbest,'d'); %解析并显示优化结果,具体分析见电路描述文件注释
toc;
2、电路描述文件twoStage_Description.m
=====================================
function obj = twoStage_Description(x,display)
global GBW CS CF CL PM kp2 KT gamma Ccmax Ccmin VN AL scale myTITLE; %所有设计变量设置为全局变量,与优化程序一致
VN2 = VN^2;
%% convert variables above into structures used in our optimization-----
%------gm/id gds/id cgg/id cdd/id cgd/id---------------------------
L1 = x(1); Vgs1 = x(2); Vds1 = 0.3;
L2 = x(3); Vgs2 = x(4); Vds2 = 0.4;
L3 = x(5); Vgs3 = x(6); Vds3 = 0.20;
L4 = x(7); Vgs4 = x(8); Vds4 = 0.25; %每个MOS管的L、Vgs、Vds取值,其中某些为固定值,另一些来自于待优化变量向量X
[gm_id1 gds_id1 cgg_id1 cgd_id1 cdd_id1] = N_parse( L1 , Vgs1 , Vds1 );
[gm_id2 gds_id2 cgg_id2 cgd_id2 cdd_id2] = P_parse( L2 , Vgs2 , Vds2 );
[gm_id3 gds_id3 cgg_id3 cgd_id3 cdd_id3] = P_parse( L3 , Vgs3 , Vds3 );
[gm_id4 gds_id4 cgg_id4 cgd_id4 cdd_id4] = N_parse( L4 , Vgs4 , Vds4 );%解析得到每个MOS管的小信号参数
%------conversion ends-------------------------------------------------
%% Circuit Description & Current Iteration-----------------------
%--适当放水--
GBW_s = GBW * scale;
VN2_s = VN2 / scale;
kp2_s = kp2 * scale;
% 迭代过程控制变量
Iteration_num = 100; % 最大迭代次数
I_old = 1e10; % 前一次迭代结果
I_step = 1e10; % 前一次迭代改进程度
I_tol = 1e-9; % 迭代停止相对误差限
%--待定寄生参数--
cgg1=0; cdd1=0;
cdd2=0;
cgg3=0; cgd3=0; cdd3=0;
cdd4=0;
g21=1; g43=1;
Iteration_cnt = Iteration_num;
while Iteration_cnt>0 %迭代循环,最终确定各支路电流
beta=CF/(CS+CF+cgg1); %计算反馈系数,考虑了输入寄生电容
C1=cdd1+cdd2+cgg3; %Stage 1 负载电容
C2=cdd3+cdd4+CL+(1-beta)*CF; %Stage 2 负载电容
Cc_noise=KT*gamma*(1+g21)/beta/(0.5*(VN2_s)-KT*(1+gamma*(1+g43))/C 2); %根据噪声要求计算的补偿电容值
Cc_power=sqrt(C1*C2*kp2_s*beta*gm_id1/gm_id3); %根据功耗最小原则计算的补偿电容值
if Cc_noise > 0
Cc=max(Cc_noise, Cc_power);
if Cc>Ccmax
Cc=Ccmax;
elseif Cc<Ccmin
Cc=Ccmin;
end
else
Cc=Ccmax;
end %最终选定的补偿电容值
gm1=2*pi*GBW_s*(Cc+cgd3)/beta; %计算M1所需要的跨导值
gm3=2*pi*GBW_s*(C1*C2/(Cc+cgd3)+C1+C2)*kp2_s; %计算M3所需要的跨导值
%----更新待定参数----------
id1=gm1/gm_id1;
id3=gm3/gm_id3;
cgg1=cgg_id1*id1; cdd1=cdd_id1*id1;
cdd2=cdd_id2*id1;
cgg3=cgg_id3*id3; cgd3=cgd_id3*id3; cdd3=cdd_id3*id3;
cdd4=cdd_id4*id3;
g21=gm_id2/gm_id1; g43=gm_id4/gm_id3;
I_new = ( id1 + id3 ) * 2000;
%---迭代退出控制---
I_stepN = abs( I_new - I_old );
if I_stepN / I_old < I_tol || I_stepN > I_step * 2
break;
end
I_step = I_stepN;
I_old = I_new;
Iteration_cnt = Iteration_cnt - 1;
end
% Objective
obj=I_new; %优化目标,此例中为总电流
%% ------------Circuit Specification Check--------------
al = beta*gm_id1*gm_id3/(gds_id1+gds_id2)/(gds_id3+gds_id4);
gbw = beta*gm1/(Cc+cgd3)/2/pi;
vn2 = 2*KT/beta/Cc*gamma*(1+g21)+2*KT/C2*(1+gamma*(1+g43));
p2 = gm3/(C2+C1+C2*C1/Cc)/2/pi;
pm = 180*atan (p2/gbw)/pi; %用小信号参数表达的各项设计指标,计算出数值解%% -----constraints functions----------------
%------g(x) <= 0 ------ %各项不等式形式的约束条件,都要写成g(x)<=0的形式g(1) = (AL-al)/AL; %AL < al
g(2) = (GBW-gbw)/GBW; %GBW < gbw
g(3) = (vn2-VN2)/VN2; %vn2 < VN2
g(4) = (PM-pm)/PM; %PM < pm %增益、带宽、噪声、相位裕度约束条件
g(5) = 3 - gm_id2;
g(6) = 3 - gm_id4;
g(7) = gm_id2 - 10;
g(8) = gm_id4 - 10; %gmid2,gmid4需要在3~10的范围内
%------geq(x) ==0 -----
geq = []; %等式形式的约束条件,一般用不到
%----------------------
%% No need to modify this section ! %当约束条件不满足时,就会以罚函数的形式增加到函数值上
% No need to modify the section below!
% No need to modify the section below!!
% No need to modify the section below!!!
% Apply nonlinear constraints by the penalty method
% Z=f+sum_k=1^N lam_k g_k^2 *H(g_k) where lam_k >> 1
% Penalty constant >> 1
PEN=10^15;
lam=PEN; lameq=PEN;
geq_tol = 1e-32;
for k=1:length(g)
if g(k) > 0
obj = obj + lam*g(k)^2;
end
end
for k=1:length(geq)
if abs(geq(k)) > geq_tol
obj = obj + lameq*geq(k)^2;
end
end
% No need to modify the section above!
% No need to modify the section above!!
% No need to modify the section above!!!
%% 计算并显示各MOS管尺寸
if nargin==2 && display == 'd' %调用该方法时,如果有第二参数'd',则表示解析并显示优化结果
disp(myTITLE);
disp('Results:');
%------------显示各MOS管尺寸------------
disp('************ Design Parameters ************');
[L_opt W_opt gmid_opt idw_opt] = N_getSize( 'M1', L1 , Vgs1 , Vds1, id1); %调用
查询函数获得器件尺寸和工作状态
[L_opt W_opt gmid_opt idw_opt] = P_getSize( 'M2', L2 , Vgs2 , Vds2, id1);
[L_opt W_opt gmid_opt idw_opt] = P_getSize( 'M3', L3 , Vgs3 , Vds3, id3);
[L_opt W_opt gmid_opt idw_opt] = N_getSize( 'M4', L4 , Vgs4 , Vds4, id3); %L、Vgs、Vds、Id可以唯一确定器件的尺寸
disp(['I_opt(mA) = ' num2str(I_new,'%1.4g') ', Id1(mA) = '
num2str(id1*1000,'%1.4g') ', Id3(mA) = ' num2str(id3*1000,'%1.4g')]);
disp(['Cc(pF) = ' num2str(Cc*1e12,'%1.4g')]);
%------------显示运放指标参数------------
disp('************ Circuit Specifications ************');
disp(['Adc_cl(dB) = ' num2str(20* log10 (al),'%1.4g') ', GBW_cl = '
num2str(gbw,'%1.4g')]);
disp(['PM = ' num2str(pm,'%1.4g') ', Vn_rms = ' num2str(sqrt (vn2),'%1.4g')]); %
显示其它任何感兴趣的电路参数和指标
end
end
Matlab辅助简单模拟电路的EDA优化程序(7)
优化程序到上一篇为止其实已经结束了,楼主决定最后再发两个应用实例作为收尾,权当抛砖引玉。
若有筒子感兴趣,欢迎留言~~
Folded Cascode Amplifier
这是一种常用的运放结构。
一般建模为一个二极点电路:主极点在输出,次极点在折叠处。
在电路描述文件中,计算最终的工作电流依然使用迭代法:从忽略所有寄生开始,逐渐逼近考虑寄生条件下的电流值。
FCA_min.m源代码如下:
======================
%Folded Cascode OTA Design Program
%input pair M1
%folded pair M2 M2c
%loading pair M3 M3c
clc;
loadLib('smic13');
tic;
%-----------circuits parameters----------
global GBW CS CF CL PM kp2 KT gamma VN AL scale myTITLE;
myTITLE = '******** Optimization of Folded-Cascode One-Stage Amplifier ********'; GBW = 1200e6; %loop bandwidth
PM = 60;
AL_dB = 40; %loop gain, unit is dB
AL = 10^(AL_dB/20); %loop gain
VN = 200e-6; %total noise
CS = 6000e-15; %sampling capcitor,unit is F
CF = 1500e-15; %feedback capacitor
CL = 2500e-15; %load capacitor
VICM = 0.9; %input common voltage,unit is V
VOMAX = 1.3; %output maximum voltage
VOMIN = 0.6; %output minimum voltage
VTH = 0.50; %threshold voltage of nmos
KT = 4.14e-21;
gamma = 1;
kp2 = tan(pi*PM/180);
scale = 1.01;
% %-----------function options for PSO--------------------
Lb = [130e-9 0.45 130e-9 0.45 0.10 0.45 130e-9 0.45 0.10 0.45 0.13e-6 0.13e-6];
Ub = [2e-6 0.8 2e-6 0.8 0.40 0.8 2e-6 0.8 0.40 0.8 2e-6 2e-6 ];
x0 = (Lb+Ub)./2;
structure = @FCA_Description;
disp(myTITLE);
para=[50 3000 0.95 0];
[gbest,fbest] = pso_min(structure,x0,Lb,Ub,para);
structure(gbest,'d');
toc;
======================
======================
FCA_Description.m源代码如下:
======================
%input pair M1
%folded pair M2 M2c
%loading pair M3 M3c
function obj = FCA_Description(x,display)
global GBW CS CF CL PM kp2 KT gamma VN AL scale myTITLE;
VN2 = VN^2;
%% convert variables above into structures used in our optimization-----
%------gm/id gds/id cgg/id cdd/id cgd/id--------------------------- L1 = x(1); Vgs1 = x(2); Vds1 = 1.3 - x(5);
L2 = x(3); Vgs2 = x(4); Vds2 = x(5);
L2c = x(11); Vgs2c = x(6); Vds2c = 0.5 - x(5);
L3 = x(7); Vgs3 = x(8); Vds3 = x(9);
L3c = x(12); Vgs3c = x(10); Vds3c = 0.5 - x(9);
[gm_id1 gds_id1 cgg_id1 cgd_id1 cdd_id1] = N_parse( L1 , Vgs1 , Vds1 );
[gm_id2 gds_id2 cgg_id2 cgd_id2 cdd_id2] = P_parse( L2 , Vgs2 , Vds2 );
[gm_id2c gds_id2c cgg_id2c cgd_id2c cdd_id2c] = P_parse( L2c , Vgs2c , Vds2c );
[gm_id3 gds_id3 cgg_id3 cgd_id3 cdd_id3] = N_parse( L3 , Vgs3 , Vds3 );
[gm_id3c gds_id3c cgg_id3c cgd_id3c cdd_id3c] = N_parse( L3c , Vgs3c , Vds3c ); %------conversion ends-------------------------------------------------
%% Circuit Description & Current Iteration-----------------------
%--适当放水--
GBW_s = GBW * scale;
kp2_s = kp2 * scale;
% 迭代过程控制变量
Iteration_num = 100; % 最大迭代次数
I_old = 1e10; % 前一次迭代结果
I_step = 1e10; % 前一次迭代改进程度
I_tol = 1e-9; % 迭代停止相对误差限
%--待定寄生参数--
cgg1=0; cdd1=1e-15;
cdd2=0;
cgg2c=0; cdd2c=0;。