SPICE circuit simulator memorandum for non-electronics engineers.
最近、とある事情で、バイポーラトランジスタを使った差動増幅回路のシミュレーションをすることになりました。私は一応、電子工学を学んだ身ですが、本業は組込ソフト設計であり、アナログ回路の設計は素人同然です。
教科書を見て差動増幅回路を復習してみましたが、やはり、正確なシミュレータで動作を確認しないと、分からないことが多いです。以前にも、PSpice や LTspice をいじったことはありますが、長いこと触っていなかったので、使い方をほとんど忘れてしまいました。
KiCad と Ngspice
現在でも LTspice などは、パソコン上で回路シミュレーションするのに良い選択肢だと思うのですが、回路図入力(回路図をネットリストに変換する)を考えると、できるだけ汎用性の高い回路設計 CAD で入力する方法を覚えたほうが得策に思えました。
以前は EAGLE という CAD が、ほとんど無償で利用できたのですが、EAGLE が Autodesk 社に買収されてしまった後、アマチュア設計者が EAGLE から離れ始めているようです。新しく回路設計 CAD を覚える際には KiCad という CAD ソフトを覚える人が増えているようです。
もう一つ。KiCad を使うと、Ngspice という回路シミュレーションソフトとインテグレーションができる、というのも便利そうに思いました。Ngspice は、PSpice や LTspice と同様に、米国カリフォルニア大学バークレー校で開発された SPICE という回路シミュレータをベースとしていて、完全にソースコードが公開されているのが特徴です。また、Windows だけでなく、macOS や Linux で利用できるのも嬉しいところです。
今回は、KiCad を触りつつ、Ngspice を少し勉強してみました。以下のバージョンを使用しています。
- KiCad 6.0.2(macOS 版)
- Ngspice version 36(Linux 版)
SPICE と Ngspice 備忘録
本当は、SPICE と Ngspice についてチュートリアルを書ければ良いのですが、何しろ私はアナログ回路設計と SPICE のいずれも素人同然ですので、順を追って説明することが難しいです。そこで今回は、ネット上の情報を見ても分かりにくい点を中心に、SPICE と Ngspice の「勘所」と「落とし穴」を箇条書きでまとめておくことにしました。
そう、既にお気づきの方があるかと思いますが、これは自分自身に対する備忘録でもあるのです。何しろ、最近は新しいことを覚えてもすぐに忘れてしまうものですから。(泣) そのため、このテキストは一貫的にはなっていません。また、少しずつ拡充、修正していきたいと思いますので、その点を御了承ください。
お願い: 私の書いている内容には基本的な間違いや勘違いがたくさんあると思います。特に「それは Ngspice でなくても、オリジナルの SPICE でも同じだよ」というのが、多数あるのではないかと思います。手元にオリジナルの SPICE 3 がなかったので、動作確認(比較)できませんでした。間違いがありましたら、御教示頂けましたら幸いです。
なお、私が参考にした、ベースとなるチュートリアルは以下の 2つです。いずれも、ちょっと中途半端なところがあり、それらを読んだだけで SPICE や Ngspice の癖を理解できるようにはならないと思います。
- Introduction to SPICE | Using The spice Circuit Simulation Program | Electronics Textbook
- ngspice tutorial for beginners
あとは、Ngspice の公式マニュアルです。これは、常に手元に置いておくべきだと思います。
KiCad の部品の端子番号を SPICE 用に入れ替える
KiCad と ngspice のインテグレーションに関するチュートリアルとしては、以下が分かりやすいです。一読をお勧めします。
そこでも書かれているのですが、多くの方(私も)がつまづくであろうポイントは、KiCad の部品の端子番号と SPICE が期待している端子番号が異なる、ということです。SPICE は、例えば NPN トランジスタで、端子番号としてコレクタが 1、ベースが 2,エミッタが 3ということを期待しています。しかし、KiCad の部品ライブラリは SPICE に合わせている訳ではないので、端子番号が食い違うことがあります。
私はこのせいで、トランジスタのシミュレーションが期待通りに動かず、しばらく悩みました。上記のチュートリアルで、Alternate node sequence というキーワードを探してみてください。
SPICE で可能な解析シミュレーションの種類
SPICE では、電子回路技術者が必要とする、次のような多くの解析(シミュレーション)が可能です。
- .op: 動作点解析
- .dc: DC 解析(DC 伝達関数)
- .ac: 小信号 AC 解析(周波数解析)
- .tran: 過渡解析
他にもいろいろあるようですが、マニュアルを御参考ください。
SPICE のドットコマンドと制御コマンドの違い
まず最初に SPICE の入門者が困惑するのは、SPICE に出てくるコマンドに、ドット(.)で始まるものと、そうでないものがある、という点です。
前者は、解析方法を指示するためのコマンドなどをソースファイルの中で記述するもので、後者は、対話的に SPICE(Ngspice 含む)に指示をするためのコマンドのようです。
例えば、SPICE には .plot というドットコマンドと、plot という制御コマンド(control command)があります。この 2つは異なるものです。
大文字と小文字(2022/3/8 加筆)
SPICE(Ngspice 含む)では、大文字と小文字は区別しません。そこで、以下のような注意点もあります。
SI 単位の指定(2022/3/8 加筆)
SPICE では、以下のような SI 接頭辞が使えます。上述の通り、大文字と小文字が区別されないので注意が必要です。ネットリストで R1 in 0 3M と書くと、R1 は 3メガオームではなく、3ミリオームになります。
- T = 10^12
- G = 10^9
- MEG = 10^6(M と書くとミリ(10^-3)となってしまいます!)
- K = 10^3
- m = 10^-3(ミリです。小文字で書いたほうが良いでしょう)
- u = 10^-6(小文字で書いたほうが良いでしょう)
- n = 10^-9(同)
- p = 10^-12(同)
- f = 10^-15(同)
古い SPICE 2 について
SPICE のチュートリアルを読んでいると、次のような異なる 2つのネットリスト記法が見つかるはずです。
例1:
R1 1 0 10k
例2:
R1 in 0 10k
私が調べたところでは、SPICE 2 の時代にはノードの指定に番号しか使えなかったので、上記の例 1 のような書き方しかできなかったそうです。SPICE 3 となり、ノードの指定にシンボル名が使えるようになったは数字でなく文字列になったそうです(例 2)。なお、ノードをシンボル名で記述する場合、シンボル名の先頭に数字は置けません。(2022/3/8 加筆)
重箱の隅: SPICE 3 では、ノード名は数字でなくシンボル(任意の文字列)です。「0」と「00」は同じには扱われません。(2022/3/8 加筆)
なお、Ngspice は SPICE version 3f.5 というものをベースにしているらしいので、基本的には SPICE 3 の上位互換だと思います。(間違っていたらゴメンなさい。)
グラウンド(接地)について(2022/3/8 加筆)
SPICE では、グラウンドのノードを「0 」(ゼロ)と記述します。SPICE 3 のマニュアルでは言及がありませんでしたが、Ngspice では、このグラウンドを「GND」と記述することもできます。
歴史的な事情(2022/3/8 加筆)
SPICE の英語ドキュメントを読んでいると、ときどき card とか deck という言葉が出てきます。私はパンチカード時代にコンピュータを使った経験がないので、以下は想像ですが、SPICE は歴史の古いソフトウェアで、昔はテキストファイル入力の代わりにパンチカードを使っていたのだと思います。つまり、入力ファイルは deck(カードデック = カードを積み重ねた束)であり、ファイル内の各行は card(パンチカード)な訳です。(たぶん)
Ngspice のバッチモード
Ngspice を使って私が困惑したのは、入力ファイルに .dc で始まる解析指示と .plot(あるいは .print)を使ったコマンドを記述して、それを ngspice で実行しても、プロットもプリントも全く動作しないことです。
Ngspice の通常の動作モードでは、対話的なコマンドとして、プロットには制御コマンド(plot)を、プリントには同(print)を使わないといけません。
補足: ただし、SPICE にはドットコマンド .control と .endc というものがあり、入力ファイルでも制御コマンドを実行できるようになっています。(制御コマンドは、.control と .endc の間に並べる。)
もし Ngspice で .plot や .print を使いたい場合には、起動オプションに -b を指定して、バッチモードで動作させなくてはいけません。
run コマンド
Ngspice の入力ファイル中に、ドットコマンドで解析コマンド(.dc や .tran など)を書いた場合、プロンプトに対して対話的に、あるいは .control と .endc の間で解析(シミュレーション)を走らせるには、run コマンドを使います。run コマンドがないと解析が実行されません。
Ngspice の一般的なファイル構造
Ngspice では、一般に次のようなファイル構造となります。
- タイトル(.title というドットコマンドは省略できます。)
- ネットリストとモデル定義
- 解析指示のドットコマンド(.dc、.ac、.tran など。以下の .control 〜 .endc の間に、制御コマンドの形で書いても良い)
- .control
- 制御コマンドの列
- .endc
- .end
以下に例を示しましょう。あ、説明を忘れましたが、SPICE ではアスタリスク(*)で始まる行はコメントになります。
Example netlist
* Netlist
v1 1 0 dc 15
r1 1 0 2.2k
r2 1 2 3.3k
r3 2 0 150
* Analysis command
.dc v1 0 10 2
* Control commands
.control
run
plot v(2)
.endc
.end
参考までに、上のネットリストは、次の回路図に相当します。
コメントの記述
SPICE 3 の場合: 行頭がアスタリスク(*)で始まる行、スペースで始まる行はコメントです。
Ngspice の場合: SPICE 3 の仕様に加えて、行の途中の「$ 」(ドルの後ろにスペース)、「; 」(セミコロンの後にスペース、「//」(スラッシュ 2つ)の後はコメントになります。
継続行
SPICE では、行頭が「+」(プラス)で始まる場合は、その行の 2文字目以降が、前の行の続きになります。例えば、
.dc v1
+ 0 10 2
のように書くことができます。
互換モード
Ngspice には、PSpice や LTspice のモデル定義の読み込み方(?)との互換性のため(この辺、まだ理解が怪しいです)に、次のような指定ができます。これは通常、ホームディレクトリ直下に .spiceinit あるいは spinit というファイルを作り、その中に記述するようです。詳しくはマニュアルを御覧ください。
set ngbehavior=ltpsa
解析後の電圧値の表示やプロット
Ngspice の通常モード実行(バッチモードではない)のとき、入力ファイル中にドット形式の解析コマンド(前述)を記述して run コマンド(前述)、対話的に(あるいは .control を使って)制御コマンド形式の解析コマンドを実行すると、シミュレーションで求まった各ノードの電圧値を表示したりプロットしたりすることができます。(解析をする前には、できません。)
以下、Ngspice の対話的な制御コマンド例を示します。(つまり、これらを入力ファイルに書く場合には .control が必要。)
まず、ノード 1(SPICE 3 や Ngspice ではノード名にシンボル(文字列)も使えます。以下略)の電位を調べるには、次のような制御コマンドを使います。v は電圧、1 はノード番号ですね。
print v(1)
なお、print all とすると、表示できる全てのノードが表示されます。
解析結果の値をプロットしたい場合には、次のようにします。
plot v(1)
print や plot コマンドの詳しい文法は、マニュアルを御確認ください。
余談ですが、ドットコマンドの .print や .plot では、引数の最初に解析の種類を入れないとダメです。つまり、.print v(1) はダメで、.print dc v(1) 等と書かなくてはいけません。私はしばらく悩みました。
電流を調べる方法
SPICE で解析(シミュレーション)を走らせるとき、各ノードの電位は自動的に保存されるようですが、部品(コンポーネント)に流れる電流は、自動では保存されないようです。
まず最初のやり方として、オリジナルの SPICE では .probe というコマンドを使って部品に流れる電流をシミュレーション中に保存できます。以下は、Ngspice ではバッチモード(コマンドラインオプション -b)で動かすことになりますので、御注意ください。
Example netlist
v1 1 0 dc 15
r1 1 0 2.2k
r2 1 2 3.3k
r3 2 0 150
.probe i(r1)
.dc v1 1 10 1
.print dc v(1)
.plot dc r1#branch
.end
なお、r1#branch は、i(r1) でも大丈夫のようです。
次は、Ngspice の制御コマンドでプロットしたい場合です。一つの方法は、上記ファイルを通常モード(コマンドラインオプションなし)で実行し、対話的に run コマンド、および plot r1#branch とコマンドする方法です。これでも動きます。もう一つは、次のような入力ファイルにします。
Example netlist
v1 1 0 dc 15
r1 1 0 2.2k
r2 1 2 3.3k
r3 2 0 150
.save v(1)
.save @r1[i]
.dc v1 1 10 1
.control
run
print v(1)
plot @r1[i]
.endc
.end
.save コマンドを使うと、シミュレーション中に保存すべきパラメタを指定できるようです。「@」(アットマーク)の後ろはコンポーネント名、カッコの中の i は電流の意味です。注意点として、このように .save コマンドを書く場合には、必要なパラメタを全て列挙しなくてはいけません。.save v(1) は省略できません。
ちなみに、次のようにカッコを外して @r1 をプリントすると、抵抗器モデルにどのようなパラメタがあるのか確認できます。
bash$ cat r.cir
Example netlist
v1 1 0 dc 15
r1 1 0 2.2k
r2 1 2 3.3k
r3 2 0 150
.save @r1[i]
.dc v1 1 10 1
.control
run
print @r1
.endc
.end
bash$ ngspice r.cir
(略)
ac sensitivity [sens_cplx]=0.0454545
ac sensitivity of phase [sens_ph]=0.0454545
ac sensitivity of magnitude [sens_mag]=0.0454545
dc sensitivity and imag part of ac sensitivity [sens_imag]=0.0454545
dc sensitivity and real part of ac sensitivity [sens_real]=0.0454545
dc sensitivity [sens_dc]=0.0454545
Power [p]=0.0454545
Current [i]=0.00454545
Resistor generate noise [noisy]=1
Scale factor [scale]=1
maximum voltage over resistor [bv_max]=1e+99
exponential temp. coefficient [tce]=0
Second order temp. coefficient [tc2]=0
First order temp. coefficient [tc]=0
Multiplication factor [m]=1
Width [w]=1e-05
Length [l]=1e-05
Instance temperature difference with the rest of the circuit [dtemp]=0
Instance operating temperature [temp]=27
AC resistance value [ac]=2200
Resistance [resistance]=2200
いろんな部品の SPICE モデル
Ngspice には、そのままでは市場に出回っている各種部品の SPICE モデルが含まれていません。最新の高性能なデバイスであれば、デバイスメーカーが SPICE モデルを提供していることが多いのですが、古いデバイスではそうもいきません。Ngspice のウェブサイトでは、以下のページで SPICE モデル集を紹介しています。(日本で、アマチュアの間で長く広く使われている 2SC1815 も入っています。)
LTspice の .step コマンド
LTspice には、.step というドットコマンドがあり、例えば、回路中のある抵抗の抵抗値を(10オーム, 20オーム, …, 100オーム、など)のように振りながらシミュレーションを繰り返す機能があります。しかし、残念ながら Ngspice にはそのようなコマンドはありません。
ただし、制御コマンドでループを組むなどして、そのようなことを実現することはできるようです。マニュアルの 16.14.4.2 .step というセクションに例が紹介されていますが、やや説明不足な感じもします。私もまだ、末尾にある plot コマンドで dc1.v(2)、dc2.v(2) といった記述の意味が理解できていません。
plot 制御コマンドは複数記述できる
plot 制御コマンドを繰り返し実行すると、複数のウィンドウが開きます。電圧と電流などは、分けてプロットしたほうが見やすいでしょう。
デシベル表記や位相をプロットする方法
SPICE オリジナルのドットコマンドでは VDB() や VP() という表記ができます。制御コマンドの plot で電流をプロットするときは、db() や phase() という関数を使えます。以下に例を示します。(数式自体にはあまり意味がありません。すみません。)
plot db(@r1[i] + 2)
plot 制御コマンドいろいろ
マニュアルで plot 制御コマンドの説明を見ていると、plot expr1 [ vs scale_expr1 ] という説明があります。最初、意味が分からなかったのですが、例えば、横軸に v(1)、縦軸に v(2) といったプロットができるようです。ただし、私もまだよく調べていないので、間違っていたらゴメンなさい。
plot v(2) vs v(1)
set と let の違い
まだよく分かっていません。let コマンドを使うと、ベクトルの操作もできるみたいです。
PySpice
上のほうで書いた .step に関連しますが、Ngspice の制御コマンドによるループなどを見ていると、どうしても一昔前の古くさい言語(失礼)という感じがしてきます。もっと綺麗な構文で書けないのでしょうか。同じようなことを考えている人はあるようで、Python から Ngspice を制御するライブラリを作っていらっしゃる方があります。
どんなことができるのだろう、という方は、以下のページを御覧になると御参考になるかと思います。
NumPy や matplotlib と連携できるようで、これまた興味深いです。
今日はここまで。
お問い合わせはお気軽に!
繰り返しになりますが、私の書いている内容には基本的な間違いや勘違いがたくさんあると思います。御教示頂けましたら幸いです。