If my recollection doesn’t fail me, this was about ten years ago. I walked into the lecture hall for EE313, full of excitement. The digital CMOS course was taught by Prof. Mark Horowitz. There has always been some “deity” status attached to the man. As a self-proclaimed analog design student at the time, I was anxious to learn what the “other side” was about.

Halfway into the lecture, Prof. Horowitz began a “sales pitch” of something called CircuitBook. He was candid about us being the genuine pigs for a testbench framework that his Ph.D. student was working on. The goal was to create a reusable analog test solution stack using only Python and SPICE. With a more software approach, the unified framework hopes to “hide” all the possible diverse variations in analog test environments. I distinctly remember feeling a bit confused: why would I ever want to code my testbenches for analog?

Figures taken from the CircuitBook thesis. The framework attempts to use Python for unifying almost all components in a test (top).

Years later after I entered industry, my mind always circles back to this moment. I obviously didn’t get the full picture as a graduate student then. However, CircuitBook has aged like fine wine the longer I work in IC design. The idea sounds better each day when I need to simulate a new circuit or look at others’ testbenches. So why didn’t it take off? Here are the reasons in the author’s own words:

We have found that one of the main challenges with the CircuitBook test framework has been convincing users to adopt the system. We believe this can be attributed to the initial learning required to be productive. The CircuitBook test framework does not significantly speed up the time required to make a new test for first time when the time to learn the framework is included. The productivity gains come from reusing the resulting test collateral for future variants. Users are often concerned more about the task at hand than future benefits, so our current test framework may not be attractive to time-constrained designers.

James Mao, “CIRCUITBOOK: A FRAMEWORK FOR ANALOG DESIGN
REUSE”

No truer words have been spoken. The author went on to discuss filling the framework repository “with reusable test components”. The framework could also “provide building blocks that allow users to quickly construct tests for a particular circuit class”. The proposed strategies aim to make adoption easier. I believe what he alluded to could already be realized in schematic capture tools today – in the form of testbench templates.

Creating reusable testbench cells

As I have mentioned in a previous post, a wrapper might be necessary if it’s used again and again. For example, supplies are perhaps instantiated the most number of times, but we hardly think about creating reusable supply cells. The same applies to input stimulus for DC/AC/transient simulations.

One tip is to parametrize these cells as much as possible (e.g. using pPar) to avoid creating too many variations. It certainly doesn’t provide the full flexibility of coding in Python, but it should be good enough for most testbenches.

Here we discuss a few cases for some most common testbench cells

1. Supplies

For any given project, supply domains are typically agreed upon first. Many mixed-signal circuits require multiple supplies nowadays for optimal performance and power. Grounds could be separately on-chip to provide isolation between analog and digital lands. It begins to make more sense to create a dedicated reusable supply cell for all testbenches like below.

The cell itself is not that fancy: the simplest form involves just ideal voltage sources. Parametrization is what makes it more interesting and powerful. One example is to parametrize each source’s DC voltage for editing at the testbench’s top level.

You might spot in the figure above that the cell uses 0V voltage sources to create ground nodes. Isn’t this redundant? If the goal is to simply break the ideal ground into different names, ideal 0 Ohm resistors can also do the trick. The key here is to allow more parametrization for simulations like power supply rejection ratio (PSRR). One can parametrize the AC magnitude on ground net with pPar(“avss_ac”) for example. We can then configure the supply cell to perform such simulations without any new setups. The same applies to other sources.

Simple models for supply impedance is the natural next step. Each supply can have a RLC network in series to mimic bond wires and package traces. Keep it fully parameterizable for full flexibility.

To make it more user friendly, remember to include default values to save time when initiating this cell. When the supply cell is first initiated in a testbench, its property list and default values might look like below. Note that the default values could also be strings, so some parameters can become design variables automatically.

Example parameter list and default values
2. Input stimulus

By the same token, input stimulus can also be parametrized and made more “general”. We are interested in differential inputs in most applications. My preferred way is using ideal baluns (for reasons that Ken Kundert also wrote about it here).

Depicted above is one simple example of such a differential stimulus cell. For DC and AC sims, parameterizing the differential and common mode DC/AC source values and impedances should cover most cases.

Building on top of this, different variations are possible for transient simulations. I am a broadband signals guy, so a pulse stimulus (i.e. Vpulse or Vpwl) is often my first choice for simulating pulse responses. If you are a narrowband or converter person, Vsin might be your cup of tea. A differential clock can also be generated by using Vpulse and setting vdiff and vcm correctly. All of these sources still have the DC/AC fields, so they remain compatible with DC/AC simulations.

One can in theory build a much general stimulus cells with all possible sources and an analog mux for selection, but the return on investment starts to diminish. I recommend simply creating cells for the most common inputs like stimulus_sine, stimulus_pulse, stimulus_clk, etc., and keep the number of parameters manageable.

Below is a more elaborate version of this stimulus cell. Other features like AC-coupling and external source select can be included. Most of these features can be realized with ideal resistors and math if you don’t wish to write VerilogA modules.

3. Probing and measuring

Testbenches are the only places where we can build perfect analog computers, so let’s take advantage of this.

Here is another awesome use of ideal baluns: they are “bi-directional” and can measure differential and common mode signals. Instead of post processing simulation results, you can put in these balun based probe elements to calculate differential and common modes during simulations.

(a) Differential and common mode to complementary signal conversion. (b) Differential and common mode measurements from complementary signals

Since impedances are also transparent through baluns (like in stimulus cells), ideal voltage buffers can help isolate the probe signals in case some loads are accidentally attached.

So why go through all the trouble of using such a probe cell? Again, this probe element here opens up a new idea: pre-process signals in simulation to simplify post-processing expressions. Some post-processing expressions can become really unreadable really fast (parenthesis nightmare anyone?). I find the measurement expressions easier to follow when I don’t have to jump over several hoops to trace where each signal or variable is defined. Thus, don’t limit your imagination to just this simple probe cell. Start encapsulating some measurements you do repeatedly in reusable cells.

One simple but powerful example is a power meter (do you get the pun?). Try building one using a series voltage source, a current-controlled voltage source (ccvs) and a multiplier. A more complicated example is to build DACs + de-interleaver for combining interleaved ADC outputs. Rather than saving all ADC slices’ outputs and post process in MATLAB or Python for FFT, the combined output is already available as a saved net. Here is another benefit: one could check results during simulation to ensure the signals look healthy. Stop the run in case something doesn’t look right instead of waiting until the long simulation finishes.

4. Deep probing

But what about nets that are inside the DUT? Luckily, we can use deepprobe to bring nets deep in the hierarchy up to the top level. Deepprobe also allow you to modify loading on the internal nets of interest. So one way to probe internal differential nets is as follows

Deepprobes with balun based differential probe cell

Unfortunately, I haven’t found a way to wrap this into a “diff_deepprobe” cell. I am still looking for answers here, but for now this cell group work just as well.

One disclaimer here is that this shouldn’t be a full replacement of your typical save statements. Rather, one should use this probe strategicaly on critical net for better readability (for your own or others’ consumption). Of course, there is a personal preference to this, but I find this approach more attractive than reading netlists and save files due to direct visual feedbacks.

5. Verilog-A modules

Last but not least, you can perhaps create all of the above (and more) if you are proficient in Verilog-A. In addition to what’s already available in standard libraries, most teams might already have a separate well-maintained Verilog-A library. They could have countless hidden gems like digital constant cells, frequency meter or bias gen models. Do spend some time to study them and/or create a couple modules that help with your own simulation flows.

Creating testbench templates

With an arsenal of these reusable cells (not that different from the software modules proposed in CircuitBook), we could start building testbench templates. In essence, they are the bases and starting points for certain simulations of particular circuits.

Below is what a general purpose testbench template might look like. The template contains a supply cell, sine wave transient input stimulus, a power meter, differential probes (including deepprobes), and a digital attribute cell. The default parameter values for each cell should require minimal changes to start some quick DC/AC simulations. The probe and digital attribute cell is there for quick usage reference, further modifications, or duplications. It’s always easier to delete/copy-paste on the same schematic sheet than instantiating new cells. A reasonable simulation state should also be available (e.g., corner setups, signal saves and reference measurement expressions). Overall, the template should provide the essentials to shorten the time to hit that green run button.

Generic testbench template

Expanding upon this principle, we can build specialized testbench templates for well known characterizations on certain classes of circuits. Here is a template for simulating the regeneration time constant of a dynamic comparator. Input and clock sources are provided. Probe names are already filled in for the regeneration nodes. What’s cool is that the template can also have instructions for DUT instantiation (just like reading through some code comments). The simulation state should already contain critical measurement expressions based on the template (in this case some exponential time constant calculations).

Example testbench template for dynamic comparator regeneration time constant simulation

To keep the momentum going, here is a rapid fire round for template ideas: op-amp characterization, amplifier noise, oscillator phase noise, general purpose feedback loop stability, converter ENOB, periodic steady state analysis, PSRR, power sequencing, … Can you think about others?

I hope the message has come across loud and clear: if we really think about the day-to-day simulations we run, we could exploit some similarities among testbenches to improve productivity. Testbench templates are pre-built schematics that give us a head start when starting simulations. Instead of drawing a new schematic each time, the process becomes finding the right template, create a copy, modify and run.

The million-dollar questions

I can already hear the skeptics yelling: is this really any better than frameworks like CircuitBook? Who should build and manage these templates? Do you seriously think we have the time to manage another library for testbench templates?

For industry designers, using testbench templates could become a way to preserve and pass along knowledge. From a student’s perspective, I believe having access to testbench templates speed up the learning process. These templates allow one to spend more time exploring the design space than fighting for the right setup. They are also more visually direct than reading through codes (a schematic is worth a thousand lines of code).

While some might argue that the struggles are part of the learning, we need to look no further than the open-source software community to see the flaws in this thinking. We have enough problems during the design phase as is. I see a full parallel between building these testbench cells and templates and open-source packages ready for use and modifications.

As to who should do all the “dirty work”, the answer is always graduate students and interns 😉. Jokes aside, I think it’s a “survival of the fittest” system, in which the best cells and templates will prevail (not that different from open-source again). Many teams might already require a full library cleanup after each tape-out. The downtime between tape-outs is the perfect gap for designers to massage these templates, explore new ideas for reusable cells, and improve methodologies.

Now that we have our own version of open-source for chip design underway, readable and reusable testbench templates are just as important as the designs themselves. There is no shortage of brilliant testbench tricks and setups by our community’s gurus. We just need a more systematic and straightforward way to democratize them.