CACE Setup for a 5T-OTA

Warning

This tutorial is currently outdated. Please take a look at the ota-5t directly and use sky130_ef_ip__template as a starting point for your analog projects.

This tutorial will guide you step by step through the creation of a simple 5-transistor OTA and the CACE setup for it. It is assumed that you have already set up CACE and its dependencies.

Getting Started

In this tutorial we will design a simple circuit, the “Hello World!” of analog design, a 5-transistor OTA, and set up CACE for it.

The source files for this project are available at ota-5t. You can simply follow along and compare with this reference in case of problems.

It is assumed that you work within the nix-shell provided by CACE and that you have installed the Sky130A PDK. If not, please take a look at the Installation Overview to install Nix and enable the shell. For the installation of the PDK you can use e.g. volare.

After you have installed the PDK and activated the nix-shell, you must export PDK_ROOT so that it points to the installation directory and export PDK to the name of the PDK being used. If the PDK was installed using volare, you can set PDK_ROOT to:

export PDK_ROOT=~/.volare
export PDK=sky130A

This tutorial starts with the creation of a schematic and symbol for the OTA. The next step is to create the design testbench and to draw the layout. If you are already familiar with this, you can skip this part and start directly at Creating the CACE Datasheet. Then, the CACE set up is created: It consists of a datasheet for the OTA and a template testbench.


As the first step, create a folder and name it ota-5t. The reason for the name of the folder is that CACE takes the name of the current directory when it is called and searches for a corresponding data sheet under cace/<design_name>.yaml. In our case, this is cace/ota-5t.yaml, which we will create later. Another option is to use a generic name for the project directory and tell cace where to find the datasheet. This is useful if you have multiple designs and datasheets in just one project folder.

At the end of this tutorial, the top-level directory structure should look like this:

.
├── cace
├── gds
├── netlist
├── runs
└── xschem

In the following sections, we will create the subfolders one by one. The cace folder contains everything that is CACE-specific: the datasheet, custom scripts and template testbenches. In gds we will create the layout for the OTA. The netlist folder is generated by CACE and contains the different netlist sources of your design, e.g. the schematic netlist, the layout-extracted netlist, the C-extracted netlist and the R-C-extracted netlist for full parasitic extraction. The runs folder is generated by CACE and contains all files for each run with a timestamp, e.g. RUN_2024-06-17_12-45-27. Finally, the design schematic, the design testbench, as well as the symbol file are stored under xschem.

Adding a README.md and LICENSE to your repository is good practice.

Creating the Schematic

For schematic entry we choose to use xschem.

Create the folder xschem in the root directory, before we start xschem we need to create an xschemrc file here.

# Source the PDK xschemrc file
if {![info exists PDK]} {
    source $env(PDK_ROOT)/$env(PDK)/libs.tech/xschem/xschemrc
}

# Add current directory to xschem library path
append XSCHEM_LIBRARY_PATH :[file dirname [info script]]

This file will be automatically sourced if you start xschem in the same directory. If not you need to specify it via --rcfile.

Note

Why is this necessary? The reasons are twofold: Firstly, the PDK is automatically sourced and secondly, the xschem/ directory is added to the XSCHEM_LIBRARY_PATH. This is necessary so that all symbol references in the schematic are relative and therefore portable.

Next, go to ota-5t/xschem/ and start xschem using:

xschem ota-5t.sch

This command starts xschem and automatically sources the xschemrc file we created before. You will be greeted by a blank window since ota-5t.sch did not exist before. Save the schematic to create this file.

We need to replicate this schematic:

5-Transistor OTA Schematic

The transistors M6 and M5 make up the current mirror, where M6 is not counted as transistor for the 5-T OTA. M4 and M3 form the differential pair, and M2 and M1 are the active load. The three individual transistors on the right side are only dummies and have no real functionality but to improve the performance of the circuit after manufacturing. The nf attribute specifies the number of fingers for each transistor, we will group them together in the layout.

If you need help with placing symbols and connecting wires, please refer to the xschem manual.

Note

You can get the completed schematic from here.

Creating the Symbol

The easiest way to create a symbol from your schematic is to press A while you have the schematic open. Xschem will ask you if you want to make a symbol view from the schematic. Press OK.

Now, try to replicate this symbol:

5-Transistor OTA Schematic

Note

You can get the completed symbol from here.

Creating the Design Testbench

In CACE, we distinguish between the design testbench and the template testbench.

The design testbench is used during the development of your design, here it makes sense to place graphs and other helpful widgets to debug your circuit.

The template testbench contains placeholder variables and cannot be run on its own. CACE uses it to generate testbenches for all conditions. More about the template testbench under Creating the Template Testbench

Start xschem from ota-5t/xschem/:

xschem ota-5t_tb.sch

Again, try to replicate the design testbench:

5-Transistor OTA Design Testbench

Note

You can get the completed design testbench from here.

Drawing the Layout

Now we come to the layout phase. You can us either magic or KLayout to draw the layout of your design.

In this tutorial, we have chosen to draw the layout using KLayout and used the PCells provided by the sky130A PDK.

Warning

If you are using KLayout and PCells, please make sure to convert the layout to a static version for parasitic extraction with magic. We have provided a simple script make_pcells_static.py to do this.

The layout of the OTA uses various matching techniques to improve the real-life performance:

  • Interdigitized layout

  • Common centroid layout

  • Dummy transistors

Try to replicate the layout of the OTA:

5-Transistor OTA Layout

Note

You can get the completed layout from here.

Creating the CACE Datasheet

Finally, we come to the CACE part of this tutorial. The first step of the CACE setup is to create a datasheet for your design. The datasheet contains documentation about your design and the parameters you want to measure and under what conditions. The datasheet will be used as input for CACE.

Let’s start with the header. As you can see, it contains basic information about the design, the CACE format version, information about the author and project paths. The paths tell CACE where to find the schematic (xschem/) and the layout (gds/). The netlist path tells CACE where to generate the different netlists for the schematic, layout and parasitic extraction. CACE can also export your datasheet, in this case under doc.

#--------------------------------------------------------------
# CACE circuit characterization file
#--------------------------------------------------------------

name:           ota-5t
description:    A simple 5-transistor OTA
PDK:            sky130A

cace_format:    5.2

authorship:
  designer:         Leo Moser
  company:          Efabless
  creation_date:    May 27, 2024
  license:          Apache 2.0

paths:
  root:             ..
  schematic:        xschem
  layout:           gds
  netlist:          netlist
  documentation:    doc

This section is optional, but recommended, as CACE compares the pins with the schematic of your design. You can specify as much or as little per pin as you like.

pins:
  VDD:
    description: Positive analog power supply
    type: power
    direction: inout
    Vmin: 1.7
    Vmax: 1.9
  VSS:
    description: Analog ground
    type: ground
    direction: inout
  Ib:
    description: Bias current input
    type: signal
    direction: input
  Vp:
    description: Voltage positive input
    type: signal
    direction: input
  Vn:
    description: Voltage negative input
    type: signal
    direction: input
  Vout:
    description: Voltage output
    type: signal
    direction: output

CACE generates a testbench for each set of conditions. As not every parameter has to change in each condition, you can specify default conditions that are used if no conditions are specified in the parameter.

default_conditions:
  vdd:
    description: Analog power supply voltage
    display: Vdd
    unit: V
    typical: 1.8
  vcm:
    description: Input common mode voltage
    display: Vcm
    unit: V
    typical: 0.9
  ib:
    description: Bias current
    display: Ib
    unit: uA
    typical: 10
  cl:
    description: Output load capacitance
    display: CLoad
    unit: pF
    maximum: 1
  corner:
    description: Process corner
    display: Corner
    typical: tt
  temperature:
    description: Ambient temperature
    display: Temp
    unit: °C
    typical: 27

Finally, we arrive at the parameters section. Here you can specify parameters for which CACE runs simulations using the ngspice tool. Each entry consists of a description, limits for the parameter so that it can be evaluated (✅/❌), the simulation section and the conditions for this parameter.

The simulate section specifies which simulator and template testbench to use (ota-5t_tb.spice, we will create it in the next section) and the format of the output (ascii) as well as its file extension (.data). The output file can contain multiple values, therefore we need to tell CACE which one to use. In the case of the first parameter, the first value is the result ([result, 'null', 'null']).

Finally, the conditions are specified in either minimum/typical/maximum notation, or by enumeration. For the corner condition, we could also add the remaining corners fs and sf if we would like to. These conditions replace the corresponding default conditions. CACE generates a simulation testbench for each combination of conditions. Since we have specified 3 values for corner and 3 values for temperature, a total of 33=9 simulations are started and evaluated against the limits. If we were to add vdd as a condition with 3 different values, we would have a total of 33*3=27 simulations for this parameter.

parameters:
  dc_params:
    spec:
      a0:
        display: DC gain
        description: The DC gain of the OTA
        unit: V/V
        minimum:
          value: 50
        typical:
          value: any
        maximum:
          value: any
      ugf:
        display: Unity Gain Frequency
        description: The unity gain frequency of the OTA
        unit: Hz
        minimum:
          value: 1e6
        typical:
          value: any
        maximum:
          value: any
      pm:
        display: Phase Margin
        description: The phase margin of the OTA
        unit: °
        minimum:
          value: 60
        typical:
          value: any
        maximum:
          value: any
    tool:
      ngspice:
        template: ac.sch
        format: ascii
        suffix: .data
        variables: [a0, ugf, pm]
    plot:
      gain_vs_temperature:
        type: xyplot
        xaxis: temperature
        yaxis: a0
      phase_margin_vs_corner:
        type: xyplot
        xaxis: corner
        yaxis: pm
    conditions:
      corner:
        enumerate: [tt, ff, ss] # fs, sf
      temperature:
        minimum: -40
        typical: 27
        maximum: 130

CACE has also support for other tools which evaluate properties of the layout such as area, width, length, DRC and LVS. They also specify a limit, whereby for DRC and LVS only a maximum of 0 makes any sense at all.

  magic_area:
    spec:
      area:
        display: Area
        description: Total circuit layout area
        unit: µm²
        maximum:
          value: 600
      width:
        display: Width
        description: Total circuit layout width
        unit: µm
        maximum:
          value: any
      height:
        display: Height
        description: Total circuit layout height
        unit: µm
        maximum:
          value: any
    tool:
      magic_area

  magic_drc:
    description: Magic DRC
    display: Magic DRC
    spec:
      drc_errors:
        maximum:
          value: 0
    tool:
      magic_drc

  netgen_lvs:
    description: Netgen LVS
    display: Netgen LVS
    spec:
      lvs_errors:
        maximum:
          value: 0
    tool:
      netgen_lvs:
        script: run_project_lvs.tcl

  klayout_drc_full:
    description: KLayout DRC full
    display: KLayout DRC full
    spec:
      drc_errors:
        maximum:
          value: 0
    tool:
        klayout_drc:
            args: ['-rd', 'feol=true', '-rd', 'beol=true', '-rd', 'offgrid=true']

And that’s it! Adding a new parameter is as simple as duplicating an existing parameter and customizing it (and perhaps creating a new template testbench). If you take a look at the example repository you will find even more parameter definitions.

Creating the Template Testbench

Create the templates folder under ota-5t/cace/ and create an xschemrc file with the following content:

# Source project xschemrc
source [file dirname [info script]]/../../xschem/xschemrc

This makes sure that the xschemrc file under xschem/ is sourced so that we have access to the symbol of our design.

Next, start xschem from ota-5t/cace/templates/:

xschem ota-5t_tb.sch

Try to replicate the template testbench:

5-Transistor OTA Template Testbench

Note

You can get the completed template testbench from here.

Running CACE

Command Line Interface

To start CACE in the command line for our design, simply invoke CACE from the ota-5t folder. By default, it will find the corresponding datasheet under cace/ota-5t.yaml.

$ cace

You should get an output similar to the one shown here:

CACE CLI Running

After CACE has finished, you will get a summary for all parameters, telling you whether they passed or failed:

CACE CLI Summary

By default, CACE uses the “best” netlist available. Since we provided a layout, this is the R-C-extracted netlist of our design called “rcx”. You can also explicitly pass the netlist source to be used, e.g. for “schematic”, via --source. CACE also supports running of only a subset of the available parameters with --parameter.

$ cace --source schematic --parameter a0 pm

For troubleshooting, I like to lower the log level to “DEBUG” and only ever run one parameter in parallel. Since the simulations of a parameter also run in parallel, I set --sequential to run them one after another.

$ cace --source rcx --log-level DEBUG \
       --parallel-parameters 1 --sequential

Final Thoughts

We hope this tutorial was able to give you an introduction to setting up and using CACE. If you already designed an IP block, you can add a CACE setup to it. Or you could try adding CACE to your next design. Have fun!

Note

Did you notice any issues with this tutorial or have ideas for improvements? Please open an issue so we can improve this tutorial. Thank you!