{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "aK2t7aSWNojQ"
},
"source": [
"# OpenFASoC: Digital LDO Generator"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github"
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xjDewsT5Y4lP"
},
"source": [
"```\n",
"OpenFASOC Team, November 2022\n",
"SPDX-License-Identifier: Apache-2.0\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "L6Ck4z5ujN_k"
},
"source": [
"\n",
"|Name|Affiliation|IEEE Member|SSCS Member|\n",
"|:--:|:----------:|:----------:|:----------:|\n",
"|Mehdi Saligane (Advisor) Email ID: mehdi@umich.edu|University of Michigan|Yes|Yes|\n",
"|Ali Hammoud (Lead) Email ID: alibilal@umich.edu|University of Michigan|Yes|No|\n",
"|Pranav Lulu Email ID: pranavl@umich.edu | University of Michigan|No|No\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-Xp4cEjkeHIx"
},
"source": [
"## Introduction\n",
"Welcome! \n",
"This notebook[^1] serves as an introduction to the LDO generator: an open-source silicon generator part of [OpenFASoC](https://github.com/idea-fasoc/OpenFASOC) - An open-source framework for autonomous generation of Digital LDO. A cell-based design methodology is employed to allow full synthesizability and compatibility with computer-aided designs (CADs) flow and advanced technology nodes. Furthermore, the generator automates the design flow end-to-end in Python and supports designing completely with open-source CAD tools.\n",
"\n",
"**_Index Terms:_** Circuit generator , open source, synthesizable design, digital LDO.\n",
"\n",
"Citation: \n",
"Tutu Ajayi et al., \"An Open-source Framework for Autonomous SoC Design with Analog Block Generation,\" 2020 IFIP/IEEE 28th International Conference on Very Large Scale Integration (VLSI-SOC), 2020, pp. 141-146. \n",
"\n",
"[^1]: This notebook is targeted at users of all professional backgrounds aiming to learn how to *code* their chips. The goal is to go through all the steps of generating the LDO and an overview of the simulation results. "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YSagfjUwSFPZ"
},
"source": [
"## Digital LDO\n",
"### Purpose (Basic)\n",
"DLDO (Digital Low Dropout Voltage Regulator) allows for high efficiency custom voltage operation. Digital LDO is one preferred method for generating custom voltages on chip because it allows for regulated voltage level (VREG) near the source voltage level (VIN) and it avoids large passive components used in other analog voltage regulators. The digital design is easier to integrate. The function of the LDO is to ensure the VREG voltage output remains at a stable value equal to the reference voltage VREF. The input voltage VIN is used to drive the output VREG; VIN can be set to VDD or another voltage source. \n",
"\n",
"Fundamentally, the DLDO is a closed loop control system with:\n",
"1. A sensor that produces an error (voltage comparison) of the closed-loop-feedback (VREG) signal vs the desired reference value (VREF).\n",
"2. A controller which interprets the error and adjusts the power delivery array.\n",
"3. A tunable power delivery array which can quickly adjust the output voltage (VREG) based on the controller input.\n",
"\n",
"Below is a high-level diagram of the design."
]
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {
"id": "rqEtDhh2PYAe"
}
},
{
"cell_type": "markdown",
"metadata": {
"id": "1F6TquCMv33g"
},
"source": [
"### Applying OpenFASoC to Digital LDO\n",
"The OpenFASoC suite of generators achieve high quality and highly automated designs by combining \"auxilary\" cells with automatically generated components. The digital LDO has four such auxilary cells:"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "m2aDb6f5Uu_M"
},
"source": [
"#### VREF Gen Block\n",
"Rather than requiring additional circuitry outside the DLDO design to generate the VREF input, OpenFASoC DLDO provides a tunable 10-bit digital to analog converter integrated directly into the design. VREF can be tuned using a 10-bit digital \"trim\" input setting. This VREF block targets high resolution in the most likely range of interest: 1.6 to 1.9 Volts. The design current consumption is \\~60 pA with 3.3V supply when set to the highest trim (~1.9V VREF). Note that the voltage regulator scales to voltages higher than 1.9 volts; you can provide an external VREF in this case. \n",
"See available trim settings below: "
]
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {
"id": "JLhDcQXMaWeW"
}
},
{
"cell_type": "markdown",
"metadata": {
"id": "L9QpHdTFUw98"
},
"source": [
"#### Comparator Latch\n",
"The Comparator is a clocked strong arm latch comparator which compares VREF and VREG, converting the error information into a digital output. This comparison information is then sent to the digital control logic. A comparator output low indicates that the VREG value is lower than the reference voltage VREF value. On the other hand, a comparator output high indicates that VREG is at higher voltage than VREF. \n",
"\n",
"A diagram of the latch is included below:"
]
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {
"id": "Hni5VtwurxEO"
}
},
{
"cell_type": "markdown",
"metadata": {
"id": "MBi1_nEr1MF2"
},
"source": [
"This is a strong arm latch optimal for low power. The design has very low static current consumption."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7MmqX1mI15KG"
},
"source": [
"####Power Array Unit Cell \n",
"The unit power array cell is a PMOS transistor combined with a NMOS transistor configured as a moscap. The unit cells act as current switches and are combined to form the power delivery array. \n",
"####Capacitor \n",
"The capacitor cells each provide an equivalent of 984 fF of capacitance. These cell are used to smoothen the output voltage during sudden load shifts. The LDO design incorporates 5 such capacitor cells."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ax1kzlzt22Va"
},
"source": [
"### Digital Controller & Additional Notes\n",
"The power array controller is automatically generated from a verilog template. The generator python scripts parse user specs to determine the neccessary power array size. The verilog controller template is specialized in python. See flow below for details on the area optimizatios used in the automatic open source design. \n",
"\n",
"The digital controller receives the comparator information and adjusts the settings of each of the PMOS switches in the power array through the output control word (equal in size to the power array). Initially, all control bits in the output are set to a reset value (all high values) “1” in order to turn off all PMOS switches. The controller responds to inputs by shifting all control bits in the output register, then entering an additional high \"1\" voltage to turn off one more power switch, or an additional low \"0\" voltage to turn on one more power switch. "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "otkaMJc231Ab"
},
"source": [
"The feedback cycle repeats each clock period. The power PMOS transistors act like current switches. Each current switch allows a fixed additional current to flow from VIN to VREG, thus increasing the voltage value of VREG.\n",
"\n",
"Additionally, there are a number of current switches controlled directly by the comparator output. These direct control current switches help reduce transient response time. Additional direct control power switches (at a fixed array size) provide a trade off between latency and steady state oscillations. The number of directly controlled switches is determined automatically in the python script based on the array size; this controls the tradeoff between latency and steady state oscillations."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "h3XOYZkOjJhj"
},
"source": [
"## Generator Flow: Multi Voltage Domain Design With Open Source Tools\n",
"Before running the flow, we must set up our python environment with the necessary open-source tools. The generator uses a flexible set of tools and will support even more in the future. In the below walkthrough, we will use:\n",
"* Yosys for logic synthesis\n",
"* Openroad for placing and routing\n",
"* Klayout to produce the final GDS file\n",
"* Magic for DRC and LVS checks as well as PEX\n",
"* Ngspice for simulation\n",
"\n",
"**There may be a restart runtime warning after this code block, but disregard.**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "StLVb9Q-zYQK"
},
"outputs": [],
"source": [
"# install all tools and dependencies\n",
"import os\n",
"import pathlib\n",
"import sys\n",
"!apt install -y time build-essential\n",
"!apt install qt5-default qttools5-dev libqt5xmlpatterns5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5svg5-dev -y\n",
"!apt install ruby ruby-dev libz-dev python3-dev -y\n",
"!wget https://www.klayout.org/downloads/Ubuntu-20/klayout_0.28.3-1_amd64.deb\n",
"!dpkg -i klayout_0.28.3-1_amd64.deb\n",
"!curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba\n",
"conda_prefix_path = pathlib.Path('conda-env')\n",
"CONDA_PREFIX = str(conda_prefix_path.resolve())\n",
"%env CONDA_PREFIX={CONDA_PREFIX}\n",
"!bin/micromamba create --yes --prefix $CONDA_PREFIX\n",
"!bin/micromamba install --yes --prefix $CONDA_PREFIX \\\n",
" --channel litex-hub \\\n",
" --channel main \\\n",
" open_pdks.sky130a \\\n",
" openroad \\\n",
" netgen \\\n",
" magic \\\n",
" yosys\n",
"!bin/micromamba install --yes --prefix $CONDA_PREFIX \\\n",
" --channel conda-forge \\\n",
" svgutils ngspice\n",
"!python -m pip install matplotlib ltspice pyyaml click gdstk cairosvg svgutils --no-binary gdstk pillow\n",
"# clone OpenFASOC repo and setup env\n",
"!git clone https://github.com/alibillalhammoud/OpenFASOC\n",
"OPENFASOC_ROOT=str(pathlib.Path('OpenFASOC').resolve())\n",
"LDO_ROOT=OPENFASOC_ROOT+\"/openfasoc/generators/ldo-gen/\"\n",
"!cp OpenFASOC/openfasoc/generators/ldo-gen/blocks/sky130hvl/gds/capacitor_test_nf.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/generators/ldo-gen/blocks/sky130hvl/gds/PMOS.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/generators/ldo-gen/blocks/sky130hvl/gds/PT_UNIT_CELL.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/generators/ldo-gen/blocks/sky130hvl/gds/vref_gen_nmos_with_trim.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/generators/ldo-gen/blocks/sky130hvl/gds/LDO_COMPARATOR_LATCH.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/docs/source/notebooks/aux_files/def2gds.py OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/docs/source/notebooks/aux_files/dbtodef.tcl OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/common/platforms/sky130hvl/gds/sky130_fd_sc_hvl.gds OpenFASOC/docs/source/notebooks/ldo-gen\n",
"!cp OpenFASOC/openfasoc/common/platforms/sky130hvl/fill.json OpenFASOC/docs/source/notebooks/ldo-gen\n",
"%env PDK_ROOT=/content/conda-env/share/pdk\n",
"os.environ['PATH'] += \":/content/conda-env/bin\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5gyYr7tTjrep"
},
"source": [
"### Understanding User Input\n",
"The generator must first parse the user’s requirements into a high-level circuit description or verilog. Note that verilog is a circuit description type that uses theoretical constructs (like mathematical operators, if-else blocks, always @ blocks,... etc) to concisely describe circuits. User input parsing is implemented by reading from a JSON spec file directly in the ldo-gen repository. The JSON allows for specifying desired operating VREG and maximum load current (imax). The design is optimzed to this spec. \n",
"Please input your desired operating specifications below and run the code cell:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"id": "e9y4XRNHqXmy"
},
"outputs": [],
"source": [
"import json\n",
"#@title Code the Chip: Desired Max Load and Vreg\n",
"VREG = 1.8 #@param {type:\"slider\", min:1.8, max:2.8, step:0.1}\n",
"Iload = 0.001 #@param {type:\"slider\", min:0.001, max:0.01, step:0.000001}\n",
"with open(\"OpenFASOC/openfasoc/generators/ldo-gen/spec.json\",\"r\") as specfile:\n",
" specjson = json.load(specfile)\n",
"specjson[\"specifications\"][\"vin\"]=VREG\n",
"specjson[\"specifications\"][\"imax\"]=Iload\n",
"with open(\"OpenFASOC/openfasoc/generators/ldo-gen/spec.json\",\"w\") as specfile:\n",
" json.dump(specjson,specfile)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "I5DKyk1D9L2_"
},
"source": [
"The below example uses the sky130 pdk. The generator already has a model file for this node. The model file is used to automatically optimize the design, including: determining the number of power transistors, number of direct control transistors, and design area. \n",
"The model data is stored as a 10-degree polynomial (using polynomial coeficients). The model file ensures that the automatically generated designs meet the user-spec current requirment. This data is generated by testing the maximum load current at a sweep of reference voltages and load capabilities (power array sizes). \n",
"See below for an illustration of the model file data:"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "okQnoaXeFTao"
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gQV7dNmSAioG"
},
"source": [
"A verilog description is then produced by substituting specifics into several template verilog files. Additional files required by the Openroad flow are modified accordingly.\n",
"\n",
"Run input parsing and verilog generation by running the code below and exploring the ldo-gen/src folder in your python virtual environment:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Bu55CvsAlbIh",
"outputId": "9da9d3d6-94a3-4402-cf76-6d28cefd93e6"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"rm -f error_within_x.csv golden_error_opt.csv search_result.csv\n",
"rm -rf work\n",
"rm -rf tools/*.pyc tools/__pycache__/\n",
"cd flow && make nuke\n",
"make[1]: Entering directory '/content/OpenFASOC/openfasoc/generators/ldo-gen/flow'\n",
"[INFO][FLOW] Using platform directory ../../../common/platforms/\n",
"Makefile:66: ../../../common/platforms//config.mk: No such file or directory\n",
"make[1]: *** No rule to make target '../../../common/platforms//config.mk'. Stop.\n",
"make[1]: Leaving directory '/content/OpenFASOC/openfasoc/generators/ldo-gen/flow'\n",
"make: [Makefile:76: clean] Error 2 (ignored)\n",
"rm -f blocks/sky130hvl/ldo_custom_net.txt blocks/sky130hvl/ldo_domain_insts.txt\n",
"rm -rf ../../common/drc-lvs-check/sky130A\n",
"python3 ./tools/ldo-gen.py --output ./work --platform sky130hvl --mode verilog \n",
"#---------------------------------------------------------------------\n",
"# Parsing command line arguments...\n",
"#---------------------------------------------------------------------\n",
"['./tools/ldo-gen.py', '--output', './work', '--platform', 'sky130hvl', '--mode', 'verilog']\n",
"#---------------------------------------------------------------------\n",
"# Configuring Workspace\n",
"#---------------------------------------------------------------------\n",
"make[1]: Entering directory '/content/OpenFASOC/openfasoc/generators/ldo-gen'\n",
"rm -f error_within_x.csv golden_error_opt.csv search_result.csv\n",
"rm -rf work\n",
"rm -rf tools/*.pyc tools/__pycache__/\n",
"cd flow && make nuke\n",
"make[2]: Entering directory '/content/OpenFASOC/openfasoc/generators/ldo-gen/flow'\n",
"[INFO][FLOW] Using platform directory ../../../common/platforms/\n",
"Makefile:66: ../../../common/platforms//config.mk: No such file or directory\n",
"make[2]: *** No rule to make target '../../../common/platforms//config.mk'. Stop.\n",
"make[2]: Leaving directory '/content/OpenFASOC/openfasoc/generators/ldo-gen/flow'\n",
"make[1]: [Makefile:76: clean] Error 2 (ignored)\n",
"rm -f blocks/sky130hvl/ldo_custom_net.txt blocks/sky130hvl/ldo_domain_insts.txt\n",
"rm -rf ../../common/drc-lvs-check/sky130A\n",
"make[1]: Leaving directory '/content/OpenFASOC/openfasoc/generators/ldo-gen'\n",
"Loading supportedInputsFile...\n",
"One or more required specs are missing\n",
"Attempting to fill in missing entries using backup specfile\n",
"Loading platform_config file...\n",
"Config:\n",
"Mode - \"verilog\"\n",
"Model File - \"tools/..//models/model.json\"\n",
"LDO Instance Name - \"ldoInst\"\n",
"#----------------------------------------------------------------------\n",
"# Generating Verilog\n",
"#----------------------------------------------------------------------\n",
"# LDO - Power Transistor array Size = 13\n",
"# LDO - Design Area = 2637.47596049829 um^2\n",
"# LDO - Behavioural Verilog Generated\n",
"#----------------------------------------------------------------------\n",
"# Verilog Generated\n",
"#----------------------------------------------------------------------\n"
]
}
],
"source": [
"!cd OpenFASOC/openfasoc/generators/ldo-gen && make clean\n",
"!cd OpenFASOC/openfasoc/generators/ldo-gen && make sky130hvl_ldo_verilog"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XEd8QqFgkog2"
},
"source": [
"### Logic Synthesis\n",
"At this phase, the implementation of fundamental components — such as transistors and resistors — is not considered. Logic synthesis takes the verilog description from the previous step and outputs a more detailed netlist by parsing theoretical verilog constructs like always, case, if-else, operator, etc… blocks. Note that a netlist is just a list of pins and component connections. \n",
"\n",
"The YOSYS synthesis will generate the verilog netlist for the total design and a seperate verilog netlist for the LDO controller. The LDO controller is described as a verilog module because it is automatically generated from the template file (in the pyhthon scripts).\n",
"\n",
"Later in the flow, there will be additional area optimizations and special routings done completley in the open-source flow tools (open-road). We also use python to complete some of the special routing during the flow (discussed below).\n",
"\n",
"The generator treats the aux cells as macros to be inserted in the design during floorplan. At this stage, the verilog module instantions are used from \"black-box\" modules and included in the overall verilog netlist.\n",
"\n",
"You can see the synthesis step by running the code below and viewing the ldo-gen/flow/results/sky130hvl/ldo/base/1_synth.v file in your python virtual environment:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "414sh8FtlgTk"
},
"outputs": [],
"source": [
"!cd OpenFASOC/openfasoc/generators/ldo-gen/flow && make synth"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Jd1rMEAzlLUT"
},
"source": [
"### Automatic Place and Route\n",
"Now that we have a description of our circuit which includes specific connections and components to use, it is possible to consider drawing the wires, placing the components, and choosing materials. Below is a step-by-step visual breakdown of the openroad APR."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_JBpH5AOmEcl"
},
"source": [
"#### Floorplan\n",
"First, an outline of the circuit is created encompassing the area that the circuit will occupy and including all the input and output pins for the top level circuit. Inside the LDO, power rails, tap, and decap cells are placed.\n",
"\n",
"The configuration of the 5 capacitors and VREF block are fixed, but the large voltage domain will be made smaller or larger to optimze area based on the array size. During floorplan phase, several voltage domains are created using the open-road tcl script bindings. The open-road flow is used to create met5 straps which connect the ground and power rails directly to the large voltage domain rails. The VREG output of the LDO is created as a met5 power rail. VSS between the two voltage domains is shorted using met5 horizontal straps. \n",
"\n",
"You can view the above details by running floorplan and displaying gds below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ognjm4xZK01-"
},
"outputs": [],
"source": [
"!cd OpenFASOC/openfasoc/generators/ldo-gen/flow && make floorplan"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 997
},
"id": "BW8q1xrsmjre",
"outputId": "33a14273-4632-4fb9-b5fa-a49150772d71"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"OpenROAD b0c318df166641bffc7ad4f6822013dc5df3c5b7 \n",
"This program is licensed under the BSD-3 license. See the LICENSE file for details.\n",
"Components of this program may be licensed under more restrictive licenses which must be honored.\n",
"[INFO] Clearing cells...\n",
"[INFO] Merging GDS files...\n",
"\tPMOS.gds\n",
"\tPT_UNIT_CELL.gds\n",
"\tvref_gen_nmos_with_trim.gds\n",
"\tLDO_COMPARATOR_LATCH.gds\n",
"\tcapacitor_test_nf.gds\n",
"[INFO] Copying toplevel cell 'ldoInst'\n",
"INFO: Reading config file: fill.json\n",
"[INFO] Checking for missing GDS...\n",
"[ERROR] LEF Cell 'sky130_fd_sc_hvl__decap_4' has no matching GDS cell. Cell will be empty\n",
"[INFO] Writing out GDS 'out2.gds'\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
""
],
"image/svg+xml": "