ASIC 101, a documentation site on digital ASIC design for beginners

ASIC stands for Application Specific Integrated Circuit. This course will walk you through the process of creating and designing your very own first ASIC chip.

This book will provide interactive tutorials, quizzes and exercises for you to complete. For interactive lesson portions, we will mainly reference problems from ASIC tutor. If you are a Stone Arch Silicon Member, there will be small self led deliverables which correspond to onboarding, feel free to follow along if you wish.

About ASIC

So what even is an ASIC chip? Unlike general purpose processors, it is a chip built to do one job. Compared to an FPGA, an ASIC chip cannot be reprogrammed after it ships. The circuit on an ASIC chip is permanent, and wired directly into the silicon. An ASIC is typically much more expensive and time consuming to create compared to an ASIC chip. For many companies, developing their own ASICs requires an upfront cost in the millions! However, with a large market volume, the price per processor is much lower with ASIC chips. ASICs are also capable of being more performant and power efficient due to a low silicon overhead. FPGAs arent perpindicular to ASIC technology however. An engineer can benchmark and test ASIC designs on an FPGA before menufacturing, saving a lot of time and money in the case of an error.

There are three main components of digital design covered in this book.

  1. Register Transfer Level (RTL) design:

    The RTL portion involves translating high level design requirements into a cycle-accurate digital representation. Engineers use Hardare Description Languages (HDLs), to define the logic of a system. The RTL description is the foundational source code for all downstream processes. In this book you will learn how to write verilog HDL.

  2. Functional verification:

    Verification is the most time intensive and important steps of ASIC design. Verification is dedicated to proving that the RTL implementation strictly adheres to the behavioral specification of the chip. Its really important to get this stage right. Nobody wants to waste all their time and money manufacturing a broken chip! In this portion of the book, you will learn how to verify your designs using open source tools.

  3. Place and Route (PNR) / Physical Design:

    Placement and routing tools transform the verified RTL code into a physical silicon layout composed of layer drawings and polygons. In this portion of the book, you will learn how design the physical mosfets and metal interconnects on your chip.

Preresiquite Content

This book assumes prior knowledge on boolean logic design, roughly to the same level of EE2301 from the University of Minnesota.

Additionally:

  • A linux shell you're comfortable in (wsl is ok)
  • Git, and a GitHub account. (Github will be used for submitting SASi deliverables)

Instructions for setting up most of the build environment tools used in this book can be found online if not in the appendix or chapter content.

Words from the authors

ASIC design can be a challenging topic to dive headfirst into. If you are having serious issues, don't be afraid to ask a senior member of your club for help. We were all once beginners, just like your. The most important thing to do when reading this book is to have fun. Learning is fun. Have Fun! - Bear BlinSchauer

Quick Start Tutorial

A self-paced project that walks the entire chip-design flow twice: once fast, on an FPGA, so you have a working design in days instead of weeks; then again for real, through an open-source ASIC flow that ends in a GDSII layout. Both halves build the same 8-bit ALU, so the second half is about the physical-design process, not re-learning the RTL.

Part 1 — Build an 8-bit ALU (FPGA, Vivado)

Specify, write, and verify an 8-bit ALU, then synthesize and implement it in Vivado. You pick one of three adder architectures to build the ALU around:

AdderDifficulty
Ripple CarryBeginner
Carry LookaheadIntermediate
Carry SelectIntermediate

Everyone verifies, synthesizes, and implements the same way regardless of which adder they chose, then closes out the part by reading Vivado's timing, utilization, and power reports and writing up what they mean.

Part 2 — RTL to GDSII (open-source ASIC flow)

Take the same verified ALU through an open-source standard-cell flow: install the toolchain, synthesize into real standard cells, floorplan, build a power grid, place, route the clock tree and signal nets, extract parasitics, run static timing analysis, and clear signoff checks (DRC, LVS, antenna, XOR). The part ends with a GDSII layout and a tapeout-readiness checklist.

Prerequisites

  • A Linux shell you're comfortable in (WSL is fine)
  • Git, and a GitHub account for turning in work
  • Verilog at the level of EE 2301 — modules, always blocks, testbenches

Start here

Begin with What an ASIC is, which covers what you'll need before lesson 2 and gets blink, a trivial first module, simulating.

What an ASIC is, and what we're building

An ASIC — application-specific integrated circuit — is a chip built to do one job, with the logic frozen into the silicon at manufacturing time. That's the trade: an FPGA can be reprogrammed after it ships, an ASIC can't, and in exchange the ASIC is smaller, faster, and far cheaper per unit at volume.

ASIC 101 walks the whole path once, end to end, on a design small enough to finish: RTL, simulation, synthesis, place and route, and a GDS file that could actually be taped out.

What you need before lesson 2

  • A Linux shell you're comfortable in (WSL is fine)
  • Git, and a GitHub account for turning in work
  • Verilog at the level of EE 2301 — modules, always blocks, testbenches

The flow, in order

StageYou writeThe tool produces
RTLVerilog—
SimulationTestbenchWaveforms
SynthesisConstraintsGate-level netlist
Place & routeFloorplanGDSII layout

A first module

module blink #(parameter N = 24) (
  input  wire clk,
  input  wire rst_n,
  output wire led
);
  reg [N-1:0] count;
  always @(posedge clk or negedge rst_n)
    if (!rst_n) count <= 0;
    else        count <= count + 1'b1;

  assign led = count[N-1];
endmodule

Nothing here is ASIC-specific yet — that's the point. The RTL is the same; everything downstream of it changes.

Checklist

  • Read this page
  • Install the toolchain
  • Simulate blink and screenshot the waveform

ASIC 101 project: build an 8-bit ALU

This project is your first complete hardware-design flow in Vivado. You will build one 8-bit ALU, choose one adder architecture, verify it, synthesize it, implement it, and collect timing, utilization, and power results.

Overview

The project has one common specification, but you get to choose how the arithmetic hardware is built.

Everyone completes the same ALU. The only branch is the adder:

adderdifficultygo to
Ripple Carry Adderbeginnerpage 4
Carry Lookahead Adderintermediatepage 5
Carry Select Adderintermediatepage 6

You only need to complete one adder.

After your adder works, everyone returns to page 7 for verification.

Your final repository should contain:

asic_101/
├── rtl/
│   ├── adder8.v
│   ├── alu_core.v
│   └── alu_top.v
├── sim/
│   └── alu_tb.v
├── constr/
│   └── alu.xdc
├── reports/
├── screenshots/
└── README.md

By the end, you should have:

  • a working 8-bit ALU
  • an automated testbench
  • a synthesized Vivado design
  • a routed Vivado implementation
  • utilization results
  • timing results
  • power results
  • a short engineering interpretation of the results

Prerequisites

You do not need to program a physical FPGA board for this project. Vivado is being used as the synthesis, implementation, timing, and power-analysis environment.

Steps

  1. Create a folder named asic_101.

  2. Create the directory structure shown above.

  3. Open Vivado and select Create Project.

  4. Create an RTL Project.

  5. Select the FPGA board or part assigned by your university/team.

  6. Do not add RTL yet if you have not written it.

  7. Continue to the ALU specification on page 3.

Project rules

For the arithmetic block:

  • You must choose exactly one adder architecture from pages 4–6.
  • Your adder module must be named adder8.
  • It must use the interface shown on page 3.
  • Do not use a + b inside adder8.
  • Do not use a vendor adder IP block.
  • The + operator is allowed inside the testbench to calculate expected answers.
  • Your chosen adder must perform both ADD and SUB operations inside the ALU.

The rest of the ALU may use normal Verilog operators.

Results

At the end of the project, your README will contain a table like this:

metricresult
Adder architecture—
LUTs—
Flip-flops—
Carry resources—
Worst Negative Slack—
Total Negative Slack—
Total on-chip power—
Dynamic power—
Static power—

Do not fill these values in yet.

Checklist

  • Created the project folder
  • Created the Vivado RTL project
  • Selected a target FPGA
  • Read the project rules
  • Continued to page 3

Questions? Ask in the network Discord.

Build the 8-bit ALU

The ALU is the common project used by everyone in ASIC 101. You will implement eight operations and route ADD and SUB through the custom adder architecture you choose.

Overview

Your ALU accepts two 8-bit operands and a 3-bit operation code.

opoperationresult
000ADDa + b
001SUBa - b
010ANDa & b
011ORa \| b
100XORa ^ b
101NOT~a
110Shift lefta << 1
111Shift righta >> 1

The ALU also produces four status flags:

  • zero: result is zero
  • negative: most-significant bit of the result is one
  • carry: carry-out from ADD or SUB
  • overflow: signed two's-complement overflow on ADD or SUB

The core is combinational. A small registered wrapper is added so Vivado has a clean register-to-register timing path to analyze later.

Prerequisites

  • prior page: ASIC 101 project setup
  • basic combinational Verilog
  • understanding of two's-complement subtraction

Steps

1. Use one common adder interface

Whichever adder you choose later, it must use this exact module interface:

module adder8 (
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire       cin,
  output wire [7:0] sum,
  output wire       cout
);
  // your architecture goes here
endmodule

This lets every adder plug into the exact same ALU.

2. Reuse the adder for subtraction

Two's-complement subtraction is

a - b = a + (~b) + 1

That means the same adder can perform both operations.

wire sub;
wire [7:0] b_arith;

assign sub     = (op == 3'b001);
assign b_arith = b ^ {8{sub}};

For ADD:

sub = 0
b_arith = b
cin = 0

For SUB:

sub = 1
b_arith = ~b
cin = 1

3. Create rtl/alu_core.v

Use this as the project skeleton:

module alu_core (
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire [2:0] op,

  output reg  [7:0] y,
  output reg        carry,
  output reg        overflow,
  output reg        zero,
  output reg        negative
);

  wire       sub;
  wire [7:0] b_arith;
  wire [7:0] arithmetic_result;
  wire       arithmetic_cout;

  assign sub     = (op == 3'b001);
  assign b_arith = b ^ {8{sub}};

  adder8 u_adder (
    .a    (a),
    .b    (b_arith),
    .cin  (sub),
    .sum  (arithmetic_result),
    .cout (arithmetic_cout)
  );

  always @* begin
    y        = 8'h00;
    carry    = 1'b0;
    overflow = 1'b0;

    case (op)
      3'b000: begin
        y        = arithmetic_result;
        carry    = arithmetic_cout;
        overflow = (~(a[7] ^ b[7])) & (y[7] ^ a[7]);
      end

      3'b001: begin
        y        = arithmetic_result;
        carry    = arithmetic_cout;
        overflow = (a[7] ^ b[7]) & (y[7] ^ a[7]);
      end

      3'b010: y = a & b;
      3'b011: y = a | b;
      3'b100: y = a ^ b;
      3'b101: y = ~a;
      3'b110: y = a << 1;
      3'b111: y = a >> 1;

      default: y = 8'h00;
    endcase

    zero     = (y == 8'h00);
    negative = y[7];
  end

endmodule

For subtraction, carry = 1 generally corresponds to no borrow in this two's-complement implementation.

4. Create a registered top level

Create rtl/alu_top.v.

module alu_top (
  input  wire       clk,
  input  wire       rst_n,
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire [2:0] op,

  output reg  [7:0] y,
  output reg        carry,
  output reg        overflow,
  output reg        zero,
  output reg        negative
);

  reg [7:0] a_q;
  reg [7:0] b_q;
  reg [2:0] op_q;

  wire [7:0] y_comb;
  wire       carry_comb;
  wire       overflow_comb;
  wire       zero_comb;
  wire       negative_comb;

  alu_core u_core (
    .a        (a_q),
    .b        (b_q),
    .op       (op_q),
    .y        (y_comb),
    .carry    (carry_comb),
    .overflow (overflow_comb),
    .zero     (zero_comb),
    .negative (negative_comb)
  );

  always @(posedge clk) begin
    if (!rst_n) begin
      a_q      <= 8'h00;
      b_q      <= 8'h00;
      op_q     <= 3'b000;
      y        <= 8'h00;
      carry    <= 1'b0;
      overflow <= 1'b0;
      zero     <= 1'b1;
      negative <= 1'b0;
    end
    else begin
      a_q      <= a;
      b_q      <= b;
      op_q     <= op;

      y        <= y_comb;
      carry    <= carry_comb;
      overflow <= overflow_comb;
      zero     <= zero_comb;
      negative <= negative_comb;
    end
  end

endmodule

The input registers launch data through alu_core, and the output registers capture the result on the next rising clock edge. That gives Vivado a meaningful internal timing path.

5. Choose your adder

Now choose one path:

You only complete one page.

Results

Before moving on, you should have:

rtl/
├── alu_core.v
└── alu_top.v

Your adder8.v comes from whichever adder page you choose.

Checklist

  • Understand the eight ALU operations
  • Understand how ADD and SUB share one adder
  • Created alu_core.v
  • Created alu_top.v
  • Selected one adder architecture
  • Continued to page 4, 5, or 6

Questions? Ask in the network Discord.

Option A: Ripple Carry Adder

The Ripple Carry Adder is the simplest adder option. Each bit waits for the carry from the bit before it, making the structure easy to understand and easy to verify.

Overview

A one-bit full adder has three inputs:

a
b
carry-in

and two outputs:

sum
carry-out

The logic is

sum  = a XOR b XOR cin

cout = (a AND b)
     OR (a AND cin)
     OR (b AND cin)

An 8-bit Ripple Carry Adder chains eight of these stages.

cin -> bit 0 -> bit 1 -> bit 2 -> ... -> bit 7 -> cout

The important idea is that a carry may have to propagate through every stage.

Prerequisites

Steps

1. Create rtl/adder8.v

module adder8 (
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire       cin,
  output wire [7:0] sum,
  output wire       cout
);

  wire [8:0] c;

  assign c[0] = cin;

  genvar i;
  generate
    for (i = 0; i < 8; i = i + 1) begin : GEN_FULL_ADDER
      assign sum[i] = a[i] ^ b[i] ^ c[i];

      assign c[i+1] =
          (a[i] & b[i]) |
          (a[i] & c[i]) |
          (b[i] & c[i]);
    end
  endgenerate

  assign cout = c[8];

endmodule

2. Trace one carry by hand

Try:

a   = 01111111
b   = 00000001
cin = 0

The result should be

sum  = 10000000
cout = 0

Several carry signals must ripple through the design before the final sum settles.

3. Add it to the ALU

Make sure your files are

rtl/
├── adder8.v
├── alu_core.v
└── alu_top.v

Do not rename the module. alu_core.v expects a module named adder8.

4. Continue to the common flow

You are done with the adder branch.

Continue to Verify the complete ALU — page 7.

Results

The Ripple Carry Adder is a useful baseline because it uses a simple repeated structure.

Later, record what Vivado actually maps it into. FPGA synthesis may transform your RTL and use device-specific carry resources, so do not assume the post-synthesis hardware will look exactly like the source code.

Checklist

  • Created adder8.v
  • Did not use a + b inside the adder
  • Understand how the carry ripples
  • Connected the adder to alu_core
  • Continued to page 7

Questions? Ask in the network Discord.

Option B: Carry Lookahead Adder

The Carry Lookahead Adder reduces the amount of strictly serial carry logic by computing carry conditions from propagate and generate signals.

Overview

For bit i, define

p[i] = a[i] XOR b[i]
g[i] = a[i] AND b[i]

p means the stage can propagate a carry.

g means the stage generates a carry regardless of the incoming carry.

For one bit,

c[i+1] = g[i] OR (p[i] AND c[i])

Instead of waiting for each carry sequentially, a lookahead block expands the equations so multiple carry conditions can be evaluated in parallel.

This project uses two 4-bit lookahead blocks to build the 8-bit adder.

Prerequisites

Steps

1. Build a four-bit lookahead block

Create rtl/adder8.v and begin with:

module cla4 (
  input  wire [3:0] a,
  input  wire [3:0] b,
  input  wire       cin,
  output wire [3:0] sum,
  output wire       cout
);

  wire [3:0] p;
  wire [3:0] g;
  wire [4:0] c;

  assign p = a ^ b;
  assign g = a & b;

  assign c[0] = cin;

  assign c[1] =
      g[0] |
      (p[0] & c[0]);

  assign c[2] =
      g[1] |
      (p[1] & g[0]) |
      (p[1] & p[0] & c[0]);

  assign c[3] =
      g[2] |
      (p[2] & g[1]) |
      (p[2] & p[1] & g[0]) |
      (p[2] & p[1] & p[0] & c[0]);

  assign c[4] =
      g[3] |
      (p[3] & g[2]) |
      (p[3] & p[2] & g[1]) |
      (p[3] & p[2] & p[1] & g[0]) |
      (p[3] & p[2] & p[1] & p[0] & c[0]);

  assign sum[0] = p[0] ^ c[0];
  assign sum[1] = p[1] ^ c[1];
  assign sum[2] = p[2] ^ c[2];
  assign sum[3] = p[3] ^ c[3];

  assign cout = c[4];

endmodule

2. Build the 8-bit adder from two blocks

Add this below cla4 in the same file:

module adder8 (
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire       cin,
  output wire [7:0] sum,
  output wire       cout
);

  wire carry4;

  cla4 u_low (
    .a    (a[3:0]),
    .b    (b[3:0]),
    .cin  (cin),
    .sum  (sum[3:0]),
    .cout (carry4)
  );

  cla4 u_high (
    .a    (a[7:4]),
    .b    (b[7:4]),
    .cin  (carry4),
    .sum  (sum[7:4]),
    .cout (cout)
  );

endmodule

This is a block carry-lookahead design: carry logic is expanded inside each four-bit block, while the carry between the lower and upper blocks still forms one block-level dependency.

3. Test a carry-heavy input by hand

Try:

a   = 11111111
b   = 00000001
cin = 0

Expected:

sum  = 00000000
cout = 1

4. Add it to the ALU

Your files should now be:

rtl/
├── adder8.v
├── alu_core.v
└── alu_top.v

5. Continue to the common flow

You are done with the adder branch.

Continue to Verify the complete ALU — page 7.

Results

Compared with the source structure of a Ripple Carry Adder, the lookahead equations expose more carry logic in parallel.

Do not assume that means it will always win on an FPGA. Vivado is free to optimize both designs for the target device, and dedicated FPGA carry hardware can strongly affect the result.

Your job later is to report what the tool actually produced.

Checklist

  • Created the cla4 block
  • Created the top-level adder8
  • Did not use a + b inside the adder
  • Connected the adder to alu_core
  • Continued to page 7

Questions? Ask in the network Discord.

Option C: Carry Select Adder

The Carry Select Adder trades extra hardware for reduced waiting on part of the carry path. The upper half computes both possible answers in advance and selects the correct one when the lower-half carry arrives.

Overview

Split the 8-bit addition into two four-bit halves.

The lower half computes normally:

bits 3:0

At the same time, the upper half computes twice:

bits 7:4 assuming carry-in = 0
bits 7:4 assuming carry-in = 1

When the lower-half carry is finally known, a mux selects the correct upper result.

Conceptually:

                       +--> upper add, cin=0 --+
lower add --> carry ---|                       |--> mux --> final upper sum
                       +--> upper add, cin=1 --+

Prerequisites

Steps

1. Create a four-bit Ripple Carry helper

Create rtl/adder8.v.

module rca4 (
  input  wire [3:0] a,
  input  wire [3:0] b,
  input  wire       cin,
  output wire [3:0] sum,
  output wire       cout
);

  wire [4:0] c;

  assign c[0] = cin;

  genvar i;
  generate
    for (i = 0; i < 4; i = i + 1) begin : GEN_FA
      assign sum[i] = a[i] ^ b[i] ^ c[i];

      assign c[i+1] =
          (a[i] & b[i]) |
          (a[i] & c[i]) |
          (b[i] & c[i]);
    end
  endgenerate

  assign cout = c[4];

endmodule

2. Compute the upper half twice

Add the top-level module below it:

module adder8 (
  input  wire [7:0] a,
  input  wire [7:0] b,
  input  wire       cin,
  output wire [7:0] sum,
  output wire       cout
);

  wire [3:0] sum_low;
  wire       carry_low;

  wire [3:0] sum_high_0;
  wire [3:0] sum_high_1;
  wire       carry_high_0;
  wire       carry_high_1;

  rca4 u_low (
    .a    (a[3:0]),
    .b    (b[3:0]),
    .cin  (cin),
    .sum  (sum_low),
    .cout (carry_low)
  );

  rca4 u_high_if_0 (
    .a    (a[7:4]),
    .b    (b[7:4]),
    .cin  (1'b0),
    .sum  (sum_high_0),
    .cout (carry_high_0)
  );

  rca4 u_high_if_1 (
    .a    (a[7:4]),
    .b    (b[7:4]),
    .cin  (1'b1),
    .sum  (sum_high_1),
    .cout (carry_high_1)
  );

  assign sum[3:0] = sum_low;

  assign sum[7:4] =
      carry_low ? sum_high_1 : sum_high_0;

  assign cout =
      carry_low ? carry_high_1 : carry_high_0;

endmodule

3. Understand the tradeoff

The upper arithmetic is duplicated.

That means the source design contains more logic than a simple ripple structure, but the upper half does not need to wait before beginning its arithmetic.

The final selection still waits for carry_low.

4. Add it to the ALU

Your files should now be:

rtl/
├── adder8.v
├── alu_core.v
└── alu_top.v

5. Continue to the common flow

You are done with the adder branch.

Continue to Verify the complete ALU — page 7.

Results

Later, inspect whether the duplicated structure survives synthesis and how Vivado maps it to FPGA resources.

Do not assume source-code area equals physical area. Synthesis can remove, merge, or transform logic.

Checklist

  • Created the rca4 helper
  • Computed both upper-half carry cases
  • Added the output mux
  • Did not use a + b inside the adder
  • Connected the adder to alu_core
  • Continued to page 7

Questions? Ask in the network Discord.

Verify the complete ALU

Before synthesis, prove that the RTL is functionally correct. The testbench checks all 524,288 combinations of a, b, and op.

Overview

There are

256 possible values of a
256 possible values of b
8 possible operations

so the complete ALU input space is

256 × 256 × 8 = 524,288 test vectors

Because this ALU is small, exhaustive simulation is practical.

The testbench is allowed to use normal Verilog arithmetic to calculate the expected result. The design under test is still required to use your custom adder8.

Prerequisites

Complete exactly one adder page:

You should also have:

rtl/adder8.v
rtl/alu_core.v
rtl/alu_top.v

Steps

1. Create sim/alu_tb.v

`timescale 1ns/1ps

module alu_tb;

  reg  [7:0] a;
  reg  [7:0] b;
  reg  [2:0] op;

  wire [7:0] y;
  wire       carry;
  wire       overflow;
  wire       zero;
  wire       negative;

  reg  [7:0] exp_y;
  reg        exp_carry;
  reg        exp_overflow;
  reg        exp_zero;
  reg        exp_negative;
  reg  [8:0] tmp;

  integer ia;
  integer ib;
  integer iop;
  integer errors;

  alu_core dut (
    .a        (a),
    .b        (b),
    .op       (op),
    .y        (y),
    .carry    (carry),
    .overflow (overflow),
    .zero     (zero),
    .negative (negative)
  );

  task check_current;
    begin
      exp_y        = 8'h00;
      exp_carry    = 1'b0;
      exp_overflow = 1'b0;
      tmp          = 9'h000;

      case (op)
        3'b000: begin
          tmp          = {1'b0, a} + {1'b0, b};
          exp_y        = tmp[7:0];
          exp_carry    = tmp[8];
          exp_overflow = (~(a[7] ^ b[7])) & (exp_y[7] ^ a[7]);
        end

        3'b001: begin
          tmp          = {1'b0, a} + {1'b0, (~b)} + 9'd1;
          exp_y        = tmp[7:0];
          exp_carry    = tmp[8];
          exp_overflow = (a[7] ^ b[7]) & (exp_y[7] ^ a[7]);
        end

        3'b010: exp_y = a & b;
        3'b011: exp_y = a | b;
        3'b100: exp_y = a ^ b;
        3'b101: exp_y = ~a;
        3'b110: exp_y = a << 1;
        3'b111: exp_y = a >> 1;
      endcase

      exp_zero     = (exp_y == 8'h00);
      exp_negative = exp_y[7];

      #1;

      if (
        (y        !== exp_y)        ||
        (carry    !== exp_carry)    ||
        (overflow !== exp_overflow) ||
        (zero     !== exp_zero)     ||
        (negative !== exp_negative)
      ) begin

        if (errors < 20) begin
          $display(
            "FAIL op=%b a=%h b=%h | y=%h c=%b v=%b z=%b n=%b | expected y=%h c=%b v=%b z=%b n=%b",
            op, a, b,
            y, carry, overflow, zero, negative,
            exp_y, exp_carry, exp_overflow, exp_zero, exp_negative
          );
        end

        errors = errors + 1;
      end
    end
  endtask

  initial begin
    errors = 0;
    a      = 8'h00;
    b      = 8'h00;
    op     = 3'b000;

    // A few recognizable vectors appear at the beginning of the waveform.
    a = 8'h01; b = 8'h01; op = 3'b000; check_current;
    a = 8'h7F; b = 8'h01; op = 3'b000; check_current;
    a = 8'h00; b = 8'h01; op = 3'b001; check_current;
    a = 8'hAA; b = 8'h55; op = 3'b100; check_current;
    a = 8'h81; b = 8'h00; op = 3'b110; check_current;
    a = 8'h81; b = 8'h00; op = 3'b111; check_current;

    // Exhaustive verification.
    for (iop = 0; iop < 8; iop = iop + 1) begin
      for (ia = 0; ia < 256; ia = ia + 1) begin
        for (ib = 0; ib < 256; ib = ib + 1) begin
          op = iop[2:0];
          a  = ia[7:0];
          b  = ib[7:0];
          check_current;
        end
      end
    end

    if (errors == 0)
      $display("PASS: all 524288 exhaustive ALU vectors passed.");
    else
      $display("FAIL: %0d vectors failed.", errors);

    $finish;
  end

endmodule

2. Add the simulation source in Vivado

Under Simulation Sources:

  1. add sim/alu_tb.v
  2. set alu_tb as the simulation top
  3. keep alu_top as the synthesis top

The testbench intentionally instantiates alu_core directly so the combinational logic can be exhaustively checked without worrying about pipeline latency.

3. Run Behavioral Simulation

In Flow Navigator:

Simulation
→ Run Simulation
→ Run Behavioral Simulation

Run until the testbench reaches $finish.

You want to see:

PASS: all 524288 exhaustive ALU vectors passed.

4. Inspect the waveform

Zoom in near the beginning of the simulation.

Find at least:

  • one ADD
  • one SUB
  • one bitwise operation
  • one shift

Confirm that the waveform matches what you expect.

5. Save evidence

Save:

screenshots/simulation.png

The screenshot should show:

  • a
  • b
  • op
  • y
  • the four flags

Also save or screenshot the final PASS message.

Do not continue to synthesis with known simulation failures.

Results

Your project should now pass functional verification before implementation.

verification itemexpected result
Directed vectorspass
Exhaustive vectors524,288 pass
ADD/SUB flagspass
Waveform inspectedyes

Checklist

  • Added alu_tb.v
  • Set the correct simulation top
  • Behavioral simulation completed
  • All 524,288 exhaustive vectors passed
  • Saved a waveform screenshot
  • Continued to page 8

Continue to Synthesize and implement in Vivado.


Questions? Ask in the network Discord.

Synthesize and implement the ALU in Vivado

Now turn the verified RTL into an FPGA implementation. You will constrain the design, run synthesis, place and route it, and export the reports used for the final analysis.

Overview

Simulation answered:

Does the logic behave correctly?

Synthesis and implementation answer different questions:

What hardware did the tool build?
How many FPGA resources does it use?
Can it meet the requested clock?
What paths limit performance?
What power does Vivado estimate?

For this project, alu_top is the synthesis top.

The registered wrapper creates internal register-to-register timing paths through the ALU.

Prerequisites

Steps

1. Set the synthesis top

Under Sources:

right-click alu_top
→ Set as Top

Your design sources should contain:

adder8.v
alu_core.v
alu_top.v

Your testbench remains under Simulation Sources only.

2. Add a timing constraint

Create:

constr/alu.xdc

Start with a 100 MHz clock:

create_clock -name clk -period 10.000 [get_ports clk]

The period is in nanoseconds.

10 ns = 100 MHz

Add simple external interface assumptions:

set_input_delay  -clock clk 2.000 \
  [get_ports -filter {DIRECTION == IN && NAME != clk}]

set_output_delay -clock clk 2.000 \
  [get_ports -filter {DIRECTION == OUT}]

These are educational interface assumptions, not board-specific numbers.

If your team provides real board timing requirements, use those instead.

3. Run synthesis

In Flow Navigator:

Synthesis
→ Run Synthesis

When it finishes:

Open Synthesized Design

Inspect:

Schematic
Report Utilization

Look for:

  • LUTs
  • flip-flops
  • carry resources
  • whether the adder hierarchy is still recognizable

Save:

screenshots/synthesized_schematic.png

4. Run implementation

In Flow Navigator:

Implementation
→ Run Implementation

Then:

Open Implemented Design

Vivado will place and route the synthesized FPGA resources onto the target device.

You do not need to generate a bitstream for this assignment.

5. Create a reports folder

Make sure this exists:

reports/

If the Vivado working directory is not your repository root, use absolute file paths in the commands below.

6. Export utilization

In the Vivado Tcl Console:

report_utilization -file reports/utilization.rpt

7. Export timing

report_timing_summary -file reports/timing_summary.rpt

Also run:

check_timing -verbose -file reports/check_timing.rpt

8. Export power

With the implemented design open:

report_power -file reports/power.rpt

9. Export a DRC report

report_drc -file reports/drc.rpt

10. Save implementation evidence

Save screenshots of:

screenshots/implemented_device.png
screenshots/timing_summary.png
screenshots/power_summary.png

Your screenshots do not need to contain every number. The .rpt files are the actual source of the final metrics.

Results

After implementation, your repository should contain:

reports/
├── check_timing.rpt
├── drc.rpt
├── power.rpt
├── timing_summary.rpt
└── utilization.rpt

and:

screenshots/
├── simulation.png
├── synthesized_schematic.png
├── implemented_device.png
├── timing_summary.png
└── power_summary.png

Checklist

  • alu_top is synthesis top
  • Added the clock constraint
  • Synthesis completed
  • Inspected the synthesized schematic
  • Implementation completed
  • Exported utilization report
  • Exported timing report
  • Exported timing-check report
  • Exported power report
  • Exported DRC report
  • Saved implementation screenshots
  • Continued to page 9

Continue to Analyze and submit the design.


Questions? Ask in the network Discord.

Analyze and submit the ALU

The final step is to turn Vivado's reports into an engineering summary. Record area proxies, timing, and power, explain what limits the design, and submit the complete repository.

Overview

This page is intentionally PPA-style:

Power
Performance
Area

But remember what you implemented.

Vivado mapped your RTL to an FPGA, not to ASIC standard cells.

That means:

  • LUT count is an FPGA area proxy, not ASIC cell area
  • Vivado FPGA power is not ASIC power
  • FPGA routing and dedicated carry chains affect timing
  • the same RTL may behave very differently in an ASIC physical-design flow

The point is to learn how to read implementation reports and reason about hardware tradeoffs.

Prerequisites

Steps

1. Record the adder you chose

In your README:

Adder architecture: Ripple Carry

or:

Adder architecture: Carry Lookahead

or:

Adder architecture: Carry Select

2. Read the utilization report

Open:

reports/utilization.rpt

Record at least:

  • LUTs
  • flip-flops/registers
  • dedicated carry resources if present

Depending on the target device, the exact carry primitive name may differ.

Do not report the number of lines of Verilog as area.

3. Read the timing summary

Open:

reports/timing_summary.rpt

Record:

  • requested clock period
  • Worst Negative Slack, or WNS
  • Total Negative Slack, or TNS
  • the startpoint and endpoint of the worst setup path

Interpret WNS:

WNS >= 0  → requested setup timing is met
WNS < 0   → at least one setup path misses the constraint

Then inspect the worst path.

Ask:

  • Does it pass through the adder?
  • Does it pass through the final ALU output mux?
  • Which operation appears to dominate the path?
  • Did Vivado map the arithmetic into dedicated carry hardware?

4. Read the power report

Open:

reports/power.rpt

Record:

  • Total On-Chip Power
  • Dynamic Power
  • Device Static Power
  • power-analysis confidence level, if shown

Dynamic power is associated with switching activity.

Static power exists even when logic is not actively toggling.

For the base assignment, the normal post-route Vivado power report is enough.

5. Optional: improve power estimation with switching activity

For a more advanced result, generate a SAIF file from simulation and use that switching activity in the power report.

A typical Vivado Simulator flow uses commands such as:

open_saif alu.saif
log_saif [get_objects -r *]
run all
close_saif

Then, with the synthesized or implemented design open, read the activity file before generating power:

read_saif alu.saif
report_power -file reports/power_saif.rpt

Hierarchy names often differ between the testbench and implemented design. If Vivado reports poor SAIF matching, use the appropriate -strip_path when reading the file.

This section is optional unless your team specifically requires activity-based power analysis.

6. Check implementation health

Open:

reports/check_timing.rpt
reports/drc.rpt

Do not blindly ignore warnings.

For each serious warning or error, decide whether it is:

  • expected for this educational setup
  • caused by an incomplete constraint
  • caused by an RTL problem
  • caused by a project configuration problem

If the design has unresolved timing or DRC problems, mention them in the README.

7. Create the final results table

Put this in README.md:

## ASIC 101 ALU results

| metric | result |
|--------|-------:|
| Adder architecture | |
| Target FPGA | |
| Clock period | |
| LUTs | |
| Flip-flops | |
| Carry resources | |
| WNS | |
| TNS | |
| Total On-Chip Power | |
| Dynamic Power | |
| Device Static Power | |
| Power confidence | |

8. Write a short interpretation

Under the table, answer these questions in your own words:

  1. What adder architecture did you choose, and why?
  2. What is the critical timing path?
  3. Did the design meet the 100 MHz clock constraint?
  4. What resource appears most important to the arithmetic implementation?
  5. How much of the estimated power is dynamic versus static?
  6. What would you change if you wanted to optimize the design for speed?
  7. Why are these FPGA measurements not the same thing as ASIC PPA?

Keep this section short. A few sentences or bullets are enough.

9. Final repository structure

Your submission should look approximately like:

asic_101/
├── rtl/
│   ├── adder8.v
│   ├── alu_core.v
│   └── alu_top.v
├── sim/
│   └── alu_tb.v
├── constr/
│   └── alu.xdc
├── reports/
│   ├── check_timing.rpt
│   ├── drc.rpt
│   ├── power.rpt
│   ├── timing_summary.rpt
│   └── utilization.rpt
├── screenshots/
│   ├── simulation.png
│   ├── synthesized_schematic.png
│   ├── implemented_device.png
│   ├── timing_summary.png
│   └── power_summary.png
└── README.md

10. Push to GitHub

Before submitting:

git status
git add .
git commit -m "Complete ASIC 101 ALU"
git push

Make sure the reports and screenshots actually made it into the repository.

Results

A complete ASIC 101 submission demonstrates the entire introductory RTL-to-FPGA implementation loop:

specification
→ RTL
→ custom arithmetic architecture
→ exhaustive verification
→ synthesis
→ implementation
→ timing analysis
→ utilization analysis
→ power analysis
→ engineering interpretation

The next ASIC-specific step is to take verified RTL into a standard-cell physical-design flow and measure actual ASIC area, timing, and power.

Checklist

  • Recorded adder architecture
  • Recorded LUT and register utilization
  • Recorded carry resources
  • Recorded WNS and TNS
  • Inspected the critical path
  • Recorded total, dynamic, and static power
  • Checked timing warnings
  • Checked DRC warnings
  • Completed the README results table
  • Wrote the short engineering interpretation
  • Included reports
  • Included screenshots
  • Pushed the final repository

Questions? Ask in the network Discord.

Open-source ASIC flow: RTL to GDSII

This half of ASIC 101 takes the verified ALU from RTL all the way through an open-source ASIC physical-design flow. You will synthesize into real standard cells, create a die and core, build a power grid, place cells, build the clock tree, route metal, extract parasitics, run timing and physical verification, and inspect the final GDSII.

Overview

The flow in the first half of ASIC 101 used Vivado to implement the ALU on an FPGA.

This half targets an ASIC process.

The conceptual flow is:

RTL
 ↓
lint
 ↓
logic synthesis
 ↓
standard-cell netlist
 ↓
floorplan
 ↓
power distribution network
 ↓
placement
 ↓
clock tree synthesis
 ↓
global routing
 ↓
detailed routing
 ↓
parasitic extraction
 ↓
static timing analysis
 ↓
physical verification
 ↓
GDSII

The main tools are:

tooljob
LibreLaneorchestrates the complete RTL-to-GDS flow
YosysRTL synthesis and technology mapping
OpenROADfloorplan, placement, CTS, routing, STA, optimization
OpenRCXresistance/capacitance extraction
Magiclayout processing, extraction, DRC, stream-out
KLayoutlayout viewing, stream-out, DRC
NetgenLVS
Volareobtains compatible open-source PDK builds

Why does this say LibreLane instead of OpenLane?

OpenLane 2 was continued by its original authors as LibreLane. Current installations and commands use:

librelane

The architecture is still the OpenLane 2 lineage, and OpenROAD is still the main physical-design engine.

If you see tutorials using:

./flow.tcl

or:

openlane

check their date before copying commands.

What are we physically building?

We are hardening the alu_top design as a small digital macro.

The result contains:

  • a die boundary
  • a core area
  • rows of standard cells
  • combinational cells
  • flip-flops
  • clock buffers
  • tap and endcap cells
  • power rails and straps
  • signal routing
  • vias
  • filler cells
  • physical verification data
  • GDSII geometry

This is not automatically a complete packaged chip.

A standalone tapeout normally also needs top-level integration such as:

  • IO/pad cells
  • ESD structures
  • pad ring or bump planning
  • package connections
  • foundry-specific signoff requirements
  • shuttle-specific wrapper/integration requirements

Think of this project as creating a hardened digital block that could later be integrated into a larger chip.

Prerequisites

  • completed ASIC 101 ALU project
  • working Verilog for adder8, alu_core, and alu_top
  • Git
  • Linux, WSL2, or macOS
  • at least 8 GiB RAM; 16 GiB is strongly preferred
  • comfort using a terminal

Steps

  1. Keep your working RTL from the Vivado project.

  2. Create a new physical-design directory:

mkdir -p asic_101_gds
cd asic_101_gds

mkdir -p rtl
mkdir -p docs
mkdir -p screenshots
  1. Copy your RTL into:
asic_101_gds/
└── rtl/
    ├── adder8.v
    ├── alu_core.v
    └── alu_top.v
  1. Continue to install the open-source toolchain.

Results

At the end of this section you will have multiple views of the same design:

viewwhat it represents
RTL Verilogbehavioral hardware description
gate-level Verilogstandard-cell connectivity
LEFabstract physical macro view
DEFplaced/routed implementation data
ODBOpenROAD database
SDCtiming constraints
SPEFextracted parasitic RC
SDFannotated delays
Libertytiming/power models
SPICEtransistor/electrical netlist
GDSIIfinal mask-layout geometry

Checklist

  • Understand the complete RTL-to-GDS flow
  • Understand that this project is a hardened macro, not automatically a complete packaged chip
  • Created the new project directory
  • Copied the working ALU RTL
  • Continued to page 11

Questions? Ask in the network Discord.

Install LibreLane, OpenROAD, and the ASIC toolchain

Install the complete reproducible open-source ASIC environment. LibreLane bundles compatible versions of Yosys, OpenROAD, Magic, KLayout, Netgen, and the other tools used by the default flow.

Overview

Do not separately install random versions of every EDA tool unless you know exactly why you are doing it.

ASIC flows are sensitive to tool versions.

LibreLane provides a matched environment so:

LibreLane
Yosys
OpenROAD
Magic
KLayout
Netgen
OpenRCX
Volare

work together.

There are three common installation methods:

methodrecommendation
Nixbest/reproducible
AppImageeasiest on Linux/WSL
Dockerfallback

For the network, Nix is the default path.

AppImage is a good fallback if Nix gives you trouble.

Prerequisites

Steps

1. Windows users: install WSL2

Open PowerShell as Administrator:

wsl --install -d Ubuntu

Restart if Windows asks you to.

Then check:

wsl --list --verbose

You want Ubuntu to show:

VERSION
2

LibreLane requires WSL2, not WSL1.

Launch Ubuntu from the Start menu.

From this point onward, run Linux commands inside Ubuntu/WSL, not PowerShell.

2. Linux and WSL users: install basic tools

sudo apt-get update
sudo apt-get install -y curl git

3. Install Nix

Do not install Nix with apt.

Use the current Nix installer:

curl --proto '=https' --tlsv1.2 -fsSL \
  https://artifacts.nixos.org/nix-installer | \
  sh -s -- install --no-confirm --extra-conf "
extra-substituters = https://nix-cache.fossi-foundation.org
extra-trusted-public-keys = nix-cache.fossi-foundation.org:3+K59iFwXqKsL7BNu6Guy0v+uTlwsxYQxjspXzqLYQs=
extra-experimental-features = nix-command flakes
"

Close the terminal completely and open it again.

Why the binary cache?

Without it, Nix may build large EDA tools from source.

The cache lets you download reproducible pre-built tool binaries instead.

4. Clone LibreLane

cd ~
git clone https://github.com/librelane/librelane

Enter the repository:

cd ~/librelane

5. Enter the EDA environment

nix-shell

Your shell prompt should indicate that you are inside a Nix shell.

Every ASIC command in later pages assumes you are inside this environment.

If you leave the shell, enter it again with:

cd ~/librelane
nix-shell

6. Run the smoke test

librelane --smoke-test

The first run may also obtain the supported PDK through Volare.

The smoke test must finish successfully before continuing.

7. Confirm the important tools exist

Run:

librelane --version
yosys -V
openroad -version
klayout -v
magic --version
netgen -batch <<<'quit'

Exact version strings will change over time.

What matters is that the commands execute inside the LibreLane environment.

8. Optional fallback: AppImage

On supported Linux systems:

sudo apt-get update
sudo apt-get install -y \
  build-essential python3 python3-venv python3-pip \
  python3-tk curl make git

Download the matching LibreLane devshell AppImage from the current LibreLane release page.

Most x86-64 machines use:

librelane-devshell-x86_64.AppImage

Then:

chmod a+x ~/librelane-devshell-$(uname -m).AppImage
~/librelane-devshell-$(uname -m).AppImage

Test it:

librelane --smoke-test

Do not install both methods just because both exist. Pick one working environment.

9. Run the built-in example

Create a scratch folder:

mkdir -p ~/asic_examples
cd ~/asic_examples

Run:

librelane --run-example spm

If the example reaches the end successfully, your machine has completed a real RTL-to-GDS flow.

10. Open the example layout

Inside the folder containing the copied example configuration:

librelane --last-run --flow OpenInKLayout config.json

You should see physical chip geometry rather than RTL source code.

Results

A working installation should provide:

librelane
yosys
openroad
klayout
magic
netgen

and a working Sky130 PDK managed by Volare.

Official documentation:

Checklist

  • WSL2/Linux/macOS environment works
  • Nix or AppImage environment works
  • librelane --smoke-test passes
  • Yosys runs
  • OpenROAD runs
  • KLayout opens
  • Built-in example finishes
  • Opened an example layout
  • Continued to page 12

Questions? Ask in the network Discord.

Understand the PDK and standard-cell library

Before running the ALU, understand what a PDK actually gives the tools. The RTL is process-independent; the PDK is what turns that logic into geometry and electrical models for a real manufacturing process.

Overview

A PDK, or Process Design Kit, is the interface between chip designers and a semiconductor manufacturing process.

For this tutorial we use:

sky130A

with the default high-density standard-cell library:

sky130_fd_sc_hd

Sky130A contains five main metal routing layers plus local interconnect.

RTL does not contain transistor geometry

This Verilog:

assign y = a & b;

does not tell a foundry:

where to draw diffusion
where to draw polysilicon
how wide metal should be
what spacing is legal
how fast the gate is
how much capacitance it presents

The PDK and standard-cell library provide those facts.

Standard cells

A standard cell is a pre-designed physical implementation of a small logic function.

Examples include:

inverter
NAND
NOR
AND
OR
XOR
multiplexer
buffer
flip-flop
clock buffer
tie cell
tap cell
filler cell

A synthesized ASIC is mostly a large number of these cells placed in rows and connected with metal.

Different views of one cell

The same cell can have several representations.

file/viewcontains
.lib Libertydelay, slew, capacitance, power, timing arcs
LEFabstract size, pins, routing blockages
GDSfull physical geometry
SPICEtransistor-level electrical representation
Verilogfunctional model

The tool uses the cheapest useful view for each task.

For example:

  • synthesis needs logic/timing information
  • placement needs cell dimensions
  • routing needs pins and obstructions
  • stream-out needs full GDS geometry
  • LVS needs connectivity/electrical information

FEOL and BEOL

FEOL, front end of line, creates devices such as transistors.

BEOL, back end of line, creates the interconnect stack above those devices.

A routed digital block contains many BEOL shapes:

metal wires
vias
power straps
clock routes
signal routes

Prerequisites

Steps

1. Find your PDK root

LibreLane/Volare normally manages the PDK under your home directory.

Try:

echo "${PDK_ROOT:-$HOME/.volare}"

You can also inspect:

ls ~/.volare

Do not modify PDK files for this tutorial.

2. Understand sky130A

sky130A is the fully qualified PDK variant name.

Use:

sky130A

not:

sky130

The variant matters because the backend metal stack and extracted interconnect behavior are part of the process definition.

3. Understand the standard-cell library name

The default Sky130 standard-cell library used by the flow is:

sky130_fd_sc_hd

Break the name apart conceptually:

sky130
fd
sc
hd

The important part for this class is that hd is a high-density digital standard-cell library.

4. Look at cell names after synthesis

Later you will see names similar to:

sky130_fd_sc_hd__and2_1
sky130_fd_sc_hd__mux2_1
sky130_fd_sc_hd__dfxtp_1
sky130_fd_sc_hd__buf_2

The suffix often represents a drive-strength variant.

A stronger cell can drive more load or improve slew, but usually consumes more area and power.

This is one of the basic physical-design tradeoffs:

stronger drive
→ possibly faster
→ usually larger
→ usually more power/capacitance

5. Understand PVT corners

Real silicon is not one perfect device.

Timing changes with:

Process
Voltage
Temperature

Together these are often called PVT conditions.

Physical interconnect also has corners, so LibreLane's reports may use fully qualified interconnect/process/voltage/temperature corners.

Do not report only the best corner and pretend it represents every chip.

6. Know what the PDK controls

The PDK provides or constrains things such as:

  • legal metal layers
  • routing directions
  • widths
  • spacings
  • via definitions
  • design rules
  • standard-cell dimensions
  • timing models
  • power models
  • RC extraction information
  • IO routing layers
  • well tap cells
  • endcap cells
  • filler and decap cells

The PDK is why a layout for one process cannot simply be fabricated in another process.

Results

You should now be able to explain this sentence:

Yosys maps the ALU into the logic cells available in the selected standard-cell library, and OpenROAD physically places and connects those cells using the geometry, routing, timing, and extraction information supplied by the PDK.

Checklist

  • Know what a PDK is
  • Know what a standard cell is
  • Know the difference between Liberty, LEF, GDS, SPICE, and Verilog cell views
  • Know the difference between FEOL and BEOL
  • Know what PVT means
  • Continued to page 13

Questions? Ask in the network Discord.

Configure and run the ALU flow

Create the LibreLane design configuration and run a complete baseline RTL-to-GDS implementation before tuning individual stages.

Overview

LibreLane is a flow orchestrator.

Instead of manually invoking every program, you provide:

RTL
constraints
PDK choice
physical-design settings

LibreLane creates a sequence of steps and passes the design state from one tool to the next.

A configuration file is not HDL.

It describes how the EDA flow should implement the HDL.

Prerequisites

  • PDK and standard cells
  • working adder8.v
  • working alu_core.v
  • working alu_top.v
  • inside the LibreLane environment

Steps

1. Prepare the project

Your folder should look like:

asic_101_gds/
├── rtl/
│   ├── adder8.v
│   ├── alu_core.v
│   └── alu_top.v
├── screenshots/
└── config.json

2. Create config.json

Start with:

{
  "DESIGN_NAME": "alu_top",

  "VERILOG_FILES": [
    "dir::rtl/adder8.v",
    "dir::rtl/alu_core.v",
    "dir::rtl/alu_top.v"
  ],

  "CLOCK_PORT": "clk",
  "CLOCK_PERIOD": 10.0,

  "PDK": "sky130A",
  "STD_CELL_LIBRARY": "sky130_fd_sc_hd",

  "FP_SIZING": "absolute",
  "DIE_AREA": [0, 0, 150, 150],
  "CORE_AREA": [10, 10, 140, 140],

  "FP_CORE_UTIL": 35,
  "PL_TARGET_DENSITY_PCT": 45
}

3. Understand every field

DESIGN_NAME

alu_top

must match the top-level Verilog module.

VERILOG_FILES

tells synthesis which RTL files belong to the design.

CLOCK_PORT

identifies the top-level clock port.

CLOCK_PERIOD

is in nanoseconds.

10 ns = 100 MHz

The period is a constraint, not a promise.

The flow tries to produce a physical implementation that satisfies it.

PDK

selects the manufacturing-process configuration.

STD_CELL_LIBRARY

selects the standard-cell library.

FP_SIZING

set to absolute means we are explicitly choosing physical dimensions.

DIE_AREA

is the outer physical block boundary:

x0 y0 x1 y1

in micrometers.

CORE_AREA

is the region inside the die where standard-cell rows are created.

Our starting geometry is intentionally roomy because the ALU is tiny and we want enough space to clearly inspect the PDN and routing.

FP_CORE_UTIL

is still useful as an educational reference for utilization-oriented experiments, although explicit die/core geometry fixes the available physical region.

PL_TARGET_DENSITY_PCT

controls the target cell-placement density.

Do not optimize these numbers yet.

First make a baseline run.

4. Run the full flow

From the project directory:

librelane config.json

The default flow is Classic.

This is equivalent to explicitly writing:

librelane --flow Classic config.json

5. Watch the step names

You should see steps corresponding to stages such as:

Verilator lint
Yosys synthesis
pre-PNR STA
floorplan
tap/endcap insertion
PDN generation
global placement
IO placement
detailed placement
CTS
global routing
antenna checking/repair
detailed routing
RC extraction
post-PNR STA
IR-drop reporting
GDS stream-out
DRC
LVS
manufacturability checks

The exact numbering can change between releases.

The step names matter more than the numeric prefixes.

6. Find the run directory

After the run:

ls runs

A run directory will contain individual step folders.

A typical run contains:

runs/<run-tag>/
├── 01-...
├── 02-...
├── ...
├── final/
├── error.log
├── info.log
├── warning.log
└── resolved.json

7. Find the final views

find runs -path "*/final/*" -maxdepth 4 -type f | head -50

The final directory may contain:

def/
gds/
lef/
lib/
nl/
odb/
pnl/
sdc/
sdf/
spef/
spice/
metrics.csv
metrics.json

8. Open the final layout in KLayout

librelane --last-run --flow OpenInKLayout config.json

9. Open it in OpenROAD

librelane --last-run --flow OpenInOpenROAD config.json

KLayout is excellent for viewing final geometric layers.

OpenROAD is better for understanding the physical-design database, timing paths, cells, nets, congestion, and routing.

10. Save a baseline screenshot

Save:

screenshots/baseline_gds.png

Do not worry if it looks mostly like colored rectangles right now.

The next pages explain what every major structure is.

Results

You should now have your first ASIC implementation of the ALU.

Do not call the project finished merely because a .gds file exists.

You still need to understand:

  • what synthesis built
  • what the floorplan means
  • how power is delivered
  • why cells are where they are
  • how the clock is distributed
  • where routing congestion appears
  • whether timing closes
  • whether DRC/LVS/signoff checks pass

Checklist

  • Created config.json
  • Understand every configuration field
  • Full flow completed
  • Located the run directory
  • Located final GDS
  • Opened KLayout
  • Opened OpenROAD
  • Saved baseline screenshot
  • Continued to page 14

Questions? Ask in the network Discord.

Synthesis: turn RTL into standard cells

Synthesis converts the behavioral RTL into a gate-level network and maps that network onto cells from the Sky130 standard-cell library.

Overview

Start with RTL:

always @(posedge clk) begin
  a_q <= a;
end

After synthesis, the design contains an actual library flip-flop cell.

Start with:

assign y = a ^ b;

After synthesis, the logic may become:

  • XOR cells
  • NAND/NOR combinations
  • AOI/OAI cells
  • mux cells
  • some other equivalent network

Synthesis is allowed to transform logic as long as the resulting circuit is logically equivalent under the design constraints.

Three conceptual synthesis phases

RTL elaboration
→ generic Boolean/sequential network
→ technology mapping

Why your adder source may not survive literally

You chose an architecture such as:

Ripple Carry
Carry Lookahead
Carry Select

That architecture expresses your RTL intent.

Yosys and its technology-mapping passes may:

  • flatten hierarchy
  • propagate constants
  • simplify Boolean expressions
  • remove redundant logic
  • remap functions
  • resize/restructure logic later in PNR

Therefore:

compare the implemented results, not just the number of operators you typed.

Prerequisites

Steps

1. Locate the synthesis step

Find it without relying on a hard-coded step number:

RUN=$(ls -dt runs/* | head -1)
find "$RUN" -maxdepth 1 -type d -name '*yosys-synthesis*'

Store the directory:

SYNTH_DIR=$(find "$RUN" -maxdepth 1 -type d -name '*yosys-synthesis*' | head -1)
echo "$SYNTH_DIR"

2. Inspect synthesis output files

find "$SYNTH_DIR" -maxdepth 1 -type f -printf '%f\n' | sort

Look for:

log files
netlists
reports
state_out.json

3. Search the mapped netlist for Sky130 cells

grep -R "sky130_fd_sc_hd__" "$SYNTH_DIR" | head -40

You should see standard-cell instance names.

4. Count cell-name occurrences

This is only a rough text-level exploration, not the authoritative area report:

grep -Rho "sky130_fd_sc_hd__[A-Za-z0-9_]*" "$SYNTH_DIR" \
  | sort \
  | uniq -c \
  | sort -nr \
  | head -30

Later OpenROAD/metrics reports provide more reliable physical counts and area.

5. Find the synthesis statistics

Search:

grep -RniE "area|cells|wires|ABC|stat" "$SYNTH_DIR" | head -80

Look at the Yosys log and identify:

  • number of cells
  • cell types
  • sequential elements
  • combinational elements
  • area estimate if reported

6. Compare RTL and netlist

Ask:

Can I still recognize the adder hierarchy?
Did synthesis flatten it?
What cell implements the input/output registers?
Are there explicit XOR cells?
Are there mux cells?
Were some operations combined?

7. Understand the clock before CTS

At this stage the design has clocked cells, but the physical clock tree has not been built yet.

Synthesis knows:

these flip-flops are driven by clk

It does not yet know the final physical clock-buffer locations and routed clock wires.

8. Understand area at this stage

Synthesis area is mainly:

sum of standard-cell areas

It is not final die area.

Final physical area also needs:

  • whitespace
  • placement rows
  • tap/endcap cells
  • clock buffers
  • routing resources
  • PDN
  • physical margins
  • possibly decap/filler cells

9. Save evidence

Save a short text excerpt or screenshot showing mapped Sky130 cells:

screenshots/synthesis_cells.png

Results

You should now understand the boundary:

RTL describes function
synthesis chooses a gate-level implementation
physical design assigns real positions and wires

Checklist

  • Located the Yosys synthesis step
  • Found a mapped netlist
  • Found Sky130 standard-cell names
  • Identified flip-flop cells
  • Inspected synthesis statistics
  • Understand why RTL architecture and final physical implementation may differ
  • Continued to page 15

Questions? Ask in the network Discord.

Floorplanning: die, core, rows, pins, taps, and endcaps

Floorplanning creates the physical canvas on which the design will be built. This is where abstract logic first receives a real physical boundary.

Overview

Two rectangles matter immediately:

+----------------------------------+
|              DIE                 |
|                                  |
|   +--------------------------+   |
|   |          CORE            |   |
|   |                          |   |
|   |  standard-cell rows      |   |
|   |                          |   |
|   +--------------------------+   |
|                                  |
+----------------------------------+

Die area

The die area is the outer boundary of the block being hardened.

In this project:

"DIE_AREA": [0, 0, 150, 150]

means approximately:

150 µm × 150 µm

for the block boundary.

Core area

The core area is the inner region where standard-cell rows are created.

"CORE_AREA": [10, 10, 140, 140]

creates margins around the core.

Why not fill the entire die with cells?

Physical design needs room for:

  • routing
  • power distribution
  • clock buffers
  • timing-fix buffers
  • legal placement movement
  • congestion relief
  • physical-only cells

A design with no whitespace can become impossible to route or impossible to fix.

Placement sites and rows

Standard cells are not placed at arbitrary coordinates.

They sit on legal sites arranged into rows.

Cells are designed to align so neighboring cells can share power rails and follow the library's placement geometry.

Tap cells

CMOS wells/substrate regions must be tied to the correct supply potentials.

Tap cells provide legal well/substrate connections at required intervals.

They are physical infrastructure, not part of your Boolean function.

Endcap cells

Endcaps protect/legalize the ends of standard-cell rows according to library/process requirements.

Again, they are physical-only cells.

Prerequisites

Steps

1. Locate the floorplan state

RUN=$(ls -dt runs/* | head -1)

FP_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*openroad-floorplan*' | head -1)

echo "$FP_DIR"

2. Open the floorplan in OpenROAD

librelane \
  --with-initial-state "$FP_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

3. Identify the die boundary

In the GUI, find the outer block rectangle.

This is not a decorative border.

It is the physical boundary used by the implementation.

4. Identify the core

Look inside the die for the region containing placement rows.

Ask:

How much margin exists between the core and die?
Why might routing or PDN need that margin?

5. Inspect rows

Zoom in until you can see the repeated standard-cell row structure.

Rows generally alternate orientation so adjacent rows can share power rails correctly.

6. Find the tap/endcap stage

TAP_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*tapendcapinsertion*' | head -1)

echo "$TAP_DIR"

Open it:

librelane \
  --with-initial-state "$TAP_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

Now compare this with the raw floorplan.

Look for physical-only cells added to the rows.

7. Understand utilization

Core utilization is conceptually:

standard-cell area
------------------ × 100%
usable core area

Higher utilization means:

more cells packed into less area

That can improve compactness, but can also cause:

routing congestion
poor timing
insufficient room for buffers
harder legalization

Lower utilization usually means more whitespace and a larger core.

8. Understand aspect ratio

An aspect ratio near:

1.0

produces a roughly square core.

A rectangular core may be useful for:

  • interface geometry
  • macro placement
  • top-level integration
  • routing structure
  • package constraints

There is no universal ideal shape.

9. Measure dimensions

Record:

die width
die height
core width
core height

Calculate:

die area  = width × height
core area = width × height

Use µm and µm².

10. Save screenshots

Save:

screenshots/floorplan.png
screenshots/tap_endcap.png

Results

Record:

floorplan metricvalue
Die width
Die height
Die area
Core width
Core height
Core area
Aspect ratio
Target utilization/density

Checklist

  • Can identify die boundary
  • Can identify core boundary
  • Can identify placement rows
  • Understand placement sites
  • Understand tap cells
  • Understand endcap cells
  • Understand utilization
  • Recorded dimensions
  • Continued to page 16

Questions? Ask in the network Discord.

Power distribution: VDD, ground, rails, straps, and IR drop

The power distribution network, or PDN, delivers current from the block's power connections to every standard cell.

Overview

Logic gates cannot function without physical power.

A chip does not receive ideal 1 and 0 values.

It receives electrical supply networks:

VDD / VPWR
ground / VGND

The PDN often has a hierarchy:

upper metal straps
      ↓
lower-level power distribution
      ↓
standard-cell rails
      ↓
transistor source/body connections

Signal routing and power routing are different jobs

Signal routing connects logic nets:

adder carry
mux select
result bit
clock

Power routing distributes current to a huge number of cells.

A PDN needs:

  • enough metal width
  • enough connections
  • appropriate pitch
  • adequate via connections
  • low enough resistance
  • acceptable voltage drop

IR drop

Any real conductor has resistance.

Voltage drop is approximately:

V = I × R

If a region draws current through too much resistance, the local supply voltage falls.

That can:

  • slow cells
  • worsen timing
  • reduce noise margin
  • cause functional failure in severe cases

Prerequisites

Steps

1. Find the PDN generation stage

RUN=$(ls -dt runs/* | head -1)

PDN_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*generatepdn*' | head -1)

echo "$PDN_DIR"

2. Open the design after PDN generation

librelane \
  --with-initial-state "$PDN_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

3. Hide signal layers selectively

Use the OpenROAD GUI layer controls.

Toggle metal layers on and off.

Find the repetitive VDD/ground structures.

Zoom in enough to distinguish:

power rails
power straps
vias

4. Follow one power path conceptually

Pick a standard-cell row and answer:

How does this row reach VDD?
How does it reach ground?
Which metal layers carry the larger PDN structures?
Where are vias used to change layers?

5. Understand vias

A wire on one metal layer does not automatically connect to a crossing wire on another layer.

A via is required for an electrical connection between layers.

In dense current paths, multiple vias may be used to reduce resistance and improve reliability.

6. Understand why upper metal is useful

Higher metal layers are often better suited to long-distance distribution because the process may provide different width/pitch/resistance options on those layers.

The exact layer usage is PDK- and flow-dependent.

7. Find the IR-drop report

The default Classic flow includes an OpenROAD IR-drop reporting step when enabled.

Find it:

find "$RUN" -maxdepth 1 -type d -iname '*irdrop*'

Inspect files:

IR_DIR=$(find "$RUN" -maxdepth 1 -type d -iname '*irdrop*' | head -1)
find "$IR_DIR" -maxdepth 2 -type f -printf '%p\n' | sort

Search reports:

grep -RniE "drop|voltage|worst|VDD|VPWR|VGND" "$IR_DIR" | head -100

8. Be careful interpreting tiny-design power

Our ALU is extremely small.

Its current profile is not representative of a CPU or large accelerator.

The goal here is to understand:

the analysis
the physical structure
the meaning of voltage drop

not to claim this block has solved full-chip power integrity.

9. Save screenshots

Save:

screenshots/pdn.png
screenshots/ir_drop.png

If the GUI provides an IR-drop heatmap for the loaded state, use it.

Results

Record:

PDN itemobservation
Main visible power layers
Standard-cell rail direction
Strap direction
Worst reported voltage drop
Any PDN warnings

Checklist

  • Can identify VDD/ground structures
  • Know what a via does
  • Know why PDN is not ordinary signal routing
  • Understand IR drop
  • Found the IR-drop report
  • Saved PDN evidence
  • Continued to page 17

Questions? Ask in the network Discord.

Placement: where the standard cells physically go

Placement assigns physical coordinates to the synthesized standard cells while trying to satisfy wirelength, density, routability, and timing goals.

Overview

Before placement, the netlist says:

cell A connects to cell B
cell B connects to cell C

but it does not say:

cell A is at x=43.2 µm, y=71.4 µm

Placement creates those coordinates.

Global placement

Global placement finds good approximate locations.

Cells may not yet be perfectly legal on placement sites.

It tries to optimize objectives such as:

wirelength
density
routability
sometimes timing

Detailed placement

Detailed placement legalizes cells:

inside legal rows
on legal sites
without illegal overlaps

while trying not to destroy the global-placement solution.

Why placement affects timing

Wire delay depends on physical distance and load.

A net that was "just a wire" in RTL may become:

a long RC interconnect

in silicon.

Moving connected cells closer can reduce wire delay and capacitance.

Why placement affects routing

If too many nets need the same region:

routing demand > routing capacity

and congestion appears.

Prerequisites

Steps

1. Find global placement

RUN=$(ls -dt runs/* | head -1)

GPL_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*openroad-globalplacement' | tail -1)

echo "$GPL_DIR"

There may be an earlier globalplacementskipio stage.

For this page use the later main global-placement state when available.

2. Open global placement in OpenROAD

librelane \
  --with-initial-state "$GPL_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

3. Identify cell clusters

Zoom in.

Try to distinguish:

flip-flops
combinational cells
buffers
physical-only cells

Use instance selection/properties in the GUI.

4. Find detailed placement

DPL_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*detailedplacement*' | head -1)

echo "$DPL_DIR"

Open it:

librelane \
  --with-initial-state "$DPL_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

5. Compare global vs detailed placement

Look for:

  • cells snapped to rows
  • overlap removal
  • local movement
  • row alignment

6. Open heatmaps

In OpenROAD GUI, inspect available heatmaps such as:

placement density
routing congestion
power/IR-drop views if available for the state

A heatmap converts a huge physical dataset into spatial information.

For congestion:

hot region
= lots of routing demand relative to capacity

7. Understand density

If placement is too dense:

cells compete for routing access
buffers have nowhere to go
routing detours increase
timing can worsen

If placement is too sparse:

die/core becomes larger
wirelength can grow
area efficiency decreases

The goal is not maximum density.

The goal is a design that closes:

timing
routing
power
physical verification

at acceptable area.

8. Inspect optimization cells

Physical design may insert or resize cells that were not obvious in the original RTL:

buffers
stronger/slower drive variants
timing repair cells

This is normal.

The physical netlist evolves during implementation.

9. Save screenshots

Save:

screenshots/global_placement.png
screenshots/detailed_placement.png
screenshots/congestion_heatmap.png

Results

Record:

placement itemobservation
Placement density
Visible whitespace
Congestion hotspots
Added buffers visible
Legalized rowsyes/no

Checklist

  • Understand global placement
  • Understand detailed placement
  • Can see legal standard-cell rows
  • Can explain why density is not simply "higher is better"
  • Inspected congestion
  • Saved placement screenshots
  • Continued to page 18

Questions? Ask in the network Discord.

Clock tree synthesis: build the physical clock network

Clock Tree Synthesis, or CTS, turns the logical clock connection into a physical network designed to reach every sequential element with controlled delay and skew.

Overview

Before CTS, the netlist conceptually says:

clk → every flip-flop

A single ideal driver cannot physically drive a large chip.

Real clock routing has:

wire resistance
wire capacitance
sink capacitance
buffer delay
different path lengths

CTS inserts a tree of clock buffers.

Conceptually:

             clk
              |
          clock buffer
          /          \
      buffer        buffer
      /   \          /   \
    FF    FF       FF    FF

Clock latency

Clock latency is the time required for the clock edge to travel from its source to a sink.

Clock skew

Clock skew is the difference in clock arrival time between sinks.

If:

FF_A clock arrives at 1.0 ns
FF_B clock arrives at 1.2 ns

then the difference is:

0.2 ns

Skew affects setup and hold timing.

Why clocks receive special treatment

The clock controls when state changes.

Clock quality affects essentially every register-to-register timing path in the block.

Prerequisites

Steps

1. Find the CTS step

RUN=$(ls -dt runs/* | head -1)

CTS_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*openroad-cts*' | head -1)

echo "$CTS_DIR"

2. Open the post-CTS design

librelane \
  --with-initial-state "$CTS_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

3. Highlight the clock net

Use OpenROAD's GUI to select or search for:

clk

Trace the network.

Look for clock buffers added by CTS.

4. Compare pre-CTS and post-CTS cell counts

Compare an earlier placement state with the CTS state.

CTS normally increases the number of cells because it inserts clock-tree elements.

5. Find clock reports

Search the CTS and later STA directories:

grep -RniE "skew|latency|clock" "$CTS_DIR" | head -100

Later multi-corner STA reports may provide more complete clock information.

6. Understand insertion delay

The clock at a register is not an ideal zero-delay event.

The tree contributes real delay.

This is why post-CTS timing is more physically realistic than pre-CTS timing.

7. Setup intuition

For a simplified register-to-register path:

launch FF
→ combinational logic
→ capture FF

the data must arrive early enough before the capture clock edge.

A setup violation means the data path is too slow for the required cycle after accounting for clock timing and constraints.

8. Hold intuition

Data must not change too soon after the capture clock edge.

A hold violation is dangerous because simply lowering clock frequency does not automatically fix it.

Hold is about minimum delay, not maximum cycle time.

9. Save evidence

Save:

screenshots/clock_tree.png

Try to make the highlighted clock network visible.

Results

Record:

CTS itemvalue/observation
Clock period
Clock buffers inserted
Reported skew
Clock latency/insertion delay
Post-CTS setup status
Post-CTS hold status

Checklist

  • Understand CTS
  • Understand clock latency
  • Understand clock skew
  • Can visually identify the clock network
  • Understand setup vs hold at a high level
  • Saved clock-tree screenshot
  • Continued to page 19

Questions? Ask in the network Discord.

Routing: turn nets into metal and vias

Routing creates the physical metal shapes that electrically connect the placed cells.

Overview

Placement gives each pin a location.

Routing must connect pins through legal metal tracks while obeying:

minimum width
minimum spacing
via rules
routing-layer rules
obstructions
capacity
antenna constraints

Global routing

Global routing decides approximate paths and routing regions.

Think:

which corridors and layers should this net use?

It estimates congestion and creates routing guides.

Detailed routing

Detailed routing assigns actual legal tracks, segments, and vias.

Think:

exactly which metal shape goes where?

Preferred routing directions

Metal layers often have preferred horizontal or vertical routing directions.

Alternating directions makes multi-layer routing manageable.

Do not assume every wire stays on one layer.

Vias

Whenever a routed connection changes metal layers, a via provides the vertical electrical connection.

Congestion

Congestion occurs when too many nets compete for limited routing resources.

The router may respond by:

  • detouring
  • changing layers
  • moving through less congested regions

Long detours add wirelength and parasitic RC.

Prerequisites

Steps

1. Find global routing

RUN=$(ls -dt runs/* | head -1)

GRT_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*globalrouting*' | head -1)

echo "$GRT_DIR"

2. Open global-routing state

librelane \
  --with-initial-state "$GRT_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

Inspect congestion/route guides if available in the GUI.

3. Find detailed routing

DRT_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*detailedrouting*' | head -1)

echo "$DRT_DIR"

Open it:

librelane \
  --with-initial-state "$DRT_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

4. Toggle metal layers

Turn layers on and off individually.

Observe that:

  • one layer tends to carry one direction
  • another carries the other direction
  • vias connect them

5. Follow one signal

Select a net such as one output bit or an internal arithmetic net.

Trace it across:

driver pin
wire segment
via
another metal layer
sink pin

6. Inspect the clock route

Compare the clock network with ordinary signal nets.

The clock may use different routing behavior or layer constraints than general signals.

7. Check total wirelength

The Classic flow includes wirelength reporting.

Search:

find "$RUN" -maxdepth 1 -type d -iname '*wirelength*'

and:

grep -RniE "wire|length" "$RUN"/*wirelength* 2>/dev/null | head -80

8. Understand antenna violations

During fabrication, long unconnected metal structures can accumulate charge during plasma processing.

That charge can damage thin transistor gate oxides.

This is the antenna effect.

The flow checks antenna properties and may repair violations using methods such as:

  • routing changes
  • antenna diodes

Antenna rules are manufacturing rules, not logical RTL rules.

9. Inspect detailed-routing DRC

Detailed routing also checks routing-rule violations.

Search:

grep -RniE "violation|drc|error" "$DRT_DIR" | head -100

10. Save screenshots

Save:

screenshots/global_routing.png
screenshots/detailed_routing.png
screenshots/metal_layers.png

Results

Record:

routing itemvalue/observation
Total wirelength
Routing congestion
Detailed-route violations
Antenna violations before repair
Antenna violations after repair
Lowest signal routing layer
Highest signal routing layer

Checklist

  • Understand global routing
  • Understand detailed routing
  • Can identify metal wires
  • Can identify vias
  • Inspected multiple metal layers
  • Understand congestion
  • Understand antenna effect
  • Continued to page 20

Questions? Ask in the network Discord.

Parasitics and static timing analysis

After routing, the wires are no longer abstract connections. Their physical geometry creates resistance and capacitance that must be extracted and included in timing analysis.

Overview

An RTL wire looks ideal:

wire carry;

A silicon interconnect behaves more like a distributed electrical network containing:

resistance
capacitance
coupling
driver resistance
receiver capacitance

Longer wires generally mean more parasitic effects.

RC extraction

OpenRCX extracts physical interconnect parasitics from the routed design.

These may be written into:

SPEF

files.

SPEF stands for Standard Parasitic Exchange Format.

Static Timing Analysis

STA analyzes timing mathematically without applying every possible simulation vector.

For each timing path it uses:

cell delays
wire parasitics
clock timing
constraints
slew
load
PVT corner

to calculate arrival and required times.

Slack

Simplified:

slack = required arrival time - actual arrival time

For setup:

positive slack = passes
zero slack     = exactly at limit
negative slack = violation

Prerequisites

Steps

1. Find RC extraction

RUN=$(ls -dt runs/* | head -1)

RCX_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*openroad-rcx*' | head -1)

echo "$RCX_DIR"

Inspect output files:

find "$RCX_DIR" -maxdepth 2 -type f -printf '%p\n' | sort

2. Find SPEF

find "$RUN" -type f -iname '*.spef' | head -20

Do not try to manually understand an entire SPEF file.

Open the beginning:

SPEF=$(find "$RUN" -type f -iname '*.spef' | head -1)
head -80 "$SPEF"

Notice:

nets
capacitances
resistances
connections

3. Find post-PNR STA

STA_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*stapostpnr*' | head -1)

echo "$STA_DIR"

List reports:

find "$STA_DIR" -type f -printf '%p\n' | sort

4. Open the timing summary

Look for:

summary.rpt

For example:

cat "$STA_DIR/summary.rpt"

Record:

  • worst setup slack
  • worst hold slack
  • total negative setup slack
  • total negative hold slack if reported
  • violating endpoints
  • corner

5. Inspect the worst setup path

Search the corner reports:

grep -Rni "slack" "$STA_DIR" | head -100

Open the report containing the worst max/setup timing path.

Identify:

launch register
logic cells
net delays
capture register
clock arrival information
final slack

6. Inspect the worst hold path

Find the min/hold report.

Notice that the worst hold path may be very short.

That is expected.

Hold analysis asks whether data changes too early.

7. Understand cell delay vs net delay

A timing path is not just logic gates.

It contains:

cell delay + interconnect delay

After route, net delay can become a major part of the critical path.

This is one reason post-route STA is more meaningful than an RTL-level timing guess.

8. Understand timing corners

A design should be checked across the PVT/interconnect corners configured by the PDK.

Different corners can dominate:

setup
hold
slew
power

Do not assume the same corner is worst for everything.

9. Open timing paths graphically

Open final OpenROAD:

librelane --last-run --flow OpenInOpenROAD config.json

Use the timing-path viewer to inspect the worst path spatially.

Ask:

Is it physically long?
Does it cross the ALU?
Is most delay cell delay or net delay?
Does it contain buffering?

10. Save evidence

Save:

screenshots/worst_setup_path.png
screenshots/worst_hold_path.png

Results

Record:

timing metricresult
Clock period
Worst setup slack
Total negative setup slack
Worst hold slack
Setup-violating endpoints
Hold-violating endpoints
Worst setup corner
Worst hold corner
Critical path startpoint
Critical path endpoint

Checklist

  • Found SPEF
  • Understand resistance and capacitance parasitics
  • Found post-route STA
  • Recorded worst setup slack
  • Recorded worst hold slack
  • Inspected the worst timing path
  • Understand cell delay vs net delay
  • Understand multi-corner analysis
  • Continued to page 21

Questions? Ask in the network Discord.

Power, performance, area, and efficiency

A physical design is not judged by one number. Power, performance, area, routability, and correctness interact, and improving one can make another worse.

Overview

The common shorthand is:

PPA

meaning:

Power
Performance
Area

Power

Digital power is often discussed as:

dynamic power
static/leakage power

A common intuition for switching power is:

P_dynamic ∝ α C V² f

where:

  • α is switching activity
  • C is capacitance
  • V is supply voltage
  • f is switching frequency

This is an intuition, not a complete chip-power equation.

Performance

For this synchronous block, performance is constrained by timing.

A smaller achievable clock period means a higher possible clock frequency:

f = 1 / T

Area

ASIC area may refer to different things:

standard-cell area
core area
die/block area

Do not mix them.

Efficiency is not one universal metric

Examples include:

area efficiency
energy per operation
performance per area
power density

Choose a metric that matches the design goal.

Prerequisites

Steps

1. Open final metrics

RUN=$(ls -dt runs/* | head -1)

cat "$RUN/final/metrics.csv"

For machine-readable inspection:

python3 -m json.tool "$RUN/final/metrics.json" | less

2. Search useful metrics

grep -iE \
'area|util|power|slack|tns|wns|wire|cell|drc|lvs|antenna|ir' \
"$RUN/final/metrics.csv"

Metric names can change as the flow evolves.

Use the semantic meaning, not a memorized line number.

3. Record physical area

Record separately:

standard-cell area
core area
die/block area

For our explicit floorplan:

die = 150 µm × 150 µm

but your actual reports are the authority.

4. Calculate area utilization

A useful conceptual metric is:

cell utilization =
standard-cell area / core area

Do not confuse this with placement target density.

5. Record performance

Use post-route timing.

If your clock period is:

10 ns

the requested frequency is:

100 MHz

But if setup timing fails, the design has not demonstrated operation at that target.

A rough period estimate based only on worst setup slack can help intuition:

approximate required period
≈ constrained period - worst setup slack

when WNS is negative under the same assumptions.

Treat this as an approximation, not a complete signoff calculation.

6. Inspect power reports

Find power reports:

find "$RUN" -type f -iname '*power*' -o -iname '*irdrop*'

Search:

grep -RniE "total|internal|switch|leak|power" \
  "$RUN"/*sta* "$RUN"/*power* 2>/dev/null | head -120

Record the categories that the current flow actually reports.

7. Interpret power carefully

Power accuracy depends on switching-activity assumptions.

If the flow does not have realistic activity information, treat power as an estimate suitable for learning and relative comparison.

Do not present a vectorless estimate as measured silicon power.

8. Define one project efficiency metric

For example:

performance density =
frequency target / core area

or:

cell packing efficiency =
standard-cell area / core area

State exactly what you calculated and its units.

Do not invent a vague single "chip efficiency percentage."

9. Think in tradeoffs

Examples:

smaller core
→ less area
→ possibly more congestion
→ potentially worse timing
larger drive cells
→ potentially better timing
→ more area
→ more load/power
more buffers
→ may fix slew/timing
→ adds area and power
lower clock frequency
→ easier setup timing
→ lower throughput

10. Save your PPA table

Add to the project README:

## ASIC PPA

| metric | value |
|--------|------:|
| Standard-cell area | |
| Core area | |
| Die/block area | |
| Cell utilization | |
| Clock period | |
| Requested frequency | |
| Worst setup slack | |
| Worst hold slack | |
| Total power estimate | |
| Dynamic/switching power | |
| Leakage/static power | |
| Worst IR drop | |
| Total routed wirelength | |

Results

You should be able to explain why this statement is wrong:

Design A is better because it has fewer cells.

A complete comparison needs the design objective and physical results.

Checklist

  • Recorded standard-cell area
  • Recorded core and die area
  • Calculated utilization
  • Recorded timing
  • Recorded power estimate
  • Recorded IR drop
  • Recorded wirelength
  • Defined any efficiency metric explicitly
  • Continued to page 22

Questions? Ask in the network Discord.

Signoff checks: DRC, LVS, antenna, XOR, and manufacturability

A GDS file is only useful if its geometry is legal and its extracted connectivity matches the intended circuit.

Overview

Several different checks answer different questions.

checkquestion
DRCIs the geometry legal for the manufacturing rules?
LVSDoes the extracted layout connectivity match the schematic/netlist?
AntennaCould manufacturing charge damage transistor gates?
XORDo two independently generated layout streams match geometrically?
STADoes timing satisfy the constraints across required corners?
IR dropIs the supply network electrically acceptable under the modeled conditions?

Passing one does not imply passing the others.

DRC

Design Rule Checking tests geometry rules such as:

minimum metal width
minimum spacing
via enclosure
minimum area
layer interaction rules

LVS

Layout Versus Schematic asks:

Does the circuit extracted from the physical layout
match the intended netlist?

DRC can pass while LVS fails.

A beautiful legal layout can still be electrically wrong.

XOR

LibreLane can stream GDS through more than one backend and compare them.

Geometric differences may reveal stream-out inconsistencies.

Prerequisites

Steps

1. Find DRC steps

RUN=$(ls -dt runs/* | head -1)

find "$RUN" -maxdepth 1 -type d \
  \( -iname '*magic-drc*' -o -iname '*klayout-drc*' \)

2. Search DRC reports

grep -RniE "drc|violation|error|count" \
  "$RUN"/*drc* 2>/dev/null | head -120

Record Magic and KLayout DRC results separately if both are present.

3. Find LVS

LVS_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -iname '*netgen-lvs*' | head -1)

echo "$LVS_DIR"

Inspect:

grep -RniE "match|mismatch|lvs|error|net|device" \
  "$LVS_DIR" | head -150

The desired result is logical/layout equivalence under the checker's rules.

4. Find antenna checks

find "$RUN" -maxdepth 1 -type d -iname '*antenna*'

Inspect the reports before and after repair when both exist.

5. Find XOR

find "$RUN" -maxdepth 1 -type d -iname '*xor*'

Look for the reported geometric-difference count.

6. Read the manufacturability summary

Find:

find "$RUN" -maxdepth 2 -type f \
  -iname '*manufactur*' -o -iname '*summary*'

Also inspect:

error.log
warning.log

from the run root.

7. Do not ignore deferred errors

Some flows continue through multiple checks so you can collect more information before the final failure.

That means:

flow reached GDS

does not necessarily mean:

flow passed signoff

Read the final status and checker reports.

8. Understand what "clean" means

For this educational macro, a strong result is:

0 DRC violations
LVS clean
0 unresolved antenna violations
0 disconnected pins/nets
no setup violations
no hold violations
acceptable IR-drop report
consistent stream-out/XOR result

The exact requirements for a real tapeout are defined by the foundry/shuttle/integration platform.

9. Save evidence

Save:

screenshots/drc_clean.png
screenshots/lvs_clean.png
screenshots/signoff_summary.png

Results

Create:

signoff itemresult
Magic DRC
KLayout DRC
LVS
Antenna
XOR
Setup
Hold
Disconnected pins
IR drop

Checklist

  • Checked Magic DRC
  • Checked KLayout DRC
  • Checked LVS
  • Checked antenna
  • Checked XOR
  • Checked setup
  • Checked hold
  • Checked run error/warning logs
  • Continued to page 23

Questions? Ask in the network Discord.

Inspect every stage and every major ASIC file

The run directory is a history of the chip being constructed. Use intermediate states to visually inspect what changed at each step instead of treating the flow as a black box.

Overview

Each LibreLane step receives a design state and produces a new state.

A typical step directory contains files such as:

COMMANDS
config.json
*.log
*.odb
*.def
*.nl.v
*.pnl.v
*.sdc
state_in.json
state_out.json

Important formats

formatpurpose
.v RTLbehavioral/source logic
.nl.vgate-level netlist without explicit power connections
.pnl.vgate-level netlist with power connections
.sdctiming constraints
.defphysical implementation exchange: rows, components, pins, routing
.lefabstract macro physical view
.odbOpenROAD/OpenDB design database
.spefextracted parasitic resistance/capacitance
.sdftiming delays for timing-aware simulation
.libLiberty timing/power model
.spiceelectrical/transistor-level netlist
.gdsfinal geometric mask-layout stream

LEF vs GDS

LEF is intentionally abstract.

A macro LEF tells a parent design things such as:

block dimensions
pin shapes
routing obstructions

without requiring the parent router to understand every transistor polygon.

GDS contains the detailed physical geometry.

DEF vs GDS

DEF describes an implementation using design objects and physical coordinates.

GDS is a lower-level geometric layout stream.

ODB

ODB is OpenROAD's database representation.

It is especially useful because OpenROAD can reopen the design with rich knowledge of:

instances
nets
timing
routing
layers
parasitics

Prerequisites

Steps

1. Find the latest run

RUN=$(ls -dt runs/* | head -1)
echo "$RUN"

2. List all step directories

find "$RUN" -maxdepth 1 -mindepth 1 -type d \
  -printf '%f\n' | sort

3. Make a stage table

For each of these stages, find the matching directory:

Yosys synthesis
floorplan
tap/endcap insertion
PDN generation
global placement
detailed placement
CTS
global routing
detailed routing
RC extraction
post-PNR STA
GDS stream-out
DRC
LVS

Write the actual folder names into your README.

4. Generic command to open an intermediate OpenROAD state

Suppose:

STEP_DIR="$RUN/<step-folder>"

Then:

librelane \
  --with-initial-state "$STEP_DIR/state_out.json" \
  --flow OpenInOpenROAD \
  "$RUN/resolved.json"

Use this repeatedly.

5. Open detailed routing in KLayout

DRT_DIR=$(find "$RUN" -maxdepth 1 -type d \
  -name '*detailedrouting*' | head -1)

librelane \
  --with-initial-state "$DRT_DIR/state_out.json" \
  --flow OpenInKLayout \
  "$RUN/resolved.json"

If a GDS does not exist yet for that state, the viewer can use the physical DEF view.

6. Open final GDS in KLayout

librelane --last-run --flow OpenInKLayout config.json

7. Open final design in OpenROAD

librelane --last-run --flow OpenInOpenROAD config.json

8. Use KLayout layer controls

In KLayout:

  • zoom into one standard cell
  • toggle metal layers
  • toggle via layers
  • identify the PDN
  • identify signal routes
  • locate block pins
  • inspect the die boundary
  • inspect repeated standard-cell geometry

At very high zoom you are no longer looking at "gates" as schematic symbols.

You are looking at physical layout polygons.

9. Do not confuse colors with electrical meaning

EDA viewers assign display colors to layers.

The color is a visualization choice.

The layer name and datatype define the physical meaning.

10. Inspect final deliverables

List final files:

find "$RUN/final" -type f -printf '%p\n' | sort

Then answer:

Which file would a parent block use for abstract placement?
Which file contains final layout geometry?
Which file contains parasitics?
Which file contains delays?
Which file contains powered connectivity?
Which file contains timing constraints?

11. Build a visual progression

Save one screenshot from each major stage:

01_synthesis_or_netlist.png
02_floorplan.png
03_pdn.png
04_global_placement.png
05_detailed_placement.png
06_cts.png
07_global_routing.png
08_detailed_routing.png
09_final_gds.png

Put them in order.

This progression is one of the best ways to understand RTL-to-GDS.

Results

You should now be able to look at an arbitrary file from a digital ASIC flow and explain why it exists.

Checklist

  • Opened multiple intermediate states
  • Understand RTL vs gate-level netlist
  • Understand powered vs unpowered netlist
  • Understand LEF
  • Understand DEF
  • Understand ODB
  • Understand SPEF
  • Understand SDF
  • Understand Liberty
  • Understand SPICE
  • Understand GDSII
  • Built the visual stage progression
  • Continued to page 24

Questions? Ask in the network Discord.

Optimize the design and compare the adder architectures

Now repeat the flow as an engineering experiment. Compare the Ripple Carry, Carry Lookahead, and Carry Select versions using the same process, clock constraint, floorplan methodology, and reporting method.

Overview

A fair comparison changes one primary design variable at a time.

For the adder experiment:

same ALU
same top-level registers
same PDK
same standard-cell library
same clock period
same physical constraints
same tool flow
different adder RTL

Then compare:

area
timing
power estimate
wirelength
cell count
buffer count
routing
congestion

Why FPGA results and ASIC results can disagree

An FPGA has:

LUTs
dedicated carry chains
fixed routing architecture
fixed programmable resources

An ASIC has:

standard cells
custom placement
custom routing
different wire RC
different cell choices

An architecture that performs well on an FPGA is not guaranteed to rank the same way in an ASIC.

Prerequisites

Steps

1. Create three design copies

For example:

experiments/
├── ripple/
├── lookahead/
└── carry_select/

Each folder should use the appropriate adder8.v.

2. Keep the baseline configuration identical

Use the same:

CLOCK_PERIOD
PDK
STD_CELL_LIBRARY
DIE_AREA
CORE_AREA
placement density
flow version

for the first comparison.

Do not secretly give one architecture more area.

3. Run all three

Example:

cd experiments/ripple
librelane config.json

cd ../lookahead
librelane config.json

cd ../carry_select
librelane config.json

4. Record synthesis results

For each version, record:

mapped cell count
estimated cell area
major cell types

5. Record physical results

For each version:

standard-cell area
die/core area
utilization
wirelength
buffer count

6. Record timing

For each version:

worst setup slack
worst hold slack
critical path
critical-path corner

7. Record power

Use the same analysis assumptions for all three.

Record the power categories reported by the flow.

Relative comparison is much more meaningful when the methodology is identical.

8. Record signoff quality

Do not rank a design with violations above a clean design just because one PPA number looks attractive.

Record:

DRC
LVS
antenna
setup
hold
routing violations

9. Build the comparison table

| metric | Ripple | Lookahead | Carry Select |
|--------|-------:|----------:|-------------:|
| Mapped cells | | | |
| Standard-cell area | | | |
| Core area | | | |
| Utilization | | | |
| Wirelength | | | |
| Worst setup slack | | | |
| Worst hold slack | | | |
| Power estimate | | | |
| Worst IR drop | | | |
| DRC clean | | | |
| LVS clean | | | |

10. Explain the result physically

Do not stop at:

Lookahead was faster.

Explain:

what did synthesis map?
what is the critical path?
how many cells were inserted?
what happened to wirelength?
did routing become harder?
did the architecture survive optimization?

11. Experiment with utilization

After the fair baseline comparison, pick one adder and vary floorplan size or utilization methodology.

For example, compare:

roomy core
moderate core
tight core

Do not choose values that make the design trivially impossible.

Observe:

cell density
congestion
wirelength
timing
area

12. Experiment with clock period

Try a more aggressive clock target.

Example progression:

10 ns
8 ns
6 ns

Do not assume the tool will close timing.

The point is to find where implementation becomes difficult and understand why.

13. Optional synthesis exploration

LibreLane provides a synthesis-exploration flow that can try multiple synthesis strategies.

Use:

librelane --flow SynthesisExploration config.json

Treat this as an optimization experiment after you understand the baseline.

14. Keep reproducibility information

Save:

resolved.json
metrics.csv
metrics.json
tool version
PDK version

for each run.

If another student cannot reproduce your comparison, it is not a strong engineering comparison.

Results

Your conclusion should answer:

  1. Which adder used the least cell area?
  2. Which had the best setup timing?
  3. Which had the most routing/wirelength?
  4. Which used the most estimated power?
  5. Did the original RTL structure remain recognizable?
  6. Did the ranking match your Vivado/FPGA result?
  7. What tradeoff would you choose for a real design?

Checklist

  • Ran all three adder architectures
  • Used identical baseline physical constraints
  • Compared cell area
  • Compared timing
  • Compared power
  • Compared wirelength
  • Compared signoff status
  • Performed one density/area experiment
  • Performed one clock-period experiment
  • Wrote a physical explanation, not only a ranking
  • Continued to page 25

Questions? Ask in the network Discord.

Final RTL-to-GDS submission and tapeout-readiness checklist

Package the complete project so another engineer can reproduce the design, inspect every major stage, verify the signoff results, and understand what remains before actual fabrication.

Overview

A successful tutorial result is not just:

alu_top.gds

A strong ASIC deliverable includes:

source
constraints
configuration
run metadata
physical views
timing data
parasitics
verification reports
PPA metrics
engineering interpretation

Hardened macro vs full chip

Your alu_top is a hardened digital block.

It is not automatically a full standalone chip with:

pad ring
ESD
package
power pads
clock pad
reset pad
bond wires
bumps
shuttle wrapper
foundry delivery package

A higher-level design can integrate the macro using abstract views such as LEF plus timing models and connect it into a full-chip implementation.

"GDS exists" is not signoff

Before a fabrication submission, the relevant project must satisfy the actual foundry/shuttle signoff requirements.

For this class, you will demonstrate the corresponding open-source checks and clearly state their status.

Prerequisites

Steps

1. Final repository structure

A good repository looks like:

asic_101_gds/
├── rtl/
│   ├── adder8.v
│   ├── alu_core.v
│   └── alu_top.v
├── screenshots/
│   ├── baseline_gds.png
│   ├── synthesis_cells.png
│   ├── floorplan.png
│   ├── tap_endcap.png
│   ├── pdn.png
│   ├── global_placement.png
│   ├── detailed_placement.png
│   ├── congestion_heatmap.png
│   ├── clock_tree.png
│   ├── global_routing.png
│   ├── detailed_routing.png
│   ├── metal_layers.png
│   ├── worst_setup_path.png
│   ├── worst_hold_path.png
│   ├── drc_clean.png
│   └── lvs_clean.png
├── config.json
└── README.md

Do not commit giant disposable run directories unless your team specifically wants them in Git.

Instead, archive or publish the required final reports/views according to the network submission instructions.

2. Record reproducibility metadata

In README:

librelane --version
yosys -V
openroad -version

Also record:

PDK
standard-cell library
clock period
adder architecture
date of run

Keep the run's:

resolved.json

with your archived submission when requested.

3. Final PPA table

| metric | value |
|--------|------:|
| Adder architecture | |
| PDK | sky130A |
| Standard-cell library | sky130_fd_sc_hd |
| Clock period | |
| Requested frequency | |
| Mapped cells | |
| Standard-cell area | |
| Core dimensions | |
| Core area | |
| Die dimensions | |
| Die area | |
| Utilization | |
| Total routed wirelength | |
| Worst setup slack | |
| Worst hold slack | |
| Total negative setup slack | |
| Power estimate | |
| Worst IR drop | |

4. Final signoff table

| check | status |
|-------|--------|
| RTL simulation | |
| Lint | |
| Synthesis | |
| Detailed routing | |
| Routing DRC | |
| Antenna | |
| Magic DRC | |
| KLayout DRC | |
| LVS | |
| Setup timing | |
| Hold timing | |
| XOR/stream comparison | |
| IR-drop report | |

Never write PASS unless you actually inspected the report.

5. Include the stage progression

Your README should show or link to:

floorplan
→ PDN
→ placement
→ CTS
→ routing
→ final GDS

For each image, write one sentence explaining what physically changed.

6. Explain the critical path

Include:

startpoint
endpoint
clock corner
logic/network path
worst slack

Then explain whether the delay is dominated by:

logic depth
cell delay
wire delay
routing distance
fanout

7. Explain your area

Distinguish:

cell area
core area
die area

and explain why they are different.

8. Explain your power result

State:

what report produced it
what switching/activity assumptions were available
whether the value is measured or estimated

For this project it is an estimate.

9. Explain what GDS contains

Your final GDS contains physical geometric structures for the hardened block.

You should be able to point out:

  • die/block boundary
  • standard-cell rows
  • standard cells
  • PDN
  • clock network
  • signal routing
  • vias
  • filler structures
  • pins

10. Explain what still remains for a real chip

A real product/shuttle integration may still require:

  • top-level SoC integration
  • hardened memory/analog macros
  • padframe
  • IO cells
  • ESD
  • package/bump/bond planning
  • full-chip power integrity
  • full-chip clock/reset planning
  • shuttle wrapper
  • density/fill requirements
  • foundry-specific signoff decks
  • final tapeout package review

The exact checklist depends on the fabrication program.

11. Write the final engineering conclusion

Answer:

  1. What did you build?
  2. Which adder did you choose?
  3. What happened to it during synthesis?
  4. What limited performance?
  5. What determined area?
  6. Where did routing consume space?
  7. Did the design pass DRC and LVS?
  8. Did setup and hold timing pass?
  9. What would you optimize next?
  10. What is the next step between this macro and manufactured silicon?

12. Final concept check

You should be able to explain the entire sentence below without hand-waving:

The RTL was synthesized by Yosys into Sky130 standard cells, floorplanned and placed into a die/core geometry by OpenROAD, connected to a generated PDN, clock-buffered during CTS, routed with legal metal and vias, extracted into parasitic RC, analyzed with multi-corner STA and power/IR-drop estimation, physically checked with DRC/antenna/LVS-related signoff steps, and streamed into GDSII for physical integration or fabrication preparation.

Results

You have completed an end-to-end introductory digital ASIC flow:

RTL
→ GATES
→ FLOORPLAN
→ PDN
→ PLACEMENT
→ CTS
→ ROUTING
→ EXTRACTION
→ STA
→ POWER
→ DRC/LVS
→ GDSII

The important result is not the colorful GDS screenshot.

The important result is that you understand what changed at each stage, what each artifact means, and what evidence is required before claiming the design is physically correct.

Checklist

  • Repository is organized
  • Tool and PDK information recorded
  • PPA table complete
  • Signoff table complete
  • Stage screenshots complete
  • Critical path explained
  • Area explained
  • Power estimate explained
  • DRC checked
  • LVS checked
  • Setup checked
  • Hold checked
  • Final GDS inspected
  • Hardened macro vs complete chip distinction understood
  • Final engineering conclusion written
  • ASIC 101 RTL-to-GDS complete

Questions? Ask in the network Discord.

RTL

This section is still being written. Check back soon — in the meantime, the Quick Start Tutorial covers RTL design as part of building the 8-bit ALU.

Simulation

This section is still being written. Check back soon — in the meantime, the Quick Start Tutorial covers verifying a design in simulation.

Place & Route

This section is still being written. Check back soon — in the meantime, the Quick Start Tutorial walks through the open-source place-and-route flow.

Additional Projects

Smaller, self-contained builds that don't fit the main course sequence. More are on the way — for now, see Ring Oscillator.

Ring Oscillator

A 5-stage ring oscillator on SKY130, from schematic to simulated frequency. This page doubles as the formatting reference: every construct the renderer understands is used somewhere below.

TL;DR: an odd number of inverters in a loop has no stable DC operating point, so it oscillates at roughly f = 1 / (2 * N * t_pd). Five stages of the standard inverter lands near 1.2 GHz at tt.

Overview

The ring oscillator is the hello world of analog design: it needs correct device models, a working simulator, and nothing else. If this page simulates cleanly, your toolchain setup is good and every later tutorial will run.

Inline styles for reference: bold, italic, both, inline code, struck, and an external link to the SKY130 PDK docs.

Prerequisites

  • xschem and ngspice installed and on $PATH
  • SKY130A PDK with $PDK_ROOT exported
    • built with open_pdks
    • includes the sky130_fd_pr primitives library
  • Basic familiarity with SPICE netlists

Schematic

5-stage ring oscillator

Keep the loop symmetric: identical W/L on every stage, and buffer the tap so the probe capacitance does not load the ring.

Netlist

* ring_osc.spice : 5-stage ring oscillator, sky130 tt
.lib $PDK_ROOT/sky130A/libs.tech/ngspice/sky130.lib.spice tt

.subckt inv in out vdd gnd
XM1 out in gnd gnd sky130_fd_pr__nfet_01v8 W=1   L=0.15
XM2 out in vdd vdd sky130_fd_pr__pfet_01v8 W=2.1 L=0.15
.ends

Xi1 n5 n1 vdd 0 inv
Xi2 n1 n2 vdd 0 inv
Xi3 n2 n3 vdd 0 inv
Xi4 n3 n4 vdd 0 inv
Xi5 n4 n5 vdd 0 inv

Vdd vdd 0 1.8
.ic v(n1)=0
.tran 10p 20n
.end

Run it

  1. Export the environment
    1. export PDK_ROOT=/usr/local/share/pdk
  2. Launch the simulation
    1. ngspice ring_osc.spice
    2. wait for the transient to finish
  3. Measure the period on v(n5) and invert it

Results

CornerVDDf_oscPower
tt1.80 V1.21 GHz84 uW
ss1.62 V0.89 GHz61 uW
ff1.98 V1.63 GHz118 uW

Frequency tracks 1/t_pd, so expect roughly linear movement with VDD across corners.

Checklist

  • schematic drawn, ERC clean
  • transient runs at tt
  • ss / ff corners swept
  • layout drawn, DRC and LVS clean

Further reading

Appendix

Reference material and setup notes will go here. This section is still being written — check back soon.