ディジタル回路シミュレータ「SimcirJS」をひさしぶりに使ってみた

はじめに

NTT西日本の ふるかわ といいます。

本記事は、入社XX年(ナイショ)のベテラン(?)技術者が、ひさしぶりにディジタル回路シミュレータを触ってみたくなった顛末記のようなものです。

本記事は2025年11月時点の情報に基づいています。

対象読者

まわりの記事と比較すると、すこし異色かも知れません。 本記事は、ディジタル回路に興味があるひと、「コンピュータの中身ってどうやって動いてるんだっけ」ということをちょっと覗いてみたいひと、などに、ごく簡単な導入ができたらいいな、と思って書き記すものです。 あまり、お勉強お勉強にならないように気を付けますが、代わりに(?)学術的に厳密でもないかも知れないので、入門編の読み物としてサラっと読んでみていただけるとありがたいです。

背景・目的

あまりこれと言った背景はないのですが、なぜか無性に「3進カウンタ」が作りたくなりました。

0→1→2→0→1→2→… と、みっつの値を繰り返すカウンタです。野球の「ストライク」(または「アウト」)のカウンタをイメージしてもらうとよろしいかと思います。 ディジタル回路の特性上、2n進カウンタ(2進、4進、8進、…)はとても簡単に作れるのですがそれ以外のカウンタは、ちょっと面倒だったりします。

こんなとき、約四半世紀前に大学生をしていたころなら、巨大なディジタル回路実験盤を持ち出して大変な思いをしていましたが、イマドキそんなのはシミュレータを使えば簡単にシミュレーションできるようになっています。 しかもありがたいことに無償で使えるものもありますから、これを活用するのが便利です。ということで、ひさびさの利用になる「SimcirJS」というシミュレータを使ってみることにしました。

SimcirJSとは

HTML5とJavaScriptでできたディジタル回路シミュレータで、MITライセンスで公開されています。 ブラウザから利用できるため、インストール不要で使い始めることができます。高専・大学等の授業でも多く利用されているようで、教材等が公開されているものもあります。 わたしも、いくつかのサイトを参考にさせていただきました。それらは、文末の参考資料の節にまとめます。

まずは触ってみよう

SimcirJSの作者さんのサイト「Kazuhiko Arase's Workplace」 https://kazuhikoarase.github.io/simcirjs/index.html にアクセスすれば、すぐに利用することができます。

SimcirJSのWebサイト画面例、ウィンドウの下方にSimcirJSのワークエリアがある
SimcirJSの画面例

左側から回路の要素を選んで、右側にドラッグアンドドロップし、

SimcirJSのWebサイト画面で、左側ツールエリアから右側ワークエリアに向けてパーツをドラッグアンドドロップで設置するところ
SimcirJSの操作例

回路の端子同士をドラッグ操作でつなぐと結線されます。

SimcirJSのWebサイト画面例、ワークエリアに設置したふたつの部品の端子間をマウスでドラッグし、結線をする様子
SimcirJSの結線操作例

このとき注意事項は、回路の右側の端子(白)は出力で、いくつも分岐させられますが、 回路の左側の端子(橙)は入力になるので、分岐はできません。

「DC」は直流電源(Direct Current)、「LED」は発光ダイオード(Light-Emitting Diode)なので、このふたつを結線すると、「LEDが光った」ことになり、 画面上ではLEDの表示が黒丸から赤丸に変わります。

SimcirJSのWebサイト画面例、SimcirJSのワークエリア内でDCとLEDを結線し、LEDが光っているところ。比較用に未結線のLEDがあり、そちらは光っていない。
SimcirJS動作例、DCとLEDを結線するとLEDが点灯する

試しに、ディジタル回路らしく、AND回路とOR回路の動きを確かめておきましょう。 どちらも入力をふたつ・出力をひとつ持つ回路ですが、 AND回路は入力が両方とも1のときだけ出力も1に、 逆にOR回路は入力が両方とも0のときだけ出力も0に、 それぞれなるような回路です。
ここで、0とは電圧なし、1は電圧ありのことなので、「DC」回路とトグルスイッチ(「Toggle」)を使って、次のような回路を組んでみましょう。
SimcirJSのWebサイト画面例、SimcirJSのワークエリアにDC、ToggleとAND・OR及び確認用のLEDを設置。Toggleスイッチを切り替えた際のLEDの光り方を例示。一方でもONならLEDが光っているのがOR回路、両方がONのときだけLEDが光るのがAND回路。
SimcirJSの動作例 AND回路とOR回路

「トグルスイッチ」とは、部屋の電気(照明)のスイッチのように、スイッチから指を離しても切り替わった状態が維持されるようなスイッチのことです。 「Toggle」の上にある「PushOn」「PushOff」のスイッチは、指で押している間だけON(またはOFF)になるようなスイッチです。 このような動作確認のときは、指を離しても切り替わったままになっている方が便利なので、トグルスイッチを利用するのがよいでしょう。
トグルスイッチをONにすれば「DC」とつながって電圧あり(つまり入力1)、OFFなら電圧なし(入力0)になりますから、 ANDとORの動きを確かめることができました。

JKフリップフロップ回路

まず、フリップフロップとは

フリップフロップ回路とは、1bit (2値) の状態を保持できる回路のことです。 「フリップフロップ」(flip-flop) とは、シーソーがあっちこっちに傾くときの擬音だそうで、 その名の通り、シーソーを思い浮かべていただくのがいちばん分かりやすいと思います。 いま、なにも乗っていないシーソーが左に傾いているとします。なにもしなければ左に傾いているままです。 そこで右側にだけ荷物をのせると、今度は右に傾きます。ここまでは当たり前なのですが、 ミソはその次で、右に傾いたあとで、荷物を降ろすとどうなるでしょうか。そうです、荷物を降ろしても シーソーは右に傾いたままになります。次にもういちど左に荷物を載せて、左に傾けると、 その荷物を降ろした後もシーソーは左に傾いたままになります。
これはどういうことかというと、シーソーは、「最後に荷物が載った状態(降ろす直前の状態)」を「保持している」 ということになります。言い換えると「最後に荷物が載った側がどちらか」を「覚えている」とも言えます。
この「右」と「左」を「0」と「1」に読み替えると、シーソーは1bitのメモリ装置である、と言えることになります。
フリップフロップ回路もシーソーと同じように、最後にかけられた信号の状態を保持するような回路です。

JKフリップフロップとは

フリップフロップ回路には、いくつかの種類があります。 その中のひとつであるJKフリップフロップ回路(以下 JK-FF) は、JとKのふたつの値とクロック(CLK)、合計3つの入力端子を持っています。 また、出力としてはQと~Qのふたつの端子を持っています。「~Q」は、「Qの逆」という意味で、Q=0なら~Q=1、Q=1なら~Q=0という関係です。
まずはふたつの値、JとKについて説明します。
(J,K)=(1,0)のときは、フリップフロップ回路の状態には「1」がセットされます。右に傾いた状態です。このときフリップフロップ回路の出力も「1」になります。 (J,K)=(0,1)のときは、同様に値0がセットされます。左に傾いた状態です。フリップフロップ回路の出力は「0」になります。 (J,K)=(0,0)のとき、つまり入力が何もないときは、前の状態を保持します。シーソーどちらにも荷物がない状態なので、 最後に傾いた方を覚えています。フリップフロップ回路の出力は、直前の出力が継続されます。
次にJK-FFのいちばんの特徴である、(J,K)=(1,1)のときの動きです。シーソーに喩えると、「両側に荷物を載せた状態」 とも言える、特殊な入力です。シーソーであれば、右にも左にも傾かず、水平に釣り合ってしまいます。ディジタル回路では、 これはすこしマズそうです。0でも1でもないものは存在させられないですから。なので、JK-FFでは、(J,K)=(1,1)のときは、 「いまの状態を反転させる」という特別な動きを定義しています。いまが1なら0をセット、いまが0なら1をセット、 というように動きます。したがって、フリップフロップからの出力も、直前の出力と逆のものに切り替えられます。 これを利用することで、JK-FFの状態を0→1→0→1…と順に変更していくことができます。 なにかに使えそうです。
ただしひとつ注意すべき点があります。(J,K)=(1,1)の状態をずっと続けるとどうなるでしょうか。 これもシーソーに喩えると、シーソーが右に左にバタバタしてしまいそうです。「ボタンを押したらシーソーが 左右に倒れる装置」があったとして、そのボタンをポチ・ポチ・…と押しているときはいいのですが、 「長押し」をしてしまうとよくなさそうです。さらに付け加えると、「長押し」でなかったとしても、 ポチっと1回だけ押したつもりがバタバタっと左右に2回分の動きになってしまうかも知れません。 これはまずいです。
最後に出力Q・~Qですが、これはJKーFFの状態により、0または1のどちらかが出力されます。 JK-FFの状態が0のときはQ=0が、JK-FFの状態が1のときはQ=1がそれぞれ出力されます。 先に述べたように(J,K)=(1,1)が入力され、JK-FFの状態が0→1→0→1…と切り替わるとき、 出力Qの値も、Q=0→1→0→1…と切り替わります。

クロックとは

そこでJK-FFにもうひとつ、クロック(CLK)という入力を付けます。 クロックというのは、「CPUの最大クロックは5.4GHz」などと言っている、このクロックと同じものです。 クロックを喩えるなら、「メトロノーム」を思い浮かべてください。音楽の時間に使う、カチコチとリズムを取る、あれです。 ディジタル回路のさまざまな動作を、メトロノームがカチコチとリズムを刻んだ瞬間だけ動作するように制御します。 (J,K)=(1,1)の入力をずっと続けていても、メトロノームがカチコチと刻んだタイミングだけ、シーソーが倒れるように すればよい、というアイディアです。この「メトロノームがカチコチと刻んだタイミング」のことを、「クロックタイミング」といいます。クロックタイミングが1秒間に何回訪れるかを示すのが「クロック周波数」です。 ですので、クロック周波数が速いと、クロックタイミングがより頻繁に訪れ、よってシーソーの倒れる頻度が高くなります。 「CPUのクロック周波数が速いと計算能力も高い」ということと、なんとなくですが結び付きそうです。
ちなみにクロック波形には通常は矩形波(方形波)を入力しますが、矩形波の立ち上がりまたは立ち下がり どちらかの瞬間をクロックタイミングとするケースが多いです。SimcirJSのJK-FFでは、 立ち下がりの瞬間をクロックタイミングとしています。PushOnボタン操作でいうと、押して、離した瞬間が クロックタイミングになります。(これ、実は後の伏線になっています。)

クロック信号の矩形波グラフが左右ふたつ。左は立ち上がりの例、右は立ち下がりの例。
クロック波形の例

カウンタ回路を作る

前置きが長くなりましたが、このJK-FFを使って、カウンタ回路を作ることができます。 クロック入力付きのJK-FF回路は、SimcirJSに初めから登録されているので、これを利用しましょう。

SimcirJSのWebサイト画面例、左側ツールエリアにあるJKフリップフロップ回路を示す
SimcirJSのJKフリップフロップ回路


JK-FFの「(J,K)=(1,1)のときはいまの状態を反転させる」を利用すると、 J=K=1のとき、クロックタイミングごとに 状態がOFF→ON→OFF→ON…と変化していきます。 状態が変化するので、あわせて出力も0→1→0→1…と変化します。 これは、見方を変えると、入力をJ=K=1に固定しておくと、クロックが入るごとに状態が変わることになります。 さらに言い換えると、クロックが入った回数を、1回だけ数えている、ということになります。 記憶できる値が0か1かの1bitなので、すぐに桁あふれ(オーバーフロー)を起こしてしまいますが 動作としては「カウンタ」と言えるものができます。「1bitのカウンタ」です。

SimcirJSのWebサイト画面例、ワークエリア内でのJKフリップフロップを使った1bitカウンタの作成例および回路図
SimcirJSでJK-FFで1bitカウンタを作る

ただ、数えられる値があまりに少なすぎて、「カウンタ」というイメージがあまり湧きません。 どうにかして、もう少し多くの値を数えられるようにならないでしょうか。 桁あふれ(オーバーフロー)してしまうのが問題なので、「桁上がり」の仕組みを作れば、桁数を増やして 数えられる値を増やしていけそうです。 桁上がりの仕組みなので、0→1になって、次に1→0になるときに、上位桁をひとつ繰り上げればよいことになります。
というのはよいのですが、実際問題として「1→0になるとき」を検出するのは、どうすればよいでしょうか。 1→0になる、ON→OFFになる、矩形波が立ち下がる、…。そうなんです、実は、JK-FFの出力(Q)を、 そのまま次のJK-FFのCLKに入れるだけでいいんです。「立ち下がりがクロックタイミングになっている」のは この応用を見越した伏線だったのです。非常に巧妙な設計ですね。
ということで、こういう回路を組んでみます。実際どうなるか

SimcirJSのWebサイト画面例、ワークエリア内でのJKフリップフロップを使った2bitカウンタの作成例および回路図
SimcirJSでJK-FFで2bitカウンタを作る


…と、2bitのカウンタができあがりました。2bitなので4値、つまり0→1→2→3→0→1→2→3→…、 と数えられます。同じように後ろに後ろにJK-FFをつなげていくと、3bit、4bit、…のカウンタが作れます。 冒頭で「2n進カウンタはとても簡単に作れる」と記載しましたが、このとおりです。

3進カウンタへの道

どうやって3進に

さて、欲しいのは3進カウンタでした。つまり0→1→2→0→1→2→… と繰り返してほしいのです。 ぱっと思いつくのは、3より大きな最小の2n数である4進カウンタを使って、 0→1→2→3→0→1→2→3→…となるところの「余計なもの」つまり「→3」の部分を削る方法です。 「カウンタ状態が3のときにも、表示上は2と同じにする」という方法もありますが、 この場合0→1→2→2→0→1→2→2→…という、ちょっとコレジャナイ感のカウンタができてしまうので却下とします。

強制リセット

「→3 の部分を削る」と書きましたが、「→3」の瞬間で状態をリセットしてしまうと、→3が削られることになります。 JK-FFの状態を無理やりリセットできると便利そうです。
市販の実際のICチップでは、リセット(クリア)のついたJK-FFがいろいろ販売されています。 例えばテキサスインスツルメンツ社 SN74LS73AN、や、東芝社 TC74HC107AF などがそうです。 ですが、SimcirJSで用意されているJK-FFには、リセット端子はありません。

なければ作る!?

筆者は実家が町工場でして、幼少の頃より「なければ作る、壊れたら直す」の精神で生きてきました(若干誇張)。 「リセット付きJK-FF」も、ANDやORを組み合わせれば作れますので、なければ作るの精神で臨んでみましょう。 ちなみに元から用意されているJK-FFも、実はANDやORの組み合わせで作られています。JK-FFのパーツを ダブルクリックすると

SimcirJSのWebサイト画面例、ツールエリアにある標準準備のJK-FFをダブルクリックし、内容が表示されたところ。2個のRSフリップフロップを含む複数の部品から構成されている様子。
SimcirJSの標準準備のJK-FFの中身

のように、登録されている回路が出てきます。高級言語のライブラリ関数のようなものですね。 なので、同じように「リセット付きJK-FF」をひとつ自作して、登録してしまいましょう。

リセット付きJK-FF

ということで、もとのJK-FFの中身を参考にしながら、リセット付きJK-FFの回路を作りました。

SimcirJSのWebサイト画面例、ワークエリア内でリセット付きJKフリップフロップ回路を構成した例。2個のRSフリップフロップとその他合計30個程度の部品を使って構成している。
SimcirJSでのリセット付きJKフリップフロップ構成例

リセット付きJKフリップフロップの論理回路図例
リセット付きJKフリップフロップの回路図例

これを解説しているとちょっと長くなりそうなので、すいませんが、ポイントだけにします。

  • SimcirJS標準のJK-FFの回路にリセット(RST)入力端子を付け足して、ここに入力があった際には、両方の「RS-FF」にリセット入力(~S,~R)=(1,0)が入るようにしました(青破線部)
    (このとき、SimcirJS標準搭載のRS-FFは、入力が(S,R)ではなく、(~S,~R)であることに注意)
  • その他の部分はSimcirJS標準のJK-FFの回路を基にしていますが、「3入力NAND」回路を、2入力AND回路とNOT回路に分解しています(赤破線部)

この通り作るか、またはJSONコードを載せておくので、使ってみてください。

リセット付きJK-FFのJSONコードを表示

{
  "width":800,
  "height":400,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"DC","id":"dev0","x":16,"y":144,"label":"DC"},
    {"type":"Toggle","id":"dev1","x":80,"y":88,"label":"Toggle","state":{"on":false}},
    {"type":"PushOn","id":"dev2","x":80,"y":144,"label":"PushOn"},
    {"type":"PushOn","id":"dev3","x":80,"y":304,"label":"PushOn"},
    {"type":"Toggle","id":"dev4","x":80,"y":208,"label":"Toggle","state":{"on":false}},
    {"type":"AND","id":"dev5","x":208,"y":112,"label":"AND"},
    {"type":"AND","id":"dev6","x":208,"y":184,"label":"AND"},
    {"type":"AND","id":"dev7","x":264,"y":112,"label":"AND"},
    {"type":"NOT","id":"dev8","x":328,"y":112,"label":"NOT"},
    {"type":"NOT","id":"dev9","x":328,"y":184,"label":"NOT"},
    {"type":"RS-FF","id":"dev10","x":384,"y":144,"label":"RS-FF"},
    {"type":"NAND","id":"dev11","x":472,"y":112,"label":"NAND"},
    {"type":"NAND","id":"dev12","x":472,"y":184,"label":"NAND"},
    {"type":"NOT","id":"dev13","x":288,"y":320,"label":"NOT"},
    {"type":"AND","id":"dev14","x":344,"y":320,"label":"AND"},
    {"type":"OR","id":"dev15","x":312,"y":272,"label":"OR"},
    {"type":"NOT","id":"dev16","x":472,"y":320,"label":"NOT"},
    {"type":"AND","id":"dev17","x":536,"y":320,"label":"AND"},
    {"type":"LED","id":"dev18","x":424,"y":32,"label":"LED"},
    {"type":"LED","id":"dev19","x":576,"y":32,"label":"LED"},
    {"type":"NOT","id":"dev20","x":208,"y":32,"label":"NOT"},
    {"type":"OR","id":"dev21","x":512,"y":272,"label":"OR"},
    {"type":"RS-FF","id":"dev22","x":552,"y":144,"label":"RS-FF"},
    {"type":"AND","id":"dev23","x":264,"y":184,"label":"AND"},
    {"type":"In","id":"dev24","x":144,"y":88,"label":"J"},
    {"type":"In","id":"dev25","x":144,"y":144,"label":"CLK"},
    {"type":"In","id":"dev26","x":144,"y":208,"label":"K"},
    {"type":"In","id":"dev27","x":144,"y":304,"label":"RST"},
    {"type":"Out","id":"dev28","x":632,"y":96,"label":"Q"},
    {"type":"Out","id":"dev29","x":632,"y":192,"label":"~Q"}
  ],
  "connectors":[
    {"from":"dev1.in0","to":"dev0.out0"},
    {"from":"dev2.in0","to":"dev0.out0"},
    {"from":"dev3.in0","to":"dev0.out0"},
    {"from":"dev4.in0","to":"dev0.out0"},
    {"from":"dev5.in0","to":"dev24.out0"},
    {"from":"dev5.in1","to":"dev25.out0"},
    {"from":"dev6.in0","to":"dev25.out0"},
    {"from":"dev6.in1","to":"dev26.out0"},
    {"from":"dev7.in0","to":"dev5.out0"},
    {"from":"dev7.in1","to":"dev22.out1"},
    {"from":"dev8.in0","to":"dev7.out0"},
    {"from":"dev9.in0","to":"dev23.out0"},
    {"from":"dev10.in0","to":"dev15.out0"},
    {"from":"dev10.in1","to":"dev14.out0"},
    {"from":"dev11.in0","to":"dev20.out0"},
    {"from":"dev11.in1","to":"dev10.out0"},
    {"from":"dev12.in0","to":"dev10.out1"},
    {"from":"dev12.in1","to":"dev20.out0"},
    {"from":"dev13.in0","to":"dev27.out0"},
    {"from":"dev14.in0","to":"dev9.out0"},
    {"from":"dev14.in1","to":"dev13.out0"},
    {"from":"dev15.in0","to":"dev8.out0"},
    {"from":"dev15.in1","to":"dev27.out0"},
    {"from":"dev16.in0","to":"dev27.out0"},
    {"from":"dev17.in0","to":"dev12.out0"},
    {"from":"dev17.in1","to":"dev16.out0"},
    {"from":"dev18.in0","to":"dev10.out0"},
    {"from":"dev19.in0","to":"dev22.out0"},
    {"from":"dev20.in0","to":"dev25.out0"},
    {"from":"dev21.in0","to":"dev11.out0"},
    {"from":"dev21.in1","to":"dev27.out0"},
    {"from":"dev22.in0","to":"dev21.out0"},
    {"from":"dev22.in1","to":"dev17.out0"},
    {"from":"dev23.in0","to":"dev22.out0"},
    {"from":"dev23.in1","to":"dev6.out0"},
    {"from":"dev24.in0","to":"dev1.out0"},
    {"from":"dev25.in0","to":"dev2.out0"},
    {"from":"dev26.in0","to":"dev4.out0"},
    {"from":"dev27.in0","to":"dev3.out0"},
    {"from":"dev28.in0","to":"dev22.out0"},
    {"from":"dev29.in0","to":"dev22.out1"}
  ]
}


説明していませんでしたが、SimcirJSの回路は、全部JSONで表記が可能です。 ワークエリアを Ctrl+クリック すると表示が切り替わります。もういちどCtrl+クリックすると元の表示に戻ります。 (Mac系マシンご利用の場合は Command+クリック です)
SimcirJSのWebサイト画面例、ツールエリア・ワークエリアがなくなり、JSONコードが表示されている。Ctrl-クリックでJSONコード表示・通常表示を切り替えられる。
SimcirJSの画面例 JSONコード表示

登録のやり方・・・

さて登録だ、と思ったのですが、登録方法は「simcir-library.js ファイルに回路定義した内容を追記する」とのこと。 ということは、サイト上のSimcirJSの設定ファイルの編集権限が必要、ということになります。 つまり、誰かが立てたサイト上のSimcirJSを使わせてもらってるのではだめで、 自分でhttpdを立てて、自らSimcirJSをインストールせよ、ということになります。

httpdサーバ

筆者はたまたま手元にESXi環境があり、LinuxOSの仮想マシンが稼働していたので、ここにさっとhttpdを立てて、SimcirJSを置いてみました。 サイトさえ立てばよく、必ずしもLinuxである必要はありませんので、手元にLinux環境がない場合は、Windowsのローカル環境にhttpdを 立てるやり方でも大丈夫です。

SimcirJSの入手方法については、いま https://kazuhikoarase.github.io/simcirjs/index.html を利用しているなら、画面上の方にダウンロードボタンがあります。

kazuhikoarase.github.io サイトのSimcirJSダウンロード用のボタン位置を示す図面
SimcirJSのダウンロード

または https://github.com/kazuhikoarase/simcirjs/archive/master.zip からダウンロードできます(同じリンク先です)。

インストールといっても./configure も make も不要で、ダウンロードしたZIPファイルを展開し、 そのファイル群を httpd の DocumentRoot 下のどこかにコピーするだけの簡単インストールです。 そのまま展開するとフォルダ名が「simcirjs-master」になりますが、ちょっと長いのでフォルダ名を「simcirjs」とし、 DocumentRoot直下の、/var/www/html/simcirjs/ に、一式をコピーしました。

あと、そのままでは index.html ファイルがなく、アクセスが少し面倒なので、sample.html をそのままコピーして index.html を作っておきました。

これで、自PC上のブラウザから、自前のSimcirJSが利用できるようになりました。

自作部品の登録

自作部品の登録は先は [DocumentRoot]/simcirjs/simcir-library.js のファイルです。先ほど作った「リセット付きJK-FF」を いちばん最後に追記しておきます。追記後の simcir-library.js を掲載しますが、ちょっと長いので、スクロールしてご覧ください。 部品の名称は「JK-FF-RST」としました。

//
// SimcirJS - library
//
// Copyright (c) 2014 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
//  http://www.opensource.org/licenses/mit-license.php
//

// includes following device types:
//  RS-FF
//  JK-FF
//  T-FF
//  D-FF
//  8bitCounter
//  HalfAdder
//  FullAdder
//  4bitAdder
//  2to4BinaryDecoder
//  3to8BinaryDecoder
//  4to16BinaryDecoder

simcir.registerDevice('RS-FF',
{
  "width":320,
  "height":160,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"NAND","id":"dev0","x":184,"y":32,"label":"NAND"},
    {"type":"NAND","id":"dev1","x":184,"y":80,"label":"NAND"},
    {"type":"In","id":"dev2","x":136,"y":24,"label":"~S"},
    {"type":"In","id":"dev3","x":136,"y":88,"label":"~R"},
    {"type":"Out","id":"dev4","x":232,"y":32,"label":"Q"},
    {"type":"Out","id":"dev5","x":232,"y":80,"label":"~Q"},
    {"type":"PushOff","id":"dev6","x":88,"y":24,"label":"PushOff"},
    {"type":"PushOff","id":"dev7","x":88,"y":88,"label":"PushOff"},
    {"type":"DC","id":"dev8","x":40,"y":56,"label":"DC"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev2.out0"},
    {"from":"dev0.in1","to":"dev1.out0"},
    {"from":"dev1.in0","to":"dev0.out0"},
    {"from":"dev1.in1","to":"dev3.out0"},
    {"from":"dev2.in0","to":"dev6.out0"},
    {"from":"dev3.in0","to":"dev7.out0"},
    {"from":"dev4.in0","to":"dev0.out0"},
    {"from":"dev5.in0","to":"dev1.out0"},
    {"from":"dev6.in0","to":"dev8.out0"},
    {"from":"dev7.in0","to":"dev8.out0"}
  ]
}
);

simcir.registerDevice('JK-FF',
{
  "width":480,
  "height":240,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"RS-FF","id":"dev0","x":216,"y":112,"label":"RS-FF"},
    {"type":"RS-FF","id":"dev1","x":344,"y":112,"label":"RS-FF"},
    {"type":"NAND","numInputs":3,"id":"dev2","x":168,"y":80,"label":"NAND"},
    {"type":"NAND","numInputs":3,"id":"dev3","x":168,"y":144,"label":"NAND"},
    {"type":"NAND","id":"dev4","x":296,"y":80,"label":"NAND"},
    {"type":"NAND","id":"dev5","x":296,"y":144,"label":"NAND"},
    {"type":"NOT","id":"dev6","x":168,"y":24,"label":"NOT"},
    {"type":"In","id":"dev7","x":120,"y":64,"label":"J"},
    {"type":"In","id":"dev8","x":120,"y":112,"label":"CLK"},
    {"type":"In","id":"dev9","x":120,"y":160,"label":"K"},
    {"type":"Out","id":"dev10","x":424,"y":80,"label":"Q"},
    {"type":"Out","id":"dev11","x":424,"y":144,"label":"~Q"},
    {"type":"Toggle","id":"dev12","x":72,"y":64,"label":"Toggle"},
    {"type":"PushOn","id":"dev13","x":72,"y":112,"label":"PushOn"},
    {"type":"Toggle","id":"dev14","x":72,"y":160,"label":"Toggle"},
    {"type":"DC","id":"dev15","x":24,"y":112,"label":"DC"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev2.out0"},
    {"from":"dev0.in1","to":"dev3.out0"},
    {"from":"dev1.in0","to":"dev4.out0"},
    {"from":"dev1.in1","to":"dev5.out0"},
    {"from":"dev2.in0","to":"dev1.out1"},
    {"from":"dev2.in1","to":"dev7.out0"},
    {"from":"dev2.in2","to":"dev8.out0"},
    {"from":"dev3.in0","to":"dev8.out0"},
    {"from":"dev3.in1","to":"dev9.out0"},
    {"from":"dev3.in2","to":"dev1.out0"},
    {"from":"dev4.in0","to":"dev6.out0"},
    {"from":"dev4.in1","to":"dev0.out0"},
    {"from":"dev5.in0","to":"dev0.out1"},
    {"from":"dev5.in1","to":"dev6.out0"},
    {"from":"dev6.in0","to":"dev8.out0"},
    {"from":"dev7.in0","to":"dev12.out0"},
    {"from":"dev8.in0","to":"dev13.out0"},
    {"from":"dev9.in0","to":"dev14.out0"},
    {"from":"dev10.in0","to":"dev1.out0"},
    {"from":"dev11.in0","to":"dev1.out1"},
    {"from":"dev12.in0","to":"dev15.out0"},
    {"from":"dev13.in0","to":"dev15.out0"},
    {"from":"dev14.in0","to":"dev15.out0"}
  ]
}
);

simcir.registerDevice('T-FF',
{
  "width":320,
  "height":160,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"JK-FF","id":"dev0","x":168,"y":48,"label":"JK-FF"},
    {"type":"In","id":"dev1","x":120,"y":32,"label":"T"},
    {"type":"In","id":"dev2","x":120,"y":80,"label":"CLK"},
    {"type":"Out","id":"dev3","x":248,"y":32,"label":"Q"},
    {"type":"Out","id":"dev4","x":248,"y":80,"label":"~Q"},
    {"type":"Toggle","id":"dev5","x":72,"y":32,"label":"Toggle"},
    {"type":"PushOn","id":"dev6","x":72,"y":80,"label":"PushOn"},
    {"type":"DC","id":"dev7","x":24,"y":56,"label":"DC"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev1.out0"},
    {"from":"dev0.in1","to":"dev2.out0"},
    {"from":"dev0.in2","to":"dev1.out0"},
    {"from":"dev1.in0","to":"dev5.out0"},
    {"from":"dev2.in0","to":"dev6.out0"},
    {"from":"dev3.in0","to":"dev0.out0"},
    {"from":"dev4.in0","to":"dev0.out1"},
    {"from":"dev5.in0","to":"dev7.out0"},
    {"from":"dev6.in0","to":"dev7.out0"}
  ]
}
);

simcir.registerDevice('D-FF',
{
  "width":540,
  "height":200,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"In","id":"dev0","x":128,"y":24,"label":"D"},
    {"type":"In","id":"dev1","x":168,"y":128,"label":"CLK"},
    {"type":"NOT","id":"dev2","x":176,"y":64,"label":"NOT"},
    {"type":"NAND","id":"dev3","x":224,"y":32,"label":"NAND"},
    {"type":"NAND","id":"dev4","x":224,"y":96,"label":"NAND"},
    {"type":"RS-FF","id":"dev5","x":272,"y":64,"label":"RS-FF"},
    {"type":"NOT","id":"dev6","x":296,"y":128,"label":"NOT"},
    {"type":"NAND","id":"dev7","x":352,"y":32,"label":"NAND"},
    {"type":"NAND","id":"dev8","x":352,"y":96,"label":"NAND"},
    {"type":"RS-FF","id":"dev9","x":400,"y":64,"label":"RS-FF"},
    {"type":"Out","id":"dev10","x":480,"y":32,"label":"Q"},
    {"type":"Out","id":"dev11","x":480,"y":96,"label":"~Q"},
    {"type":"Toggle","id":"dev12","x":80,"y":24,"label":"Toggle"},
    {"type":"PushOn","id":"dev13","x":80,"y":128,"label":"PushOn"},
    {"type":"DC","id":"dev14","x":32,"y":72,"label":"DC"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev12.out0"},
    {"from":"dev1.in0","to":"dev13.out0"},
    {"from":"dev2.in0","to":"dev0.out0"},
    {"from":"dev3.in0","to":"dev0.out0"},
    {"from":"dev3.in1","to":"dev1.out0"},
    {"from":"dev4.in0","to":"dev1.out0"},
    {"from":"dev4.in1","to":"dev2.out0"},
    {"from":"dev5.in0","to":"dev3.out0"},
    {"from":"dev5.in1","to":"dev4.out0"},
    {"from":"dev6.in0","to":"dev1.out0"},
    {"from":"dev7.in0","to":"dev5.out0"},
    {"from":"dev7.in1","to":"dev6.out0"},
    {"from":"dev8.in0","to":"dev6.out0"},
    {"from":"dev8.in1","to":"dev5.out1"},
    {"from":"dev9.in0","to":"dev7.out0"},
    {"from":"dev9.in1","to":"dev8.out0"},
    {"from":"dev10.in0","to":"dev9.out0"},
    {"from":"dev11.in0","to":"dev9.out1"},
    {"from":"dev12.in0","to":"dev14.out0"},
    {"from":"dev13.in0","to":"dev14.out0"}
  ]
}
);

simcir.registerDevice('8bitCounter',
{
  "width":320,
  "height":420,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"T-FF","id":"dev0","x":184,"y":16,"label":"T-FF"},
    {"type":"T-FF","id":"dev1","x":184,"y":64,"label":"T-FF"},
    {"type":"T-FF","id":"dev2","x":184,"y":112,"label":"T-FF"},
    {"type":"T-FF","id":"dev3","x":184,"y":160,"label":"T-FF"},
    {"type":"T-FF","id":"dev4","x":184,"y":208,"label":"T-FF"},
    {"type":"T-FF","id":"dev5","x":184,"y":256,"label":"T-FF"},
    {"type":"T-FF","id":"dev6","x":184,"y":304,"label":"T-FF"},
    {"type":"T-FF","id":"dev7","x":184,"y":352,"label":"T-FF"},
    {"type":"Out","id":"dev8","x":264,"y":16,"label":"D0"},
    {"type":"Out","id":"dev9","x":264,"y":64,"label":"D1"},
    {"type":"Out","id":"dev10","x":264,"y":112,"label":"D2"},
    {"type":"Out","id":"dev11","x":264,"y":160,"label":"D3"},
    {"type":"Out","id":"dev12","x":264,"y":208,"label":"D4"},
    {"type":"Out","id":"dev13","x":264,"y":256,"label":"D5"},
    {"type":"Out","id":"dev14","x":264,"y":304,"label":"D6"},
    {"type":"Out","id":"dev15","x":264,"y":352,"label":"D7"},
    {"type":"In","id":"dev16","x":120,"y":16,"label":"T"},
    {"type":"In","id":"dev17","x":120,"y":112,"label":"CLK"},
    {"type":"PushOn","id":"dev18","x":72,"y":112,"label":"PushOn"},
    {"type":"DC","id":"dev19","x":24,"y":16,"label":"DC"},
    {"type":"Toggle","id":"dev20","x":72,"y":16,"label":"Toggle"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev16.out0"},
    {"from":"dev0.in1","to":"dev17.out0"},
    {"from":"dev1.in0","to":"dev16.out0"},
    {"from":"dev1.in1","to":"dev0.out0"},
    {"from":"dev2.in0","to":"dev16.out0"},
    {"from":"dev2.in1","to":"dev1.out0"},
    {"from":"dev3.in0","to":"dev16.out0"},
    {"from":"dev3.in1","to":"dev2.out0"},
    {"from":"dev4.in0","to":"dev16.out0"},
    {"from":"dev4.in1","to":"dev3.out0"},
    {"from":"dev5.in0","to":"dev16.out0"},
    {"from":"dev5.in1","to":"dev4.out0"},
    {"from":"dev6.in0","to":"dev16.out0"},
    {"from":"dev6.in1","to":"dev5.out0"},
    {"from":"dev7.in0","to":"dev16.out0"},
    {"from":"dev7.in1","to":"dev6.out0"},
    {"from":"dev8.in0","to":"dev0.out0"},
    {"from":"dev9.in0","to":"dev1.out0"},
    {"from":"dev10.in0","to":"dev2.out0"},
    {"from":"dev11.in0","to":"dev3.out0"},
    {"from":"dev12.in0","to":"dev4.out0"},
    {"from":"dev13.in0","to":"dev5.out0"},
    {"from":"dev14.in0","to":"dev6.out0"},
    {"from":"dev15.in0","to":"dev7.out0"},
    {"from":"dev16.in0","to":"dev20.out0"},
    {"from":"dev17.in0","to":"dev18.out0"},
    {"from":"dev18.in0","to":"dev19.out0"},
    {"from":"dev20.in0","to":"dev19.out0"}
  ]
}
);

simcir.registerDevice('HalfAdder',
{
  "width":320,
  "height":160,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"Toggle","id":"dev0","x":96,"y":80,"label":"Toggle"},
    {"type":"DC","id":"dev1","x":48,"y":56,"label":"DC"},
    {"type":"AND","id":"dev2","x":192,"y":80,"label":"AND"},
    {"type":"XOR","id":"dev3","x":192,"y":32,"label":"XOR"},
    {"type":"In","id":"dev4","x":144,"y":32,"label":"A"},
    {"type":"In","id":"dev5","x":144,"y":80,"label":"B"},
    {"type":"Out","id":"dev6","x":240,"y":32,"label":"S"},
    {"type":"Out","id":"dev7","x":240,"y":80,"label":"C"},
    {"type":"Toggle","id":"dev8","x":96,"y":32,"label":"Toggle"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev1.out0"},
    {"from":"dev2.in0","to":"dev4.out0"},
    {"from":"dev2.in1","to":"dev5.out0"},
    {"from":"dev3.in0","to":"dev4.out0"},
    {"from":"dev3.in1","to":"dev5.out0"},
    {"from":"dev4.in0","to":"dev8.out0"},
    {"from":"dev5.in0","to":"dev0.out0"},
    {"from":"dev6.in0","to":"dev3.out0"},
    {"from":"dev7.in0","to":"dev2.out0"},
    {"from":"dev8.in0","to":"dev1.out0"}
  ]
}
);

simcir.registerDevice('FullAdder',
{
  "width":440,
  "height":200,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"In","id":"dev0","x":120,"y":32,"label":"Cin"},
    {"type":"In","id":"dev1","x":120,"y":80,"label":"A"},
    {"type":"In","id":"dev2","x":120,"y":128,"label":"B"},
    {"type":"Toggle","id":"dev3","x":72,"y":32,"label":"Toggle"},
    {"type":"Toggle","id":"dev4","x":72,"y":80,"label":"Toggle"},
    {"type":"Toggle","id":"dev5","x":72,"y":128,"label":"Toggle"},
    {"type":"DC","id":"dev6","x":24,"y":80,"label":"DC"},
    {"type":"HalfAdder","id":"dev7","x":168,"y":104,"label":"HalfAdder"},
    {"type":"HalfAdder","id":"dev8","x":248,"y":56,"label":"HalfAdder"},
    {"type":"OR","id":"dev9","x":328,"y":104,"label":"OR"},
    {"type":"Out","id":"dev10","x":376,"y":104,"label":"Cout"},
    {"type":"Out","id":"dev11","x":376,"y":48,"label":"S"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev3.out0"},
    {"from":"dev1.in0","to":"dev4.out0"},
    {"from":"dev2.in0","to":"dev5.out0"},
    {"from":"dev3.in0","to":"dev6.out0"},
    {"from":"dev4.in0","to":"dev6.out0"},
    {"from":"dev5.in0","to":"dev6.out0"},
    {"from":"dev7.in0","to":"dev1.out0"},
    {"from":"dev7.in1","to":"dev2.out0"},
    {"from":"dev8.in0","to":"dev0.out0"},
    {"from":"dev8.in1","to":"dev7.out0"},
    {"from":"dev9.in0","to":"dev8.out1"},
    {"from":"dev9.in1","to":"dev7.out1"},
    {"from":"dev10.in0","to":"dev9.out0"},
    {"from":"dev11.in0","to":"dev8.out0"}
  ]
}
);

simcir.registerDevice('4bitAdder',
{
  "width":280,
  "height":480,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"FullAdder","id":"dev0","x":120,"y":72,"label":"FullAdder"},
    {"type":"FullAdder","id":"dev1","x":120,"y":136,"label":"FullAdder"},
    {"type":"FullAdder","id":"dev2","x":120,"y":200,"label":"FullAdder"},
    {"type":"FullAdder","id":"dev3","x":120,"y":264,"label":"FullAdder"},
    {"type":"In","id":"dev4","x":40,"y":80,"label":"A0"},
    {"type":"In","id":"dev5","x":40,"y":128,"label":"A1"},
    {"type":"In","id":"dev6","x":40,"y":176,"label":"A2"},
    {"type":"In","id":"dev7","x":40,"y":224,"label":"A3"},
    {"type":"In","id":"dev8","x":40,"y":272,"label":"B0"},
    {"type":"In","id":"dev9","x":40,"y":320,"label":"B1"},
    {"type":"In","id":"dev10","x":40,"y":368,"label":"B2"},
    {"type":"In","id":"dev11","x":40,"y":416,"label":"B3"},
    {"type":"Out","id":"dev12","x":200,"y":72,"label":"S0"},
    {"type":"Out","id":"dev13","x":200,"y":120,"label":"S1"},
    {"type":"Out","id":"dev14","x":200,"y":168,"label":"S2"},
    {"type":"Out","id":"dev15","x":200,"y":216,"label":"S3"},
    {"type":"Out","id":"dev16","x":200,"y":280,"label":"Cout"},
    {"type":"In","id":"dev17","x":40,"y":24,"label":"Cin"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev17.out0"},
    {"from":"dev0.in1","to":"dev4.out0"},
    {"from":"dev0.in2","to":"dev8.out0"},
    {"from":"dev1.in0","to":"dev0.out1"},
    {"from":"dev1.in1","to":"dev5.out0"},
    {"from":"dev1.in2","to":"dev9.out0"},
    {"from":"dev2.in0","to":"dev1.out1"},
    {"from":"dev2.in1","to":"dev6.out0"},
    {"from":"dev2.in2","to":"dev10.out0"},
    {"from":"dev3.in0","to":"dev2.out1"},
    {"from":"dev3.in1","to":"dev7.out0"},
    {"from":"dev3.in2","to":"dev11.out0"},
    {"from":"dev12.in0","to":"dev0.out0"},
    {"from":"dev13.in0","to":"dev1.out0"},
    {"from":"dev14.in0","to":"dev2.out0"},
    {"from":"dev15.in0","to":"dev3.out0"},
    {"from":"dev16.in0","to":"dev3.out1"}
  ]
}
);

simcir.registerDevice('2to4BinaryDecoder',
{
  "width":400,
  "height":240,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"AND","numInputs":3,"id":"dev0","x":280,"y":24,"label":"AND"},
    {"type":"AND","numInputs":3,"id":"dev1","x":280,"y":72,"label":"AND"},
    {"type":"AND","numInputs":3,"id":"dev2","x":280,"y":120,"label":"AND"},
    {"type":"NOT","id":"dev3","x":192,"y":48,"label":"NOT"},
    {"type":"AND","numInputs":3,"id":"dev4","x":280,"y":168,"label":"AND"},
    {"type":"NOT","id":"dev5","x":192,"y":96,"label":"NOT"},
    {"type":"In","id":"dev6","x":192,"y":176,"label":"OE"},
    {"type":"In","id":"dev7","x":128,"y":48,"label":"D0"},
    {"type":"In","id":"dev8","x":128,"y":96,"label":"D1"},
    {"type":"Toggle","id":"dev9","x":80,"y":48,"label":"Toggle"},
    {"type":"Toggle","id":"dev10","x":80,"y":96,"label":"Toggle"},
    {"type":"DC","id":"dev11","x":32,"y":96,"label":"DC"},
    {"type":"Out","id":"dev12","x":328,"y":24,"label":"A0"},
    {"type":"Out","id":"dev13","x":328,"y":72,"label":"A1"},
    {"type":"Out","id":"dev14","x":328,"y":120,"label":"A2"},
    {"type":"Out","id":"dev15","x":328,"y":168,"label":"A3"},
    {"type":"Toggle","id":"dev16","x":80,"y":144,"label":"Toggle"}
  ],
  "connectors":[
    {"from":"dev0.in0","to":"dev3.out0"},
    {"from":"dev0.in1","to":"dev5.out0"},
    {"from":"dev0.in2","to":"dev6.out0"},
    {"from":"dev1.in0","to":"dev7.out0"},
    {"from":"dev1.in1","to":"dev5.out0"},
    {"from":"dev1.in2","to":"dev6.out0"},
    {"from":"dev2.in0","to":"dev3.out0"},
    {"from":"dev2.in1","to":"dev8.out0"},
    {"from":"dev2.in2","to":"dev6.out0"},
    {"from":"dev3.in0","to":"dev7.out0"},
    {"from":"dev4.in0","to":"dev7.out0"},
    {"from":"dev4.in1","to":"dev8.out0"},
    {"from":"dev4.in2","to":"dev6.out0"},
    {"from":"dev5.in0","to":"dev8.out0"},
    {"from":"dev6.in0","to":"dev16.out0"},
    {"from":"dev7.in0","to":"dev9.out0"},
    {"from":"dev8.in0","to":"dev10.out0"},
    {"from":"dev9.in0","to":"dev11.out0"},
    {"from":"dev10.in0","to":"dev11.out0"},
    {"from":"dev12.in0","to":"dev0.out0"},
    {"from":"dev13.in0","to":"dev1.out0"},
    {"from":"dev14.in0","to":"dev2.out0"},
    {"from":"dev15.in0","to":"dev4.out0"},
    {"from":"dev16.in0","to":"dev11.out0"}
  ]
}
);

simcir.registerDevice('3to8BinaryDecoder',
{
  "width":360,
  "height":440,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"In","id":"dev0","x":24,"y":144,"label":"D0"},
    {"type":"In","id":"dev1","x":24,"y":192,"label":"D1"},
    {"type":"In","id":"dev2","x":24,"y":240,"label":"D2"},
    {"type":"In","id":"dev3","x":24,"y":304,"label":"OE"},
    {"type":"NOT","id":"dev4","x":72,"y":240,"label":"NOT"},
    {"type":"AND","id":"dev5","x":120,"y":248,"label":"AND"},
    {"type":"AND","id":"dev6","x":120,"y":296,"label":"AND"},
    {"type":"2to4BinaryDecoder","id":"dev7","x":184,"y":144,"label":"2to4BinaryDecoder"},
    {"type":"2to4BinaryDecoder","id":"dev8","x":184,"y":224,"label":"2to4BinaryDecoder"},
    {"type":"Out","id":"dev9","x":296,"y":32,"label":"A0"},
    {"type":"Out","id":"dev10","x":296,"y":80,"label":"A1"},
    {"type":"Out","id":"dev11","x":296,"y":128,"label":"A2"},
    {"type":"Out","id":"dev12","x":296,"y":176,"label":"A3"},
    {"type":"Out","id":"dev13","x":296,"y":224,"label":"A4"},
    {"type":"Out","id":"dev14","x":296,"y":272,"label":"A5"},
    {"type":"Out","id":"dev15","x":296,"y":320,"label":"A6"},
    {"type":"Out","id":"dev16","x":296,"y":368,"label":"A7"}
  ],
  "connectors":[
    {"from":"dev4.in0","to":"dev2.out0"},
    {"from":"dev5.in0","to":"dev4.out0"},
    {"from":"dev5.in1","to":"dev3.out0"},
    {"from":"dev6.in0","to":"dev2.out0"},
    {"from":"dev6.in1","to":"dev3.out0"},
    {"from":"dev7.in0","to":"dev0.out0"},
    {"from":"dev7.in1","to":"dev1.out0"},
    {"from":"dev7.in2","to":"dev5.out0"},
    {"from":"dev8.in0","to":"dev0.out0"},
    {"from":"dev8.in1","to":"dev1.out0"},
    {"from":"dev8.in2","to":"dev6.out0"},
    {"from":"dev9.in0","to":"dev7.out0"},
    {"from":"dev10.in0","to":"dev7.out1"},
    {"from":"dev11.in0","to":"dev7.out2"},
    {"from":"dev12.in0","to":"dev7.out3"},
    {"from":"dev13.in0","to":"dev8.out0"},
    {"from":"dev14.in0","to":"dev8.out1"},
    {"from":"dev15.in0","to":"dev8.out2"},
    {"from":"dev16.in0","to":"dev8.out3"}
  ]
}
);

simcir.registerDevice('4to16BinaryDecoder',
{
  "width":440,
  "height":360,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"In","id":"dev0","x":32,"y":56,"label":"D0"},
    {"type":"In","id":"dev1","x":32,"y":104,"label":"D1"},
    {"type":"In","id":"dev2","x":32,"y":152,"label":"D2"},
    {"type":"In","id":"dev3","x":32,"y":200,"label":"D3"},
    {"type":"In","id":"dev4","x":32,"y":264,"label":"OE"},
    {"type":"NOT","id":"dev5","x":80,"y":200,"label":"NOT"},
    {"type":"AND","id":"dev6","x":136,"y":208,"label":"AND"},
    {"type":"AND","id":"dev7","x":136,"y":256,"label":"AND"},
    {"type":"3to8BinaryDecoder","id":"dev8","x":208,"y":32,"label":"3to8BinaryDecoder"},
    {"type":"3to8BinaryDecoder","id":"dev9","x":208,"y":184,"label":"3to8BinaryDecoder"},
    {"type":"BusOut","id":"dev10","x":320,"y":88,"label":"BusOut"},
    {"type":"BusOut","id":"dev11","x":320,"y":184,"label":"BusOut"},
    {"type":"Out","id":"dev12","x":376,"y":128,"label":"A0"},
    {"type":"Out","id":"dev13","x":376,"y":184,"label":"A1"}
  ],
  "connectors":[
    {"from":"dev5.in0","to":"dev3.out0"},
    {"from":"dev6.in0","to":"dev5.out0"},
    {"from":"dev6.in1","to":"dev4.out0"},
    {"from":"dev7.in0","to":"dev3.out0"},
    {"from":"dev7.in1","to":"dev4.out0"},
    {"from":"dev8.in0","to":"dev0.out0"},
    {"from":"dev8.in1","to":"dev1.out0"},
    {"from":"dev8.in2","to":"dev2.out0"},
    {"from":"dev8.in3","to":"dev6.out0"},
    {"from":"dev9.in0","to":"dev0.out0"},
    {"from":"dev9.in1","to":"dev1.out0"},
    {"from":"dev9.in2","to":"dev2.out0"},
    {"from":"dev9.in3","to":"dev7.out0"},
    {"from":"dev10.in0","to":"dev8.out0"},
    {"from":"dev10.in1","to":"dev8.out1"},
    {"from":"dev10.in2","to":"dev8.out2"},
    {"from":"dev10.in3","to":"dev8.out3"},
    {"from":"dev10.in4","to":"dev8.out4"},
    {"from":"dev10.in5","to":"dev8.out5"},
    {"from":"dev10.in6","to":"dev8.out6"},
    {"from":"dev10.in7","to":"dev8.out7"},
    {"from":"dev11.in0","to":"dev9.out0"},
    {"from":"dev11.in1","to":"dev9.out1"},
    {"from":"dev11.in2","to":"dev9.out2"},
    {"from":"dev11.in3","to":"dev9.out3"},
    {"from":"dev11.in4","to":"dev9.out4"},
    {"from":"dev11.in5","to":"dev9.out5"},
    {"from":"dev11.in6","to":"dev9.out6"},
    {"from":"dev11.in7","to":"dev9.out7"},
    {"from":"dev12.in0","to":"dev10.out0"},
    {"from":"dev13.in0","to":"dev11.out0"}
  ]
}
);

//
//  この下を追記
//
simcir.registerDevice('JK-FF-RST',
{
  "width":800,
  "height":400,
  "showToolbox":false,
  "toolbox":[
  ],
  "devices":[
    {"type":"DC","id":"dev0","x":16,"y":144,"label":"DC"},
    {"type":"Toggle","id":"dev1","x":80,"y":88,"label":"Toggle","state":{"on":false}},
    {"type":"PushOn","id":"dev2","x":80,"y":144,"label":"PushOn"},
    {"type":"PushOn","id":"dev3","x":80,"y":304,"label":"PushOn"},
    {"type":"Toggle","id":"dev4","x":80,"y":208,"label":"Toggle","state":{"on":false}},
    {"type":"AND","id":"dev5","x":208,"y":112,"label":"AND"},
    {"type":"AND","id":"dev6","x":208,"y":184,"label":"AND"},
    {"type":"AND","id":"dev7","x":264,"y":112,"label":"AND"},
    {"type":"NOT","id":"dev8","x":328,"y":112,"label":"NOT"},
    {"type":"NOT","id":"dev9","x":328,"y":184,"label":"NOT"},
    {"type":"RS-FF","id":"dev10","x":384,"y":144,"label":"RS-FF"},
    {"type":"NAND","id":"dev11","x":472,"y":112,"label":"NAND"},
    {"type":"NAND","id":"dev12","x":472,"y":184,"label":"NAND"},
    {"type":"NOT","id":"dev13","x":288,"y":320,"label":"NOT"},
    {"type":"AND","id":"dev14","x":344,"y":320,"label":"AND"},
    {"type":"OR","id":"dev15","x":312,"y":272,"label":"OR"},
    {"type":"NOT","id":"dev16","x":472,"y":320,"label":"NOT"},
    {"type":"AND","id":"dev17","x":536,"y":320,"label":"AND"},
    {"type":"LED","id":"dev18","x":424,"y":32,"label":"LED"},
    {"type":"LED","id":"dev19","x":576,"y":32,"label":"LED"},
    {"type":"NOT","id":"dev20","x":208,"y":32,"label":"NOT"},
    {"type":"OR","id":"dev21","x":512,"y":272,"label":"OR"},
    {"type":"RS-FF","id":"dev22","x":552,"y":144,"label":"RS-FF"},
    {"type":"AND","id":"dev23","x":264,"y":184,"label":"AND"},
    {"type":"In","id":"dev24","x":144,"y":88,"label":"J"},
    {"type":"In","id":"dev25","x":144,"y":144,"label":"CLK"},
    {"type":"In","id":"dev26","x":144,"y":208,"label":"K"},
    {"type":"In","id":"dev27","x":144,"y":304,"label":"RST"},
    {"type":"Out","id":"dev28","x":632,"y":96,"label":"Q"},
    {"type":"Out","id":"dev29","x":632,"y":192,"label":"~Q"}
  ],
  "connectors":[
    {"from":"dev1.in0","to":"dev0.out0"},
    {"from":"dev2.in0","to":"dev0.out0"},
    {"from":"dev3.in0","to":"dev0.out0"},
    {"from":"dev4.in0","to":"dev0.out0"},
    {"from":"dev5.in0","to":"dev24.out0"},
    {"from":"dev5.in1","to":"dev25.out0"},
    {"from":"dev6.in0","to":"dev25.out0"},
    {"from":"dev6.in1","to":"dev26.out0"},
    {"from":"dev7.in0","to":"dev5.out0"},
    {"from":"dev7.in1","to":"dev22.out1"},
    {"from":"dev8.in0","to":"dev7.out0"},
    {"from":"dev9.in0","to":"dev23.out0"},
    {"from":"dev10.in0","to":"dev15.out0"},
    {"from":"dev10.in1","to":"dev14.out0"},
    {"from":"dev11.in0","to":"dev20.out0"},
    {"from":"dev11.in1","to":"dev10.out0"},
    {"from":"dev12.in0","to":"dev10.out1"},
    {"from":"dev12.in1","to":"dev20.out0"},
    {"from":"dev13.in0","to":"dev27.out0"},
    {"from":"dev14.in0","to":"dev9.out0"},
    {"from":"dev14.in1","to":"dev13.out0"},
    {"from":"dev15.in0","to":"dev8.out0"},
    {"from":"dev15.in1","to":"dev27.out0"},
    {"from":"dev16.in0","to":"dev27.out0"},
    {"from":"dev17.in0","to":"dev12.out0"},
    {"from":"dev17.in1","to":"dev16.out0"},
    {"from":"dev18.in0","to":"dev10.out0"},
    {"from":"dev19.in0","to":"dev22.out0"},
    {"from":"dev20.in0","to":"dev25.out0"},
    {"from":"dev21.in0","to":"dev11.out0"},
    {"from":"dev21.in1","to":"dev27.out0"},
    {"from":"dev22.in0","to":"dev21.out0"},
    {"from":"dev22.in1","to":"dev17.out0"},
    {"from":"dev23.in0","to":"dev22.out0"},
    {"from":"dev23.in1","to":"dev6.out0"},
    {"from":"dev24.in0","to":"dev1.out0"},
    {"from":"dev25.in0","to":"dev2.out0"},
    {"from":"dev26.in0","to":"dev4.out0"},
    {"from":"dev27.in0","to":"dev3.out0"},
    {"from":"dev28.in0","to":"dev22.out0"},
    {"from":"dev29.in0","to":"dev22.out1"}
  ]
}
);

すると、ツールエリアのいちばん下に、「JK-FF-RST」が追加されています。

SimcirJSのWebサイト画面例、SimcirJSのツールエリアのいちばん最後の部品に、自作のリセット付きJKフリップフロップ回路がJK-FF-RSTとして登録されているところ
SimcirJSの画面例 ツールエリアに自作部品 JK-FF-RST が追加されている

これで、リセット付きJKフリップフロップが使えるようになりました。

ちなみに、このJK-FF-RSTをダブルクリックすると、ちゃんと中身が確認できます。

自分で追加した回路を使って組み上げる

自分で追加した回路を使って、目的の「3進カウンタ」を組み上げていきましょう。 といっても、使い方はこれまでの操作と変わりません。他の回路と同じようにワークエリアにドラッグアンドドロップし、結線するだけです。

3進カウンタ

0→1→2→3→0→1→2→3→…となるところの「→3」の瞬間でリセットしたいので、 「3」の状態、すなわち両方のJK-FFが「1」(ON)のときにリセットを入れればよさそうです。 両方が1のときだけ1になればいいので、AND回路が使えそうです。両方のJK-FFの出力QをAND回路に入力し、そのAND回路出力をRST端子につなぎこめば よさそうです。

なのですが、実は、両方のJK-FFのRST端子にそのまま入れてしまうと、うまく動きません。

3進カウンタのSimcirJS構成図と回路図、及びToggleボタンを押下したときのLEDの遷移パタン。LEDは上位ビット用・下位ビット用に計ふたつ、初期は(下位,上位)=(0,0)で、Toggle1回押下で(下位,上位)=(1,0)、2回押下で(下位,上位)=(0,1)と正しく動くが、3回以上押下しても(下位,上位)=(0,1)のままで変化しない。
3進カウンタの回路例と動作例 うまく動かないケース

両方同じタイミングで入れてしまうと、両方のJK-FFが同時に 0 になった瞬間に、下位側のJK-FFの1→0の 立ち下がり信号で上位側JK-FFが再度 1 に遷移してしまうためです。 対策として、上位側にリセットを入れるタイミングを少し遅らせます。バッファ(BUF)を入れるか、 ロジック上は意味のない「NOT-NOT」を通して上位側のリセットに入れます。

3進カウンタのSimcirJS構成図と回路図、及びToggleボタンを押下したときのLEDの遷移パタン。LEDは上位ビット用・下位ビット用に計ふたつ、初期は(下位,上位)=(0,0)で、Toggle1回押下で(下位,上位)=(1,0)、2回押下で(下位,上位)=(0,1)と正しく動き、また3回押下すると正しく初期状態に戻る。
3進カウンタの回路例と動作例 うまく動くケース

これで、思っていた通り動くようになりました。

動作例

ということで3進カウンタができたので、4進カウンタと合わせて、野球のカウンタ(BSO)のようにしてみました。 ついでに「4bit7seg」という便利な回路もあるので、あわせて組み込んでみました。LEDの点灯数と数字で ボールカウント・アウトカウントを表示してくれます。B/S/Oのそれぞれのボタンを押すごとに、B/S/Oが ひとつずつカウントされていきます。

SimcirJSのWebサイト画面例、野球のボール・ストライク・アウトのカウンタのような表示がされている。
SimcirJSで作成した野球カウンタ(BSO)の例

この回路も示しておきます。

野球のBSOカウンタの回路図、Bは4進カウンタ、SとOは3進カウンタを利用している論理回路図の例。
野球のBSOカウンタの回路図

さいごに

本物の野球のカウンタのように利用するのであれば、次のような機能もあるとよいのか、と思います。

  • Bが3→0に戻るとき(フォアボール)、Sも0に戻す、Oはそのまま
  • Sが2→0に戻るとき(三振)、Bも0に戻す。Oを増やしたい気がするが、「振り逃げ」のケースがあり得るので、Oはそのまま
  • Oが2→0に戻るとき(チェンジ)、BとSも0に戻す

どれも、リセット入力を利用することで実現可能です。その意味では、B用の4進カウンタも、「JK-FF」ではなく「JK-FF-RST」で 組んでおくべきでした。上記を満たすためには、どんな条件のときに、どのJK-FF-RSTにリセット信号を入れればよいか、 またそのときも、今回と同じようなタイミング調整(NOT-NOT回路)の必要があるか、興味のある方は、考えてみて、 SimcirJSで試してみてください。

まとめ

  • SimcirJSを使うと、ディジタル回路のシミュレーションが簡単にできます
  • すでにあるものを利用することもできますが、自分で立てたhttpd上へのインストールも、とても簡単にできます
  • 自作の回路を登録するには、すこし手間はかかりますが、決して難しくはありません
  • このよう簡単に試すことができるシミュレータで、ディジタル回路に興味を持っていただけるとありがたいです。
  • 筆者自身はディジタル回路をさわるのはひさびさで、かなり勘が鈍ってしまっていました。たまにはさわっておかないとダメですね。

執筆者

ふるかわ やすゆき (古川 靖之) NTT西日本 バリューデザイン部 所属

ふだんは、情報機器開発に携わっています。以前はビジネスフォンの開発も行っていました。

前職では法人営業SEで、自治体様を担当していました。その前は安全帽装備で建設現場に入っていたこともあります。もっと前はアプリ開発をしていたこともあります。ハード(電気電子)・ソフト(情報)・筐体(機械)をひととおり経験している、弊社では少し珍しいタイプの人間です。

技術士(電気電子部門、情報工学部門、機械部門、経営工学部門、総合技術監理部門)

参考資料・出典

本記事の作成にあたり参考にしたもの、そもそも自身でSimcirJSを使うために参照したものを紹介します。

SimcirJSを利用できるサイト

作者さんのサイト: https://kazuhikoarase.github.io/simcirjs/
作者さんのサイトです。ダウンロードもここからできますし、このサイト上でSimcirJSを利用することもできます。

論理回路シミュレータ SimcirJS の使い方: https://lecture.ecc.u-tokyo.ac.jp/JOHZU/joho/Y2016/LogicSimulator/LogicSimulator/01.html
SimcirJSの使い方の説明とともに、実際に利用できるページも用意されています。 ワークエリアが広くとってあります。

スク解ホーム: https://kaisaba.f5.si/html/simcirjs-master/index.html
赤色以外のLED(緑色・青色)や、3入力以上の論理ゲート回路が準備されています。 また、作成した回路のPCへの保存や、PCに保存したファイルからの読み出しができるようにされています。

ライセンス

SimcirJSはMITライセンスで公開されています。本記事に、配布コードの一部を引用した部分があることから、 SimcirJSのライセンス全文を掲載します。

MIT License

Copyright (c) 2014 Kazuhiko Arase

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

© NTT WEST, Inc.