KLayoutで断面図を作成するXSectionの紹介
2020年9月11日 森山作成
XSection は、KLayoutに付属するツールの1つです。パッケージとして提供されています。日本語に翻訳したマニュアル( +XSection )があります。
XSectionの実行例
a. 以下のようにKLayoutのレイアウト画面上で定規(ルーラーまたはXSection用の定規)を使って断面図を見たい場所を指定します。
https://gyazo.com/93fa6adba043924e0f17d8d2f82f139b
b.Tools → Xsection → Run Script を実行すると、 KLayoutの別のタブに以下のような断面図が表示されます(表示を見やすくするためY軸方向は10倍にしています)。これはSOI CMOSの例です。
https://gyazo.com/85ff87e49e11055e07b8045ad605de4f
XSection機能を実現するには、xsファイルという平面レイアウトを垂直な材料スタックに変換する方法を記述したスクリプトを作成する必要があります。
XSectionのインストール
KLayoutを起動し、Tools → Manage Packages。以下から、xsectionを選択し、xsection 1.4 - Ruby scriptをダブルクリック。選択されApplyボタンが出るので、インストール。
https://gyazo.com/55a6261c6f4f5f5727634ac0734b9fb1
以下の画面が出ても、OKで継続してください。
https://gyazo.com/9a21ca15053c5d38d261b218ca360b9d
XSectionの実行方法
Toolsのメニュに以下のように、XSection 1.4 Scriptsが追加されますので、Run Scriptを実行できます。実際に実行できるのは、xsファイル作成後です。
https://gyazo.com/c74e66a7ab5a7558bb6ead4f7cd54a1b
xsファイルとは
以下の例(YSS-PMOSの作りかけです)のように、平面レイアウトのレイヤー情報から、マスクを作成し、縦方向にどのように材料を積むか、あるいは削るかを記述するものです。マニュアルは、 +XSファイルリファレンス 、 +XSファイル入門 を参考にしてださい。
code: demo.xs
# デモのためのPMOSプロセス記述例:
# - Source/Drain 拡散
# - Al ゲートの形成
# - Source/DrainとAl ゲートへのコンタクト
# - 2nd メタル層の形成
# 図の精度をあげるため、レイアウト用のデータベースユニットを10倍細かくする:
dbu(dbu * 0.1)
# 基本オプション: シミュレーションする深さと高さを宣言する
# 以下がデフォルト値
# depth(2.0)
# height(2.0)
# 加工による遺物(artefact)を取り除くための基本的な精度を宣言する例:
delta(5 * dbu)
# レイアウトレイヤーの宣言
# 可能な操作 (l1 = layer(..); l2 = layer(..))
# "or" l1.or(l2)
# "and" l1.and(l2)
# "xor" l1.xor(l2)
# "not" l1.not(l2)
# "size" l1.sized(s) (s の単位はミクロン)
# or l1.sized(x, y) (x, y の単位はミクロン)
# "invert" l1.inverted
# lpoly = layer("3/0")
# lpoly = layer("5/0")
# lactive = layer("2/0")
lactive = layer("3/0")
lfox = lactive.inverted
# lwn = layer("1/0") # nwl
# lcg = layer("4/0")
cnt = layer("7/0") # cnt?
# ml1 = layer("6/0")
ml1 = layer("8/0")
via1 = layer("9/0")
ml2 = layer("10/0")
parea = layer("18/0")
new_diff = lactive
# 処理ステップ:
# 次に、断面図に移動します。レイアウトジオメトリから、プロセスを段階的に
# シミュレーションしてマテリアルスタックを作成します。
# 基本的な考え方は、すべての活動は表面で起こるということです。
# 材料を(既存またはマスク上に)堆積したり、材料をエッチングして平坦化できます。
# 材料は、測定線に沿った断面で見られる2次元の図形です。
# 次の手順は、単純なプロセスを模倣しています。
# nドープのバルクから始め、それを材料「nbulk」に割り当てます
nbulk = bulk
# ボロン ドープ
pplus = mask(new_diff).grow(0.6, 0.2, :mode => :round, :into => nbulk)
# 60nmの gate oxideを堆積する
# "deposit" は "all.grow" の別名であり、 "all"はすべて"everything"をカバーする特別なマスクです.
gox = deposit(0.06)
# デポし、スペーサーをエッチングする。堆積はコンフォーマルであり、エッチングは異方性です。
# (conformal: 0.1, 0.1, anisotropic: 0.1). 注意:"etch" は "all.etch"の別名。
ox1 = deposit(0.1, 0.1)
etch(0.1, :into => ox1)
# カバーされてないところのゲート酸化膜を除去する
# アイソレーションのデポ
iso = deposit(0.7, 0.7, :mode => :round)
output("400/0", iso) # デモのため出力
# ゲートと、ソース/ドレインコンタクトをエッチング
# "taper"は、側壁の角度が5度の穴を円錐形にします
mask(cnt).etch(1.0, :into => iso, :taper => 4)
# プラグを形成するためタングステンを埋める
w = deposit(0.15, 0.15)
# tungsten CMP: take off 0.45 micron measured from the top level of the
# w, iso materials from w and iso.
# Alternative specifications are:
# :downto => {material(s)} planarize down to these materials
# :to => z planarize to the given z position measured from 0 (the initial wafer surface)
planarize(:into => w, iso, :less => 0.65) # ml1 isolation and etch, metal deposition and CMP
iso2 = deposit(0.3)
mask(ml1).etch(0.3, :into => iso2, :taper => 5)
alu1 = deposit(0.3, 0.3)
planarize(:into => alu1, :less => 0.3) # finally output all result material.
# output specification can be scattered throughout the script but it is
# easier to read when put at the end.
output("gox (301/1)", gox)
output("ox1 (305/0)", ox1)
output("pd (306/0)", pplus)
output("iso (308/0)", iso)
output("w (309/0)", w)
output("iso2 (310/0)", iso2)
output("alu1 (311/0)", alu1)
layers_file("OpenRule1um_xs.lyp")
code: sample.xs:
# 入力レイヤーを準備する
m1 = layer("1/0")
# マスクm1上に厚さが0.3で横方向の延長が0.1で、楕円形のエッジ輪郭を持つ金属を成長させる
metal1 = mask(m1).grow(0.3, 0.1, :mode => :round)
# 材料データをターゲットレイアウトに出力する
output("0/0", bulk)
output("1/0", metal1)`
以下のような入力を使用します:
https://gyazo.com/e7b6a0fc5bfc8fb085e82e380cf9ba27
このスクリプトは、単純な断面を生成します:
https://gyazo.com/1ff4d5c9d6191175ab35c9cae4828d87
Xsectionのサンプルのgithub
https://gyazo.com/b3c984213d2768feb56a9972f930b564
https://gyazo.com/0ef4b356faf5fac827089547f4d881f3
code: cmos.xs:
# A simple CMOS process description demonstrating:
# - Well formation
# - Field oxide formation
# - Gate formation with LDD spacers/implant
# - W plug creating and W CMP
# - First metal layer formation
# Pick a 10x finer database unit for enhanced accuracy:
dbu(dbu * 0.1)
# Basic options: declare the depth of the simulation and the height.
# These are the defaults:
# depth(2.0)
# height(2.0)
# Declare the basic accuracy used to remove artefacts for example:
delta(5 * dbu)
# Declaration the layout layers.
# Possible operations are (l1 = layer(..); l2 = layer(..))
# "or" l1.or(l2)
# "and" l1.and(l2)
# "xor" l1.xor(l2)
# "not" l1.not(l2)
# "size" l1.sized(s) (s in micron units)
# or l1.sized(x, y) (x, y in micron units)
# "invert" l1.inverted
lpoly = layer("3/0")
lactive = layer("2/0")
lfox = lactive.inverted
lwn = layer("1/0")
lcg = layer("4/0")
m1 = layer("6/0")
# Process steps:
# Now we move to cross section view: from the layout geometry we create
# a material stack by simulating the process step by step.
# The basic idea is that all activity happens at the surface. We can
# deposit material (over existing or at a mask), etch material and
# planarize.
# A material is a 2D geometry as seen in the cross section along the
# measurement line.
# The following steps mimic a simple process.
# Start with the p doped bulk and assign that to material "pbulk"
# "bulk" delivers the wafer's cross section.
pbulk = bulk
# create a n-well by growing the mask into the pbulk material. The
# pbulk material is consumed by this step. We grep 0.5 in depth and
# 0.05 to the inside using a round approximation.
nwell = mask(lwn).grow(0.5, -0.05, :mode => :round, :into => pbulk)
# field oxide formation: we use the mask twice, once to grow upwards and
# once to grow into the existing material. We use round approximation to
# build a "hill", although that is not showing the typical beak.
# Note, that we first derive the mask and use it twice. That ensures we
# use the same seed for both contributions. Afterwards we join the
# contributions to form the field oxide.
# "bias" will shrink the resulting area.
mfox = mask(lfox)
fox1 = mfox.grow(0.2, 0.2, :bias => 0.1, :mode => :round)
fox2 = mfox.grow(0.2, 0.2, :bias => 0.1, :mode => :round, :into => pbulk, nwell) fox = fox1.or(fox2)
# deposit 20nm gate oxide.
# "deposit" is an alias for "all.grow" where "all" is a special mask covering "everything".
gox = deposit(0.02)
# create poly and put silicide atop of that
poly = mask(lpoly).grow(0.15, -0.05, :mode => :round)
silicide = grow(0.10, :on => poly)
# implant the LDD areas. Note the "through" specification which allows to grow into the
# pbulk/nwell even if covered by GOX (normally that would prevent).
# Also note, that "diffuse" is actually an alias for "all.grow".
pldd = diffuse(0.05, 0.02, :into => nwell, :through => gox, :bias => 0.01, :mode => :round)
nldd = diffuse(0.05, 0.02, :into => pbulk, :through => gox, :bias => 0.01, :mode => :round)
# deposit and etch the spacer. Deposition is conformal while etch is anisotropic
# (conformal: 0.05, 0.05, anisotropic: 0.05). Note that "etch" is an alias for "all.etch".
ox1 = deposit(0.05, 0.05)
etch(0.05, :into => ox1)
# implant the p+ and n+ source drain regions
pd = diffuse(0.1, -0.05, :into => pldd, nwell, :through => gox, :mode => :round) nd = diffuse(0.1, -0.05, :into => nldd, pbulk, :through => gox, :mode => :round) # remove gate oxide where not covered
# deposit isolation
iso = deposit(0.7, 0.7, :mode => :round)
output("400/0", iso) # for demonstration
# etch the gate and source/drain contacts
# "taper" will make the holes conical with a sidewall angle of 5 degree.
mask(lcg).etch(1.0, :into => iso, :taper => 4)
# fill with tungsten to form the plugs
w = deposit(0.15, 0.15)
# tungsten CMP: take off 0.45 micron measured from the top level of the
# w, iso materials from w and iso.
# Alternative specifications are:
# :downto => {material(s)} planarize down to these materials
# :to => z planarize to the given z position measured from 0 (the initial wafer surface)
planarize(:into => w, iso, :less => 0.65) # m1 isolation and etch, metal deposition and CMP
iso2 = deposit(0.2)
mask(m1).etch(0.3, :into => iso2, :taper => 5)
alu1 = deposit(0.2, 0.2)
planarize(:into => alu1, :less => 0.2) # finally output all result material.
# output specification can be scattered throughout the script but it is
# easier to read when put at the end.
output("nwell (300/0)", nwell)
output("fox (301/0)", fox)
output("gox (301/1)", gox)
output("poly (302/0)", poly)
output("silicide (302/1)", silicide)
output("pldd (303/0)", pldd)
output("nldd (304/0)", nldd)
output("ox1 (305/0)", ox1)
output("pd (306/0)", pd)
output("nd (307/0)", nd)
output("iso (308/0)", iso)
output("w (309/0)", w)
output("iso2 (310/0)", iso2)
output("alu1 (311/0)", alu1)
layers_file("cmos.lyp")