Session 4: Layout & Fabrication
Assignments
- Block diagram: Sketch your project's architecture showing major modules and data flow (e.g., Pocket Synth: button inputs → tone selector → oscillator → PWM output)
-
Explore a standard cell: Open the sky130 standard cell library in KLayout and find an inverter
sky130_fd_sc_hd__inv_1Identify metal, poly, and diffusion layers. In the container:klayout /foss/pdks/sky130A/libs.ref/sky130_fd_sc_hd/gds/sky130_fd_sc_hd.gdsTip: Use Edit → Find (Ctrl+F) to search for "inv_1"
-
Connect the dots: Pick one block from your diagram, what standard cells might implement it? (e.g., "counter" needs flip-flops, "tone selector" needs muxes)
Klayout
I started by opening Klayout from the terminal using: klayout The program opened successfully and a tip window appeared. Since it included instructions on how to disable it later, I selected Yes. I have not worked with this software before, so I began by trying to understand the interface.

Understanding the interface
I created a new hierarchical layout in Klayout and selected the sg13g2 technology. I saved the file in the /foss/designs directory.
Hierarchical design was explained in the lecture. Instead of drawing every structure manually each time, you define a cell once and reuse it multiple times. If changes are needed later, you only modify the original cell and all instances update automatically. This is similar to parametric design and makes complex layouts more manageable.
After selecting the sg13g2 technology, the user interface changed and felt familiar. Panning works with the middle mouse button and zooming with the scroll wheel. The layer panel was populated with all process layers, including substrate, active, poly, contacts, and metal layers. The library panel also updated to include the sg13g2 devices.

It took me a while to figure out that editing mode was not enabled by default. I found the option to activate it under:
file > setup > application > editing mode
I had to restart the software for the change to take effect.
After enabling editing mode, I was able to drag devices from the library onto the canvas and draw basic shapes. Below is my first IC design.

Explore the sky130 standard cell
I opened the standard cell library in Klayout using:
Like any curious person, I immediately started taking it apart. I realized I should probably have taken a screenshot before and after. I pressed Ctrl+Z but nothing happened. It felt like this kind of software should have an undo button. Eventually I found out that undo works with ++U++.

I put the parts back together and realized this did not look like the inverter I expected. This was not the inverter it was ipflow_isobufsec_16. I needed to find the actual inverter sky130_fd_sc_hd__inv_1.

I used the tip from the class page and searched for _inv_1, but it didn’t find anything at first. I changed the option to search in all cells and adjusted the filter. Two different inverters showed up and I picked sky130_fd_sc_hd__inv_2 r0 *1 11.96,0. When I clicked it, only a box appeared on the canvas. I realized I was off track. I ended up scrolling through the cell list until I found the correct one.
When I double-clicked it, it was only a show/hide option, and dragging it onto the canvas just created a box. I wanted to see the actual layout. I then figured out that I had to right-click the cell and choose Show as New Top. There it was.

I measured the cell size as X: 1.75 µm and Y: 3.2 µm. I wanted to see next if I could find where the 130 nm comes from.
Gate measurement first attempt
I began by removing some of the layers since the view was quite confusing. I did not really know what I was looking at. There were also a lot of layers. I noticed that the layers shown in bold font were the ones that actually contained geometry but the layers with something in them only had numbers. There were also useful right-click options in the layer window, such as visibility follows selection.

I started hiding layers that looked unnecessary and keeping only the ones that seemed relevant, I managed to get a somewhat clearer picture. I placed a few rulers to get an idea of the dimensions, but I still wasn’t sure where exactly the gate region was.

At that point, I remembered that the selected technology was still sg13g2. I realized that might be the source of the confusion, so I decided to fix the technology setup before continuing.
Technology import and selection
I searched through the PDK directory and found the Sky130 KLayout technology file at:
/foss/pdks/sky130A/libs.tech/klayout/tech.sky130A.lyt
In Klayout, under the Tools menu, there is a Manage Technologies option. I tried creating a new technology and manually inserting the path, but that did not work.
After searching how to properly import a technology in KLayout, I discovered that you need to right-click inside the technologies window and choose Import Technology. Once I activated the sky130A technology for the layout, the layer names changed from numbers to meaningful names such as poly, diff, and nwell. The color scheme also updated, making the layout much easier to read.
Gate measurement and input and output.
Now the layout looked much cleaner. I also noticed an option in the layer right-click menu to hide empty layers, which helped a lot. There were 22 visible layers, but some of them did not contain much geometry I started again by hiding unnecessary layers and focusing on the ones that looked relevant to finding the gate length.

The layer defining the gate was poly.drawing. The poly stripe runs along the Y-axis and crosses both the PMOS (top) and NMOS (bottom), meaning the same gate controls both transistors. Since the poly runs vertically, the gate length must be measured in the X-direction. I measured the gate length to be approximately 150 nm.
I initially expected 130 nm, but there are technical reasons for this. The Sky130 node name does not seam to directly correspond to the exact physical gate length. In fact, the minimum poly width in the PDK is around 150 nm. I also found this mentioned on github:
"Minimum width: for metal, for implants, for feature size (polysilicon layer) that defines the transistor gate length (ex: sky130 poly width >150nm)"

With that measurement confirmed, I moved on to identifying VDD, VSS, input, and output in the layout. I enabled additional layers, and the structure became clear.
You can see in the image below that:
- The PMOS transistor is located in the upper region, inside the nwell (green big square).
- The NMOS transistor is located in the lower region.
- The top metal rail(blue) connects to VDD(VPWR).
- The bottom metal rail(blue) connects to VSS (VGND).
- The vertical gray layer(li1.drawing) to the right connection between the two transistors forms the output.
- The poly contact forms the input.

Layers in sky130_fd_sc_hd__inv_1
| Layer Name | Physical Meaning | Role |
|---|---|---|
| poly.drawing | Polysilicon gate material | Forms the transistor gate. When poly crosses diffusion, a MOSFET is created. |
| diff.drawing | Active (diffusion) region | Defines source and drain regions. The transistor channel forms where diffusion overlaps with poly. |
| nwell.drawing | N-well region | Contains the PMOS transistor in the upper part of the inverter. |
| met1.drawing | Metal 1 routing layer | Used for power rails (VPWR, VGND) and signal routing. |
| li1.drawing | Local interconnect layer | Used for internal routing inside the cell and for connecting diffusion and poly to metal1. |
Thinker SkyCraft Blend
It was a pleasant surprise after spending hours staring at 2D squares at nanometer scale to come across this article by Thorsten Knoll explaining how to generate 3D models from the SKY130 OpenPDK.
He used the inverter as an example, so I didn’t need to generate a new cell. I tried it in Blender and it was amazing to see the 3D view of the stack-up and the layout.

Quick workbench render

view of the Polysilicon gate layer

Minecraft schematic. One day I will import it into Minecraft, walk around the model, and maybe even sleep on the Mosfet gate.
You can find all the file here:
Thinkercad model | blender model | minecraft model
Project Architecture
It took a bit of time to decide what project to work on. I needed something simple enough that I could focus on learning the new microelectronics environment, but still functional and meaningful, with clear inputs and outputs.
concept
I first thought about designing a digital clock, but that would require precise timing and more complexity than I want at this stage. I also considered building a small synthesizer core, but that would introduce analog circuits, which would complicate the project.
In the end, I decided to go with a 4-bit up/down counter.
The counter is simple, but it still includes a few building blocks:
- A clock input
- Flip-flops (state storage)
- Logic gates (next-state logic)
- Control inputs (enable, reset, up/down)
- Output display (either LEDs in binary or a hex/7-segment decoder)
I understand the operation of a counter fairly well, and it is one of the most common digital circuits. That means the conceptual part should be manageable, and I can focus on the microelectronics implementation details such as standard cells, synthesis, and layout.
This makes it a good balance between familiarity and challenge.
Block Diagram
flowchart TD
subgraph Inputs
BTN1[Up/Down Direction Switch]
BTN2[Enable Control]
BTN3[Asynchronous Reset]
CLK[System Clock]
end
subgraph Processing
LOGIC[Combinational Counter Logic]
REG[4-Bit Register 4 D Flip-Flops]
end
subgraph Output
DEC[BCD to Seven-Segment Decoder]
DISP[Seven-Segment Display]
end
BTN1 --> LOGIC
BTN2 --> LOGIC
BTN3 --> REG
CLK --> REG
REG -- Current State Feedback --> LOGIC
LOGIC -- Next State Logic --> REG
REG -- 4-bit Binary Output --> DEC
DEC -- Segment Drive Signals --> DISP
At first I thought I could use a JK flip-flop and there is an up/down counter example on Falstad. I assumed I would only need to add my own reset and enable control.
However, when looking through the Sky130 library, I could not find any JK flip-flop cell. I did find examples of people implementing JK flip-flops using combinations of available standard cells, but that adds unnecessary complexity for this point. I decided to adapt the design to use a D flip-flop, which is the standard sequential element used in ASIC design. I found the cell: sky130_fd_sc_ms__dfrbp which is a D flip-flop with inverted reset and complementary outputs. This looks like a good candidate for the project.
Connect the dots
Next task was to focus on the counter block since it seems important to get that block right.
I started in Falstad, just to sketch a rough flip-flop based counter idea. Falstad has a D flip-flop, but not one with a reset. I also found a MOSFET flip-flop example circuit, but that one didn’t have a proper clock input. So it felt like I couldn’t directly use what Falstad already had for the kind of standard-cell style flip-flop I was aiming for. Falstad circuits
At that point it occurred to me that maybe I could find an actual CMOS schematic of the SKY130 cell I had picked. But when I searched online I mostly ended up on sites trying to sell “beech flip-flops” or generic logic ICs, not real standard cell I was looking for.
So I went back to the SKY130 documentation. It has high-level schematics and the full GDS layout, but not really the “middle ground” view I was hoping for. What I wanted was simple: roughly how many MOSFETs are inside the cell, and how the structure is organized.
After digging around for a while without finding a satisfying answer, I the cell layout was not a pixle image but a SVG. That’s one of my favorite format, so I opened it in my trusted tool: Inkscape.

From there I started tearing layers apart to make the layout readable. The polysilicon gates are a key layer, because each poly gate crossing diffusion corresponds to a transistor. By visually counting the poly gates that form active devices, I ended up with an estimate of ~17 CMOS pairs. You can also clearly see the standard cell structure: PMOS devices on top (in n-well green square) and NMOS devices on the bottom.

You can find the file here:
Inkscape teardown_sky130_fd_sc_ms__dfrbp_1
I next wanted to look at the netlist to see if I could confirm the number of transistors and get a better sense of how they are connected. I wasn’t able to find this specific extracted cell netlist in the container foss/pdks/ directory, but I did find the cell on GitHub along with the SPICE file:
- Cell on GitHub: sky130_fd_sc_ms / dfrbp
- SPICE netlist: sky130_fd_sc_ms__dfrbp_1.spice
Looking at the net-list, I could clearly see the device count: 17 PFETs and 17 NFETs, for a total of 34 transistors inside the cell. This matched surprisingly with what I had estimated earlier by counting polysilicon gates in the layout.

I then opened KLayout to see if I could find the same cell locally. However, I noticed that the standard cells in my foss/pdks/ directory were from the hd library and followed the naming convention _hd__<cell_name>, while the cell I had examined earlier was from the ms library _ms__<cell_name>.
The cell I had been analyzing was:
sky130_fd_sc_ms__dfrbp_1
But in my local installation I found the corresponding high-density version:
sky130_fd_sc_hd__dfrbp Documentation
sky130_fd_sc_hd__dfrbp GitHub repo
The naming is very similar, and the functionality is nearly equivalent, but they belong to different standard cell libraries. The hd library stands for high density, while ms stands for medium speed.
Picking a cell part 2
I now had a cell to work with, so I opened it in KLayout and did a quick inspection. I counted 16 CMOS pairs and compared that to the extracted netlist and it matched.
At this point I was starting to feel more confident about understanding how the physical layout relates to the transistor-level netlist. Seeing the devices in the layout and then recognizing them in the SPICE file made the abstraction layers feel much less mysterious.

Simulating the cell in Ngspice
We had previously simulated at the transistor level, so now I wanted to try running a simulation at the standard-cell level.
In last session 3 we used:
That line loads the SKY130 device models (BSIM4, process corner tt), but it does not include the standard cell library.
I found that the cell library lives here:
To find the correct subcircuit definition and its pin order, I used grep:
Which returned:
5213:.subckt sky130_fd_sc_hd__dfrbp_1 CLK D RESET_B VGND VNB VPB VPWR Q Q_N
5268:.subckt sky130_fd_sc_hd__dfrbp_2 CLK D RESET_B VGND VNB VPB VPWR Q Q_N
This showed me the exact pin order required when instantiating the cell in ngspice.
I initially expected a small file per cell, but instead found a single large netlist (~18,000 lines) containing all hd cells. The dfrbp definition inside it matched the transistor-level netlist I had previously inspected.

Net-list in
sky130_fd_sc_hd.spice
At that point the hierarchy became clearer:
-
.lib- loads transistor physics models -
.include- loads the standard cell netlists -
.subckt- defines the cell interface -
X[nr]- instantiates in the cell
flowchart LR
A(sky130_fd_sc_hd__dfrbp.gds)
B(.include / sky130_fd_sc_hd.spice)
C(.subckt sky130_fd_sc_hd__dfrbp_1)
D(x sky130_fd_pr__nfet_01v8)
E(.lib/sky130.lib.spice tt)
A --> B --> C --> D --> E
sky130.lib.spiceis the lowest abstraction layer I directly interact with. It contains BSIM4 (level=49) compact transistor models, which are mathematical approximations of real semiconductor physics. Below that lies the physical silicon behavior, which is not simulated directly in SPICE.
The cell simulation
With all that information I was ready to make a code and finaly try to simulate the dfrbp flip-flop in Ngspice. It seemed straightforward: include the device models (.lib), include the standard cell library (.include), instantiate the dfrbp cell, and drive it with clock, D, and reset signals. This is the code I made:
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt
.include "/foss/pdks/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice"
* Power for the cell
VVPWR VPWR 0 {VDD}
VVGND VGND 0 0
VVPB VPB 0 {VDD}
VVNB VNB 0 0
* clock: 20ns period
VCLK CLK 0 PULSE(0 {VDD} 5n 100p 100p 10n 20n)
* RESET_B signal
VRESB RESET_B 0 PWL(0n 0 40n 0 40.1n {VDD} 120n {VDD} 120.1n 0 160n 0 160.1n {VDD} 200n {VDD})
*D signal
VD D 0 PWL(0n 0 60n 0 60.1n {VDD} 100n{VDD} 100.1n 0 140n 0 140.1n {VDD} 200n {VDD})
* DUT pin order from the netlist same naming:
* .subckt sky130_fd_sc_hd__dfrbp_1 CLK D RESET_B VGND VNB VPB VPWR Q Q_N
X0 CLK D RESET_B VGND VNB VPB VPWR Q QN sky130_fd_sc_hd__dfrbp_1
* small loads
CQ Q VGND 5f
CQN QN VGND 5f
.control
tran 100n 200n
plot v(CLK)+8 v(D)+6 v(RESET_B)+4 v(Q)+2 v(QN)
.endc
.end
I ran the simulation with ngspice sky130_ff.sp and got a plot that showed what I was expecting.

The cell uses an active-low reset
RESET_B. WhenRESET_B = 0, the outputQis forced to the reset state regardless ofDor clock activity. WhenRESET_B = 1, the flip-flop capturesDon the active clock edge and holds its state between edges. The complementary outputQ_Nremains the inverse ofQ.
4-bit ripple counter - dfrbp
Since the single-cell simulation worked well, I wanted to connect three more flip-flops and see if I could make it count. I added three more dfrbp cells and kept only the clock as input. The simulation ran and it worked. It counted down, which was not my intention, but I realized that changing the chaining from Q to Q_N would reverse the direction and make it count up.

SKY130 Digital Technology Stack
| Layer | Example | What It Defines | Who Controls It | What Can Change |
|---|---|---|---|---|
| Process | sky130 |
Fabrication technology (130nm CMOS) | SkyWater Foundry | Nothing (fixed silicon) |
| Design Rules | n/a | Layout constraints (spacing, width, enclosure) | SkyWater Foundry | Must be followed |
| Device Models | BSIM | Electrical transistor behavior | SkyWater Foundry | Same for all libraries |
| Standard Cell Library | fd_sc_*, ef_sc_*, osu_sc_* |
Pre-designed logic cells | Foundry or 3rd parties | Transistor sizing, layout style |
| Library Flavor | hd, hs, ms, hdl, ls |
Speed/area/leakage tradeoff | Library designer | Optimization strategy |
| Cell | dfxbp_1, inv_1 |
Specific logic function + drive strength | Library designer | Drive strength variants |
| Transistors | sky130_fd_pr__nfet_01v8 |
CMOS implementation | Cell designer | Width, sizing |
| Geometry | Poly, Diffusion, Metal | Physical layout shapes | Layout designer | Placement within rules |
flowchart LR
P["Process"]
L["Libraries"]
C["Cells"]
T["Transistors"]
G["Geometry"]
P --> L --> C --> T --> G