Functional Verification of a Differential Operation Amplifier
Functional Verification of a Differential Operation Amplifier
Functional Verification of a Differential Operation Amplifier
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 )