Skip to content

Session 3: Schematic Design & Simulation

Homework

Homework

  1. Reuse and.sp netlist, which has a 2-input AND gate to make a 2-input NAND gate (e.g., remove the output inverter) and change the models to refer to the PDK models
  2. Simulate it in SPICE, verify truth table (it will look something like the right table), and measure propagation delays (low-to-high and high-to-low)
  3. Write an initial analog block that you can use in your chip project (e.g., an adder, counter, etc.)

Here’s a good starting point: https://analoghub.ie/category/verilogModels/article/counter

Words

AI-generated summary

This section includes to be summarized using NotebookLM (Source: lecture page)

SPICE (Simulation Program with Integrated Circuit Emphasis) is the industry standard for analog circuit simulation.

SPICE(集積回路を重視したシミュレーションプログラム)は、アナログ回路シミュレーションにおける業界標準です。


A PDK (Process Development Kit) is a collection of files and rules provided by a foundry to tell design tools how to design for a specific manufacturing process. It contains essential components such as SPICE device models, design rules (minimum widths and spacings), and standard cell libraries.

Sky130 refers to the SkyWater 130nm process, which is one of the most mature open-source PDKs available. By using the Sky130 PDK, you can use specific models (like the sky130_fd_pr__pfet_01v8 we used in your netlist) to simulate and verify that your design will function correctly when actually fabricated on silicon

PDK (Process Development Kit) とは、特定の半導体製造プロセスでチップを設計するためにファウンドリ(製造工場)が提供する設計データのセットです。これには、トランジスタの挙動を再現する SPICEモデル、製造上の最小寸法を定めたデザインルール、標準論理ゲートの集まりである標準セルライブラリなどが含まれます。

Sky130 は、SkyWater社が提供する 130nm 製造プロセスのことです。私たちがシミュレーションで使用した sky130_fd_pr__nfet_01v8 などのモデル名は、この Sky130 PDK に含まれる具体的な部品データであり、これを使うことで実際のチップ製造に即した正確な設計と検証が可能になります。


A truth table is a mathematical table used in logic and electronics to show the functional relationship between all possible combinations of inputs and their resulting outputs,. In digital systems, these inputs and outputs are represented as binary states: 1 (HIGH/True) and 0 (LOW/False)

NAND gate Truth table

A B NAND output
0 0 1
0 1 1
1 0 1
1 1 0

真理値表(Truth Table)とは、論理ゲートや回路において、すべての入力の組み合わせに対してどのような出力が得られるかを一覧にまとめた表

Homework 1

Homework

  1. Reuse and.sp netlist, which has a 2-input AND gate to make a 2-input NAND gate (e.g., remove the output inverter) and change the models to refer to the PDK models

AND gate from session 2

alt text

Where is and.sp netlist located

On Docker container

.
├── foss
│   ├── designs
│   └── examples
│       └── analog_basics
│           ├── and.sp
│           ├── or.sp
│           └── schmitt.sp
and.sp
AND gate (click to view)
and.sp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
* AND gate ngspice example

* NGSPICE transistor models
.model mosn NMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16 
.model mosp PMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16

* 1 V power supply
vsup VDD 0 1 


* AND pull-up network -- two pmos in parallel
Mp1 nOUT A VDD VDD mosp L=0.35u W=2u 
Mp2 nOUT B VDD VDD mosp L=0.35u W=2u


* Pull-down network -- two nmos in series
Mn1 nOUT A npd 0 mosn L=0.35u W=2u 
Mn2 npd B 0 0 mosn L=0.35u W=2u

* Inverter, or a logical NOT
Mp3 AND nOUT VDD VDD mosp L=0.35u W=2u
Mn3 AND nOUT 0 0 mosn L=0.35u W=2u

* Input voltage source, ramps up to VDD then back down
vin1 A 0 PWL(0 0 2mS 0 2.001mS 1V 3mS 1V 3.001mS 0) 
vin2 B 0 PWL(0 0 1mS 0 1.001mS 1V 2.5mS 1V 2.5001mS 0) 

.control 
* transient simulation using vin sweep
  tran 100n 4m 

* plot vout against vin 
  plot v(A) 
  plot v(B) 
  plot v(AND)
.endc

.end

Remove the output inverter from and.sp

and.sp
20
21
22
* Inverter, or a logical NOT  
Mp3 AND nOUT VDD VDD mosp L=0.35u W=2u  
Mn3 AND nOUT 0 0 mosn L=0.35u W=2u  
NAND gate (click to view)
nand.sp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
* AND gate ngspice example -> Change to NAND gate 

* NGSPICE transistor models
.model mosn NMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16 
.model mosp PMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16

* 1 V power supply
vsup VDD 0 1 


* AND pull-up network -- two pmos in parallel
Mp1 nOUT A VDD VDD mosp L=0.35u W=2u 
Mp2 nOUT B VDD VDD mosp L=0.35u W=2u


* Pull-down network -- two nmos in series
Mn1 nOUT A npd 0 mosn L=0.35u W=2u 
Mn2 npd B 0 0 mosn L=0.35u W=2u

* ========= remove the output inverter ============
* Inverter, or a logical NOT
* Mp3 AND nOUT VDD VDD mosp L=0.35u W=2u
* Mn3 AND nOUT 0 0 mosn L=0.35u W=2u
* =================================================

* Input voltage source, ramps up to VDD then back down
vin1 A 0 PWL(0 0 2mS 0 2.001mS 1V 3mS 1V 3.001mS 0) 
vin2 B 0 PWL(0 0 1mS 0 1.001mS 1V 2.5mS 1V 2.5001mS 0) 

.control 
* transient simulation using vin sweep
  tran 100n 4m 

* plot vout against vin 
  plot v(A) 
  plot v(B) 
  plot v(AND)
.endc

.end

Change the models to refer to the PDK models

What does this mean?

AI-generated summary

This section includes to be summarized using NotebookLM (Source: lecture page)

  1. Changing to PDK Models Remove the generic .model descriptions and rewrite them using the actual model names from the SkyWater 130nm PDK manufacturing process.

    • mosp → sky130_fd_pr__pfet_01v8
    • mosn → sky130_fd_pr__nfet_01v8
  2. Adjusting the Power Supply Voltage Since the standard SkyWater 130nm models are designed for 1.8V operation, it is appropriate to change the power supply voltage (vsup) and the input signals (vin1, vin2) to 1.8V.

  1. PDKモデルへの変更 汎用的な.modelの記述を削除し、実際の製造プロセスであるSkyWater 130nm PDKのモデル名に書き換えます。

    • mosp → sky130_fd_pr__pfet_01v8
    • mosn → sky130_fd_pr__nfet_01v8
  2. 電源電圧の調整 SkyWater 130nmの標準モデルは1.8V用であるため、電源電圧(vsup)と入力信号(vin1, vin2)を1.8Vに変更するのが適切です。

  1. Changing to PDK Models
NAND gate (before)
3
4
5
* NGSPICE transistor models
.model mosn NMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16 
.model mosp PMOS level=49 version=3.3.0 tox=10n nch=1e17 nsub=5e16
NAND gate (after)
3
4
5
* Include PDK Library
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt
*.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice.tt.red" <- this is wrong path

On Docker container

.
├── foss
│   ├── designs
│   ├── examples
│   └── pdks
│       └── sky130A
│           └── libs.tech
│               └── ngspice
│                   ├── sky130.lib.spice.ff.red
│                   ├── sky130.lib.spice.fs.red
│                   ├── sky130.lib.spice.sf.red
│                   ├── sky130.lib.spice.ss.red
│                   └── sky130.lib.spice.tt.red

Note

The reason for modifying L (Length) and W (Width) is to optimize the design for the actual manufacturing process, the SkyWater 130nm PDK (Sky130), rather than using generic simulation values.
- L (Length): This refers to the length of the transistor’s switching region (the gate). The original value of 0.35 µm assumes an older-generation process. In the Sky130 PDK, however, due to process scaling, 0.15 µm is a practical standard size.
- W (Width): This determines the amount of current the transistor can drive. In a standard logic design such as this NAND gate, a width of around W = 1 µm is sufficient to properly drive the circuit, while maintaining a good balance between power consumption and area (the occupied chip size).

L(Length)とW(Width)を書き換える理由は、汎用的なシミュレーション用の値から、SkyWater 130nm PDK(Sky130)という実際の製造プロセスに即した設計に最適化するためです。
- L(Length):トランジスタのスイッチ部分(ゲート)の長さを指します。元の0.35μmは古い世代のプロセスを想定した数値ですが、Sky130 PDKにおいてはプロセスの微細化に合わせて 0.15μm が実用的な標準サイズとなります
- W(Width):トランジスタが流せる電流の量を決定します。今回のNANDゲートのような標準的なロジック設計においては、W=1μm 程度でも十分に回路を駆動でき、消費電力と面積(チップ上の専有サイズ)のバランスを良好に保つことが可能です


NAND gate (before)
3
4
5
6
7
8
9
* AND pull-up network -- two pmos in parallel
Mp1 nOUT A VDD VDD mosp L=0.35u W=2u 
Mp2 nOUT B VDD VDD mosp L=0.35u W=2u

* Pull-down network -- two nmos in series
Mn1 nOUT A npd 0 mosn L=0.35u W=2u 
Mn2 npd B 0 0 mosn L=0.35u W=2u
NAND gate (after)
3
4
5
6
7
8
9
* AND pull-up network -- two pmos in parallel
Xp1 nOUT A VDD VDD sky130_fd_pr__pfet_01v8 L=0.15u W=1u 
Xp2 nOUT B VDD VDD sky130_fd_pr__pfet_01v8 L=0.15u W=1u

* Pull-down network -- two nmos in series
Xn1 nOUT A npd 0 sky130_fd_pr__nfet_01v8 L=0.15u W=1u 
Xn2 npd B 0 0 sky130_fd_pr__nfet_01v8 L=0.15u W=1u

2. Adjusting the Power Supply Voltage

Note

sky130_fd_pr__nfet_01v8 is 1V8 (=1.8V) model

NAND gate (before)
7
8
* 1 V power supply
vsup VDD 0 1 
NAND gate (after)
7
8
* 1.8 V power supply
Vsup VDD 0 1.8 
NAND gate (before)
26
27
28
* Input voltage source, ramps up to VDD then back down
vin1 A 0 PWL(0 0 2mS 0 2.001mS 1V 3mS 1V 3.001mS 0) 
vin2 B 0 PWL(0 0 1mS 0 1.001mS 1V 2.5mS 1V 2.5001mS 0) 
NAND gate (after)
26
27
28
* Input voltage source, ramps up to VDD then back down
Vin1 A 0 PWL(0 0 2mS 0 2.001mS 1.8V 3mS 1.8V 3.001mS 0) 
Vin2 B 0 PWL(0 0 1mS 0 1.001mS 1.8V 2.5mS 1.8V 2.5001mS 0) 

Note

Since the output inverter has been removed, the final output node of the circuit has changed from AND to nOUT.

NAND gate (before)
34
35
36
37
* plot vout against vin 
  plot v(A) 
  plot v(B) 
  plot v(AND)
NAND gate (after)
34
35
36
37
* plot vout against vin 
  plot v(A) 
  plot v(B) 
  plot v(nOUT)
my_nand.sp (click to view)
my_nand.sp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
*NAND gate ngspice with PDK model (sky130A)

* Include the Sky130 device models
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt

* 1.8 V power supply
Vsup VDD 0 1.8 


* Input voltage source, ramps up to VDD then back down
Vin1 A 0 PWL(0 0 2mS 0 2.001mS 1.8V 3mS 1.8V 3.001mS 0) 
Vin2 B 0 PWL(0 0 1mS 0 1.001mS 1.8V 2.5mS 1.8V 2.5001mS 0) 

* AND pull-up network -- two PMOS in parallel
Xp1 nOUT A VDD VDD sky130_fd_pr__pfet_01v8_hvt L=0.15u W=1u 
Xp2 nOUT B VDD VDD sky130_fd_pr__pfet_01v8_hvt L=0.15u W=1u

* Pull-down network -- two NMOS in series
Xn1 nOUT A npd 0 sky130_fd_pr__nfet_01v8 L=0.15u W=1u 
Xn2 npd B 0 0 sky130_fd_pr__nfet_01v8 L=0.15u W=1u

* Output load capacitor (typical gate load)
Cload nOUT 0 10f

.control 
* transient simulation using vin sweep
  tran 100n 4m 

* plot vout against vin 
  plot v(A) 
  plot v(B) 
  plot v(nOUT)
.endc

.end

Homework 2

Homework

2. Simulate it in SPICE, verify truth table (it will look something like the right table), and measure propagation delays (low-to-high and high-to-low)

How to run a code and stop ngspice

/foss/designs > ngspice my_nand.sp

ngspice 1 -> quit
ngspice-45.2 done
/foss/designs >

my_nand.sp got an error

/foss/designs > ngspice my_nand.sp 
******
** ngspice-45.2 : Circuit level simulation program
** Compiled with KLU Direct Linear Solver
** The U. C. Berkeley CAD Group
** Copyright 1985-1994, Regents of the University of California.
** Copyright 2001-2025, The ngspice team.
** Please get your ngspice manual from https://ngspice.sourceforge.io/docs.html
** Please file your bug-reports at http://ngspice.sourceforge.net/bugrep.html
** Creation Date: Mon Feb 16 14:08:33 UTC 2026
******

Note: No compatibility mode selected!


Circuit: * nand gate ngspice with pdk model (sky130a)

Error on line 1171 or its substitute:
  m.xp1.msky130_fd_pr__pfet_01v8_hvt nout a vdd vdd xp1:sky130_fd_pr__pfet_01v8_hvt__model l=    1.500000000000000e-07     w=    1.000000000000000e-06     nf=    1.000000000000000e+00     ad=    0.000000000000000e+00     as=    0.000000000000000e+00     pd=    0.000000000000000e+00     ps=    0.000000000000000e+00     nrd=    0.000000000000000e+00     nrs=    0.000000000000000e+00     sa=    0.000000000000000e+00     sb=    0.000000000000000e+00     sd=    0.000000000000000e+00   
could not find a valid modelname
    Simulation interrupted due to error!

ngspice 1 -> 

Since Philippe’s spike code worked (I named it “p-nand.sp”), I generated “c_nand.sp” with AI

p_nand.sp (click to view)
p_nand.sp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
* NAND gate ngspice with PDK / code from Philippe

* Include the Sky130 device models
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt

* Power supply: 1.8V
Vdd vdd gnd 1.8


* Inputs
* PULSE(initial final delay rise fall widht period)
VinA inA gnd PULSE(0 1.8 0ns 100ps 100ps 2ns 4ns)
VinB inB gnd PULSE(0 1.8 0ns 100ps 100ps 2ns 8ns)

* Two PMOS transistors in parralel for the pull-up network  (W=1u, L=150n)
* Format: Mname drain gate source body model W=... L=...
Xp1 NAND inA vdd vdd sky130_fd_pr__pfet_01v8_hvt  l=0.150  w=0.99
Xp2 NAND inB vdd vdd sky130_fd_pr__pfet_01v8_hvt  l=0.150  w=0.99

* Two NMOS transistors in series for the pull-down network  (W=0.5u, L=150n)
Xn1 NAND inA npd gnd sky130_fd_pr__nfet_01v8  l=0.150  w=0.495
Xn2 npd  inB gnd gnd sky130_fd_pr__nfet_01v8  l=0.150  w=0.495

* Output load capacitor (typical gate load)
Cload NAND gnd 10f

* Simulation: transient analysis for 30ns
.tran 10p 30ns

* Save node voltages for plotting
.save v(inA) v(inB) v(NAND)

* Control block for ngspice
.control
run
plot v(inA) v(inB) v(NAND)
plot v(inA) v(NAND)
plot v(inB) v(NAND)
meas tran tpd_hl TRIG v(inA) VAL=0.9 RISE=1 TARG v(NAND) VAL=0.9 FALL=1
meas tran tpd_lh TRIG v(inA) VAL=0.9 FALL=1 TARG v(NAND) VAL=0.9 RISE=1
meas tran tpd_hl TRIG v(inB) VAL=0.9 RISE=1 TARG v(NAND) VAL=0.9 FALL=1
meas tran tpd_lh TRIG v(inB) VAL=0.9 FALL=1 TARG v(NAND) VAL=0.9 RISE=1

.endc

.end
c_nand.sp (click to view)

ChatGPT: “Since p_nand.sp works, please make my_nand.sp work as well.”

c_nand.sp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
* NAND gate using Sky130A PDK (working version)

* Include Sky130 models (absolute path)
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt

* Power supply 1.8V
VDD vdd 0 1.8

* Inputs (same timing as your original PWL but in ns scale)
VinA A 0 PWL(0 0 2m 0 2.001m 1.8 3m 1.8 3.001m 0)
VinB B 0 PWL(0 0 1m 0 1.001m 1.8 2.5m 1.8 2.5001m 0)

* PMOS pull-up network (parallel)
Xp1 nOUT A vdd vdd sky130_fd_pr__pfet_01v8_hvt L=0.150 W=0.99
Xp2 nOUT B vdd vdd sky130_fd_pr__pfet_01v8_hvt L=0.150 W=0.99

* NMOS pull-down network (series)
Xn1 nOUT A npd 0 sky130_fd_pr__nfet_01v8 L=0.150 W=0.495
Xn2 npd  B 0   0 sky130_fd_pr__nfet_01v8 L=0.150 W=0.495

* Output load capacitor
Cload nOUT 0 10f

* Transient analysis
.tran 100n 4m

.control
run
plot v(A) v(B) v(nOUT)
.endc

.end

alt text
alt text

To see the propagation delays(low-to-high and high-to-low), I added the following lines

c_nand.sp
30
31
32
33
34
35
36
*1. Measure high-to-low propagation delay (tpd_hl)  
*Measure the time from Input A rising (near 2ms) to Output nOUT falling  
meas tran tpd_hl trig v(A) val=0.9 rise=1 targ v(nOUT) val=0.9 fall=1  

*2. Measure low-to-high propagation delay (tpd_lh)  
*Measure the time from Input B falling (near 2.5ms) to Output nOUT rising.  
meas tran tpd_lh trig v(B) val=0.9 fall=1 targ v(nOUT) val=0.9 rise=1  
alt text

I got this

tpd_hl              =  -5.608465e-08 targ=  2.000444e-03 trig=  2.000500e-03
tpd_lh              =  1.381929e-08 targ=  2.500064e-03 trig=  2.500050e-03
AI-generated summary

This section includes to be summarized using NotebookLM (Source: lecture page)

Definitions of Terms
- tpd_hl (High-to-Low Delay): The time it takes for the output to fall from High to Low following an input change.
- tpd_lh (Low-to-High Delay): The time it takes for the output to rise from Low to High.
- trig (Trigger): The simulation time when the input signal crossed the threshold (0.9V).
- targ (Target): The simulation time when the output signal crossed the threshold.

Analyzing My Data - tpd_lh ≈ 13.8 ns (1.38×\(10^{-8}\)s):
- This is a valid positive delay. The input triggered at 2.500050ms, and the output responded shortly after at 2.500064ms.
- tpd_hl ≈ -56 ns (Negative Value!):
This is physically impossible for a real circuit as the output cannot change before the input. Reason: It likely indicates that your output nOUT crossed the 0.9V threshold at 2.000444ms, which was before your trigger input A reached 0.9V at 2.000500ms. You should check your input pulse slopes or see if input B was already affecting the output.

この結果は、入力信号が変化してから出力信号が反応するまでの時間を記録したものです。
用語の意味
- tpd_hl (High-to-Low Delay): 入力が立ち上がり、出力が HighからLowへ 変化する際の遅延時間です。
- tpd_lh (Low-to-High Delay): 入力が立ち下がり、出力が LowからHighへ 変化する際の遅延時間です。
- trig (Trigger): 入力が基準電圧(今回の場合0.9V)に達した瞬間の時刻です。
- targ (Target): 出力が基準電圧に達した瞬間の時刻です。

データの読み解き
- tpd_lh = 1.38e-08 秒 (約13.8ナノ秒): これは正常な正の値です。2.500050msに入力が変化し、2.500064msに出力が反応したことを示しています。
- tpd_hl = -5.60e-08 秒 (負の値): 注意が必要です。数値がマイナスになっています。これは、入力が判定基準(0.9V)に達する「前」に出力が変化してしまったことを意味します。
原因: 入力信号(A)の立ち上がりが非常にゆっくりであるか、別の入力信号(B)の影響ですでに出力が変化し始めていた可能性があります。

c_inverter.sp (click to view)

ChatGPT: “Since p_nand.sp works, please make inverter.sp work as well.”

* CMOS Inverter Simulation (Sky130A working version)

* Include Sky130 device models
.lib "/foss/pdks/sky130A/libs.tech/ngspice/sky130.lib.spice" tt

* Power supply: 1.8V
VDD vdd 0 1.8

* Input pulse
* PULSE(initial final delay rise fall width period)
Vin in 0 PULSE(0 1.8 1n 100p 100p 2n 4n)

* PMOS (pull-up)
Xp out in vdd vdd sky130_fd_pr__pfet_01v8_hvt L=0.150 W=0.99

* NMOS (pull-down)
Xn out in 0 0 sky130_fd_pr__nfet_01v8 L=0.150 W=0.495

* Output load capacitor
Cload out 0 10f

* Transient analysis
.tran 10p 20n

.save v(in) v(out)

.control
run
plot v(in) v(out)

meas tran tpd_hl TRIG v(in) VAL=0.9 RISE=1 TARG v(out) VAL=0.9 FALL=1
meas tran tpd_lh TRIG v(in) VAL=0.9 FALL=1 TARG v(out) VAL=0.9 RISE=1

.endc

.end

alt text

Homework 3

3. Write an initial analog block that you can use in your chip project (e.g., an adder, counter, etc.)
Here’s a good starting point: https://analoghub.ie/category/verilogModels/article/counter

WIP