Skip to content

Session 4: Layout & Fabrication

Class page | Class recording

Assignments

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.

klayout

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.

ui klay

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.

first design

Explore the sky130 standard cell

I opened the standard cell library in Klayout using:

klayout /foss/pdks/sky130A/libs.ref/sky130_fd_sc_hd/gds/sky130_fd_sc_hd.gds

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++.

undo

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.

inv_2

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.

inverter

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.

nr layers

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.

mesurment first

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.

new tech

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)"

second messure

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.

cmost layout

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.

blender

Quick workbench render

poly layer

view of the Polysilicon gate layer

skycraft

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.

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.

inkscape close

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:

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.

netlist ff

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.

klayout cell netlist klayout dffbp

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:

.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt

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:

/foss/pdks/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice

To find the correct subcircuit definition and its pin order, I used grep:

grep -n "dfrbp" sky130_fd_sc_hd.spice

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.

netlist hd

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.spice is 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.

plot sim

The cell uses an active-low reset RESET_B. When RESET_B = 0, the output Q is forced to the reset state regardless of D or clock activity. When RESET_B = 1, the flip-flop captures D on the active clock edge and holds its state between edges. The complementary output Q_N remains the inverse of Q.

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.

counter

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