Silly script: Two-stage OP compensation

As a complement to one of my lectures on compensation of operational amplifiers, I wrote a crude MATLAB example for testing stability and ability to loop for example currents, voltages, etc. In some sense, this could be done using veriloga blocks and slighlty more accurate circuit descriptions. But yet — this is a quite good way of understanding the operation of something as simple as a two-pole system.

I’m referring to a standard two-stage amplifier with a differential-pair in the first stage and a common-source at the output. Attached is also a plot result from octave illustrating the pole/zero placement.

And you get some results in raw format:
 octave:1> antikPoleZero f_ug = 3.0917e+08 phi_m = 54.465 p_1 = -1.1171e+05 p_2 = -3.2733e+09 p_3 = -7.7695e+12 z_1 = 2.2957e+10 

So, just an example/suggestion of simple ways to get some more understanding of the operation of the circuit.

 % % Mainly, this "demo" concentrates on the classical two-stage % amplifier. This implies also that we have not employed the % suggested technique by J. Baker, et al. % % Some of the design rules:

 % Miller % z_1 approx 10*w_ug => gm_II = 10*gm_I % p_2 approx 2.2*w_ug => C_C = 0.22 * C_II % or more generically => C_C = 2.2*C_II/(gm_II/gm_I) % Nulling resistor: % And then (nulling resistor option 2, where z_1 -> inf): % p_2 approx 1.73*w_ug => C_C = 1.73 * C_II / (gm_II/gm_I) % p_3 > 10 * w_ug % R_Z = 1/gm_II % Setting up the frequencies % No need to touch this % ========================================================= N = 256; f = logspace(1, 11, N); w = 2*pi*f; s = j*w; % Some "process"-dependent parameters. Assuming a relatively % strong channel-length modulation. lambda = 0.05; % ========================================================= % ========================================================= % Do your changes here. Why not a for loop on top? You can % characterize the phase margin as function of tail current, % or similar. % ========================================================= % ========================================================= % ========================================================= % Going to a more circuit-level representation: % Tail current through the differential pair. I_0 = 100e-6; % Effective input voltage on diff-pair transistors: Veff_I = 0.2; % The second-stage driving capacitor. For sake of argument, % the effective is slightly higher here. Veff_II = 0.4; % The mirror ratio between the output stage and the input % stage, i.e., the output stage drives K times more current % than the differential pair. % Notice that the gm_II = gm_I * K * Veff_I / Veff_II; K = 20; % Internal stage capacitance. For sake of modeling, we have % assumed that the drive transistor in the second stage also % scales with K (given a constant current and Veff_II). % C_I is approximately the CGS of the drive transistor. % Assuming some fF-cap on the gate: C_I = K*10e-15; % C_II is the load capacitance. C_II = 2e-12; % Some tentative compensation network to start with. C_C = 0.22 * C_II; R_Z = 1 ; % AND ALSO SEE BELOW! % ========================================================= % ========================================================= % ========================================================= % We can now form the different parameters, etc. % Given the parameters above, calculate the transfer function: % No need to touch this. % ============================================================= % First stage: gm_I = 2*I_0 / Veff_I; g_I = lambda*I_0; % Second stage: gm_II = 2*K*I_0/Veff_II; g_II = lambda*K*I_0; A_I = gm_I / g_I; A_II = gm_II / g_II; a = A_I * A_II; b = (C_II + C_C)/g_II + (C_I+C_C)/g_I + a*C_C/gm_I + R_Z*C_C; c = ((1/(g_I*g_II))*(C_I*C_II + C_C*C_I + C_C*C_II) + ... R_Z*C_C*(C_I/g_I + C_II/g_II)); d = R_Z*C_I*C_II*C_C/g_I/g_II; z_1 = 1/(C_C/gm_II - R_Z*C_C); % ========================================================= % ========================================================= % ========================================================= R_Z = 1 /gm_II; % ========================================================= % ========================================================= % ========================================================= A_s = a * ( 1 - s /z_1) ./ ... ( 1 + b*s + c*s.^2 + d*s.^3); % Derive the roots as: p = roots([1 c/d b/d 1/d ]); % Just for some pretty-printing. p_1 = p(3); p_2 = p(2); p_3 = p(1); % Amplitude and phase characteristics log_A = 20*log10(abs(A_s)); ang_A = 180*unwrap(angle(A_s))/pi; % Find the unity-gain frequency (in Hz) and phase margin f_ug = mean(f(find(abs(log_A)==min(abs(log_A))))); phi_m = mean(ang_A(find(abs(log_A)==min(abs(log_A)))))+180; % the mean-thing is there to avoid some numerical issues. fh = figure(1); subplot(2,1,1); sh(1) = semilogx(f, log_A); hold on; ph(1) = plot(abs(p_1/2/pi), 0, 'x'); ph(2) = plot(abs(p_2/2/pi), 0, 'x'); ph(3) = plot(abs(p_3/2/pi), 0, 'x'); ph(4) = plot(abs(z_1/2/pi), 0, 'o'); lh = line(f_ug*[1 1], [20*log10(abs(A_s(1))) -150]); tl(1) = title('Amplitude characteristics'); tl(2) = ylabel('|A^2(j \omega )|'); hold off; subplot(2,1,2); sh(2) = semilogx(f, ang_A); hold on; ph(5) = plot(abs(p_1/2/pi), 0, 'x'); ph(6) = plot(abs(p_2/2/pi), 0, 'x'); ph(7) = plot(abs(p_3/2/pi), 0, 'x'); ph(8) = plot(abs(z_1/2/pi), 0, 'o'); lh = line(f_ug*[1 1], [0 -180]); tl(3) = ylabel('arg{ A(j \omega )}'); tl(4) = xlabel('Frequency [Hz]'); hold off; set(tl,'FontSize',18); set(ph,'LineWidth',4); set(sh,'LineWidth',4); % ============================================================= % Dumping some data in raw format f_ug phi_m p_1 p_2 p_3 z_1 

% =============================================================