Open Silicon, Hands-On | Part 1: The Map → Part 2: A Golden Model
Software developers have a superpower that hardware engineers have spent careers envying: a build that takes seconds. You change a line, you run the tests, you know. The open-source chip-design toolchain has quietly given hardware a small version of that loop. On the laptop I'm writing this on, a small CPU goes from RTL to a mapped netlist on a real 130 nm cell library in about half a second. RTL, short for register-transfer level, is the source code you write; the netlist is the gates it becomes.
This series is the guided tour. There are eight parts and one running example, and there's one rule. Every output I paste came from a log file, every listing is a real file or an exact excerpt, and anything I didn't run is labeled not run here so you never have to wonder.
The example is a deliberately boring teaching machine: an 8-bit accumulator CPU with eight instructions and sixteen bytes of memory, in the spirit of the classic textbook SAP-1. It isn't a product and it isn't clever. Boring is the point. A design this small fits in your head, so all your attention goes to the flow.
Why you need a map first
Hardware tooling looks like a junk drawer until you know what each tool is for. The trick is to see every stage as a claim about the stage above it. The RTL claims to implement the spec. The netlist claims to implement the RTL. The layout claims to implement the netlist. The silicon claims to implement the layout. Each tool in the flow exists to check exactly one of those claims while checking is still cheap.
That "cheap" matters more than anything else in this field. A lint warning costs a minute. A failing simulation costs an hour. A timing violation found after layout costs days. A bug found in fabricated silicon costs a respin. The whole discipline is about moving every check as far left as you can.
Here's the whole flow in one table. Keep it open in a tab; every later part zooms into a row.
| Stage | What you hold | Open tools | The question it answers |
|---|---|---|---|
| Spec | a document | any editor | what should this thing do? |
| Reference model | an executable program | any language (Python here) | what exactly happens, step by step? |
| RTL | SystemVerilog source | Verilator lint, Yosys frontend | can this be built as hardware? |
| Simulation and verification | waves, logs, proofs | Verilator, Icarus Verilog, cocotb, SymbiYosys | does it match the model, for every input we can afford? |
| Bus integration | a slave on a standard bus | the same simulators | can software actually drive it? |
| Synthesis | a gate netlist | Yosys, ABC | which gates is this, and how many? |
| Standard cells and timing | area and delay numbers | liberty files, OpenSTA | how big and how fast, on this process? |
| Place and route | a placed, wired layout | OpenROAD, OpenLane | where do the wires physically go? |
| Signoff | DRC and LVS reports, GDSII | Magic, KLayout, Netgen | will the foundry accept it? |
| Silicon or FPGA | a chip or a bitstream | a shuttle run, Yosys with nextpnr | does it work in the real world? |
The tools, one paragraph each
Verilator compiles SystemVerilog into C++ and gives you a fast, cycle-based, two-state simulator, plus a very good open-source linter. Two-state means no X or Z values: a signal is 0 or 1, and unknowns get resolved for you. That's great for speed and for random-initialization tricks, and it's a limitation if you need to see unknowns propagate.
Icarus Verilog is the other classic: an event-driven, four-state simulator. It's slower, but it models X and Z faithfully and handles delays and old-style testbenches. cocotb lets you write testbenches in Python on top of a simulator instead of writing them in SystemVerilog or C++. Whatever you simulate, you'll want a waveform viewer: GTKWave is the long-standing choice, Surfer is a newer one, and both read VCD or FST files.
Yosys is the synthesis workhorse: it reads your RTL, optimizes it, and writes gates. It calls ABC for logic optimization and technology mapping. The same Yosys also drives SymbiYosys, the front end for formal verification, and feeds nextpnr when the target is an FPGA (a reprogrammable chip) instead of a custom chip.
Two simulators, two philosophies
Use Verilator when you want speed, random initial state, and a C++ or Python-driven testbench. Use Icarus Verilog when you need honest four-state behavior or event-level timing. Plenty of teams run both, because they disagree about different bugs.
OpenSTA is the static timing analyzer: hand it a liberty library, a netlist and an SDC constraints file, and it reports every path and every slack. OpenROAD does the physical work, which means floorplanning, placement, clock-tree synthesis and routing. OpenLane wraps Yosys, OpenROAD and the signoff tools behind one configuration file, and OpenROAD-flow-scripts is the Makefile-based sibling. For signoff, Magic and KLayout check design rules (DRC) and view the layout, and Netgen compares the layout's extracted netlist against the intended one (layout versus schematic, or LVS). OpenRAM generates SRAM (static RAM) macros when flip-flops stop being a sane way to store bits.
The open PDKs
None of that tooling can make a chip without a process design kit, and the PDK is the reason this whole ecosystem exists. A PDK is the foundry's published contract. It holds device models, the layout design rules your geometry must obey, the rules for extracting parasitics, and a standard-cell library with timing, area and layout views. Three open PDKs are widely used: SkyWater SKY130 (130 nm), GlobalFoundries GF180MCU (180 nm) and IHP's open SG13G2 (130 nm SiGe BiCMOS).
This series uses SKY130 and, within it, the high-density standard-cell library, sky130_fd_sc_hd. The name decodes neatly: SkyWater 130 nm, foundry-provided, standard cells, high density. A cell like sky130_fd_sc_hd__nand2_1 is a 2-input NAND at drive strength 1. You'll meet a few dozen of them by Part 7.
Installing it
There are two sane routes. The first is the OSS CAD Suite, a prebuilt bundle of open EDA tools (Yosys, SymbiYosys, nextpnr, Icarus Verilog, Verilator, GTKWave and more) that you unpack and activate. The second is your system's package manager. I used Homebrew on an Apple-silicon Mac.
1# route 1, not run here: a prebuilt bundle (unpack it, then activate it in each shell)
2source oss-cad-suite/environment
3
4# route 2: system packages (how my Verilator and Yosys got onto this machine)
5brew install verilator yosys
6
7# not run here: cocotb is a Python package
8pip install cocotbVerilator also needs a C++ compiler and make, which most developer machines already have. Here's what my machine reports. Every number in this series comes from these versions.
1--- verilator
2Verilator 5.052 2026-09-05 rev vUNKNOWN-built20260905
3--- yosys
4Yosys 0.69+post (git sha1 143eb14f9cc55d6f8927e68523b0c9d2166ed02c, Release, AppleClang clang++ 21.0.0.21000334)
5Python 3.13.9OpenSTA, OpenROAD and OpenLane have their own install guides (OpenLane's guide walks through Nix and container-based setups), and I'll point at them where they matter. The SKY130 liberty file is the only download the whole tutorial needs.
What I could and couldn't run
Installed and run for this series: Verilator, Yosys and Python. Not installed, so taught but never faked: Icarus Verilog, cocotb, SymbiYosys, OpenSTA, OpenROAD and OpenLane, Magic, KLayout, Netgen, GTKWave and nextpnr. Any listing that touches those tools is marked not run here.
What "silicon-ready" does and doesn't mean
I'm going to use the phrase "silicon-ready" in this series, and I want to define it before it misleads anyone. In these articles it means one narrow thing: a design on which every cheap check that can catch an expensive mistake has passed. The RTL lints clean. A model-based testbench agrees with it, including from random initial state. A few properties are proven rather than tested. It synthesizes onto a real cell library, the mapped netlist still passes the same tests, and the area and speed estimates are written down with their error bars.
It does not mean a chip. By the end of Part 7 you'll have a gate netlist, an area figure, a pre-layout speed estimate and a regression suite. You will not have a placed-and-routed layout, clean physical verification, post-route timing across corners, a power analysis, test structures, an I/O ring or a package. Part 8 lists all of that honestly.
"The bug I see most often isn't in the design. It's a design that was verified against itself."
A netlist is not a chip
A mapped netlist has no wires. Its delays assume every connection is free and every clock edge arrives everywhere at once. Real wires and a real clock tree change timing, sometimes by a lot. Treat every pre-layout number in this series as an estimate and a ceiling, never a promise.
The running example and the plan
The teaching machine is called acc8: an 8-bit accumulator, a 4-bit program counter, a zero flag, and a unified 16-byte memory for code and data. Eight instructions: load, add, subtract, store, load-immediate, jump, jump-if-zero, halt. That's it. The entire design, including its bus wrapper and generated opcode package, is 294 lines of SystemVerilog.
Here's the project layout we'll build, one directory per stage of the map.
1model/ the Python golden model, assembler, random-program generator
2rtl/ SystemVerilog: opcode package (generated), memory, core, CPU, Wishbone wrapper
3tb/ Verilator C++ testbenches, mutation runner, waveform-to-text tool
4formal/ properties and the scripts that prove them
5synth/ Yosys scripts: generic, SKY130, black-box macro, FPGA
6ci/ one script that re-checks everything on every pushThe plan runs like this. Part 2 writes the golden model in Python. Part 3 writes the RTL and lints it. Part 4 builds a self-checking co-simulation and then attacks it with deliberate bugs. Part 5 wraps the CPU in a Wishbone slave and introduces formal verification. Part 6 synthesizes with Yosys. Part 7 maps onto SKY130 and estimates area and speed. Part 8 covers layout, signoff, FPGA prototyping, CI and the honest readiness checklist.
In Part 2 we write the thing that makes every later check meaningful: a Python model of the CPU, tested before we trust it. We also build a random-program generator and tune it by looking at its own coverage numbers.