02.02.2014 Views

Functional Verification of a Differential Operation Amplifier

Functional Verification of a Differential Operation Amplifier

Functional Verification of a Differential Operation Amplifier

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

WHITE PAPER<br />

FUNCTIONAL VERIFICATION OF A DIFFERENTIAL<br />

OPERATIONAL AMPLIFIER


Abstract –The low-voltage, high-performance IC's employed in modern communication products frequently<br />

must employ fully differential signal paths in order to achieve sufficient signal amplitude with a minimum <strong>of</strong><br />

power. The <strong>Differential</strong> <strong>Amplifier</strong>, which is the building block for these signal processing circuits, is the<br />

example used in this tutorial which examines simulations and measurements <strong>of</strong> Typical Characteristics as<br />

well as use <strong>of</strong> advanced environment features in the application <strong>of</strong> an analog functional verification<br />

methodology. Applying standard measurement techniques <strong>of</strong> basic amplifier characteristics such as Open<br />

Loop gain, frequency response, rejection ratios and amplifier circuit stability, specifics <strong>of</strong> simulation setup<br />

and results analysis are included in the example scripts provided. In addition, advanced analyses, such as<br />

statistical analysis, and Distortion Analysis are also covered with the view <strong>of</strong> developing a complete circuit<br />

characterization that would be useful in enabling Analog Design Reuse. This tutorial presentation will briefly<br />

discuss measurement techniques, the simulation test circuits, simulation, and calculations used to obtain them<br />

and will focus on the use simulation script that can reproduce the "circuit data sheet" with a minimum <strong>of</strong><br />

user interaction, for example when the circuit layout is complete and parasitic elements are extracted.<br />

Additionally, automating the script as a part <strong>of</strong> a design team's Analog <strong>Functional</strong> <strong>Verification</strong> Plan will be<br />

discussed.<br />

I. INTRODUCTION<br />

Computer simulation was early used to assist designers to assess circuit performance[1] long before the invention <strong>of</strong><br />

SPICE[2], now over 30 years old. Stability and frequency response <strong>of</strong> feedback based systems were predicted with<br />

the use <strong>of</strong> Analog computers. The requirement for Highly linear, High gain elements lead to the commercial use for<br />

<strong>Operation</strong>al <strong>Amplifier</strong>s in Analog computers[3], which then were also applied to modify systems thus studied to<br />

improve their performance.<br />

Logic simulators, in the form <strong>of</strong> simple programs to prove out the behavior <strong>of</strong> complex Boolean expressions, may<br />

have been the first to run on digital computers. As specialized applications, however they were almost an afterthought<br />

to synthesis programs using HDL’s,[4, 22] developed to verify that the system being build behaved as<br />

expected. These simulators, however, provided the first opportunity to enhance the simulation into a design<br />

verification tool, providing the ability to compare the output <strong>of</strong> a logic block with its specification, as represented by<br />

output vectors and delays.<br />

SPICE as the overwhelmingly successful analog circuit simulator running on digital computers, added delay<br />

measurement functions allowing gate level timing characterization for use in digital simulation. Completing the<br />

picture for the digital design flow, Physical verification tools allowed logic vs. layout checking, and interconnect<br />

delay extraction allowing Logic <strong>Verification</strong> run prior to tapeout to reliably predict silicon functionality, even<br />

addressing some signal integrity issues.<br />

Significant advancements in Analog simulation have provided us with accurate device models easily extracted from<br />

silicon test devices, superb schematic capture and design analysis environments for interactive simulation, physical<br />

verification tools that can accurately extract parasitic devices, including substrate resistances and interconnect<br />

resistance, inductance, and capacitance, based on 3-dimensional layout information and even mixed-signal and RF<br />

simulation capabilities. In spite <strong>of</strong> this, “analog functional verification” remained as impossible as analog synthesis<br />

until the development <strong>of</strong> analog behavioral modeling[21] capabilities that worked with the standard analog and<br />

mixed signal simulators. This allows the development <strong>of</strong> signal transformations used to allow signal and circuit<br />

characteristics to be checked, and to generate the analog stimuli required to check circuit behavior. Even this wasn’t<br />

sufficient with out an automated post-simulation analysis capability, currently not supported in the analog HDL’s<br />

Within the Cadence Custom IC toolset, this requirement is in place with the OCEAN (Open Command Environment<br />

for Analysis) scripting capability for the Analog Design Environment (formerly Analog Artist) along with the<br />

Spectre Circuit Simulator with its Verilog-A ® capability + RF analyses + Mixed-Signal Capability.<br />

Today utilizing the Spectre simulator with its Verilog-A ® and Mixed Signal interface capability along with the<br />

OCEAN Language, one can take any set <strong>of</strong> simulations and post simulation calculations and easily turn this into a<br />

script to be run automatically, generating Pass/Fail results, Results tables and Plots shown results useful for designer<br />

reference or in design reviews.


II.<br />

EXAMPLE CIRCUIT<br />

While the choice <strong>of</strong> the specific circuit used to demonstrate a verification methodology is not crucial, the selection<br />

<strong>of</strong> the operational amplifier provides one with a significant number <strong>of</strong> specifications defined extensively in the<br />

literature[5,6,7,8], and a circuit that most readers will have studied to some extent at some time in their career. The<br />

fully-differential variant chosen is applicable to many designs in progress and in the literature today[9, 10, 11, 12,<br />

13].<br />

The fully-differential op-amp provides a wide signal range and good common-mode, power supply and substrate<br />

rejection due to its symmetric construction. This makes it popular wherever fully differential signal paths must be<br />

used, for example where the supply voltage is limited due to the process chosen. Circuits used in Mixed-Signal IC’s<br />

are <strong>of</strong>ten subject to this restriction. Another application to use these extensively is communications[11] where<br />

switched capacitor type <strong>of</strong> filters[10] and converters are frequently used, generating significant substrate transients<br />

that must be adequately rejected.<br />

The circuit topology chosen for this case is a fully differential current mirror opamp with n-channel input devices<br />

and a current gain <strong>of</strong> 6, based on figure 6-14 in Johns & Martin [6], built on the TSMC 0.18u CMOS Technology<br />

using the Logic PDK (Process Design Kit) available to TSMC customers on their website. The Schematic is shown<br />

in Figure 1. While both Bandwidth and DC gain are important, the DC gain was the primary objective <strong>of</strong> this<br />

design, leading to the selection <strong>of</strong> N-channel input devices. Again, while some optimization was performed, the<br />

primary function <strong>of</strong> this circuit is to support the development <strong>of</strong> a verification script.<br />

Figure 1 Fully <strong>Differential</strong> Current Mirror Opamp with CMFB<br />

The following table lists the target specifications for the circuit. The list was collated from a number <strong>of</strong> published<br />

articles, and text books, as well as published Manufacturers Data Sheets.<br />

Symbol Description Target Specification<br />

A OL DC Gain 60 dB min<br />

GBW Gain Bandwidth Product 50M min<br />

UGFreq Unity Gain Frequency 1M Hz min<br />

Bwol Open Loop Gain 3dB Bandwidth 100k Hz min<br />

A MARGIN Gain Margin -20 dB<br />

Φ MARGIN Phase Margin 30 deg<br />

V OS Input Offset Voltage ±5mv<br />

V OSDrift Offset Voltage Drift 100n V/deg C<br />

Zin Input Impedance 10K min @ 1M Hz<br />

Zout Output Impedance 10K max @ 1M Hz


SlewRate Slew Rate 20M V/sec min<br />

F MAX Maximum Frequency (Large Signal) N/A<br />

OvrShoot Overshoot 10% max<br />

T settle Settling Time 125n sec<br />

V CM min Common Mode Voltage 0.75 V<br />

V CM max Common Mode Voltage 1.5 V<br />

I SC Short Circuit Current N/A<br />

V OL Output Compliance – Low 100m V max<br />

V OH Output Compliance – High Vdd – 100m V max<br />

I DD Supply Current 10 mA max<br />

V DD Supply Voltage 1.6v – 2.2v<br />

P DISS Power Dissipation 20 mW<br />

ENV Equivalent Noise Voltage 20 nV/√Hz Max@ 1kHz<br />

f BV Bandwidth <strong>of</strong> Noise Voltage 1k Hz max<br />

ENI Equivalent Noise Current N/A<br />

f BI Bandwidth <strong>of</strong> Noise Current N/A<br />

CMRR Common Mode Rejection Ratio 120 dB min<br />

PSRR Power Supply Rejection Ratio 100 dB min<br />

THD Total Harmonic Distortion 1% max at 1Mhz<br />

SFDR Spurious Free Dynamic Range 80 dB at 1Mhz<br />

IP3 3 rd Order Intermodulation Product Power 20 dB<br />

III.<br />

VERIFICATION SCRIPT<br />

While our objective is an automatic functional verification, this cannot currently be developed automatically. In the<br />

development we will start with the Simulation Plan to match the specifications to the simulations. Next we will<br />

review the associated “circuitry” required to drive our Device Under Test (DUT). We will then visit the subject <strong>of</strong><br />

capturing the interactive simulations in OCEAN script format. We will finish by demonstrating the use <strong>of</strong> the script<br />

and examine the results generated by the script.<br />

A. Simulation Plan<br />

All <strong>of</strong> the specifications will be measured at the typical process, voltage and temperature. In addition a set <strong>of</strong> plots<br />

will be created for reference by circuit designers, consisting <strong>of</strong> Frequency Response, Rejection Ratios, Step<br />

Response and Vos drift vs. Temp.<br />

• Typical DC sweep – V OSDrift, I DD<br />

• Typical AC sweep – A OL, GBW, UGF, f 3dB, A MARGIN, Φ MARGIN, Zin<br />

• Typical XF sweep – CMRR, PSRR<br />

• Typical Transient – %OS, SR, T settle<br />

• Designers Data sheet - Typical PVT<br />

ƒ Plot OL Freq Response, Measure A OL A MARGIN , & Φ MARGIN<br />

ƒ Plot CMRR & PSRR and measure DC values<br />

ƒ Plot Step Response and measure SR and %OS<br />

ƒ Plot Vos vs. Temp for a maximum input transistor Size Mismatch<br />

• Corner Simulations – repeat <strong>of</strong> above tests at 0 C, 1.6 v Slow Process, 100 C, 2.2v Fast Models and 27 C, 1.8v<br />

for Typical, Slow/Fast and Fast/Slow models. – Plot Aol, and bar chart <strong>of</strong> Ad, CMRR, PSRR and Iss<br />

• AC Sweep – Zout<br />

• AC Sweep – CMFB Aol, Gm PhaseM, f3dB, UGF<br />

• Transient Sweep Overdriven Square Wave – Voh Vol<br />

• Transient Sweep 1M Hz Sine – THD, Plot Output Spectrum<br />

• Noise – ENV, fBV<br />

• Parametric AC sweep – Vcm Min and Vcm Max (Common Mode Range)<br />

• Monte Carlo – V OS , yield on Typical Specs


• PSS + PAC – IP3, SFDR.<br />

B. Simulation Test Benches<br />

While it is not necessary to limit oneself to a single test bench definition, it is best to keep the number as small as<br />

possible for the convenience <strong>of</strong> those who must maintain and or reuse them. With careful consideration the test<br />

bench shown in Figure 2 is capable <strong>of</strong> supporting all simulations with the exception <strong>of</strong> the PSS +PAC, which uses<br />

the test bench shown in Figure 3. This is accomplished by setting variables for unused elements to 0, rather than by<br />

defining a new schematic for each configuration. The principle idea for the primary test bench is based on test<br />

circuits[14, 15, 16, 17] used in the industry for many years, using a second amplifier to feed back the output error to<br />

the input, allowing the output to be correctly biased.<br />

Figure 2 Opamp Test Bench Schematic<br />

Figure 3 Testbench for IP3 and SFDR measurements<br />

Using the behavioral model written in Verilog-A[21] (See Appendix B – Verilog-A Models ) this element has been<br />

made to block AC, and to have unity gain for transient simulations.


Since the DC bias is set with an amplification <strong>of</strong> “gain” thru the feedback amplifier, the error at the output <strong>of</strong> the<br />

DUT is = Vos/gain. With gain = 100 this error signal = 1% <strong>of</strong> Vos.<br />

In the AC simulation, the output <strong>of</strong> the feedback amplifier is effectively a DC source, thus opening the loop around<br />

the amplifier. Allowing direct measurement <strong>of</strong> the Open Loop characteristics at the DUT outputs.<br />

The XF analysis is perfectly suited for measurement <strong>of</strong> the Rejection Ratios[18]. By setting the DUT input nodes<br />

(Where the Voltage represents the Offset) as the XF “output” nodes the gain from each source represents the change<br />

in the input voltage due to a change in that supply, or wVin/wVsupply. The Common Mode Rejection Ratio is<br />

classically defined as Vd/Vc or wVout/wVin/wVout/wVcm which reduces to wVcm/wVin, the inverse <strong>of</strong> the XF<br />

result from the Common Mode Source. Similar results apply to the other Rejection Ratios.<br />

The Common Mode Feedback circuit measurements can be made by setting the variable for the AC voltage on the<br />

source at the amplifier output to one, leaving the others set to zero, and using an equation to calculate the<br />

It is generally a good idea to keep circuit test benches with the circuit itself, distinguishing it with a specific name<br />

extension. I like to use _TB. Numeric extensions can be added where more than one test bench is<br />

required.<br />

C. Script Development<br />

The script development for a circuit generally would be completed along with the detailed schematic design, with a<br />

successful test along with interactive simulations proving both the design and the <strong>Verification</strong> program. Once it has<br />

been completed, the test program can be re-used after layout and Physical verification, and again after any ECO’s.<br />

Scripts for variants <strong>of</strong> the basic design can be re-used most easily by copying the test bench and replacing the<br />

element under test with the new circuit. Then most <strong>of</strong> the script can be re-used with changes only to the top cell,<br />

results paths and specifications.<br />

The critical features <strong>of</strong> a useful verification program are:<br />

ƒ Completeness: It must test All <strong>of</strong> the circuit specifications<br />

ƒ Identification/Reporting <strong>of</strong> failures: To aid troubleshooting<br />

ƒ Reporting <strong>of</strong> results: In the form <strong>of</strong> a summary at the end, as well as in results file<br />

ƒ Must be capable <strong>of</strong> running without user interaction.<br />

ƒ Must be easily created or configured<br />

The majority <strong>of</strong> the simulation script used can be automatically generated based on the interactive simulation setup.<br />

Using the simulation testbench shown above in Figure 2, the various simulations are setup interactively using the<br />

Analog Design Environment (ADE). The first Setup is the one for the 4 typical sweeps that generate the designers<br />

data sheet. Once the simulations and the measurements and plot commands are setup, the “state” <strong>of</strong> the ADE<br />

window is saved for later use. In addition the state is saved in an OCEAN script like that shown in Appendix C –<br />

Sample Generated Script that can be used to repeat the simulation non-interactively. This is repeated for all <strong>of</strong> the<br />

other simulation setups in the simulation plan. The resulting ocean scripts are the starting point for the verification<br />

script.<br />

While the basic simulation and measurement functions are part <strong>of</strong> the OCEAN language, some additional utility<br />

functions shown in Appendix D – SKILL AFV Utility Functions were developed to simplify the process <strong>of</strong> checking<br />

measurements, recording “Pass/Fail” results, and configuring the plots generated. These functions can be loaded<br />

into the user’s environment during initialization, by the “.cdsinit” file for use during script development, or by the<br />

“.oceanrc” file for use in batch mode.<br />

The resulting verification script shown in Appendix E OCEAN script for CmirDiffAmp4 can be summarized in<br />

the Psuedo-Code description shown in Figure 4. While there is possible improvement in the “ease <strong>of</strong> creation” area,<br />

the script does meet all <strong>of</strong> the requirements laid out at the beginning <strong>of</strong> this section.


Initialize the Specification Limits database<br />

For Typical Corner with input transistor Size Mismatch generate plots<br />

OL Freq Response, Measure A OL A MARGIN , & Φ MARGIN<br />

CMRR & PSRR vs Frequency<br />

Step Response<br />

Vos vs Temp<br />

For each Corner(Typ, Fast/hot, Slow/cold, Slow/fast and Fast/slow)<br />

Run Dcsweep, AC, XF and transient simulations<br />

For each Measurement( V OSDrift, I DD ,A OL, GBW, UGF, f 3dB,<br />

A MARGIN, Φ MARGIN, Z in ,CMRR, PSRR, %OS, SR, T settle )<br />

Calculate result and compare to specification<br />

For Typical corner run AC sweep and measure Zout compared to specification<br />

For Typical corner run AC sweep and measure CMFB parameters compared to<br />

specification: Aol, Gm PhaseM, f3dB, UGF<br />

Run Transient Simulations with Overdriven Square Wave test Voh Vol<br />

Run Transient Sweep with 1M Hz Sine measure and test THD,<br />

Plot Output Spectrum<br />

Run Noise test ENV, fBV<br />

Run Parametric AC sweep<br />

measure and test Vcm Min and Vcm Max (Common Mode Range)<br />

Run Monte Carlo est V OS , yield on Typical Specs<br />

( V OSDrift, I DD ,A OL, GBW, UGF, f 3dB,<br />

A MARGIN, Φ MARGIN, Z in ,CMRR, PSRR, %OS, SR, T settle )<br />

Run PSS + PAC measure IP3, SFDR.<br />

Generate report and failure summary(if not passing)<br />

Figure 4 Psuedo-code <strong>of</strong> <strong>Amplifier</strong> <strong>Verification</strong><br />

D. Using the Script<br />

Ideally one would be able to setup a daily check comparing the date <strong>of</strong> the design save with the date <strong>of</strong> the results<br />

save, re-running the simulations (overnight) when the date <strong>of</strong> the design is newer than the date <strong>of</strong> the results.<br />

This portion <strong>of</strong> the setup would be accomplished with a shell or perl script. Since the OCEAN usage model doesn’t<br />

allow netlist generation with the “ocean” executable the script should also ensure that the netlist has been<br />

regenerated. Batch scripts to handle this are also easily created. Users with a simulation farm can set-up a “queue”<br />

for these programs using a program like Platform Computing’s “LSF”.<br />

Running the basic script, once the netlist has been created, is done with the following unix command (this can be<br />

one line in a shell script to verify an entire design):<br />

: ocean –log RESULTS/CmirDiffAmp4/OpampVerif.log < OCEAN/OpampVerif.ocn<br />

> RESULTS/CmirDiffAmp4/OpampVerif.out<br />

When the end <strong>of</strong> the input script is reached the program will terminate, with the results created as shown in the next<br />

section. Other scripts can determine if the results passed or failed by the extension <strong>of</strong> the summary file written to<br />

RESULTS/ the date <strong>of</strong> “cmirrdiffamp4.pass” can be used to block script execution when there are no<br />

changes to the design.<br />

Once the cell layout has been completed, one could rely on LVS results to be confident that the Schematic results<br />

meet specification, or one could run the same script on both the schematic and the layout by using different<br />

“configurations” with the hierarchy editor. One choice would be to run the simulations for the Typical corner on the<br />

schematic and the rest <strong>of</strong> the simulations on the layout.


Likewise the script can be used to verify that a behavioral model generated for the cell is satisfactory, or perhaps to<br />

optimize the model to match the extracted layout results.<br />

For larger designs, using standard building blocks verified with scripts similar to those presented here, one could run<br />

faster simulations using the verified analog behavioral models for increased confidence <strong>of</strong> behavioral results,<br />

reducing the need to simulate the full design at the transistor level, and allowing simulations to be done where<br />

simulations at the transistor level would not be practical.<br />

At the least, one can verify each specification <strong>of</strong> a circuit at an appropriate level. Knowing that the amplifier has<br />

been fully characterized, one need not re-verify the stability or the output compliance, merely that the gain is correct<br />

or, for communications applications, that the eye-opening is sufficient.<br />

E. Output Results<br />

In addition to the log file, and the results summary, the script generates 4 plots with typical conditions and a<br />

summary plot from the corners simulation. A summary table <strong>of</strong> measured results from the simulations is also<br />

generated. The outputs generated are shown in Appendix A – Script Generated Results.<br />

At the time paper submission the script was run on the schematic view <strong>of</strong> the amplifier completing in 14 min<br />

showing 50 failures out <strong>of</strong> 127 measurements made.<br />

IV.<br />

FUTURE DEVELOPMENTS<br />

Cadence Design Systems will be enhancing the measurement capabilities <strong>of</strong> the Spectre simulator in upcoming<br />

releases. This will provide for a tighter integration <strong>of</strong> the measurements with the simulator, even allowing<br />

simulations to terminate when all required measurements have been obtained. At this point the techniques used will<br />

need to be extended to take advantage <strong>of</strong> these features.<br />

Measurement <strong>of</strong> some simulation results is also possible within the Verilog-A and Verilog-AMS languages. These<br />

are primarily useful during transient simulations in a manner similar to that used in Verilog for functional<br />

verification <strong>of</strong> digital circuits. However the availability <strong>of</strong> alternate quantities allows results to be treated as signals<br />

for other stimulus and measurement modules, or to be saved in the results database. Values <strong>of</strong> Verilog-A module<br />

variables can be saved in the results database, and read using OCEAN commands. Verilog-A modules can write<br />

measurement results to a file, which can be read and parsed by SKILL TM functions in the OCEAN script to log<br />

results in the summary.<br />

Other potential improvements could be the inclusion <strong>of</strong> “limits” and limits checking in the Corners tool and the<br />

ADE output pane, as well as Cadence defined functions similar to those defined in Appendix D – SKILL AFV<br />

Utility Functions.<br />

The development <strong>of</strong> wrapper scripts to compare results to design, re-netlist and re-simulate is a task that also<br />

remains for future work, but one for which few significant challenges would be envisioned, given the similar<br />

methodology currently in use on all-digital designs.<br />

V. CONCLUSIONS<br />

Due to the more complicated nature <strong>of</strong> analog specifications, development <strong>of</strong> scripts for Analog <strong>Functional</strong><br />

<strong>Verification</strong> is more difficult than for Digital <strong>Functional</strong> <strong>Verification</strong>, but not impossible, and is not really that<br />

difficult using the Analog Design Environment, as shown in the example script. The utility functions presented<br />

simplify this further. <strong>Verification</strong> <strong>of</strong> the extracted layout <strong>of</strong> the design was accomplished by simply rerunning the<br />

script.<br />

An automated methodology for verifying analog cells by simulation has been presented. Design teams using such a<br />

methodology at various levels <strong>of</strong> hierarchy will be able to tape-out large mixed-signal designs with increased<br />

confidence <strong>of</strong> silicon functionality and performance.


ACKNOWLEDGEMENTS<br />

The Author would like to thank Hank Jones for the assistance with the utility functions. Without his help, the<br />

functional “wish” list would still be just that.<br />

The Author would like to thank the following companies for supporting various portions <strong>of</strong> this work, for asking the<br />

“how do I” questions that lead to this work and for the opportunity to test out some <strong>of</strong> these ideas in practice:<br />

National Semiconductor, Xicor, Burr-Brown (now part <strong>of</strong> Texas Instruments), Motorola and Vitesse.<br />

REFERENCES<br />

[1] J. A. G. Jess, “Designing Electronic Engines with Electronic Engines: 40 Years <strong>of</strong> Bootstrapping <strong>of</strong> a<br />

Technology Upon Itself,” IEEE Trans.Computer-Aided Design, vol. CAD-19, pp 1404-1427, Dec. 2000.<br />

[2] L. W. Nagel, “SPICE2: A Computer Program to Simulate Semiconductor Circuits,” University <strong>of</strong> California,<br />

Berkeley, Memo. no. ERL-M250, May 1975.<br />

[3] R. A. Pease, “The Story <strong>of</strong> the P2 – The First Successful Solid-State <strong>Operation</strong>al <strong>Amplifier</strong> with Picoampere<br />

Input Currents” in Analog Circuit Design: Art, Science and Personalities, J. Williams, Ed. Boston, MA:<br />

Butterworth-Heinemann, 1991, ch. 9, pp 67-78.<br />

[4] Y.Chu, D. L. Dietmeyer, J. R. Duley, F. J. Hill. M. R. Barbacci, C. W. Rose, G. Order, B. Johnson, and M.<br />

Roberts, “ Three Decades <strong>of</strong> HDLs – Part I: CDL through TI-HDL,” IEEE Design Test Comput., vol. 9, pp 69-<br />

81, June 1992.<br />

[5] J.E. Solomon. "The monolithic op amp: a tutorial study," IEEE J. Solid-State Circuits, vol. SC-9.6, pp 314-<br />

332, Dec. 1974 .<br />

[6] David Johns and Ken Martin, Analog Integrated Circuit Design, New York: Wiley & Sons, 1997.<br />

[7] Jacob Millman, MicroElectronics: Digital and Analog Circuits and Systems, New York: McGraw-Hill, 1979<br />

[8] Paul Gray and Robert Meyer, Analysis and Design <strong>of</strong> Analog Integrated Circuits: 2nd Ed, New York: Wiley &<br />

Sons, 1984<br />

[9] G.Ferri and W. Sansen “A Rail-toRail Constant-g m Low-Voltage CMOS <strong>Operation</strong>al Transconductance<br />

<strong>Amplifier</strong>,” IEEE J. Solid-State Circuits, vol 32, pp 1563-1567, Oct. 1997.<br />

[10] K. Bult& G.J.G.M. Geelen, “A Fast-Settling CMOS Op Amp for SC Circuits with 90-dB DC gain,” IEEE J.<br />

Solid-State Circuits, Vol. 25, No. 6, pp 1379-1384, Dec. 1990.<br />

[11] T.C. Choi, R.T. Kaneshiro, R.W. Brodersen, P.R. Gray W.B. Jett & M. Wilcox, “High-Frequency CMOS<br />

Switched Capacitor Filters for Communications Application” IEEE J. Solid-State Circuits, vol. 18, pp 652-<br />

663, Dec. 1983.<br />

[12] M. Banu, J.M. Khoury & Y. Tsividis “Fully <strong>Differential</strong> <strong>Operation</strong>al <strong>Amplifier</strong>s with Accurate Output<br />

Balancing.” IEEE J. Solid-State Circuits, Vol. 23, No. 6, pp. 1410-1414, Dec. 1988<br />

[13] K.R. Laker & W.M.C. Sansen, Design <strong>of</strong> Analog Integrated Circuits and Systems New York: McGraw-Hill,<br />

1994<br />

[14] C.F. Wojslaw and E.A. Moustakas, <strong>Operation</strong>al <strong>Amplifier</strong>s, New York: Wiley & Sons, 1986<br />

[15] Don Lewis “Testing <strong>Operation</strong>al <strong>Amplifier</strong>s” Electronics Test (Benwill Publishing) January 1979<br />

[16] Don Lewis “Compensation <strong>of</strong> Linear IC Test Loops” Electronics Test (Benwill Publishing) May 1979<br />

[17] M. Yamatke, “A Simplified Test-Set for Op Amp Characterization” National Semiconductor Application Note<br />

24, April 1986<br />

[18] Ken Kundert, The Designer’s Guide to Spice & Spectre, Boston: Kluwer, 1995<br />

[19] P.E. Allen and D.R. Holberg, CMOS Analog Circuit Design, New York: Oxford Univ. Press, 1987<br />

[20] J. Vandenbussche, G. Van der Plas, W. Daemes, A. Van den Bosch, G. Gielen, M. Steyart and W. Sansen,<br />

“Systematic Design <strong>of</strong> High-Accuracy Current-Steering D/A Converter Macrocells for Integrated VLSI<br />

Systems,” IEEE Trans Ciruits Syst II, vol. 48, pp 300-309, Mar. 2001.<br />

[21] Dan Fitzpatrick, Ira Miller, Analog Behavioral Modeling with the Verilog-A Language Boston: Kluwer, 1998<br />

[22] Samir Palnitkar, Verilog HDL Mountain View: SunS<strong>of</strong>t, 1996


APPENDIX A – SCRIPT GENERATED RESULTS<br />

File 1: CmirDiffAmp4.spec<br />

Aol min 60 ; dB<br />

GainMargin max -20 ; dB<br />

PhaseMargin min 30 ; deg<br />

GBW min 25M ; dB -Hz<br />

UGFreq min 1M ; Hz<br />

BWol min 25K ; Hz<br />

CMRR min 120 ; dB<br />

CmRefRR min 120 ; dB<br />

PSRRdd min 100 ; dB<br />

PSRRss min 100 ; dB<br />

SlewRate min 20M ; V/s<br />

Tsettle max 125n ; S<br />

OvrShoot max 10 ; %<br />

ComplncOut max 0.1 ; V<br />

Zout max 10K ; Ohms<br />

Zin min 10K ; Ohms @ 1MHz<br />

VcommonLow max 0.5 ; Volts<br />

VcommonHigh max 0.7 ; Volts (from supply)<br />

CMFBPhMar min 30 ; deg<br />

CMFBAol min 20 ; dB<br />

ENV max 20n ; V/sqrt(Hz) @ Fbv<br />

Fbv max 1K ; Hz<br />

THD max 1 ; % at typical<br />

Idd max 10m ; amps<br />

Vos<br />

range -5m 5m ; V<br />

VosDrift max 100n ; V/degC<br />

Pdiss max 20m ; W<br />

SFDR min 80 ; dB<br />

IP3 min 20 ; dB<br />

File 2 CmirDiffAmp4.fail<br />

ANALOG TEST RESULTS FROM RUN CmirDiffAmp4<br />

TEST PASS FAIL RUNS<br />

Idd 6 0 6<br />

VosDrift 1 0 1<br />

THD 0 1 1<br />

GainMargin 6 0 6<br />

CMRR 4 2 6<br />

Zout 2 0 2<br />

PSRRss 6 0 6<br />

Zin 0 1 1<br />

SlewRate 0 12 12<br />

GBW 0 6 6<br />

ENV 1 0 1<br />

Vos 6 0 6<br />

PhaseMargin 0 6 6<br />

BWol 0 6 6<br />

Fbv 1 0 1


PSRRdd 6 0 6<br />

ComplncOut 0 0 0<br />

IP3 0 0 0<br />

SFDR 0 0 0<br />

CmRefRR 4 2 6<br />

VcommonLow 1 0 1<br />

VcommonHigh 1 0 1<br />

Aol 6 0 6<br />

UGFreq 6 0 6<br />

OvrShoot 10 2 12<br />

CMFBPhMar 2 0 2<br />

Pdiss 6 0 6<br />

CMFBAol 2 0 2<br />

Tsettle 0 12 12<br />

---------- -------- -------- --------<br />

TOTALS 77 50 127<br />

File 3 CornerData.txt (Excel Import)<br />

Corner Aol (dB) GBW (dB-Hz) Gmargin(dB) Pmargin(deg) UGFreq(Hz) BWol (dB)<br />

C<br />

value(dB20((VFgainBwProd((VFgainMargin((VFphaseMargin((Vcross(dB20((VFbandwidth((VF(<br />

FFhHi 62.3743 23.5706M -26.9213 16.8194 7.04916M 17.8894K<br />

FS 62.4565 24.0718M -27.5728 17.2979 7.38016M 18.098K<br />

SF 62.6292 21.8673M -27.4202 17.6961 6.83722M 16.117K<br />

SScLo 62.4745 18.4523M -27.3845 18.4147 6.07812M 13.8458K<br />

TT 62.5099 22.8865M -27.9983 17.674 7.1341M 17.1027K<br />

Corner Idd (A) Pdiss (W) CMRR(dB) CmRefRR(dB) PSRRdd(dB) PSRRss(dB)<br />

C IDC("/VDD/MINUIDC("/VDD/MINUvalue(dB20((1 value(dB20((1 value(dB20((1 value(dB20((1<br />

FFhHi 7.46168m 14.9234m 136.997 137.114 116.466 115.685<br />

FS 7.23494m 13.0229m 137.744 137.77 115.262 114.633<br />

SF 6.67777m 12.02m 116.536 116.612 116.333 110.413<br />

SScLo 5.86347m 9.38155m 113.478 113.854 115.108 108.234<br />

TT 7.06937m 12.7249m 123.139 123.224 115.875 112.748<br />

Corner OvershootP (%)OvershootN (%)Tsettle1P(s) Tsettle1N(s) SlRtp(V/s) SlRtn(V/s)<br />

C overshoot((VT( overshoot((VT( settlingTime(( settlingTime(( abs(slewRate(( abs(slewRate((<br />

FFhHi 578.519m 579.667m 392.702n 392.711n 9.36282M 9.36244M<br />

FS 421.13m 422.409m 393.472n 393.52n 8.70094M 8.69862M<br />

SF 610.425m 611.165m 336.877n 336.958n 10.9525M 10.9469M<br />

SScLo 370.662m 372.252m 380.535n 381.647n 8.56432M 8.52218M<br />

TT 555.055m 556.263m 363.963n 364.018n 9.96758M 9.96487M


File 4 OLFreqResp.gif<br />

File 5 RejRatios.gif


File 7 VosDrift.ps<br />

File 6 StepResponse.ps


File 8 Corners.gif


File 9 CMRange.ps<br />

File 10 CMFB.ps


File 11 Noise.ps<br />

File 12 Zout.ps


File 13 SineTrans.ps<br />

File 14 THDplot.ps


APPENDIX B – VERILOG-A MODELS<br />

Verilog A Model used to close the feedback loop for DC simulations and Open it for AC simulations.<br />

// This module drives the output based on the input DCOP..<br />

// for small signal analyses.. ac<br />

// Buffers the output for others<br />

// designed to work with differential amplifier in unity gain config..<br />

// but feedback resistors don’t have to match input resistors<br />

// average output voltage will go to the feedback resistors<br />

// difference output * gain will go out on vos..<br />

// except during transient when inputs go to outputs<br />

‘include "constants.h"<br />

‘include "discipline.h"<br />

module acOpenDiff( inp, inn, inref, outp, outn, vos);<br />

input inp, inn, inref;<br />

output outp, outn, vos;<br />

electrical inp, inn, inref, outp, outn, vos;<br />

parameter real gain = 1; // sets dc gain for closed loop tests.<br />

real vin, vbias;<br />

analog begin<br />

@(initial_step("static")) begin<br />

vin = gain*V(inp,inn);<br />

vbias = (V(inp,inref)+V(inn,inref))/2;<br />

end<br />

if (analysis("ac","noise")) begin<br />

V(vos)


APPENDIX C – SAMPLE GENERATED SCRIPT<br />

This is the code generated after the first CMFB circuit Simulations. It was modified and appended to the<br />

<strong>Verification</strong> script. The corresponding result in the “OpampVerif.ocn” is highlighted in bold text below in<br />

Appendix E OCEAN script for CmirDiffAmp4.<br />

simulator( ’spectre )<br />

design(<br />

"/hm/jbdavid/proj445/ieeescv/simulation/CmirDiffAmp_TB4/spectre/schematic/netl<br />

ist/netlist")<br />

resultsDir(<br />

"/hm/jbdavid/proj445/ieeescv/simulation/CmirDiffAmp_TB4/spectre/schematic" )<br />

path( "~/proj445/TSMC18/models" )<br />

modelFile(<br />

’("log018.scs" "bip")<br />

’("log018.scs" "tt_3vna")<br />

’("log018.scs" "tt_na")<br />

’("log018.scs" "tt_3v")<br />

’("ResModel.scs" "res_t")<br />

’("log018.scs" "res")<br />

’("log018.scs" "tt")<br />

)<br />

analysis(’dc ?saveOppoint t )<br />

analysis(’ac ?start "1" ?stop "100G" ?dec "20" )<br />

desVar( "Fdist" 1M )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "inCMFB" 1 )<br />

desVar( "VswngP" 1 )<br />

desVar( "Tpin" 2.5u )<br />

desVar( "Tdin" 0 )<br />

desVar( "Tr" 10n )<br />

desVar( "lndiffa" 1.441u )<br />

desVar( "wndiffa" 960.03u )<br />

desVar( "Cload" 100p )<br />

desVar( "Rload" 10M )<br />

desVar( "K" 5 )<br />

desVar( "wnout" 32u )<br />

desVar( "wpcmir" 480u )<br />

desVar( "wndiff" 960u )<br />

desVar( "lnout" 2.88u )<br />

desVar( "lndiff" 1.44u )<br />

desVar( "lpcmir" 1.44u )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "wp" 120u )<br />

desVar( "wn" 120u )<br />

desVar( "wmir" 3u )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 2 )<br />

desVar( "Vcm" 1.0 )<br />

desVar( "lpmirr" .36u )<br />

desVar( "Iref" 300u )<br />

desVar( "ACin" 0 )<br />

desVar( "ACout" 0 )<br />

desVar( "VswngN" "-VswngP" )


option( ’reltol "1e-5"<br />

)<br />

temp( 27 )<br />

run()<br />

Stage1Gain = (OP("/I0/NM0" "gm") / (OP("/I0/NM0" "gds") + OP("/I0/PM0"<br />

"gds")))<br />

plot( Stage1Gain ?expr ’( "Stage1Gain" ) )<br />

Acmfbn = dB20((VF("/outn") / (VF("/outn") - VF("/cmout"))))<br />

plot( Acmfbn ?expr ’( "Acmfbn" ) )<br />

PhMarginNcmfbcl = phaseMargin(VF("/outn"))<br />

plot( PhMarginNcmfbcl ?expr ’( "PhMarginNcmfbcl" ) )<br />

AclPcmfb = dB20(VF("/outp"))<br />

plot( AclPcmfb ?expr ’( "AclPcmfb" ) )<br />

PhclNcmfb = phase(VF("/outn"))<br />

plot( PhclNcmfb ?expr ’( "PhclNcmfb" ) )<br />

PhclPcmfb = phase(VF("/outp"))<br />

plot( PhclPcmfb ?expr ’( "PhclPcmfb" ) )<br />

AclNcmfb = dB20(VF("/outn"))<br />

plot( AclNcmfb ?expr ’( "AclNcmfb" ) )<br />

PhMarginPcmfbcl = phaseMargin(VF("/outp"))<br />

plot( PhMarginPcmfbcl ?expr ’( "PhMarginPcmfbcl" ) )<br />

Acmfbp = dB20((VF("/outp") / (VF("/outp") - VF("/cmout"))))<br />

plot( Acmfbp ?expr ’( "Acmfbp" ) )<br />

BWcmfbN = bandwidth(VF("/outn") 0.5 "low")<br />

plot( BWcmfbN ?expr ’( "BWcmfbN" ) )<br />

BWcmfbP = bandwidth(VF("/outp") 0.5 "low")<br />

plot( BWcmfbP ?expr ’( "BWcmfbP" ) )<br />

PhiCmfbN = phase((VF("/outn") / (VF("/outn") - VF("/cmout"))))<br />

plot( PhiCmfbN ?expr ’( "PhiCmfbN" ) )<br />

PhiCmfbP = phase((VF("/outp") / (VF("/outp") - VF("/cmout"))))<br />

plot( PhiCmfbP ?expr ’( "PhiCmfbP" ) )


APPENDIX D – SKILL AFV UTILITY FUNCTIONS<br />

The following Code block should be loaded at beginning <strong>of</strong> script or by .oceanrc .<br />

/*<br />

* AFVsetPlot: function which drives plotter<br />

* setup. Controls are plotterName, outputFile, header,<br />

* mailLogNames, and window coordinates.<br />

*<br />

* author: Hank Jones<br />

* Cadence Design Systems<br />

*<br />

* date: 05/02/01<br />

*/<br />

procedure(AFVsetPlot(@key plotterName<br />

outputFile<br />

(title " ")<br />

subTitle<br />

(bbox list(100:200 800:800))<br />

)<br />

"Adjusts Waveform Window Size, sets titles, and Plot Options"<br />

let((plotWin plotfile)<br />

;;go with default plotter name if plotterName is not specified<br />

when(plotterName<br />

hardCopyOptions(?hcPlotterName plotterName))<br />

;;check the parent directory for write permissions<br />

if(isWritable((plotfile=simplifyFilename(strcat(outputFile "/..")))) then<br />

;;if no file we are good and can create the file but if it exists can<br />

;;we overwrite it?<br />

if(!isFile(simplifyFilename(outputFile)) ||<br />

isWritable(simplifyFilename(outputFile)) then<br />

hardCopyOptions(?hcOutputFile outputFile)<br />

else<br />

warn("Output file %s is not writable\n" simplifyFilename(outputFile))<br />

)<br />

else<br />

warn("Cannot write to parent directory %s\n" plotfile)<br />

)<br />

hardCopyOptions("hcHeader" nil)<br />

hardCopyOptions("hcMailLogNames" nil)<br />

plotWin = newWindow()<br />

)<br />

)<br />

hiResizeWindow(plotWin bbox)<br />

addTitle(title)<br />

when(subTitle<br />

addSubwindowTitle(subTitle))<br />

t<br />

/*


* the following database allows users to specify analog limits<br />

* for various tests. This table <strong>of</strong> values is keyed on the test<br />

* name given by user.<br />

*<br />

* The values will be checked against one <strong>of</strong> five tests:<br />

* min = value<br />

* range ; min


;;AFVtestInit("./myFile")<br />

procedure(AFVtest(test value)<br />

let(((testValue AnalogTests[test]))<br />

case(car(testValue)<br />

;;minimum value test<br />

("min"<br />

;;if the value is too small we count an error<br />

if(aelNumber(value) < cadr(testValue) then<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue)+1 nth(4 testValue)+1)<br />

cadr(testValue)<br />

else<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)+1<br />

cadddr(testValue) nth(4 testValue)+1)<br />

nil<br />

)<br />

);"min"<br />

;;maximum value test<br />

("max"<br />

;;if the value is too large we count an error<br />

if(aelNumber(value) > cadr(testValue) then<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue)+1 nth(4 testValue)+1)<br />

cadr(testValue)<br />

else<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)+1<br />

cadddr(testValue) nth(4 testValue)+1)<br />

nil<br />

)<br />

);"max"<br />

;;value range test<br />

("range"<br />

let(((lowerLimit cadr(testValue))<br />

(upperLimit caddr(testValue)))<br />

;;if the value is too small or large we count an error<br />

if(aelNumber(value) < lowerLimit ||<br />

aelNumber(value) > upperLimit then<br />

AnalogTests[test] = list(car(testValue) lowerLimit upperLimit<br />

cadddr(testValue)<br />

nth(4 testValue)+1 nth(5 testValue)+1)<br />

list(lowerLimit upperLimit)<br />

else<br />

AnalogTests[test] = list(car(testValue) lowerLimit upperLimit<br />

cadddr(testValue)+1 nth(4 testValue)<br />

nth(5 testValue)+1)<br />

nil<br />

)<br />

);let<br />

);"range"<br />

("pcnt"


let(((lowerLimit cadr(testValue))<br />

(upperLimit caddr(testValue)/100.0)<br />

temp)<br />

when(zerop(lowerLimit)<br />

error("Initial value for \"pcnt\" should be non-zero: %n\n"<br />

lowerLimit)<br />

)<br />

;;get the absolute limit for this test<br />

temp = lowerLimit * upperLimit<br />

;; add temp to get the upperlimit<br />

upperLimit = lowerLimit + temp<br />

;; subtract from lowerlimit to get the absolute lower limit<br />

lowerLimit = lowerLimit - temp<br />

;;if the value is too small or large we count an error<br />

if(aelNumber(value) < lowerLimit ||<br />

aelNumber(value) > upperLimit then<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue) nth(4 testValue)+1<br />

nth(5 testValue)+1)<br />

list(lowerLimit upperLimit)<br />

else<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue)+1 nth(4 testValue)<br />

nth(5 testValue)+1)<br />

nil<br />

)<br />

);let<br />

);"pcnt"<br />

("porm"<br />

let(((lowerLimit cadr(testValue))<br />

(upperLimit caddr(testValue))<br />

temp)<br />

;;get the absolute limit for this test<br />

;; add temp to get the upperlimit<br />

temp = lowerLimit + upperLimit<br />

;; subtract from lowerlimit to get the absolute lower limit<br />

lowerLimit = lowerLimit - upperLimit<br />

upperLimit = temp<br />

;;if the value is too small or large we count an error<br />

if(aelNumber(value) < lowerLimit ||<br />

aelNumber(value) > upperLimit then<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue) nth(4 testValue)+1<br />

nth(5 testValue)+1)<br />

list(lowerLimit upperLimit)<br />

else<br />

AnalogTests[test] = list(car(testValue) cadr(testValue)<br />

caddr(testValue)<br />

cadddr(testValue)+1 nth(4 testValue)<br />

nth(5 testValue)+1)<br />

nil<br />

)<br />

);let<br />

);"porm"


)<br />

)<br />

(t<br />

error("Test not defined in input file: %L\n" test)<br />

)<br />

);case<br />

procedure(AFVlogReport(runName "t")<br />

"Prints AnaFuncVerif Test Summary to CIW, Returns t if Tests OK"<br />

let((len AnaTestRuns AnaTestPasses AnaTestFails)<br />

when(runName<br />

printf(" ANALOG TEST RESULTS FROM RUN %s\n" runName)<br />

printf("%-25s %-10s %-10s %-10s\n" "TEST" "PASS" "FAIL" "RUNS")<br />

AnaTestRuns = 0<br />

AnaTestPasses = 0<br />

AnaTestFails = 0<br />

foreach(key AnalogTests<br />

len = length(AnalogTests[key])<br />

;unless(zerop(nth(len-1 AnalogTests[key]))<br />

printf("%-25s %-10n %-10n %-10n\n" key nth(len-3 AnalogTests[key])<br />

nth(len-2 AnalogTests[key]) nth(len-1 AnalogTests[key]))<br />

AnaTestRuns = AnaTestRuns + nth(len-1 AnalogTests[key])<br />

AnaTestPasses = AnaTestPasses + nth(len-3 AnalogTests[key])<br />

AnaTestFails = AnaTestFails + nth(len-2 AnalogTests[key])<br />

;)<br />

);foreach AnalogTests<br />

printf("----------<br />

-------- -------- --------\n")<br />

printf("%-25s %-10n %-10n %-10n\n" "TOTALS" AnaTestPasses<br />

AnaTestFails AnaTestRuns )<br />

if((AnaTestFails > 0) then<br />

printf("%-10n Failures %s Tests did Not pass\n" AnaTestFails runName)<br />

else<br />

printf("%-25s All Tests PASS\n" runName)<br />

)<br />

);when<br />

(AnaTestFails == 0) ; Return value nil => Failures<br />

)<br />

)<br />

/* this procedure is an enhanced version <strong>of</strong> AFVlogReport<br />

* that also creates a file - in /.[pass|fail]<br />

* using the extenstion pass only if all tests passed.<br />

* Jonathan David jbdavid@cadence.com<br />

*/<br />

procedure(AFVreport(@key runName (ResultsDir "./RESULTS") "tt")<br />

"Prints AnaFuncVerif Test Summary to CIW and file, Returns t if Tests OK"<br />

let((len AnaTestRuns AnaTestPasses AnaTestFails AnaRsltsFile RsltsPort)<br />

when(runName<br />

printf(" ANALOG TEST RESULTS FROM RUN %s\n" runName)<br />

printf("%-25s %-10s %-10s %-10s\n" "TEST" "PASS" "FAIL" "RUNS")<br />

AnaTestRuns = 0<br />

AnaTestPasses = 0<br />

AnaTestFails = 0<br />

foreach(key AnalogTests<br />

len = length(AnalogTests[key])<br />

;unless(zerop(nth(len-1 AnalogTests[key]))


)<br />

)<br />

printf("%-25s %-10n %-10n %-10n\n" key nth(len-3 AnalogTests[key])<br />

nth(len-2 AnalogTests[key]) nth(len-1 AnalogTests[key]))<br />

AnaTestRuns = AnaTestRuns + nth(len-1 AnalogTests[key])<br />

AnaTestPasses = AnaTestPasses + nth(len-3 AnalogTests[key])<br />

AnaTestFails = AnaTestFails + nth(len-2 AnalogTests[key])<br />

;)<br />

);foreach AnalogTests<br />

printf("----------<br />

-------- -------- --------\n")<br />

printf("%-25s %-10n %-10n %-10n\n" "TOTALS" AnaTestPasses<br />

AnaTestFails AnaTestRuns )<br />

if((AnaTestFails > 0) then<br />

printf("%-10n Failures %s Tests did Not pass\n" AnaTestFails runName)<br />

AnaRsltsFile = strcat( ResultsDir "/" runName ".fail" )<br />

else<br />

printf("%-25s All Tests PASS\n" runName)<br />

AnaRsltsFile = strcat( ResultsDir "/" runName ".pass" )<br />

)<br />

RsltsPort = outfile( AnaRsltsFile );<br />

when(RsltsPort<br />

fprintf( RsltsPort " ANALOG TEST RESULTS FROM RUN %s\n" runName)<br />

fprintf( RsltsPort "%-25s %-10s %-10s %-10s\n"<br />

"TEST" "PASS" "FAIL" "RUNS")<br />

foreach(key AnalogTests<br />

len = length(AnalogTests[key])<br />

;unless(zerop(nth(len-1 AnalogTests[key]))<br />

fprintf(RsltsPort "%-25s %-10n %-10n %-10n\n" key<br />

nth(len-3 AnalogTests[key])<br />

nth(len-2 AnalogTests[key])<br />

nth(len-1 AnalogTests[key])<br />

)<br />

);foreach AnalogTests<br />

fprintf( RsltsPort<br />

"---------- -------- -------- --------\n")<br />

fprintf( RsltsPort "%-25s %-10n %-10n %-10n\n" "TOTALS" AnaTestPasses<br />

AnaTestFails AnaTestRuns )<br />

close( RsltsPort )<br />

);when RsltsPort<br />

);when runName<br />

(AnaTestFails == 0) ; Return value nil => Failures<br />

procedure(AFVtestVerilog(fileName "t")<br />

let((line (fp infile(fileName)))<br />

if(fp then<br />

while((line=lineread(fp))<br />

AFVtest(get_pname(car(line)) cadr(line))<br />

)<br />

printf("Done processing file %s\n" fileName)<br />

else<br />

error("Cannot OPEN file %s \n" fileName)<br />

)<br />

)<br />

)<br />

procedure(AFVtestDump()<br />

foreach(key AnalogTests


)<br />

)<br />

printf("AnalogTests contains %L for key %s\n" AnalogTests[key] key)


APPENDIX E OCEAN SCRIPT FOR CMIRDIFFAMP4<br />

This Code was run with the following unix command:<br />

: ocean –log RESULTS/CmirDiffAmp4/OpampVerif.log < OCEAN/OpampVerif.ocn<br />

> RESULTS/CmirDiffAmp4/OpampVerif.out<br />

The following directory structure was used for this project. The project working directory is the normal location for<br />

starting Cadence tools for this project ~/proj446/icu . The ocean scripts are maintained in the OCEAN subdirectory,<br />

specification files in the SPECS subdirectory. The Pass/Fail summary files are written directly to the<br />

RESULTS directory while all other results are written into a design specific subdirectory, in this case<br />

RESULTS/CmirDiffAmp4/.<br />

AFVtestInit( "./SPECS/CmirDiffAmp4.spec") ; load and init the specifications<br />

simulator( 'spectre )<br />

design(<br />

"~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/schematic/netlist/netlist")<br />

resultsDir(<br />

"~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/keyPerftyp" )<br />

path( "/pdk/TSMC18/models" )<br />

modelFile(<br />

'("log018.scs" "bip")<br />

'("log018.scs" "tt_3vna")<br />

'("log018.scs" "tt_na")<br />

'("log018.scs" "tt_3v")<br />

'("ResModel.scs" "res_t")<br />

'("log018.scs" "res")<br />

'("log018.scs" "tt")<br />

)<br />

save('allv)<br />

save('i "E2" )<br />

analysis('xf ?start "10K" ?stop "1G" ?dec "20"<br />

?p "/inp" ?n "/inn" )<br />

analysis('dc ?saveOppoint t ?param "temp" ?start "0"<br />

?stop "100" ?step "5" )<br />

analysis('ac ?start "1K" ?stop "1G" ?dec "20" )<br />

analysis('tran ?stop "5u" )<br />

;; design Vars for the Test bench<br />

desVar( "inCMFB" 0 )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "Fdist" 1M )<br />

desVar( "ACin" 1 )<br />

desVar( "Tpin" 2u )<br />

desVar( "Tdin" 10n )<br />

desVar( "Tr" 10n )<br />

desVar( "Cload" 100p )<br />

desVar( "Rload" 1M )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 1.8 )<br />

desVar( "Vcm" 0.9 )<br />

desVar( "Iref" 300u )


desVar( "ACout" 0 )<br />

desVar( "VswngP" 1 )<br />

desVar( "VswngN" "-VswngP" )<br />

;; designvars for the design<br />

desVar( "wpmirr" 1m )<br />

desVar( "lmir" 2u )<br />

desVar( "K" 6 )<br />

desVar( "wnout" 100u )<br />

desVar( "wpcmir" 500u )<br />

desVar( "wndiff" 3m )<br />

desVar( "lnout" 10u )<br />

desVar( "lndiff" 1.5u )<br />

desVar( "lpcmir" 5u )<br />

desVar( "wp" .5m )<br />

desVar( "wmir" 12u )<br />

desVar( "lpmirr" 10u )<br />

desVar( "Iref" 300u )<br />

desVar( "lp" 1u )<br />

desVar( "wndiffa" "wndiff+30n" )<br />

desVar( "lndiffa" "lndiff+1n" )<br />

option( ’reltol "1e-5"<br />

)<br />

temp( 27 )<br />

;********************************Run the Typical Simulation<br />

run()<br />

;*******************<br />

; Process the Results<br />

;********** insert Plot Win setup commands here<br />

; OL Freq Response First<br />

;************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/OLFreqResp.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Open Loop Freq Response"<br />

)<br />

;***************************************<br />

; Reorder Outputs to get just the AC results<br />

;*****************<br />

;<br />

displayMode( "composite")<br />

Aolf = dB20((VF("/outp") - VF("/outn")))<br />

plot( Aolf ?expr ’( "Aol" ) )<br />

PHol = phase(((VF("/outp") - VF("/outn")) / (VF("/inp") - VF("/inn"))))<br />

plot( PHol ?expr ’( "PHol" ) )<br />

Aol = value(dB20((VF("/outp") - VF("/outn"))) 0)<br />

Zin = (VF("/inp") / IF("/E2/PLUS"))<br />

Zin1M = mag(value(Zin 1M))<br />

;<br />

if((TestVal = AFVtest("Aol" Aol)) then<br />

printf("SPECFAIL: Typical Aol = %2.2f Min Aol = %n dB\n" Aol TestVal)<br />

)<br />

GBW = gainBwProd((VF("/outp") - VF("/outn")))<br />

Gmargin = gainMargin((VF("/outp") - VF("/outn")))<br />

if((TestVal = AFVtest("GainMargin" Gmargin)) then


printf("SPECFAIL: Typical Gain Margin = %2.2f Max = %2.2f dB\n" Gmargin<br />

TestVal)<br />

)<br />

if((TestVal = AFVtest("GBW" GBW)) then<br />

printf(strcat("SPECFAIL: Gain BW (typ) = "<br />

aelSuffixWithUnits(GBW "dB-Hz" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB-Hz" )<br />

"\n"<br />

)<br />

)<br />

)<br />

;<br />

if((TestVal = AFVtest("Zin" Zin1M)) then<br />

printf(strcat("SPECFAIL: Zin @1MHz (typ) = "<br />

aelSuffixWithUnits(Zin1M "Ohms" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "Ohms" )<br />

"\n"<br />

)<br />

)<br />

)<br />

Pmargin = phaseMargin((VF("/outp") - VF("/outn")))<br />

if((TestVal = AFVtest("PhaseMargin" Pmargin)) then<br />

printf(strcat("SPECFAIL: Phase Margin (typ) = "<br />

aelSuffixWithUnits(Pmargin "deg" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "deg" )<br />

"\n"<br />

)<br />

)<br />

)<br />

UGF = cross(dB20((VF("/outp") - VF("/outn"))) 0 1 "either")<br />

if((TestVal = AFVtest("UGFreq" UGF)) then<br />

printf(strcat("SPECFAIL: UGF (typ) = "<br />

aelSuffixWithUnits(UGF "Hz" 4 )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "Hz" 4 )<br />

"\n"<br />

)<br />

)<br />

)<br />

DomPoleFreq = bandwidth((VF("/outp") - VF("/outn")) 3 "low")<br />

if((TestVal = AFVtest("BWol" DomPoleFreq)) then<br />

printf(strcat("SPECFAIL: OpLp 3dB BW (typ) = "<br />

aelSuffixWithUnits(DomPoleFreq "Hz" 4 )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "Hz" 4 )<br />

"\n"<br />

)<br />

)<br />

)<br />

;<br />

;//**** Add Scalar Outputs to Plot **<br />

;


addWaveLabel( 1 list( 1000 Aol) ; // point on the wave for the label<br />

sprintf(nil "DC OL Gain = %2.2f dB" Aol )<br />

?textOffset 10:-30<br />

?justify "lowerLeft"<br />

)<br />

addWaveLabel( 1 list( UGF 0) ; // point on the wave for the label<br />

strcat("Unity Gain Fr. = " aelSuffixWithUnits(UGF "Hz" 4 ) )<br />

?textOffset -50:-30<br />

?justify "lowerLeft"<br />

)<br />

addWindowLabel( list(0.15 0.2 )<br />

strcat("Gain Margin = " aelSuffixWithUnits(Gmargin "dB")<br />

"\nPhase Margin = " aelSuffixWithUnits(Pmargin "deg")<br />

"\nGain BandWidth = " aelSuffixWithUnits(GBW "dB_Hz")<br />

"\nDominant Pole = " aelSuffixWithUnits(DomPoleFreq "Hz")<br />

)<br />

)<br />

;<br />

;//***** Plot this window and setup a new one<br />

;<br />

hardCopy()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/RejRatios.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Rejection Ratios"<br />

)<br />

;*************************************<br />

CMRR = dB20((1 / getData("/VCM" ?result "xf-xf")))<br />

plot( CMRR ?expr ’( "CMRR" ) )<br />

PSRRdd = dB20((1 / getData("/VDD" ?result "xf-xf")))<br />

plot( PSRRdd ?expr ’( "PSRR+" ) )<br />

PSRRss = dB20((1 / getData("/VSS" ?result "xf-xf")))<br />

plot( PSRRss ?expr ’( "PSRR-" ) )<br />

CmRefRR = dB20((1 / getData("/VOUT" ?result "xf-xf")))<br />

plot( CmRefRR ?expr ’( "CmRef_RR" ) )<br />

dcCMRR = value(dB20((1 / getData("/VCM" ?result "xf-xf"))) 0)<br />

dcCmRefRR = value(dB20((1 / getData("/VOUT" ?result "xf-xf"))) 0)<br />

dcPSRRdd = value(dB20((1 / getData("/VDD" ?result "xf-xf"))) 0)<br />

dcPSRRss = value(dB20((1 / getData("/VSS" ?result "xf-xf"))) 0)<br />

addWindowLabel( list(0.15 0.2 ) ;// the relative location for the Text<br />

strcat("CMRR = " aelSuffixWithUnits(dcCMRR "dB")<br />

"\nPSRR+ = " aelSuffixWithUnits(dcPSRRdd "dB")<br />

"\nPSRR- = " aelSuffixWithUnits(dcPSRRss "dB")<br />

"\nCmRefRR = " aelSuffixWithUnits(dcCmRefRR "dB")<br />

)<br />

)<br />

if((TestVal = AFVtest("CMRR" dcCMRR)) then<br />

printf(strcat("SPECFAIL: CMRR(DC) (typ) = "<br />

aelSuffixWithUnits(dcCMRR "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

"\n"<br />

)


)<br />

)<br />

if((TestVal = AFVtest("CmRefRR" dcCmRefRR)) then<br />

printf(strcat("SPECFAIL: CMFB RR(DC) (typ) = "<br />

aelSuffixWithUnits(dcCmRefRR "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("PSRRdd" dcPSRRdd)) then<br />

printf(strcat("SPECFAIL: PSRR Vdd(DC) (typ) = "<br />

aelSuffixWithUnits(dcPSRRdd "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("PSRRss" dcPSRRss)) then<br />

printf(strcat("SPECFAIL: PSRR Vss(DC) (typ) = "<br />

aelSuffixWithUnits(dcPSRRss "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

"\n"<br />

)<br />

)<br />

)<br />

;<br />

;//***** Plot this window and setup a new one<br />

;<br />

hardCopy()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/StepResponse.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Large Signal Step Response"<br />

)<br />

;*************************************<br />

displayMode( "strip")<br />

TranOutput = (VT("/outp") - VT("/outn"))<br />

plot( TranOutput ?expr ’( "TranOutput" ) )<br />

TranInput = (VT("/uginp") - VT("/uginn"))<br />

plot( TranInput ?expr ’( "TranInput" ) )<br />

plot( VT("/outp") )<br />

plot( VT("/outn") )<br />

;SlewRate = slewRate((VT("/outp") - VT("/outn")) 2.5e-06 t 3.5e-06 t 10 90)<br />

OvershootP = overshoot((VT("/outp") - VT("/outn")) 4e-06 t 5e-06 t)<br />

OvershootN = overshoot((VT("/outp") - VT("/outn")) 3e-06 t 4e-06 t)<br />

;Slewsinglep = slewRate(VT("/outp") 2.5e-06 t 3.5e-06 t 10 90)<br />

;Slewsinglem = slewRate(VT("/outp") 3.5e-06 t 4.5e-06 t 10 90)<br />

;OvershootPp = overshoot(VT("/outp") 2.5e-06 t 3.5e-06 t)<br />

;OvershootPm = overshoot(VT("/outp") 3.5e-06 t 4.125e-06 t)<br />

;RiseTime = riseTime((VT("/outp") - VT("/outn")) 3.5e-06 t 4.5e-06 t 10 90)<br />

;OvershootN = overshoot(VT("/outn") 3e-06 t 3.125e-06 t)


;Tsettle0r1 = (settlingTime((VT("/outp") - VT("/outn")) 3e-06 t 4e-06 t 0.1) -<br />

cross((VT("/uginp") - VT("/uginn")) 0 2 "rising"))<br />

Tsettle1P = (settlingTime((VT("/outp") - VT("/outn")) 4e-06 t 5e-06 t 1)<br />

- cross((VT("/uginp") - VT("/uginn")) 0 2 "rising"))<br />

Tsettle1N = (settlingTime((VT("/outp") - VT("/outn")) 3e-06 t 4e-06 t 1)<br />

- cross((VT("/uginp") - VT("/uginn")) 0 2 "falling"))<br />

SlewRateP = abs(slewRate((VT("/outp") - VT("/outn")) 3.5e-06 t 4.5e-06 t 10<br />

90))<br />

SlewRateN = abs(slewRate((VT("/outp") - VT("/outn")) 2.5e-06 t 3.5e-06 t 10<br />

90))<br />

addWindowLabel( list(0.6 0.7 ) ;// the relative location for the Text<br />

strcat("Overshoot = " aelSuffixWithUnits(OvershootP "%")<br />

"\nSlewRate = " aelSuffixWithUnits(SlewRateP "V/s")<br />

"\nTsettle1% = " aelSuffixWithUnits(Tsettle1P "s")<br />

)<br />

)<br />

if((TestVal = AFVtest("SlewRate" SlewRateP)) then<br />

printf(strcat("SPECFAIL: SlewRate/ (typ) = "<br />

aelSuffixWithUnits(SlewRateP "V/s" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V/s" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("SlewRate" SlewRateN)) then<br />

printf(strcat("SPECFAIL: SlewRate\\ (typ) = "<br />

aelSuffixWithUnits(SlewRateN "V/s" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V/s" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("OvrShoot" OvershootP)) then<br />

printf(strcat("SPECFAIL: Overshoot/ (typ) = "<br />

aelSuffixWithUnits(OvershootP "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("OvrShoot" OvershootN)) then<br />

printf(strcat("SPECFAIL: Overshoot\\ (typ) = "<br />

aelSuffixWithUnits(OvershootN "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Tsettle" Tsettle1P)) then<br />

printf(strcat("SPECFAIL: Tsettle/ (typ) = "<br />

aelSuffixWithUnits(Tsettle1P "%%" )<br />

" Maximum specified = "


aelSuffixWithUnits(TestVal "%%" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Tsettle" Tsettle1N)) then<br />

printf(strcat("SPECFAIL: Tsettle\\ (typ) = "<br />

aelSuffixWithUnits(Tsettle1N "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

"\n"<br />

)<br />

)<br />

)<br />

;<br />

;//***** Plot this window and setup a new one<br />

;<br />

hardCopy()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/VosDrift.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Offset Voltage Drift"<br />

)<br />

;*************************************<br />

displayMode( "composite")<br />

plot( VS("/vos") ?expr ’( "Vos" ))<br />

Vos = VDC("/vos")<br />

VosDrift = value(deriv(VS("/vos")) 27)<br />

addWaveLabel( 1 list( 27 Vos) ; // point on the wave for the label<br />

strcat("Vos Drift = " aelSuffixWithUnits(VosDrift "V/deg C" 4 ) )<br />

?textOffset 20:30<br />

?justify "lowerLeft"<br />

)<br />

if((TestVal = AFVtest("VosDrift" VosDrift)) then<br />

printf(strcat("SPECFAIL: VosDrift (typ) = "<br />

aelSuffixWithUnits(VosDrift "V/deg C" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "V/deg C" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Vos" Vos)) then<br />

printf(strcat("SPECFAIL: Vos (typ) = "<br />

aelSuffixWithUnits(Vos "V" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

Idd = IDC("/VDD/MINUS")<br />

if((TestVal = AFVtest("Idd" Idd)) then<br />

printf(strcat("SPECFAIL: Idd (typ) = "<br />

aelSuffixWithUnits(Idd "A" )


" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "A" )<br />

"\n"<br />

)<br />

)<br />

)<br />

Pdiss = Idd*VAR("Vdd")<br />

if((TestVal = AFVtest("Pdiss" Pdiss)) then<br />

printf(strcat("SPECFAIL: Pdiss (typ) = "<br />

aelSuffixWithUnits(Pdiss "W" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "W" )<br />

"\n"<br />

)<br />

)<br />

)<br />

;//***** Plot this window and setup New Analyses and run them..<br />

hardCopy()<br />

resultsDir(<br />

"~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/schematic" )<br />

desVar( "VswngP" "Vdd" )<br />

loadPcf("./OCEAN/OpampVerif.pcf")<br />

loadDcf("./OCEAN/OpampVerif.dcf")<br />

cornerRun()<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/Corners.ps"<br />

?title ""<br />

)<br />

cornerMeas()<br />

addTitle(strcat("<strong>Amplifier</strong> PVT Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

)<br />

currentSubwindow( 1 )<br />

awvSetXLimit( awvGetCurrentWindow() list( 1K 1G ) ?subwindow 1 )<br />

addSubwindowTitle( "Open Loop Gain")<br />

;<br />

; awvRedisplayWindow( awvGetCurrentWindow() )<br />

;<br />

hardCopy()<br />

;<br />

/***********************************************<br />

*<br />

* these results will be vectors or waves as shown here:<br />

*<br />

ocean> ocnPrint(Aol)<br />

C<br />

value(dB20((VF("outp") - VF("outn"))) 0) (dB)<br />

FFhHi 62.3743<br />

FS 62.4565<br />

SF 62.6292<br />

SScLo 62.4745<br />

TT 62.5099<br />

t<br />

*<br />

** use the value command to get the individual values


*<br />

ocean> value(Aol "TT")<br />

62.50989<br />

*********************************************/<br />

Idd = IDC("/VDD/MINUS")<br />

Pdiss = Idd*VDC("/vdd!")<br />

Vos = VDC("/vos")<br />

Aol = value(dB20((VF("/outp") - VF("/outn"))) 0)<br />

GBW = gainBwProd((VF("/outp") - VF("/outn")))<br />

Gmargin = gainMargin((VF("/outp") - VF("/outn")))<br />

Pmargin = phaseMargin((VF("/outp") - VF("/outn")))<br />

UGF = cross(dB20((VF("/outp") - VF("/outn"))) 0 1 "either")<br />

DomPoleFreq = bandwidth((VF("/outp") - VF("/outn")) 3 "low")<br />

dcCMRR = value(dB20((1 / getData("/VCM" ?result "xf-xf"))) 0)<br />

dcCmRefRR = value(dB20((1 / getData("/VOUT" ?result "xf-xf"))) 0)<br />

dcPSRRdd = value(dB20((1 / getData("/VDD" ?result "xf-xf"))) 0)<br />

dcPSRRss = value(dB20((1 / getData("/VSS" ?result "xf-xf"))) 0)<br />

OvershootP = overshoot((VT("/outp") - VT("/outn")) 4e-06 t 5e-06 t)<br />

OvershootN = overshoot((VT("/outp") - VT("/outn")) 3e-06 t 4e-06 t)<br />

Tsettle1P = (settlingTime((VT("/outp") - VT("/outn")) 4e-06 t 5e-06 t 10)<br />

- cross((VT("/uginp") - VT("/uginn")) 0 2 "rising"))<br />

Tsettle1N = (settlingTime((VT("/outp") - VT("/outn")) 3e-06 t 4e-06 t 10)<br />

- cross((VT("/uginp") - VT("/uginn")) 0 2 "falling"))<br />

SlewRateP = abs(slewRate((VT("/outp") - VT("/outn")) 3.5e-06 t 4.5e-06 t 10<br />

90))<br />

SlewRateN = abs(slewRate((VT("/outp") - VT("/outn")) 2.5e-06 t 3.5e-06 t 10<br />

90))<br />

;<br />

; now get the corner values<br />

selectResults( ’dcOp )<br />

; first print the data files<br />

Crnrfile = outfile( "RESULTS/CmirDiffAmp4/CornerData.txt" )<br />

ocnPrint( ?output Crnrfile ?numSpaces 4 "Corner"<br />

"Aol (dB) " "GBW (dB-Hz) " "Gmargin(dB) "<br />

"Pmargin(deg) " "UGFreq(Hz)" "BWol (dB)")<br />

ocnPrint( ?output Crnrfile Aol GBW Gmargin Pmargin UGF DomPoleFreq)<br />

ocnPrint( ?output Crnrfile ?numSpaces 4 "Corner "<br />

"Idd (A) " "Pdiss (W) " "CMRR(dB) "<br />

"CmRefRR(dB) " "PSRRdd(dB) " "PSRRss(dB) " )<br />

ocnPrint( ?output Crnrfile Idd Pdiss dcCMRR<br />

dcCmRefRR dcPSRRdd dcPSRRss)<br />

ocnPrint( ?output Crnrfile ?numSpaces 4 "Corner"<br />

"OvershootP (%)" "OvershootN (%)" "Tsettle1P(s)"<br />

"Tsettle1N(s)" "SlRtp(V/s)" "SlRtn(V/s)" )<br />

ocnPrint( ?output Crnrfile OvershootP OvershootN<br />

Tsettle1P Tsettle1N SlewRateP SlewRateN)<br />

close(Crnrfile)<br />

Corners = sweepValues();<br />

foreach(Corner Corners<br />

; first print the data files<br />

if((TestVal = AFVtest("Idd" value(Idd Corner))) then<br />

printf(strcat("SPECFAIL: Idd = "<br />

aelSuffixWithUnits(value(Idd Corner) "A" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "A" )<br />

" Corner: " Corner<br />

"\n"


)<br />

)<br />

)<br />

if((TestVal = AFVtest("Pdiss" value(Pdiss Corner))) then<br />

printf(strcat("SPECFAIL: Pdiss = "<br />

aelSuffixWithUnits(value(Pdiss Corner) "W" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "W" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Vos" value(Vos Corner))) then<br />

printf(strcat("SPECFAIL: Vos = "<br />

aelSuffixWithUnits(value(Vos Corner) "V" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Aol" value(Aol Corner))) then<br />

printf("SPECFAIL: Aol = %2.2f Min Aol = %n dB Corner: %s\n"<br />

value(Aol Corner) TestVal Corner)<br />

)<br />

if((TestVal = AFVtest("GainMargin" value(Gmargin Corner))) then<br />

printf("SPECFAIL: Gain Margin = %2.2f Max = %2.2f dB Corner: %s\n"<br />

value(Gmargin Corner) TestVal Corner)<br />

)<br />

if((TestVal = AFVtest("GBW" value(GBW Corner))) then<br />

printf(strcat("SPECFAIL: Gain BW = "<br />

aelSuffixWithUnits(value(GBW Corner) "dB-Hz" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB-Hz" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("PhaseMargin" value(Pmargin Corner))) then<br />

printf(strcat("SPECFAIL: Phase Margin = "<br />

aelSuffixWithUnits(value(Pmargin Corner) "deg" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "deg" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("UGFreq" value(UGF Corner))) then<br />

printf(strcat("SPECFAIL: UGF = "<br />

aelSuffixWithUnits(value(UGF Corner) "Hz" 4 )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "Hz" 4 )


)<br />

)<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

if((TestVal = AFVtest("BWol" value(DomPoleFreq Corner))) then<br />

printf(strcat("SPECFAIL: OpLp 3dB BW = "<br />

aelSuffixWithUnits(value(DomPoleFreq Corner) "Hz" 4 )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "Hz" 4 )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("CMRR" value(dcCMRR Corner))) then<br />

printf(strcat("SPECFAIL: CMRR(DC) = "<br />

aelSuffixWithUnits(value(dcCMRR Corner) "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("CmRefRR" value(dcCmRefRR Corner))) then<br />

printf(strcat("SPECFAIL: CMFB RR(DC) = "<br />

aelSuffixWithUnits(value(dcCmRefRR Corner) "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("PSRRdd" value(dcPSRRdd Corner))) then<br />

printf(strcat("SPECFAIL: PSRR Vdd(DC) = "<br />

aelSuffixWithUnits(value(dcPSRRdd Corner) "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("PSRRss" value(dcPSRRss Corner))) then<br />

printf(strcat("SPECFAIL: PSRR Vss(DC) = "<br />

aelSuffixWithUnits(value(dcPSRRss Corner) "dB" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "dB" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("SlewRate" value(SlewRateP Corner))) then


printf(strcat("SPECFAIL: SlewRate/ = "<br />

aelSuffixWithUnits(value(SlewRateP Corner) "V/s" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V/s" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("SlewRate" value(SlewRateN Corner))) then<br />

printf(strcat("SPECFAIL: SlewRate\\ = "<br />

aelSuffixWithUnits(value(SlewRateN Corner) "V/s" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V/s" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("OvrShoot" value(OvershootP Corner))) then<br />

printf(strcat("SPECFAIL: Overshoot/ = "<br />

aelSuffixWithUnits(value(OvershootP Corner) "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("OvrShoot" value(OvershootN Corner))) then<br />

printf(strcat("SPECFAIL: Overshoot\\ = "<br />

aelSuffixWithUnits(value(OvershootN Corner) "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Tsettle" value(Tsettle1P Corner))) then<br />

printf(strcat("SPECFAIL: Tsettle/ = "<br />

aelSuffixWithUnits(value(Tsettle1P Corner) "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

" Corner: " Corner<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Tsettle" value(Tsettle1N Corner))) then<br />

printf(strcat("SPECFAIL: Tsettle\\ = "<br />

aelSuffixWithUnits(value(Tsettle1N Corner) "%%" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

" Corner: " Corner<br />

"\n"<br />

)


)<br />

)<br />

); foreach<br />

delete(’analysis)<br />

; now to find the Common Mode Range<br />

resultsDir( "~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/CMRange" )<br />

analysis(’dc ?saveOppoint t )<br />

analysis(’ac ?start "1K" ?stop "1G" ?dec "20" )<br />

desVar( "inCMFB" 0 )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "Fdist" 1M )<br />

desVar( "ACin" 1 )<br />

desVar( "VswngP" 1.5 )<br />

desVar( "Tpin" 2u )<br />

desVar( "Tr" 10n )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 1.8 )<br />

desVar( "Vcm" 0.9 )<br />

desVar( "Iref" 300u )<br />

desVar( "ACout" 0 )<br />

desVar( "VswngN" "-VswngP" )<br />

option( ’reltol "1e-5"<br />

)<br />

temp( 27 )<br />

paramAnalysis("Vcm" ?values ’(0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45<br />

0.5 0.55 0.60 0.65 0.70 0.75 0.80<br />

0.85 0.90 0.95 1 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40<br />

1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 )<br />

)<br />

paramRun()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/CMrange.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Common Mode Range"<br />

)<br />

;*************************************<br />

Aol_DC = value(dB20((VF("/outp") - VF("/outn"))) 1000)<br />

plot( Aol_DC ?expr ’( "Aol_DC" ) )<br />

CMRmin = root(value(db20(VF("/outp")-VF("/outn")),1K),<br />

ymax(value(db20(VF("/outp")-VF("/outn")),1K))-3,1)<br />

CMRmax = root(value(db20(VF("/outp")-VF("/outn")),1K),<br />

ymax(value(db20(VF("/outp")-VF("/outn")),1K))-3,2)<br />

VcommonHigh = value(VAR("Vdd") 0.5) - CMRmax;<br />

addWindowLabel( list(0.4 0.4 ) ;// the relative location for the Text<br />

strcat("CMRmin = " aelSuffixWithUnits(CMRmin "V")<br />

"\nCMRmax = " aelSuffixWithUnits(CMRmax "V")<br />

)<br />

)<br />

if((TestVal = AFVtest("VcommonLow" CMRmin)) then<br />

printf(strcat("SPECFAIL: Vcm Low (typ) = "<br />

aelSuffixWithUnits(CMRmin "V" )<br />

" Maximum specified = "


aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("VcommonHigh" VcommonHigh)) then<br />

printf(strcat("SPECFAIL: Vcm High (from Vdd) = "<br />

aelSuffixWithUnits(VcommonHigh "V" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

hardCopy()<br />

; now the cmfb circuit<br />

; this next section is the modified version <strong>of</strong> the<br />

; code from Appendix C – Sample Generated Script<br />

resultsDir( "~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/schematic" )<br />

analysis('dc ?saveOppoint t )<br />

analysis('ac ?start "1" ?stop "100G" ?dec "20" )<br />

desVar( "Fdist" 1M )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "inCMFB" 1 )<br />

desVar( "VswngP" 1 )<br />

desVar( "Tpin" 2.5u )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vcm" 0.9 )<br />

desVar( "Iref" 300u )<br />

desVar( "ACin" 0 )<br />

desVar( "ACout" 0 )<br />

desVar( "VswngN" "-VswngP" )<br />

option( 'reltol "1e-5"<br />

)<br />

temp( 27 )<br />

run()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/CMFB.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Common Mode Feedback"<br />

)<br />

;*************************************<br />

displayMode( "strip")<br />

;AclPcmfb = dB20(VF("/outp"))<br />

;plot( AclPcmfb ?expr '( "AclPcmfb" ) )<br />

;PhclNcmfb = phase(VF("/outn"))<br />

;plot( PhclNcmfb ?expr '( "PhclNcmfb" ) )<br />

;PhclPcmfb = phase(VF("/outp"))<br />

;plot( PhclPcmfb ?expr '( "PhclPcmfb" ) )<br />

;AclNcmfb = dB20(VF("/outn"))<br />

;plot( AclNcmfb ?expr '( "AclNcmfb" ) )<br />

;PhMarginPcmfbcl = phaseMargin(VF("/outp"))<br />

;plot( PhMarginPcmfbcl ?expr '( "PhMarginPcmfbcl" ) )


;PhMarginNcmfbcl = phaseMargin(VF("/outn"))<br />

;plot( PhMarginNcmfbcl ?expr ’( "PhMarginNcmfbcl" ) )<br />

Acmfbn = dB20((VF("/outn") / (VF("/outn") - VF("/cmout"))))<br />

plot( Acmfbn ?expr ’( "Acmfbn" ) )<br />

Acmfbp = dB20((VF("/outp") / (VF("/outp") - VF("/cmout"))))<br />

plot( Acmfbp ?expr ’( "Acmfbp" ) )<br />

BWcmfbN = bandwidth(VF("/outn") 3 "low")<br />

;plot( BWcmfbN ?expr ’( "BWcmfbN" ) )<br />

BWcmfbP = bandwidth(VF("/outp") 3 "low")<br />

;plot( BWcmfbP ?expr ’( "BWcmfbP" ) )<br />

PhiCmfbN = phase((VF("/outn") / (VF("/outn") - VF("/cmout"))))<br />

plot( PhiCmfbN ?expr ’( "PhiCmfbN" ) )<br />

PhiCmfbP = phase((VF("/outp") / (VF("/outp") - VF("/cmout"))))<br />

plot( PhiCmfbP ?expr ’( "PhiCmfbP" ) )<br />

PhMarginNcmfbol = phaseMargin((VF("/outn") / (VF("/outn") - VF("/cmout"))))<br />

PhMarginPcmfbol = phaseMargin((VF("/outp") / (VF("/outp") - VF("/cmout"))))<br />

CMFBAolP = value( Acmfbp 0)<br />

CMFBAolN = value( Acmfbn 0)<br />

addWindowLabel( list(0.4 0.4 ) ;// the relative location for the Text<br />

strcat("BW Pside = " aelSuffixWithUnits(BWcmfbP "Hz")<br />

"\nBW Nside = " aelSuffixWithUnits(BWcmfbN "Hz")<br />

"\nPhMar Pside = " aelSuffixWithUnits(PhMarginPcmfbol "deg")<br />

"\nPhMar Nside = " aelSuffixWithUnits(PhMarginPcmfbol "deg")<br />

"\nAol cmfb Pside = " aelSuffixWithUnits(CMFBAolP "dB")<br />

"\nAol cmfb Nside = " aelSuffixWithUnits(CMFBAolN "dB")<br />

)<br />

)<br />

if((TestVal = AFVtest("CMFBAol" CMFBAolP)) then<br />

printf(strcat("SPECFAIL: CMFBAol (P) = "<br />

aelSuffixWithUnits(CMFBAolP "V" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("CMFBAol" CMFBAolN)) then<br />

printf(strcat("SPECFAIL: CMFBAol (N) = "<br />

aelSuffixWithUnits(CMFBAolN "V" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("CMFBPhMar" PhMarginPcmfbol)) then<br />

printf(strcat("SPECFAIL: CMFBPhMar (P) = "<br />

aelSuffixWithUnits(PhMarginPcmfbol "V" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("CMFBPhMar" PhMarginNcmfbol)) then<br />

printf(strcat("SPECFAIL: CMFBPhMar (N) = "


aelSuffixWithUnits(PhMarginNcmfbol "V" )<br />

" Minimum specified = "<br />

aelSuffixWithUnits(TestVal "V" )<br />

"\n"<br />

)<br />

)<br />

)<br />

hardCopy()<br />

;;*************************** NOISE<br />

delete(’analysis)<br />

path( "./models" ) ; to use models with noimod = 3<br />

resultsDir( "~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/noise" )<br />

analysis(’noise ?start "1" ?stop "1G" ?dec "20"<br />

?p "/outp" ?n "/outn" ?oprobe "" ?iprobe "/VIN" )<br />

analysis(’dc ?saveOppoint t )<br />

analysis(’ac ?start "1" ?stop "1G" ?dec "20" )<br />

desVar( "Fdist" 1M )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "inCMFB" 0 )<br />

desVar( "VswngP" 1 )<br />

desVar( "Tpin" 2.5u )<br />

desVar( "Tdin" 0 )<br />

desVar( "Tr" 10n )<br />

desVar( "Cload" 100p )<br />

desVar( "Rload" 10M )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 2 )<br />

desVar( "Vcm" 1.0 )<br />

desVar( "Iref" 300u )<br />

desVar( "ACin" 1 )<br />

desVar( "ACout" 0 )<br />

desVar( "VswngN" "-VswngP" )<br />

option( ’reltol "1e-5"<br />

)<br />

temp( 27 )<br />

run()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/Noise.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Noise"<br />

)<br />

;*************************************<br />

displayMode("composite")<br />

ENV = ymin(getData("in" ?result "noise-noise"))<br />

plot( getData("out" ?result "noise-noise") )<br />

plot( getData("in" ?result "noise-noise") )<br />

Fbv = bandwidth(clip((1 / getData("in" ?result "noise-noise")) 1 10000000) 6<br />

"high")<br />

addWindowLabel( list(0.4 0.4 ) ;// the relative location for the Text<br />

strcat("ENV = " aelSuffixWithUnits(ENV "V/sqrt(Hz)")<br />

"\nFbv = " aelSuffixWithUnits(Fbv "Hz")<br />

)


)<br />

if((TestVal = AFVtest("ENV" ENV)) then<br />

printf(strcat("SPECFAIL: ENV input = "<br />

aelSuffixWithUnits(ENV "V/sqrt(Hz)" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "V/sqrt(Hz)" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Fbv" Fbv)) then<br />

printf(strcat("SPECFAIL: Fbv input = "<br />

aelSuffixWithUnits(Fbv "Hz" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "Hz" )<br />

"\n"<br />

)<br />

)<br />

)<br />

hardCopy()<br />

;;******************************** ZOUT<br />

delete(’analysis)<br />

resultsDir( "~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/ImpeadOut" )<br />

analysis(’dc ?saveOppoint t )<br />

analysis(’ac ?start "1" ?stop "100G" ?dec "20" )<br />

desVar( "inCMFB" 0 )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 0 )<br />

desVar( "Fdist" 1M )<br />

desVar( "ACin" 0 )<br />

desVar( "Tpin" 2u )<br />

desVar( "Tdin" 10n )<br />

desVar( "Tr" 10n )<br />

desVar( "Cload" 100p )<br />

desVar( "Rload" 1M )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 1.8 )<br />

desVar( "Vcm" 0.9 )<br />

desVar( "Iref" 300u )<br />

desVar( "ACout" 1 )<br />

desVar( "VswngP" 1 )<br />

desVar( "VswngN" "-VswngP" )<br />

temp( 27 )<br />

run()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/Zout.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Output Impedance"<br />

)<br />

;*************************************<br />

Zoutn = (VF("/von") / IF("/V8/PLUS"))<br />

plot( Zoutn ?expr ’( "Zoutn" ) )<br />

Zoutp = (VF("/vop") / IF("/V7/PLUS"))


plot( Zoutp ?expr ’( "Zoutp" ) )<br />

Zoutn1M = value(real((VF("/von") / IF("/V8/PLUS"))) 1M)<br />

;plot( Zoutn1M ?expr ’( "Zoutn1M" ) )<br />

Zoutp1M = value(real((VF("/vop") / IF("/V7/PLUS"))) 1M)<br />

;plot( Zoutp1M ?expr ’( "Zoutp1M" ) )<br />

if((TestVal = AFVtest("Zout" Zoutp1M)) then<br />

printf(strcat("SPECFAIL: Zout@1M P = "<br />

aelSuffixWithUnits(Zoutp1M "Ohms" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "Ohms" )<br />

"\n"<br />

)<br />

)<br />

)<br />

if((TestVal = AFVtest("Zout" Zoutn1M)) then<br />

printf(strcat("SPECFAIL: Zout@1M N = "<br />

aelSuffixWithUnits(Zoutn1M "Ohms" )<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "Ohms" )<br />

"\n"<br />

)<br />

)<br />

)<br />

hardCopy()<br />

;;********************************** THD<br />

;and Sinusoid outputs<br />

resultsDir( "~/proj446/icu/simulation/CmirDiffAmp_TB4/spectre/THD" )<br />

analysis(’noise ?start "100" ?stop "10M" ?dec "20"<br />

?p "/outp" ?n "/outn" ?oprobe "" ?iprobe "/VIN" )<br />

analysis(’tran ?stop "5u" ?skipdc "no" ?maxiters "10"<br />

?restart "no" )<br />

desVar( "inCMFB" 0 )<br />

desVar( "DCgain" 100 )<br />

desVar( "inDist" 1 )<br />

desVar( "Fdist" 1M )<br />

desVar( "ACin" 1 )<br />

desVar( "VswngP" 0 )<br />

desVar( "Tpin" 2u )<br />

desVar( "Tdin" 0 )<br />

desVar( "Tr" 10n )<br />

desVar( "Cload" 100p )<br />

desVar( "Rload" 100K )<br />

desVar( "gain" 1 )<br />

desVar( "inAmp" .5 )<br />

desVar( "Vss" 0 )<br />

desVar( "Vdd" 1.8 )<br />

desVar( "Vcm" 1.0 )<br />

desVar( "Iref" 300u )<br />

desVar( "ACout" 0 )<br />

desVar( "VswngN" "-VswngP" )<br />

option( ’reltol "1e-5"<br />

)<br />

temp( 27 )<br />

run()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"


?outputFile "RESULTS/CmirDiffAmp4/SineTrans.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Sinusoid Response (for THD)"<br />

)<br />

;*************************************<br />

TranOutput = (VT("/outp") - VT("/outn"))<br />

plot( TranOutput ?expr ’( "TranOutput" ) )<br />

TranInput = (VT("/uginp") - VT("/uginn"))<br />

plot( TranInput ?expr ’( "TranInput" ) )<br />

plot( VT("/outp") )<br />

plot( VT("/outn") )<br />

hardCopy()<br />

;*************************************<br />

AFVsetPlot( ?plotterName "ps2"<br />

?outputFile "RESULTS/CmirDiffAmp4/thd.ps"<br />

?title strcat("Typical <strong>Amplifier</strong> Characteristics CmirDiffAmp4"<br />

getCurrentTime())<br />

?subTitle "Distortion at 1M Hz"<br />

)<br />

;*************************************<br />

plotStyle(’bar)<br />

Fourier_Spectrum = dB20((v "/outp" ?result "FOUR1-tran.test_fourier" ))<br />

plot( Fourier_Spectrum ?expr ’( "Fourier Spectrum" ) )<br />

THD = thd((VT("/outp") - VT("/outn")) 4e-06 5e-06 64)<br />

plot( THD ?expr ’( "THD" ) )<br />

addWindowLabel( list(0.4 0.4 ) ;// the relative location for the Text<br />

strcat("THD = " aelSuffixWithUnits(THD "%")<br />

"\n")<br />

)<br />

)<br />

awvSetXLimit( awvGetCurrentWindow() list(0 100M) )<br />

hardCopy()<br />

if((TestVal = AFVtest("THD" THD)) then<br />

printf(strcat("SPECFAIL: THD = "<br />

aelSuffixWithUnits(THD "%%" ) ; first "%" is Format Spec<br />

" Maximum specified = "<br />

aelSuffixWithUnits(TestVal "%%" )<br />

"\n"<br />

)<br />

)<br />

)<br />

AFVreport(?runName "CmirDiffAmp4" ?ResultsDir "./RESULTS")


APPENDIX F – CORNERS SETUP FILES PCF<br />

;; Fixed by Jonathan David to be a ral Corners PROCESS def file<br />

corAddProcess( "TSMC18" "./models" "Multiple Model Library" )<br />

corAddProcessVar( "TSMC18" "Vcm" )<br />

corAddProcessVar( "TSMC18" "Vdd" )<br />

corAddModelFileAndSectionChoices( "TSMC18" "log018.scs" ’("fs" "sf" "ff" "ss"<br />

"tt") )<br />

corAddCorner( "TSMC18" "TT" )<br />

corSetCornerGroupVariant( "TSMC18" "TT" "log018.scs" "tt" )<br />

corSetCornerVarVal( "TSMC18" "TT" "Vdd" "1.8" )<br />

corSetCornerVarVal( "TSMC18" "TT" "Vcm" "900m" )<br />

corAddCorner( "TSMC18" "SScLo" )<br />

corSetCornerGroupVariant( "TSMC18" "SScLo" "log018.scs" "ss" )<br />

corSetCornerRunTempVal( "TSMC18" "SScLo" 0 )<br />

corSetCornerVarVal( "TSMC18" "SScLo" "Vdd" "1.6" )<br />

corSetCornerVarVal( "TSMC18" "SScLo" "Vcm" "800m" )<br />

corAddCorner( "TSMC18" "FFhHi" )<br />

corSetCornerGroupVariant( "TSMC18" "FFhHi" "log018.scs" "ff" )<br />

corSetCornerRunTempVal( "TSMC18" "FFhHi" 100 )<br />

corSetCornerVarVal( "TSMC18" "FFhHi" "Vdd" "2" )<br />

corSetCornerVarVal( "TSMC18" "FFhHi" "Vcm" "1.1" )<br />

corAddCorner( "TSMC18" "SF" )<br />

corSetCornerGroupVariant( "TSMC18" "SF" "log018.scs" "sf" )<br />

corSetCornerVarVal( "TSMC18" "SF" "Vdd" "1.8" )<br />

corSetCornerVarVal( "TSMC18" "SF" "Vcm" "900m" )<br />

corAddCorner( "TSMC18" "FS" )<br />

corSetCornerGroupVariant( "TSMC18" "FS" "log018.scs" "fs" )<br />

corSetCornerRunTempVal( "TSMC18" "FS" 27 )<br />

corSetCornerVarVal( "TSMC18" "FS" "Vdd" "1.8" )<br />

corSetCornerVarVal( "TSMC18" "FS" "Vcm" "900m" )


APPENDIX G – CORNERS SETUP FILES DCF<br />

corAddMeas( "Idd" )<br />

corSetMeasExpression( "Idd" "IDC(\"/VDD/MINUS\")" )<br />

corSetMeasEnabled( "Idd" t )<br />

corSetMeasGraphicalOn( "Idd" nil )<br />

corSetMeasTextualOn( "Idd" nil )<br />

corAddMeas( "Vdd" )<br />

corSetMeasExpression( "Vdd" "VDC(\"/vdd!\")" )<br />

corSetMeasEnabled( "Vdd" t )<br />

corSetMeasGraphicalOn( "Vdd" nil )<br />

corSetMeasTextualOn( "Vdd" nil )<br />

corAddMeas( "CmRefRR" )<br />

corSetMeasExpression( "CmRefRR"<br />

"value(dB20((1 / getData(\"/VOUT\" ?result \"xf-xf\"))) 0)" )<br />

corSetMeasEnabled( "CmRefRR" t )<br />

corSetMeasGraphicalOn( "CmRefRR" nil )<br />

corSetMeasTextualOn( "CmRefRR" nil )<br />

corAddMeas( "VoutSwing" )<br />

corSetMeasExpression( "VoutSwing"<br />

"(ymax((VT(\"/outp\")-VT(\"/outn\")))-ymin((VT(\"/outp\")-VT(\"/outn\"))))"<br />

)<br />

corSetMeasEnabled( "VoutSwing" t )<br />

corSetMeasGraphicalOn( "VoutSwing" nil )<br />

corSetMeasTextualOn( "VoutSwing" nil )<br />

corAddMeas( "Vhi_diffP" )<br />

corSetMeasExpression( "Vhi_diffP"<br />

"value((VT(\"/vdd!\") - VT(\"/outp\")) 3e-06)" )<br />

corSetMeasEnabled( "Vhi_diffP" t )<br />

corSetMeasGraphicalOn( "Vhi_diffP" nil )<br />

corSetMeasTextualOn( "Vhi_diffP" nil )<br />

corAddMeas( "Vlo_diffN" )<br />

corSetMeasExpression( "Vlo_diffN"<br />

"value((VT(\"/outn\") - VT(\"/vss!\")) 3e-06)" )<br />

corSetMeasEnabled( "Vlo_diffN" t )<br />

corSetMeasGraphicalOn( "Vlo_diffN" nil )<br />

corSetMeasTextualOn( "Vlo_diffN" nil )<br />

corAddMeas( "Aol_dB" )<br />

corSetMeasExpression( "Aol_dB"<br />

"dB20((VF(\"/outp\") - VF(\"/outn\")))" )<br />

corSetMeasEnabled( "Aol_dB" t )<br />

corSetMeasGraphicalOn( "Aol_dB" t )<br />

corSetMeasTextualOn( "Aol_dB" nil )


corAddMeas( "Isc-n" )<br />

corSetMeasExpression( "Isc-n"<br />

"ymax(clip(IT(\"/V8/PLUS\") 1e-06 5e-06))" )<br />

corSetMeasEnabled( "Isc-n" t )<br />

corSetMeasGraphicalOn( "Isc-n" nil )<br />

corSetMeasTextualOn( "Isc-n" nil )<br />

corAddMeas( "PhaseMargin" )<br />

corSetMeasExpression( "PhaseMargin"<br />

"phaseMargin((VF(\"/outp\") - VF(\"/outn\")))" )<br />

corSetMeasEnabled( "PhaseMargin" t )<br />

corSetMeasGraphicalOn( "PhaseMargin" nil )<br />

corSetMeasTextualOn( "PhaseMargin" nil )<br />

corAddMeas( "UGFreq" )<br />

corSetMeasExpression( "UGFreq"<br />

"cross(dB20((VF(\"/outp\") - VF(\"/outn\"))) 0 1 \"either\")" )<br />

corSetMeasEnabled( "UGFreq" t )<br />

corSetMeasGraphicalOn( "UGFreq" nil )<br />

corSetMeasTextualOn( "UGFreq" nil )<br />

corAddMeas( "Pdiss" )<br />

corSetMeasExpression( "Pdiss"<br />

"(IDC(\"/VSS/PLUS\") * (VAR(\"Vdd\") + VAR(\"Vss\")))" )<br />

corSetMeasEnabled( "Pdiss" t )<br />

corSetMeasGraphicalOn( "Pdiss" nil )<br />

corSetMeasTextualOn( "Pdiss" nil )<br />

corAddMeas( "Vos" )<br />

corSetMeasExpression( "Vos" "VDC(\"/vos\")" )<br />

corSetMeasEnabled( "Vos" t )<br />

corSetMeasGraphicalOn( "Vos" nil )<br />

corSetMeasTextualOn( "Vos" nil )<br />

corAddMeas( "PSRRdd" )<br />

corSetMeasExpression( "PSRRdd"<br />

"value(dB20((1 / getData(\"/VDD\" ?result \"xf-xf\"))) 0)" )<br />

corSetMeasLower( "PSRRdd" 100 )<br />

corSetMeasTarget( "PSRRdd" 110 )<br />

corSetMeasEnabled( "PSRRdd" t )<br />

corSetMeasGraphicalOn( "PSRRdd" t )<br />

corSetMeasTextualOn( "PSRRdd" nil )<br />

corAddMeas( "Aol" )<br />

corSetMeasExpression( "Aol"<br />

"value(dB20((VF(\"/outp\") - VF(\"/outn\"))) 0)" )<br />

corSetMeasLower( "Aol" 60 )<br />

corSetMeasTarget( "Aol" 70 )<br />

corSetMeasEnabled( "Aol" t )


corSetMeasGraphicalOn( "Aol" t )<br />

corSetMeasTextualOn( "Aol" nil )<br />

corAddMeas( "PSRRss" )<br />

corSetMeasExpression( "PSRRss"<br />

"value(dB20((1 / getData(\"/VSS\" ?result \"xf-xf\"))) 0)" )<br />

corSetMeasLower( "PSRRss" 100 )<br />

corSetMeasTarget( "PSRRss" 110 )<br />

corSetMeasEnabled( "PSRRss" t )<br />

corSetMeasGraphicalOn( "PSRRss" nil )<br />

corSetMeasTextualOn( "PSRRss" nil )<br />

corAddMeas( "GBW" )<br />

corSetMeasExpression( "GBW" "gainBwProd((VF(\"/outp\") - VF(\"/outn\")))" )<br />

corSetMeasEnabled( "GBW" t )<br />

corSetMeasGraphicalOn( "GBW" nil )<br />

corSetMeasTextualOn( "GBW" nil )<br />

corAddMeas( "SlewRateP" )<br />

corSetMeasExpression( "SlewRateP"<br />

"slewRate((VT(\"/outp\") - VT(\"/outn\")) 3.5e-06 t 4.5e-06 t 10 90)" )<br />

corSetMeasEnabled( "SlewRateP" t )<br />

corSetMeasGraphicalOn( "SlewRateP" nil )<br />

corSetMeasTextualOn( "SlewRateP" nil )<br />

corAddMeas( "SlewRateN" )<br />

corSetMeasExpression( "SlewRateN"<br />

"slewRate((VT(\"/outp\") - VT(\"/outn\")) 2.5e-06 t 3.5e-06 t 10 90)" )<br />

corSetMeasEnabled( "SlewRateN" t )<br />

corSetMeasGraphicalOn( "SlewRateN" nil )<br />

corSetMeasTextualOn( "SlewRateN" nil )<br />

corAddMeas( "GainMargin" )<br />

corSetMeasExpression( "GainMargin"<br />

"gainMargin((VF(\"/outp\") - VF(\"/outn\")))" )<br />

corSetMeasEnabled( "GainMargin" t )<br />

corSetMeasGraphicalOn( "GainMargin" nil )<br />

corSetMeasTextualOn( "GainMargin" nil )<br />

corAddMeas( "CMRR" )<br />

corSetMeasExpression( "CMRR"<br />

"value(dB20((1 / getData(\"/VCM\" ?result \"xf-xf\"))) 0)" )<br />

corSetMeasLower( "CMRR" 100 )<br />

corSetMeasTarget( "CMRR" 110 )<br />

corSetMeasEnabled( "CMRR" t )<br />

corSetMeasGraphicalOn( "CMRR" t )<br />

corSetMeasTextualOn( "CMRR" nil )<br />

corAddMeas( "VosTemp" )<br />

corSetMeasExpression( "VosTemp" "VS(\"/vos\")" )<br />

corSetMeasEnabled( "VosTemp" t )


corSetMeasGraphicalOn( "VosTemp" nil )<br />

corSetMeasTextualOn( "VosTemp" nil )<br />

;corAddMeas( "VosDrift" )<br />

;corSetMeasExpression( "VosDrift" "value(deriv(VS(\"/vos\")) 27)" )<br />

;corSetMeasEnabled( "VosDrift" t )<br />

;corSetMeasGraphicalOn( "VosDrift" nil )<br />

;corSetMeasTextualOn( "VosDrift" nil )<br />

corAddMeas( "Isc+p" )<br />

corSetMeasExpression( "Isc+p" "ymin(clip(IT(\"/V7/PLUS\") 1e-06 5e-06))" )<br />

corSetMeasEnabled( "Isc+p" t )<br />

corSetMeasGraphicalOn( "Isc+p" nil )<br />

corSetMeasTextualOn( "Isc+p" nil )

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!