Session 7: Packaging & Board Design¶
What I did¶
The final session was about wrapping up the RGB Mixer chip project — writing proper documentation, defining a test plan, and preparing the presentation materials.
By this point the chip design was complete: RTL written and simulated, synthesized to 270 Sky130 standard cells, placed and routed in a 200×200 µm floorplan, timing verified with 98.29 ns slack.
The chip¶
RGB Mixer controls the brightness of three LEDs independently using three rotary encoders. Each encoder maps to one color channel (Red, Green, Blue). Turning an encoder adjusts the PWM duty cycle for that channel.
The design has three identical pwm_channel modules instantiated in rgb_top. Each module contains:
- An encoder reader (detects CW vs CCW rotation)
- An 8-bit counter (stores the current brightness value 0–255)
- A PWM comparator (outputs HIGH when counter < duty value)
All three share a 10 MHz clock and an active-low reset.
Pin table¶
| Pin | Direction | Description |
|---|---|---|
clk |
IN | 10 MHz clock |
rst_n |
IN | Active-low reset |
enc_r_a / enc_r_b |
IN | Red encoder A/B |
enc_g_a / enc_g_b |
IN | Green encoder A/B |
enc_b_a / enc_b_b |
IN | Blue encoder A/B |
pwm_r |
OUT | Red LED PWM |
pwm_g |
OUT | Green LED PWM |
pwm_b |
OUT | Blue LED PWM |
Supply: 1.8V · PWM resolution: 8-bit · PWM frequency: ~39 kHz
Test plan¶
Before taping out, you need to know what “correct” looks like. Here is what I would test:
- Reset — apply
rst_n=0, expect all outputs at 50% duty cycle - Encoder up — 10 CW pulses on red encoder, expect
pwm_rduty increases - Encoder down — 10 CCW pulses on green encoder, expect
pwm_gduty decreases - Counter overflow — drive past 255, expect wrap to 0, no hang
- Independent channels — drive all three encoders simultaneously, verify no cross-talk
- Timing closure — OpenROAD STA, expect positive slack at 10 MHz
- Lint — Verilator
--lint-only, expect 0 warnings - No latches — Yosys synthesis, expect 0 latches in output
All 8 tests passed in simulation. Timing slack: 98.29 ns (MET ✓). Verilator: 0 warnings.
Results¶
| Metric | Value |
|---|---|
| Standard cells | 270 |
| Flip-flops | 48× dfrtp_1 |
| Timing slack | 98.29 ns ✓ |
| Critical path | 1.58 ns |
| Total power | 54.3 µW |
| Design area | 2658 µm² |
| Utilization | 11% |
Problems I ran into¶
GDS export failed. The strm2gds command gave a “Cannot copy shapes within same layout” error. KLayout was defaulting to a different PDK. The DEF file exists and OpenROAD can read it, but I could not generate the final GDS for this session. This would be the next step before actual tapeout.
What I learned¶
Writing a test plan forces you to think about behavior before you think about implementation. Each test is basically a question: “does the chip do what I said it would do?”
The 98.29 ns timing slack means the chip could theoretically run at around 600 MHz. For LED brightness control this headroom is irrelevant — but it shows how much margin the Sky130 standard cells have at nominal conditions (25°C, 1.8V).
The hardest part of this session was not the documentation itself — it was realizing that a missing step early on (the GDS export) blocks everything downstream. In a real tapeout flow, that would be a showstopper.
DRC / LVS¶
DRC (Design Rule Check) verifies the layout follows the foundry’s physical rules — minimum wire widths, spacing between metals, via sizes, etc. LVS (Layout vs Schematic) checks that the physical layout matches the original netlist.
Both require a GDS file as input.
What I tried:
strm2gds -slib rgb_top.def -o rgb_top.gds
What happened:
Error: Cannot copy shapes within same layout
KLayout was defaulting to the IHP PDK instead of Sky130. The DEF file from OpenROAD is complete and correct — the issue was in the GDS export step, not the design itself.
Why this matters:
Without GDS you cannot run Magic DRC or Netgen LVS. In a real tapeout flow this would be a hard blocker — the foundry only accepts GDS. The next step would be to use OpenROAD’s built-in write_gds command with the correct Sky130 tech file.
What passes:
OpenROAD runs its own internal DRC during detailed placement. No violations were reported. Timing DRC (setup/hold) also passed with 98.29 ns slack.