ACG FDOTA.m
functiony = ACG FDOTA(numSim);
% ACG FDOTA returns parameter configurations for a Folded Cascode OTA architecture.
% Based on short channel MOS BSIM3v3 model and initial values
% derived from an existing design.
% Objects and their values have the same name, but object’s names begin with
% a capital letter, so that case sensitiveness is exploited.
% Each row of y matrix is composed like this:
%
% [w 1, w 3, w 5, w 7, w 9, w 12, l 1, l 3, l 5, l 7, l 9, l 12, ibias1, ibias2,
% w 16, w 19, w 21] 10
%
% numSim is the number of configurations required for simulation.
% Parameters refer to MOS transistors ordered like this: [M1 M3 M5 M7 M9 M12].
% Initial values for parameters and bounding boxes
vov in = [0.1855 0.2734 0.1598 0.1205 0.35 0.5]; % all vov are absolute values vov max = [0.6 0.45 0.3 0.3 0.45 0.75];
vov min = [0.1 0.08 0.09 0.09 0.08 0.1];
l in = [0.28e−6 0.7e−6 0.5e−6 0.5e−6 0.7e−6 0.35e−6]; 20
ib in = [18.77e−3 9.543e−3]; % currents flowing in differential branches and in
%folded ones
% actual w computed including factor of molteplicity
weff in = [2.550e−3 2.700e−3 1.400e−3 7.000e−3 2.000e−3 0.600e−3];
nvalid = 0; % counts number of valid configurations
error = 0; % useful to control inclusion within static bounds established for
% each variable
% failure = 0; % useful for diagnosis
confSet = zeros(numSim,17); % allocates space for output variable
30
% constants
121
n = 10; % part of the ADC resolution remaining after first stage Vdd = 2.5;
Cf = 4e−12; % closed loop circuit components useful to propagate performance
% constraints Cl = 4e−12;
Cs = 32e−12;
C LOAD= 7.56e−12; % equivalent load capacitor for loop gainbandwidth computation
% Cin is neglected
beta = Cf/(Cf+Cs); % feedback network transfer function 40 fc = 80e6; % sampling frequency
ks 1 = 5; % gain of the first current mirror ks 2 = 10; % gain of the second current mirror
% parameters from file mos2v5.scs (BSIM3v3 model) Vth0 n = 0.36243;
Vth0 p = −0.50587;
tox n = 5.3311e−9;
tox p = 5.529e−9;
Cox n = 6.4772e−3; 50
Cox p = 6.245361e−3;
u0 n = 311.834e−4;
u0 p = 103.218e−4;
ua n = −4.8675e−10; % mobility parameter ua p = 4.7998e−10;
vsat n = 151400;
vsat p = 2084400;
pclm n = 1.7661;
pclm p = 0.9649;
xj = 1.7e−7; 60
ud n = ua n/tox n; % mobility degradation parameter ud p = ua p/tox p;
Ec n = 2*vsat n/u0 n; % Critical field for velocity saturation Ec p = 2*vsat p/u0 p;
% parameters extracted from simulations Vth n = 0.445;
Vth p = −0.52245;
% confidence parameters useful to bias schedule 70
eps = [0.25 0.1 0 0.1 0.1];
% eps(1) regulates maximum and minimum tolerances on bounds for gm
% eps(2) is the margin for VDS3
% eps(3) regulate the difference between Vov3 and
% |Vov9|
% eps(4) is the margin for VDS9
% eps(5) is the margin for VDS12
% node instances and bounding boxes
for i=1:6 80
L(i) = SchedNode(1, 0.4, 0, l in(i)); L
% l are allowed to vary within 20% from initial values W(i) = SchedNode(1, 1, 0, weff in(i));
% w are allowed to vary within 50% from initial values
Vov(i) = SchedNode(0, vov min(i), vov max(i)); % sets bounds for Vov end
L(2) = SetRand(L(2), @dblTriGen); % sets a random pdf L(3) = SetRand(L(3), @dblTriGen);
L(6) = SetRand(L(6), @dblTriGen);
90
Vov(2) = SetRand(Vov(2), @unifGen);
Vov(3) = SetRand(Vov(3), @unifGen);
Ib(1) = SchedNode(1, 1.2, −0.05, ib in(1));
% Ibs are allowed to vary from -65% to +55% of initial values Ib(2) = SchedNode(1, 1.2, −0.05, ib in(2));
Ib(1) = SetRand(Ib(1), @unifGen);
Ib(2) = SetRand(Ib(2), @unifGen);
gm1 in = 2*fc*(C LOAD/beta)*log((2^n)*(1+Cf*beta/C LOAD)); % = 0.076 100 Gm1=SchedNode(0, gm1 in*(1−eps(1)), 200e−3*(1+eps(1)), gm1 in);
% 200e-3 is maximum gm1 allowed Gm1=SetRand(Gm1, @unifGen);
av0 min = 562; % 55 dB20 practical specification relaxed thanks to digital
% correction: the initial simulated value was 1492 while(nvalid < numSim)
%************************************************************************** 110
% starts scheduling
%**************************************************************************
% given gm1, l(1), ibias(2) marked -> vov(1) gm1 = Value(Gm1);
ibias(1) = Value(Ib(1));
l(1) = Value(L(1)); % f(gm, Idsat, L, Vov)=0
sf vov=sprintf (’%g-%g/x*(1+1/(1+(%g+1/(%g*%g))*x))’, gm1, ibias(1), ud p, . . . Ec p, l(1));
f vov = inline(sf vov, ’x’); 120
vov(1) = fzero(f vov, vov in(1));
[Vov(1), error] = SetValue(Vov(1), vov(1));
if error == 1
% failure = failure + 1;
continue
end
% given ibias(1), l(1), vov(1) -> w(1)
w(1) = 2*ibias(1)*l(1)/(u0 p*Cox p)/(vov(1)^2/(1+vov(1)*(ud p+1/(Ec p*l(1)))));
[W(1), error] = SetValue(W(1), w(1)); 130
if error == 1
% failure = failure + 1;
continue end
% vov(1), L(1) -> Vdsat(1)
vdsat(1) = vov(1)*((1+ud p*vov(1))/(1+vov(1)*(ud p+1/(Ec p*l(1)))));
ibias(2) = Value(Ib(2));
ib = ibias(1) + ibias(2);
rout min = av0 min/gm1; 140
% vov(2), L(2), ib-> w(2) vov(2) = Value(Vov(2));
l(2) = Value(L(2));
w(2) = 2*ib*l(2)/(u0 n*Cox n)/(vov(2)^2/(1+vov(2)*(ud n+1/(Ec n*l(2)))));
[W(2), error] = SetValue(W(2), w(2));
if error == 1
% failure = failure + 1;
continue
end 150
% vov(2), L(2) -> Vdsat(2)
vdsat(2) = vov(2)*((1+ud n*vov(2))/(1+vov(2)*(ud n+1/(Ec n*l(2)))));
vov(3) = Value(Vov(3));
% vov(3), L(3), ibias(2)-> w(3) l(3) = Value(L(3));
w(3) = 2*ibias(2)*l(3)/(u0 n*Cox n)/(vov(3)^2/(1+vov(3)*(ud n+1/(Ec n*l(3)))));
[W(3), error] = SetValue(W(3), w(3));
if error == 1 160
% failure = failure + 1;
continue end
% Given our model it’s not possible to impose a value for VDSs and in
% general that equality won’t occur in reality.
% However, VDS3 and VDS9 are
% chosen through VB4 and VB1 and finally the bias network.
% Since we cannot rely on our relations we introduce some confidence
% parameters in order to achieve conservativeness of the constraints. 170
% In this way we also get an approximation for the VDS we will use
% for estimating rout
eps(2) = unifGen(0.1, 0.2);
% eps3 is margin to allow M3 to be quite far from linear region
% where the output resistance is deteriorated. The random variable
% margin grants a more effective design space exploration vds(2) = vov(2) + eps(2);
eps(3) = unifGen(0, 0.1);
180
% Vov(5) is found starting from vov(2) since we want ro reject all the
% configurations in which they are too different.
% Vov(5) is allowed to vary within 100 mV
Vov(5) = SchedNode(0, vov(2)−eps(3), vov(2)+eps(3));
Vov(5) = SetRand(Vov(5), @unifGen);
vov5 temp = Value(Vov(5));
vov5 temp = min(vov5 temp, vov max(5));
vov5 temp = max(vov5 temp, vov min(5));
vov(5) = vov5 temp;
eps(4) = unifGen(0.1, 0.2); 190
vds(5) = vov(5) + eps(4);
l(5) = l(2);
w(5) = 2*ibias(2)*l(5)/(u0 p*Cox p)/(vov(5)^2/(1+vov(5)*(ud p+1/(Ec p*l(5)))));
[W(5), error] = SetValue(W(5), w(5));
if error == 1
% failure = failure + 1;
continue end
vdsat(5) = vov(5)*((1+ud p*vov(5))/(1+vov(5)*(ud p+1/(Ec p*l(5)))));
200
% To have a symmetrical output swing it is sufficient to require
%
% VDS3+ VDSsat5= VDS9+ VDSsat7 or
% VDS5− VDSsat5 = VDS7− VDSsat7
%
vdsat(3) = vov(3)*((1+ud n*vov(3))/(1+vov(3)*(ud n+1/(Ec n*l(3)))));
vds(3) = Vdd/2−vds(2);
vds(4) = Vdd/2−vds(5);
swing = vds(3)−vdsat(3);
vdsat(4) = vds(4)−swing; 210
l(4) = l(3);
% g(Vdsat, L, Vov)=0
sg vov = sprintf (’%g-x*((1+%g*x)/(1+x*(%g+1/(%g*%g))))’, vdsat(4), ud p,. . . ud p, Ec p, l(4));
g vov = inline(sg vov, ’x’);
vov(4) = fzero(g vov, vov in(4));
w(4) = 2*ibias(2)*l(4)/(u0 p*Cox p)/(vov(4)^2/(1+vov(4)*(ud p+1/(Ec p*l(4)))));
[W(4), error] = SetValue(W(4), w(4));
if error == 1 220
% failure = failure + 1;
continue end
% Sizes for M12
vds(6)=Vdd−(1.25+vov(1)+abs(Vth0 p));
eps(5) = unifGen(0.15, 0.25);
% follows from specifications on the common mode input range vov(6) = vds(6)−eps(5);
l(6) = Value(L(6)); 230
w(6) = 2*ibias(1)*l(6)/(u0 p*Cox p)/(vov(6)^2/(1+vov(6)*(ud p+1/(Ec p*l(6)))));
[W(6), error] = SetValue(W(6), w(6));
if error == 1
% failure = failure + 1;
continue end
%**************************************************************************
% end of the fundamental equality constraints
%**************************************************************************
240
vds(1) = Vdd−vds(2)−vds(6);
vdsat(6) = vov(6)*((1+ud p*vov(6))/(1+vov(6)*(ud p+1/(Ec p*l(6)))));
ud = [ud p ud n ud n ud p ud p ud p];
idsat = [ibias(1) ib ibias(2) ibias(2) ibias(2) ibias(1)];
lpic = [sqrt(3*tox p*xj) sqrt(3*tox n*xj) sqrt(3*tox n*xj) sqrt(3*tox p*xj) . . . sqrt(3*tox p*xj) sqrt(3*tox p*xj)];
pclm = [pclm p pclm n pclm n pclm p pclm p pclm p];
rds = (((vds−vdsat)+(1+ud.*vov).*vov).*l)./(idsat.*lpic.*pclm.*(1+ud.*vov));
%************************************************************************** 250
% inequality constraints
%**************************************************************************
% Rout control
gm5 = idsat(3)/vov(3)*(1+1/(1+(ud(3)+1/(Ec n*l(3)))*vov(3)));
rp = rds(2)*rds(1)/(rds(1) + rds(2));
gm7 = idsat(4)/vov(4)*(1+1/(1+(ud(4)+1/(Ec p*l(4)))*vov(4)));
rout = gm7*rds(4)*rds(5)*gm5*rds(3)*rp/(gm7*rds(4)*rds(5)+gm5*rds(3)*rp);
if rout < rout min
% failure = failure + 1; 260
continue end
% Dominant pole control and PM > 45 degrees Cin = 0.6667*Cox p*w(1)*l(1);
Co = Cl+Cf*(Cs+Cin)/(Cf+Cs+Cin);
fh = 1/(2*pi*rout*Co);
Cp1 = 0.6667*Cox n*w(3)*l(3);
r1 = rp/(1+gm5*rp);
f1 = 1/(2*pi*r1*Cp1); 270
Cp2 = 0.6667*Cox p*w(4)*l(4);
r2 = rds(5)/(1+gm7*rds(5));
f2 = 1/(2*pi*r2*Cp2);
f0 = gm1/(2*pi*Co);
if (f1 <= f0)
% failure = failure+1;
continue end
% vbias control 280
vbias(1) = vov(2)+ Vth n;
vbias(2) = vds(2)+ vov(3)+ Vth n;
vbias(4) = Vdd−vov(5)−abs(Vth p);
vbias(3) = Vdd−vds(5)−vov(4)−abs(Vth p);
if ˜all((vbias < Vdd) & (vbias > 0))
% failure = failure +1;
continue end
nvalid = nvalid+1; 290
%************************************************************************
% end of scheduling
%************************************************************************
i 1 = ibias(1)/ks 1;
i 2 = ibias(2)/ks 2;
b = biasize (i 1, i 2, w(2), vds(2), w(5), vds(5), w(3), l(3), w(4), l(4), . . . vbias(1), vbias(4));
confSet(nvalid,:) = [ w l i 1 i 2 b]; 300
end % while y = confSet;
functionz = biasize (i1, i2, w3, vds3, w9, vds9, w5, l5, w7, l7, vb1, vb4) 310
% BIASIZE gives the Ws for transistors M16, M19, M21
% of the bias network
% i1 and i2 are current sources of the mirrors: their values are fixed
% since the gain of the mirrors has been fixed.
Cox n = 6.4772e−3;
Cox p = 6.245361e−3;
u0 n = 311.834e−4;
u0 p = 103.218e−4;
Ec n = 9.7103e+006; 320
ud n = −0.091304;
Vth0 n = 0.36243;
Vth n = 0.445;
ks 2 = 10;
% calculate drain current for M16 on the bases of the ratio
% between the two currents. This is because the gain for each current mirror is
% fixed
Chi = 1+ 0.5*i1/i2; 330
i16 = i2*Chi;
i9 = ks 2*i2;
% delta = 0.42; % offset correction coefficient (empirical) useless for now
w16 = 2*i16*0.7e−6/(u0 n*Cox n)/((vb4−vb1−Vth n)^2/(1+(vb4−vb1−Vth n)*. . . (ud n+1/(Ec n*0.7e−6))));
w19 = 2*i2*0.7e−6/(u0 p*Cox p*(vds9 + sqrt(2*i9/u0 p/Cox p/w7*l7))^2);
w21 = 2*i2*1e−6/(u0 n*Cox n*(vds3 + sqrt(2*i9/u0 n/Cox n/w5*l5))^2);
z = [w16 w19 w21]; 340
serverFDOTA.ocn
; #########################################################
;
; OCEAN side server
;
; #########################################################
; #########################################################
;
; initialize simulator and design 10
simulator( ’spectre )
; set up files
design( "/home/nuzzo/simulation/FDOTAmod/spectre/schematic/netlist/netlist") resultsDir( "/home/nuzzo/simulation/FDOTAmod/spectre/schematic" )
definitionFile(
"models" 20
)
; *********************************************************
;
; setup simulation analyses
;
; dc analysis
analysis(’dc ?saveOppoint t ?dev "/V3" ?param "dc"
?start "-10m" ?stop "10m" ?step "0.1m" )
30
;ac analysis
129
analysis(’ac ?start "10" ?stop "10T")
; noise analysis
analysis(’noise ?n "/outn" ?p "/outp" ?start "0" ?stop "10G"
?oprobe "" ?iprobe "/V3")
;transient analysis
analysis(’tran ?stop "10n" ?errpreset "conservative")
40
; #########################################################
; #########################################################
;
; First part of the server kernel
;
; #########################################################
; first, get the file name prefixes
; get number of simulations to be run 50
; and number of parameters file = infile("FileNames") while(not(file)
file = infile("FileNames")) fscanf(file "%s" DataReady) fscanf(file "%s" DataFile) fscanf(file "%s" ReadyFile) fscanf(file "%s" ResultFile)
fscanf(file "%s" TransferFile) 60
fscanf(file "%d" NumSim) fscanf(file "%d" NumParam) close(file)
; vector used to read parameters from file declare(param[NumParam])
; start (or restart) simulation from iteration count
; look for all already available files 70
; (availability of file k implies that k-1 was simulated
; and uploaded. We cannot rely on the presence of results alone. . .) count=1
sprintf(filename "%s%d" DataReady count+1) while((file = infile(filename))
close(file) count = count+1
sprintf(filename "%s%d" DataReady count+1)
) 80
; wait for the DataReady semaphore sprintf(filename "%s%d" DataReady count) DFile = infile(filename)
while(not(DFile)
DFile = infile(filename))
; @@@@@@@@@@@@@@
; main server loop
; @@@@@@@@@@@@@@ 90
finished=0
while((finished==0)
;open result file
sprintf(filename "%s%d" ResultFile count) ResFile = outfile(filename)
; open parameter file
sprintf(filename "%s%d" DataFile count)
DFile = infile(filename) 100
; get new number of simulations to be run fscanf(DFile "%d" NumSim)
; configuration data is available
; read in data and simulate . . . for(j 0 NumSim−1
for(k 0 NumParam−1 fscanf(DFile "%g" p)
param[k] = p) 110
; #########################################################
;
; do platform specific characterization
;
;
alpha = 0.1 beta = 0.2
120
w 1 = param[0]
w 3 = param[1]
w 5 = param[2]
w 7 = param[3]
w 9 = param[4]
w 12 = param[5]
l 1 = param[6]
l 3 = param[7]
l 5 = param[8]
l 7 = param[9] 130
l 9 = param[10]
l 12 = param[11]
Ibias1 = param[12]
Ibias2 = param[13]
w 16 = param[14]
w 19 = param[15]
w 21 = param[16]
Chi = 1+0.5*Ibias1/Ibias2
140
; folded cascode
desVar( "W_1" w 1) desVar( "L_1" l 1) desVar( "W_2" w 1) desVar( "L_2" l 1) desVar( "W_3" w 3) desVar( "L_3" l 3) desVar( "W_4" w 3)
desVar( "L_4" l 3) 150
desVar( "W_5" w 5) desVar( "L_5" l 5) desVar( "W_6" w 5) desVar( "L_6" l 5) desVar( "W_7" w 7) desVar( "L_7" l 7) desVar( "W_8" w 7) desVar( "L_8" l 7) desVar( "W_9" w 9)
desVar( "L_9" l 9) 160
desVar( "W_10" w 9) desVar( "L_10" l 9)
;amplitude of the step voltage for slew rate desVar( "Vf" 200m)
;input parasitic capacitance
desVar( "Cin" 0.0042*w 1*l 1)
; mirror controlled
desVar( "W_12" w 12)
desVar( "L_12" l 12) 170
desVar( "W_13" beta*w 12)
;bias current source
desVar( "I_1" Ibias1)
;bias network
desVar( "W_14" Chi*alpha*w 9) desVar( "W_15" alpha*w 9)
desVar( "W_16" w 16) 180
desVar( "W_17" alpha*w 3) desVar( "W_18" alpha*w 3) desVar( "W_19" w 19) desVar( "W_20" alpha*w 9) desVar( "W_21" w 21)
;bias current source
desVar( "I_0" Ibias2)
; ********************************************************* 190
; run the actual simulation temp( 27 ) simOK = run()
; check if simulation went through
; there may be need of more sophisticated ways
; of assessing if it went fine
; the major problem is robustness of the server . . .
200
if(simOK then
; compute performance parameters
; static IO characteristic
sprintf(filenamecar "%s%d_%d" TransferFile count j) CaratFile = outfile(filenamecar)
selectResult( ’dc )
ocnPrint(?output CaratFile
?numberNotation ’scientific v("/outp")−v("/outn"))
close(CaratFile) 210
; 3dB bandwidth
BW = bandwidth((v( "/outp" ?result "ac-ac" ?resultsDir
"/home/nuzzo/simulation/FDOTAmod/spectre/schematic")−
v( "/outn" ?result "ac-ac" ?resultsDir
"/home/nuzzo/simulation/FDOTAmod/spectre/schematic") ) 3
"low")
;slew rate
SR =( ymax(deriv(v( "/outp" ?result "tran-tran" ?resultsDir 220
"/home/nuzzo/simulation/FDOTAmod/spectre/schematic" )))*2)
; total output noise from 0 to 10GHz
noise = rmsNoise(0 10000000000)
; selectResult(’dcOp)
power = −(v "/SUPPLY25" ?result "dcOp-dc" ?resultsDir
"/home/nuzzo/simulation/FDOTAmod/spectre/schematic")*(i
"/V0/PLUS"?result "dcOp-dc" ?resultsDir 230
"/home/nuzzo/simulation/FDOTAmod/spectre/schematic")
; *********************************************************
; dump input parameters to a file
; line format: w 1 w 3 w 5 w 7 w 9 w 12 l 1 l 3 l 5 l 7 l 9 l 12 Ibias1
; Ibias2 w 16 w 19 w 21
fprintf(ResFile "%8.7g \t" w 1) fprintf(ResFile "%8.7g \t" w 3)
fprintf(ResFile "%8.7g \t" w 5) 240
fprintf(ResFile "%8.7g \t" w 7) fprintf(ResFile "%8.7g \t" w 9) fprintf(ResFile "%8.7g \t" w 12) fprintf(ResFile "%8.7g \t" l 1) fprintf(ResFile "%8.7g \t" l 3) fprintf(ResFile "%8.7g \t" l 5) fprintf(ResFile "%8.7g \t" l 7) fprintf(ResFile "%8.7g \t" l 9) fprintf(ResFile "%8.7g \t" l 12)
fprintf(ResFile "%8.7g \t" Ibias1) 250 fprintf(ResFile "%8.7g \t" Ibias2)
fprintf(ResFile "%8.7g \t" w 16) fprintf(ResFile "%8.7g \t" w 19) fprintf(ResFile "%8.7g \t" w 21)
; *********************************************************
; dump performance parameters
; line format: BW SR noise power
260
fprintf( ResFile "%8.7g \t" BW) fprintf( ResFile "%8.7g \t" SR) fprintf( ResFile "%8.7g \t" noise) fprintf( ResFile "%8.7g \n" power) drain(ResFile)
) ; if simOK
; #########################################################
; end of the customized part 270
) ; for j
close(DFile) ; DataFile close(ResFile)
; when finished. . . 280
sprintf(filename "%s%d" ReadyFile count) file = outfile(filename)
fprintf(file "Ready!") close(file)
; wait for semaphore files
; both DataReady and Stop are considered. . . ok = 0
while((ok==0)
sprintf(filename "%s%d" DataReady count+1) 290 DFile = infile(filename)
if(DFile then ok=1 close(DFile)) SFile = infile("Stop")
if(SFile then ok=1 finished=1 close(SFile) sh("rm Stop")) )
300
count++
DFile = nil NumSim = nil )