MakeLSI: で半導体をつくる(2023)
MakeLSI:
2023-7-27 15:46 JST

にわかに半導体業界が盛り上がっています。その喧騒とは別に、今年も MakeLSI: でチップを作ります。

MakeLSI: であしかけ7年

今まで、しらなかったけど MakeLSI じゃなくて MakeLSI: だったらしい。なんだかんだで足掛け 7年やってます。これがやれているのも某Yさんの突破力のおかげです。ありがとう。

Chipathon の 2023にも参加し、OpenLane も試しOpenROAD のソースも読み知識もついてきた。そろそろ整理しないとね。

そして、今年は VCO

YMO が再認識される昨今、やっぱり VCO くらいは理解しておかないとね。ということで VCO を作ることにしました。VCO: Voltage Controlled Oscillator日本語では電圧制御発振器というらしい。与える電圧で発信する周波数が変わるらしい。

毎年 Inverter から始まる

毎年 Inverter から始まるのはお約束だ。MakeLSI: の scrapboxを見て Inverter を作ります。大筋はこの scrapbox の通りだけど、次の3つのことを変えて設計(というほどのことではない)してます。

KiCad v7 による回路図の作成

私が使う KiCad のバージョンも v5 から v7.0.6 に変わって使い心地もメニューも変わってしまいました。MakeLSI: の情報もちょっと読み変えないといけません。

回路図の作成を読むと、"名前の先頭に「0_」を付けてください" とありますが、私はこれをやらないようにしました。KiCad の検索で十分検索できるし、変え損なうこともあり、そうすると混在して混乱してしまうから。

シンボルを置くなどの基本操作に KiCad のバージョンの違いによる変更はありません。ただ、メニュー構成やアイコンの絵柄が大幅に変わったのでそこがちょっと混乱ポイントです。

KiCad v7 ではアノテーションを置いた瞬間にやってくれるようになりました。シンボルやワイヤーの操作も直感的になり勝手に断線することもなくなりました。調子にのってワイヤーをバンバン引いていると、知らない間にどっかのシンボルと交差して意図せぬ回路になることがあるのでそこだけ注意です。

Spice モデルの生成

KiCad v7 でネットリストの生成はは Spice と Spice Model の生成に別れました。メニューの ファイル → エクスポート → ネットリスト... から選んで生成します。われわれが欲しいのは Spice Model の方なので注意が必要です。生成のときにはなぜか拡張子がつかないので .cir をつけてセーブします。

そして、生成される形式も変わってしまいました。恐らく、より Spice の Model の表現として適切になったのだと思います。

Inv.cir
*
.subckt Inv
+       A ; input
+       VDD ; input
+       VSS ; input
+       X ; output

M1 X A VDD VDD PMOS_OR1 l=1u w=6u
M2 X A VSS VSS NMOS_OR1 l=1u w=2u
.ends

この形式だと MakeLSI: が用意している KLayout の LVS が対応してくれないので Inv を Top に PMOS_OR1 を PMOS にNMOS_OR1 を NMOS に変更します。私は awk と sed で変換するように対応しました。

Inv.cir
$ cat cir.awk
/.subckt/ { print ".subckt Top"next }
print }
$ cat do.sh
awk -f cir.awk Inv.cir | sed -e s/PMOS_OR1/PMOS/g -e s/NMOS_OR1/NMOS/g > Inv-awk.cir

KiCad でシミュレーション

MakeLSI: の資料では次にレイアウトを書くようになっていますが、まずは回路図のシミュレーションでしょう。動かないと意味がない。インバータならまぁ動くからいいとして、ちょっと複雑な物を書くとまずは回路図動かないとね。

KiCad は内部に ngspice をもっているので Spice のシミュレーションが出来ます。なお、Ubuntu の標準の ngspice と一部ライブラリかなにかがかぶるらしくて結局、一旦、標準の ngspice を削りました(uninstall)。

そういえば、KiCad の v7 にアップデートした時に .config/kicad がかぶって環境変数か何かがたりなくて .config/kicad をリネームしたっけ。まぁこの手の環境調整は永遠に繰り返されますね。

KiCad:インバータの設計(回路シミュレーション)を読めばあとはそのとおりに出来るはず。Inverter のシミュレーションは特記することがないので割愛します。

今年は VCO だよ

VCO を作ろうと思ったきっかけが2015 年のMakeLSI: で作った人の記録を見たからでした。金沢大学の資料が元のようです。

結論から言うと、この回路図はシミュレーションが動かなかった。回路図の読み方を間違えているのかもしれません。後、分周器も作ろうと思ったのですが、これは時間がなくて断念しました。無念。RFマイクロエレクトロニクス 第2版 実践応用編の該当部分は図書館に行ってコピーはしてきました。Blog によると「ゲートの長さに意味がある回路なのでその点に注意」とのことで、これちゃんとシミュレーションできるんかい?というのがちょっとした疑問。

ちょっとまて!リング・オシレータを先に

VCO にいきなりいかずにリングオシレータを作るを先にやるべきでした。例は WGex ですが、この通りにすると KLayout でもうまくいきますよ。自分が作ったときは PMOS を 6u にしました。

シミュレータが通らない!!

簡単に出来るかと思った7段のリング・オシレータ。いざシミュレーションをやって見るとうまく動きません。

これは ngspice を理解していないからです。いままでおまじないについていた TEXT の .tran の意味をちゃんと理解するようにします。

.tran の意味を理解する

.tran 10ns 2000ns 0 1000ns

MakeLSI: の資料では .tran の4番目の引数を 1000ns にしています。これはどうやらシミュレーションを 1000ns で打ち切る指示のようです。これがよくありません。打ち切らないようにしましょう。

つぎに1番目の引数。10ns になっていますが、これはシミュレーション時のデルタ時間のようです。この値を大きくすると大雑把になってしまうので細かくします。細かくしすぎると、今度はシミュレーションに時間がかかりすぎます。試したところ 100ps と 1ns にはあまり違いがなかったので 1ns にします。

3番目の引数は表示用のスタート時間です。この値でシミュレーションの最後の100ns だけを見るなどの細かい調整が出来ます。

ということで、.tran 1ns 2000nsでシミュレーションしてみます。

うまくいっている気がします。マウスで選択すると拡大できました。3ns くらいが周期みたいなので 300MHz くらい出ている計算になります。これが本当だと私の手元の機器では正確には計測できません。どうしたものでしょうか?

VCO のつもりが Current-controlled だった

リング・オシレータは出来たものの、先のVCO の回路図はそもそもシミュレーションがうまくいかなかったので、どっか回路を間違えてしまったようです。原因はおいおい調査するとして、気を通り直して別の回路をチャレンジします(おいおい)。

Camenzind さんの Current-controlled oscillator

Camenzind さんが書いた。Designing Analog Chipsという資料を参考にします。あれ?今見ると VCO じゃなくて Current-controlled じゃん。Fig. 12-8: Current-controlled oscillator for operation between 6MHz and 300MHz.を参考にしました(下の図。Camenzind の pdf から引用)。まぁいいや。気を取り直して先に進みます。

トップの回路図。KiCad の階層という機能をつかっています。階層という機能を使うと回路図を使いまわせそうな気がするので(気がするだけで実際はどうかわからない)、そうでなくても横にはみ出さないので快適かな。

VCO だと思っていた Current-controlled oscillator の回路図

KiCad v7 なれるとこれくらいはすぐに描けるようになります。と言いたいところですが、かなり苦戦しました。そして、実はこの回路でシミュレーションは動くものの LVS が通らなかったので、一つ一つチェックするということをしました。

まずはシミュレーション

まずはシミュレーションが通らないと話にならないのでシミュレーションします。実際のアウトプットは赤いプロットです。なぜか下の 2.2V 程度のところで折り返しています。そういうものなのかどうかわからないところが辛いところです。

この手のシミュレーション去年やったよね。と突如思い出しました。

コンパレータの後段で波形を整えました。

ということで波形を整えたのが青いプロット。

なんとなくこれで良さそうなので、最後にインバーターを2つつけて簡略版バッファとして出力しました。シミュレーション上はきれいに方形波になったよ。

でもよくよくみると(いやよくみなくても)、デューティ比が50%じゃないじゃん。このあたりでギブアップ。まぁちゃんと波形を整える回路を書かないといけないのでしょう。それは今後の課題ということで。

実は試行錯誤しました

出力にバッファが必要だろうとはわかっていたのですが、最初に検討した obuf は難しすぎてあっさり断念。ライブラリとしてあればいいのにね。次に、単純に Inverter を2つつけて見ました。が、思ったような波形にならずに断念。そこで、去年の Output モジュールをつけてみるという発想になりました。

懸念事項はせっかく Camenzind さんが作った回路の意味を最後に Output モジュールが破壊しているんじゃないかという点。これも今後検証でしょう。

もう一つ試したことがあって、後段にコンパレータを置く。4段目と5段目は位相が逆になっているはずなので、それを入力にコンパレータおけば安定するし、デューティ比も50%になる!!とヒラメいたのですが、シミュレーションしてみるとうまくいきませんでした。完全に位相が逆になっているわけではなく、遅延が入っているので、その遅延量に応じた波形が出るようでした。

LVS ではまる

じゃ次はレイアウトです。ちゃんと回路図をレイアウトに落とせればレイアウトの良し悪しはあっても基本的にはシミュレーションと近い結果を得ることが出来るはずです。

B の扱いではまる

回路図の書き方は人それぞれなのでしょう。Camenzind さんは B をまとめて書いてます。私もそのとおりに書いてみました。

いままで G が共通なので POL でつなぐようにしてました。うっかり、B が共通のものを POL でつないでレイアウトしてしまいました。当然、LVSで引っかかります。

加えて MakeLSI: で用意されている KLayout のスクリプトが去年からNMOS_OR1 と PMOS_OR1 を認識しなくなりました。対応としてはセッティングファイルにNMOS_OR1 と NMOS は同じであるという設定をすればいいのですが、1年前のことですっかり忘れていました。

さらに悪いことに KiCad v7 でネットリストの形式が変わりました。こうなると、何が原因で LVS が通っていないのかわかりません。この辺を整理するのにえらく時間がかかってしまいました。

小さい回路で LVS を通す

こうなると持久戦です。まずは Inverter でまず LVS を通します。この時点で KiCad v7 に変わったことによる影響と、NMOS_OR1 と NMOS の名称違いによる LVS の失敗を回避することが出来るようになりました。

後は Step by Step で、Inverter を成長させながら最終的な回路図に近づけます。

文字にして書いてしまうと1行ですが、実際には1個1個 MOS を回路図上に付け加えてはレイアウトも変更し LVS を通すという作業を延々と繰り返します。地味ですが、確実な方法でしょ。

KiCad の回路図まちがえる

Step by Step で進めば絶対にうまくいくと、確信していたのですが、途中で妙なことが起こります。KiCad の回路図を意味的には変えておらずシンボルを動かしただけなのに LVS が通らなくなるという現象です。

理屈に会わない!!!!!

原因は回路図を間違えていたことにありました。KiCad v7 になってかなり回路図を書くことが楽になったのですが、ワイヤーをつなげる時に運悪く他のシンボルのコネクト可能なポイントをまたいで置いてしまうと、その部分もコネクトされてしまいます。

KiCad の Spice Model へのエクスポートはシンボルを巡回してつくられるので、その順序によっては正しい接続と変わらない Model を出力します。ところが、シンボルを動かしてしまうと、Model 生成時の巡回順が変更されてしまうため、LVS でエラーとなる Model を出力してしまいます。

もちろん、回路図に誤りがなければこのようなことは起こりません。

結局、KiCad v7 にアップデートしたことによる影響が1つ、LVS のスクリプトの過去との互換性の問題が2つ、レイアウトの書き方の問題が1つ、オペミス1つが複雑に絡み合って LVS が通りませんでした。

大半のミスは LVS のスクリプト側で対応できる気がするので、今後は自分で LVS のスクリプトを書くようにしようかと思っています。

リンク集