(c) 2026 Simon Dorrer and Harald Pretl
Institute for Integrated Circuits and Quantum Computing, Johannes Kepler University (JKU), Linz, Austria
Important
This repository requires the IIC-OSIC-TOOLS container with tag 2026.06 or later.
Chip render of the ihp-sg13g2 analog-mixed signal template chip (1.6 mm x 1.6 mm).
Render of the TopMetal2 AMS Chip logo, generated with the tool ArtistIC.
This Makefile-driven repository simulates, builds, and fully verifies (LVS, DRC, PEX) a complete analog mixed-signal chip for the ihp-sg13g2 130nm Open-PDK, including padframe generation and top-level assembly. It uses:
- LibreLane for digital macro hardening, padframe generation and top-level assembly
- Xschem for schematic entry
- Ngspice, VACASK and CACE for analog simulation
- KLayout for viewing and routing of the layout
- Magic + Netgen and KLayout for LVS, DRC and PEX verification
- SystemVerilog, cocotb, GTKWave and Surfer for digital simulation
The repository is the starting point for your own custom silicon and provides a universal design flow solution: Just clone the repo, enter the IIC-OSIC-TOOLS container, and run make all to get a tapeout-ready analog-mixed signal chip. Focus on your design and do not care about the tools and the design flow!
Furthermore, it serves as a regression test for the above-mentioned open-source tools and their dependencies using the ihp-sg13g2 Open-PDK.
A step-by-step tutorial, including additional exercises, can be found here.
An overview of the open source IC design landscape is presented here.
Examples based on this template are:
- TinyWhisper: An Open-Source Fully-Integrated Multi-Mode Short-Wave Transmitter for Amateur Radio Applications in 130-nm CMOS
- SPARX: An Open-Source, Automated, Programmatically Generated, Frequency-Scalable Six-Port Receiver in 130-nm CMOS
- wafer.space gf180mcuD MPW Multi-Project Chip
A designer-oriented description of this chip can be found in doc/:
- doc/specifications.md: top-level specifications (technology, supplies, clock, macro inventory, functional behaviour).
- doc/pinout.md: full 32-pad bondpad table per side, with the
chip_topport and the role each pad carries insidechip_core. - doc/floorplan.md: die / core geometry, hard-macro placement coordinates, PDN strategy and the floorplan diagram.
📁 ihp-sg13g2-ams-chip-template/
├─ 📁 doc/
│ ├─ 📁 ihp-sg13g2-Open-PDK/
│ ├─ 📁 ihp-structure-proposals/
│ ├─ 📁 klayout/
│ ├─ 📁 librelane/
│ ├─ 📁 sizing/
│ ├─ floorplan.md
│ ├─ pinout.md
│ └─ specifications.md
├─ 📁 flow/
│ ├─ 📁 artistic/
│ ├─ 📁 librelane/
│ │ ├─ chip_top.sdc
│ │ ├─ config.yaml
│ │ └─ pdn_cfg.tcl
│ └─ 📁 logo/
│ └─ chip_logo_mono.png
├─ 📁 ip/
│ ├─ 📁 sg13g2_io_custom/
│ ├─ 📁 sg13g2_ip__bondpad_70x70/
│ │ ├─ 📁 final/
│ │ ├─ 📁 script/
│ │ ├─ 📁 verification/
│ │ ├─ Makefile
│ │ └─ README.md
│ ├─ 📁 sg13g2_ip__jku/
│ │ ├─ 📁 final/
│ │ ├─ 📁 logo/
│ │ ├─ 📁 script/
│ │ ├─ 📁 verification/
│ │ ├─ Makefile
│ │ └─ README.md
│ └─ 📁 sg13g2_ip__jku_names/
│ ├─ 📁 final/
│ ├─ 📁 logo/
│ ├─ 📁 script/
│ ├─ 📁 verification/
│ ├─ Makefile
│ └─ README.md
├─ 📁 layout/
│ ├─ chip_top.gds.gz
│ └─ chip_top_logo_fill.gds.gz
├─ 📁 macros/
│ ├─ 📁 counter/
│ │ ├─ 📁 final/
│ │ ├─ 📁 flow/
│ │ ├─ 📁 fpga/
│ │ ├─ 📁 netlist/
│ │ ├─ 📁 render/
│ │ ├─ 📁 rtl/
│ │ ├─ 📁 schematic/
│ │ ├─ 📁 scripts/
│ │ ├─ 📁 testbenches/
│ │ ├─ 📁 verification/
│ │ ├─ Makefile
│ │ └─ README.md
│ └─ 📁 inverter/
│ ├─ 📁 final/
│ ├─ 📁 layout/
│ ├─ 📁 netlist/
│ ├─ 📁 render/
│ ├─ 📁 schematic/
│ ├─ 📁 scripts/
│ ├─ 📁 testbenches/
│ ├─ 📁 verification/
│ ├─ Makefile
│ └─ README.md
├─ 📁 netlist/
│ ├─ 📁 layout/
│ ├─ 📁 nl/
│ ├─ 📁 pex/
│ ├─ 📁 pnl/
│ └─ 📁 spice/
├─ 📁 release/
│ └─ 📁 v.1.0.0/
│ ├─ 📁 gds/
│ ├─ 📁 img/
│ ├─ 📁 netlist/
│ └─ README.md
├─ 📁 render/
│ ├─ 📁 blender/
│ └─ 📁 img/
├─ 📁 rtl/
│ ├─ chip_core.sv
│ └─ chip_top.sv
├─ 📁 schematic/
│ └─ 📁 xschem/
│ ├─ chip_top.sch
│ ├─ chip_top.sym
│ ├─ chip_top_pex.sym
│ └─ xschemrc
├─ 📁 scripts/
│ ├─ 📁 plot_simulations/
│ ├─ add_logo_fill.sh
│ ├─ add_rectangle.py
│ └─ lay2img.py
├─ 📁 testbenches/
│ ├─ 📁 cocotb/
│ │ ├─ chip_top_tb.gtkw
│ │ ├─ chip_top_tb.py
│ │ └─ chip_top_tb.surf.ron
│ └─ 📁 xschem/
│ ├─ chip_top_tb_tran.sch
│ └─ xschemrc
├─ 📁 tutorial/
│ ├─ 📁 fig/
│ ├─ _quarto.yml
│ ├─ index.qmd
│ ├─ Makefile
│ └─ requirements.txt
├─ 📁 verification/
│ ├─ 📁 drc/
│ ├─ 📁 lvs/
│ └─ 📁 reports/
│ ├─ antenna_summary.rpt
│ ├─ antenna_violations.rpt
│ ├─ hold_setup_timing.rpt
│ ├─ irdrop.rpt
│ ├─ lvs.netgen.rpt
│ ├─ manufacturability.rpt
│ ├─ stapostpnr_*.rpt
│ ├─ stat.rpt
│ ├─ yosys_post_dff.rpt
│ ├─ yosys_pre_techmap.rpt
│ └─ yosys_synth_check.rpt
├─ CITATION.cff
├─ LICENSE
├─ Makefile
├─ README.md
└─ ToDo.md
The default Make target is help, so running make prints usage and all available targets with short descriptions.
make
make helpInitializes and updates the repository submodules (for example ArtistIC):
make init-submodulesRun this after cloning the repository, or whenever submodule pointers are updated.
We use cocotb, a Python-based testbench environment, for the verification of the chip. The underlying simulator is Icarus Verilog.
The simulation targets accept an optional CELL variable (default: chip_top).
The testbench is located in testbenches/cocotb/chip_top_tb.py. To run the RTL simulation, use:
make sim-rtl-cocotbTo run the gate-level (GL) simulation with cocotb, use:
make sim-gl-cocotbTo run the gate-level simulation with Xschem, use:
make sim-gl-xschemNote
sim-gl-xschem is available and converges, but it may take a long time depending on the hardware used.
It is therefore not included in sim-all and must be called manually.
To plot the Xschem simulation results using the Python script in scripts/plot_simulations/, use:
make sim-view-xschem
make sim-view-xschem CELL=chip_topThe target runs python3 scripts/plot_simulations/plot_<CELL>.py. CELL defaults to chip_top.
Note
sim-view-xschem is intentionally not called by sim-all.
It opens the generated Python figures, which blocks the shell until the window is closed.
It is designed for interactive use and must be called manually after the simulation has completed.
The cocotb simulations generate a waveform file under testbenches/cocotb/sim_build/chip_top.fst.
You can view it with a waveform viewer such as GTKWave or Surfer.
The waveform viewer can be changed with WAVEFORM_VIEWER=<gtkwave|surfer> (default: gtkwave).
make sim-view-cocotb # view chip_top waveform with GTKWave (default)
make sim-view-cocotb WAVEFORM_VIEWER=surfer # use Surfer insteadEach cocotb simulation folder contains a pre-configured waveform layout file (<CELL>_tb.gtkw for GTKWave, <CELL>_tb.surf.ron for Surfer).
The view target loads it automatically together with the current .fst, so signal formatting is preserved across runs.
To run all non-interactive simulation targets in sequence (RTL cocotb and GL cocotb), use:
make sim-allNote
sim-view-cocotb is intentionally not called by sim-all.
It opens a waveform viewer GUI (GTKWave or Surfer), which blocks the shell until the window is closed.
It is designed for interactive use and must be called manually after the simulation has completed.
Note
sim-gl-xschem and sim-view-xschem are also not included in sim-all because sim-gl-xschem may take a long time depending on the hardware used.
Run them manually with make sim-gl-xschem followed by make sim-view-xschem when needed.
Run the LibreLane flow with:
make librelaneAdditional targets are available for different DRC configurations:
make librelane-nodrc– run LibreLane without DRC checksmake librelane-magicdrc– run LibreLane with only Magic DRC checksmake librelane-klayoutdrc– run LibreLane with only KLayout DRC checks
These targets are also available for the digital macros. After the LibreLane flow completes successfully, the generated views are saved under flow/final/.
After completion, you can view the design using the OpenROAD GUI:
make librelane-openroadOr using KLayout:
make librelane-klayoutThese commands are also available for the digital macros.
To copy the Yosys synthesis checks, antenna-violation reports, post-PnR hold & setup timing summary, LVS report, and manufacturability report from the latest LibreLane run into verification/reports/, run:
make copy-reportsThis only works if the latest run completed without errors. This command is also available for the digital macros.
Note
The Magic and KLayout DRC reports are temporarily not copied because IHP's
metal1_pin_offgrid rule trips on the pad ring. Once it is fixed upstream
the corresponding cp lines in Makefile :: copy-reports will be re-enabled.
To copy and compress the latest GDS from flow/final/gds/ into layout/, run:
make copy-gdsTo copy the latest SPICE, PnL, and NL netlists from flow/final/spice/ into netlist/spice/, from flow/final/pnl/ into netlist/pnl/, and from flow/final/nl/ into netlist/nl/, run:
make copy-netlistThis only works if the latest run completed without errors.
To copy the latest LibreLane chip render from flow/final/render/ into render/img/, run:
make copy-renderThis creates render/img/chip_top_librelane.png. This only works if the latest run completed without errors.
Renders the top-level GDS from layout/ and saves it in the render/img/ folder:
make render-gdsThis only works if the latest run completed without errors. This command is also available for the digital macros.
To build the bondpad in the ip folder, run the following command:
make build-bondpadTo build the logos in the ip folder, run the following command:
make build-logosTo scaffold a new macro (directory tree, Makefile, README.md, sizing/plot script skeletons, CACE spec skeleton — or RTL stubs and LibreLane config for digital macros) from the templates in macros/_templates/, run:
make init-macro MACRO=<name> [TYPE=analog|digital]TYPE defaults to analog. The wrapper cell producing the final GDS is <core>_top: for MACRO=rx_fe the cells are rx_fe/rx_fe_top; a name that already ends in _top (e.g. MACRO=vco_top) yields vco/vco_top. The script prints the next steps; once the macro has content to build, add it to the MACROS list in the top-level Makefile so build-macros includes it.
To build a specific macro, run make build-<macroname> (a generic pattern target that dispatches to the macro's in-tree make all). To build all currently enabled macros (the MACROS list in the Makefile), run:
make build-macrosThe following command builds the counter digital macro:
make build-counterFor each digital macro this dispatches to its in-tree make all, which lints, simulates, runs LibreLane, copies the reports, and renders the final GDS.
Tip
Each macro has its own Makefile and README.md with additional targets, such as linting, simulation, and verification.
For example, to lint the counter or run its simulation, refer to macros/counter/README.md.
Each analog macro has its own klayout-verify and magic-verify targets that run LVS, DRC, and PEX for the top-level cell.
To build the inverter macro:
make build-inverterAll analog macros are included in build-macros alongside the digital macros.
To run LibreLane for the top-level chip and copy the resulting reports, GDS, netlist, and chip render back into the source tree, then add the logo + fill structures and render the final GDS, run:
make build-topInternally this executes (in order): librelane-nodrc → copy-reports → copy-gds → copy-netlist → copy-render → add-logo-fill → render-gds.
To initialise submodules, build the bondpad, build the logos, build the macros, and run the full build-top flow, run:
make build-allThis is useful if you want to rebuild the chip from scratch. Clone the repository, enter the IIC-OSIC-TOOLS environment, and run make build-all.
To add the chip logo (PNG → GDS) and the fill structures on top of the LibreLane output (so the final GDS in layout/ includes the artwork), run:
make add-logo-fillThis calls scripts/add_logo_fill.sh and writes layout/chip_top_logo_fill.gds.gz. The step is also called from make build-top.
Note
In the future, it is planned to replace this script and Makefile target with a custom librelane step.
Exports the schematic netlist for LVS from Xschem and places it in netlist/schematic/.
The EV_PRECISION parameter sets the number of significant digits used by Xschem's ev function when calculating device properties (default: 5). Increase this to avoid LVS mismatches caused by floating-point rounding differences between Xschem and KLayout (see xschem#465).
Currently, KLayout LVS extracts ntap and ptap devices, so the schematic netlist must include them as well. In contrast, Magic + Netgen LVS does not extract ntap and ptap. Therefore, the schematic uses lvs_ignore = short for these devices and conditional net labels (see xschem#474). To make this effective during schematic netlist export, set lvs_ignore 1 must be set in the magic-lvs-netlist target.
KLayout uses CDL netlists, while Magic uses SPICE netlists. Accordingly, klayout-lvs-netlist uses the Xschem commands set spiceprefix 1, set lvs_netlist 1, set top_is_subckt 1, and set lvs_ignore 0. In contrast, magic-lvs-netlist uses set spiceprefix 1, set lvs_netlist 0, set top_is_subckt 1, and set lvs_ignore 1.
To extract a CDL schematic netlist for KLayout LVS, use:
make klayout-lvs-netlist
make klayout-lvs-netlist CELL=chip_top
make klayout-lvs-netlist EV_PRECISION=5To extract a SPICE schematic netlist for Magic + Netgen LVS, use:
make magic-lvs-netlist
make magic-lvs-netlist CELL=chip_top
make magic-lvs-netlist EV_PRECISION=5Exports the schematic netlist from Xschem, then runs LVS. Compares the GDS layout in layout/ against the schematic netlist in netlist/schematic/. Reports are saved to verification/lvs/. The extracted layout netlist is moved to netlist/layout/.
KLayout LVS uses run_lvs.py from the IHP Open-PDK:
make klayout-lvs
make klayout-lvs CELL=chip_topMagic + Netgen LVS uses sak-lvs.sh:
make magic-lvs
make magic-lvs CELL=chip_topRuns DRC on the GDS layout in layout/. Reports are saved to verification/drc/.
KLayout DRC (minimum) runs a pre-check KLayout DRC on the final top-level layout with logo and fill structures:
make klayout-drc-minimumKLayout DRC (regular) runs a regular KLayout DRC on the final top-level layout with logo and fill structures:
make klayout-drc-regularKLayout DRC uses run_drc.py from the IHP Open-PDK with relaxed rules (FEOL, density checks, and extra rules disabled):
make klayout-drc
make klayout-drc CELL=chip_topMagic DRC uses sak-drc.sh:
make magic-drc
make magic-drc CELL=chip_topRuns parasitic extraction on the GDS layout in layout/. The extracted SPICE netlist is written to netlist/pex/.
The extracted SPICE filenames include the selected extraction mode:
klayout-pexwritesnetlist/pex/<CELL>_klayout_pex_<EXT_MODE>.spicemagic-pexwritesnetlist/pex/<CELL>_magic_pex_<EXT_MODE>.spice
The EXT_MODE parameter selects the extraction mode:
1= C-decoupled (default)2= C-coupled3= full-RC
Note
For klayout-pex, EXT_MODE=1 (C-decoupled) is not yet supported by kpex and automatically falls back to EXT_MODE=2 (CC) with a warning.
The .subckt name in the extracted SPICE file is automatically renamed from <CELL>_flat (kpex) or <CELL> (Magic) to <CELL>_pex.
If a matching Xschem symbol (schematic/<CELL>_pex.sym) exists, the .subckt pin order in the extracted SPICE file is automatically reordered to match the symbol's pin positions. This ensures the PEX netlist can be used directly with the corresponding Xschem symbol for simulation regardless of the selected EXT_MODE.
KLayout PEX uses kpex with the Magic extraction engine currently (2.5D engine is work in progress):
make klayout-pex
make klayout-pex CELL=chip_top
make klayout-pex CELL=chip_top EXT_MODE=3Magic PEX uses sak-pex.sh:
make magic-pex
make magic-pex CELL=chip_top
make magic-pex CELL=chip_top EXT_MODE=3Runs LVS, DRC, and PEX for a specific cell (e.g. chip_top):
make klayout-verify CELL=chip_top
make magic-verify CELL=chip_topRuns LVS, DRC, and PEX for the top cell:
make klayout-verify
make magic-verifyRuns full simulation (sim-all), then build-all, followed by Magic DRC for both chip_top and chip_top_logo_fill:
make allCopies the final top-level GDS with logo and fill structures from layout/ to release/v.<VERSION>/gds/, copies the generated netlists into release/v.<VERSION>/netlist/, and copies the chip renders into release/v.<VERSION>/img/.
The following netlist folders are exported:
netlist/layout->release/v.<VERSION>/netlist/layoutnetlist/pnl->release/v.<VERSION>/netlist/pnlnetlist/spice->release/v.<VERSION>/netlist/spice
The following chip renders are exported:
render/img/chip_top_black.png->release/v.<VERSION>/img/chip_top_black.pngrender/img/chip_top_white.png->release/v.<VERSION>/img/chip_top_white.pngrender/img/chip_top_librelane.png->release/v.<VERSION>/img/chip_top_librelane.png
Note
netlist/schematic and netlist/pex are currently not copied by the release target.
Run with default version (1.0.0):
make releaseRun with a custom version:
make release VERSION=2.1.0The regression target is the project's end-to-end smoke test for the IIC-OSIC-TOOLS environment. Its goal is to exercise every tool and flow in the template at least once with the shortest possible runtime. It is a tool/flow regression, not a design sign-off.
make regressionThis target also runs automatically in continuous integration: the regression GitHub Actions workflow runs make regression inside the IIC-OSIC-TOOLS container nightly (and on manual dispatch), and its status is shown by the Regression badge at the top of this README. The scheduled run is gated so it only executes when there have been changes since the previous night.
To keep the runtime low while still covering the full toolchain, the regression makes the following trade-offs:
- The counter macro is hardened with
librelane-magicdrc(only Magic DRC enabled, the slower KLayout DRC is skipped). Netgen LVS still runs as part of the flow. - The chip top-level runs
librelane-nodrc. All DRC checks are skipped to save runtime on the large top-level assembly. The macros and IP blocks are DRC-checked individually beforehand, so this only leaves the top-level routing/fill unchecked. - KLayout DRC (
run_drc.py) is skipped inside the LibreLane runs, but is still exercised in the bondpad and logo IP builds, and in the inverterklayout-verify. - Only one logo (
sg13g2_ip__jku) is regenerated. It is the only step that exercises the PNG to GDS flow. The second logo (sg13g2_ip__jku_names) uses an identical toolchain and reuses its committed views. - Exactly one CACE parameter set is run (the AC VDD sweep
ac_params, no Monte-Carlo). Swapac_paramsforac_mc_params/ac_mm_paramsin the target to also exercise the Monte-Carlo flow.
The regression runs bottom-up: first the inverter and counter macros, then the top-level assembly (submodules, bondpad, logo) and finally the chip top-level LibreLane run that integrates the freshly built macros and IP. After the counter is hardened, copy-final copies its fresh flow/final/ views into macros/counter/final/, so that the gate-level simulation (sim-gl-cocotb) and the chip top-level integration use the freshly built outputs rather than the committed ones.
The following tools and flows are checked:
| Tool / flow | Where it is exercised |
|---|---|
| git submodules | init-submodules |
| KLayout scripting (bondpad generator), KLayout DRC, Magic DRC | build-bondpad |
| PNG to GDS logo generation, KLayout DRC, Magic DRC | sg13g2_ip__jku all (single logo) |
| Xschem + ngspice (analog simulation) | inverter sim-xschem (inverter_tb_dc_vout) |
| CACE (+ ngspice) | inverter CACE, single parameter set (ac_params) |
KLayout LVS (run_lvs.py) + KLayout DRC (run_drc.py) + KLayout PEX (kpex) |
inverter klayout-verify CELL=inverter_top |
Magic extract + Netgen LVS + Magic DRC + Magic PEX (sak-pex.sh) |
inverter magic-verify CELL=inverter_top |
Magic LEF export + LIB + Verilog stub + lay2img render |
inverter build-top |
| Verilator lint | counter lint-verilog-all |
Icarus Verilog (iverilog/vvp) |
counter sim-rtl-verilog |
| cocotb (RTL + gate-level) | counter sim-rtl-cocotb, sim-gl-cocotb |
| yosys + nextpnr-ice40 + icepack (FPGA) | counter build-fpga |
| LibreLane (OpenROAD / yosys / KLayout streamout / Netgen LVS) | counter librelane-magicdrc, chip librelane-nodrc |
| Magic DRC (sign-off, run inside LibreLane) | counter librelane-magicdrc |
vlog2Verilog / vlog2Spice / spi2xspice |
counter generate-xspice |
| Xschem gate-level | counter sim-gl-xschem |
@software{2026_ams_chip_template,
author = {Dorrer, Simon and Pretl, Harald},
month = apr,
year = {2026},
title = {{GitHub Repository of an Open-Source Analog-Mixed Signal Chip Design Template for the ihp-sg13g2 Open-PDK}},
url = {https://github.com/iic-jku/ihp-sg13g2-ams-chip-template},
doi = {10.5281/zenodo.20129233}
}
First, we would like to thank the open-source chip design community for its valuable input and constructive feedback. We especially thank
- Leo Moser, who initially started template repositories based on the LibreLane flow.
- Tim Edwards for helping with Magic + Netgen LVS and PEX issues.
- Krzysztof Herman for discussions about the directory structure.
This project is funded by the JKU/SAL IWS Lab, a collaboration of Johannes Kepler University and Silicon Austria Labs.
|
|
|
Licensed under the Solderpad Hardware License v2.1, see LICENSE.