注文してあったCD4007が到着。急遽こちらのシリーズをお休みしてCD4007の動作試験をやってました。CD4007は古いICですがMOSFETのソース、ドレイン、ゲートを個別に接続可能で変幻自在、まさにMOS回路を体現しています。そこでVerilogでもCD4007のモデリングを試みました。普通はやらんと思うケド。
※かえらざるMOS回路 投稿順 INDEX
CD4007到着時に書いた記事が以下です。
部品屋根性(81) CD4007入手、特別サービス?2種類入っていた。動作はOK、多分。
CD4007は変幻自在(インバータ、2入力NAND、NOR、AND、OR、3入力NAND、NORなどいろいろできる)なデバイスです。どういうわけかアナデバ様のサイトに以下の素晴らしい資料がありました。CD4007をロジックデバイスとして使う場合はご参照ください。
Build CMOS Logic Functions Using CD4007 Array – ADALM2000
ゲートレベルシミュレータLogisimでのモデル
Logisimはゲートレベルシミュレータですが、単体MOSFETもライブラリにはありモデリングできます。ただし、以下の制約があります。これはVerilogでのモデリングも同じ。
-
- MOSFETのモデルは単方向(本来は双方向)
- サブストレートの接続は無視して3端子
- MOSFETがオフっているときの出力はHiZ
CD4007の端子番号を与えた「ゲートレベル」回路が以下に。
上記をライブラリ化して3入力NANDとして結線してみたものが以下に。下の例では全ゲートに0を与えているので、出力(12番)は1です。ロジックシミュレータには珍しくVCC、GNDを配置して接続してます。
念のため、3NANDの入力に1,1,1を与えてみました。以下のように出力は0です。ちゃんとNAND動作しているみたい。
VerilogでのCD4007モデル
Verilogにも nmos とか pmos とかの「プリミティブ・ゲート」があります。以下の制約は同じです。
-
- MOSFETは単方向
- サブストレートは無視
- オフのときはX出力
単体CD4007をモデリングしてみたものが以下に。信号名の「数字」は端子番号です。
/** @file CD4007 Dual Complementary Pair Plus Inverter */ `ifndef CD4007_V_ `define CD4007_V_ module cd4007( O12, OP1, OP13, ON5, ON8, IP14, IP2, IP11, IN7, IN4, IN9, G6, G3, G10 ); input IP14, IP2, IP11, IN7, IN4, IN9, G6, G3, G10; output O12, OP1, OP13, ON5, ON8; pmos mp1 (OP13, IP14, G6); pmos mp2 (OP1, IP2, G3); pmos mp3 (O12, IP11, G10); nmos mn1 (ON8, IN7, G6); nmos mn2 (ON5, IN4, G3); nmos mn3 (O12, IN9, G10); endmodule `endif // CD4007_V_
CD4007を使った3入力NANDのテストベンチ
以下は、CD4007を1個おいて、3入力NANDとなるように結線し、動作を検証してみるテストベンチのコードです。
/** @file CD4007 Test bench */ `timescale 1 ns / 100 ps module cd4007_tb; parameter CYCLE = 100; parameter DELAY1 = 10; wire OUT; reg tgnd, tvcc; wire t1, t2; reg [2:0] GIN; /* 3 input NAND */ cd4007 dut( .O12(OUT), .OP1(OUT), .OP13(OUT), .ON5(t2), .ON8(t1), .IP14(tvcc), .IP2(tvcc), .IP11(tvcc), .IN7(tgnd), .IN4(t1), .IN9(t2), .G6(GIN[0]), .G3(GIN[1]), .G10(GIN[2]) ); initial begin $dumpfile("cd4007_tb.vcd"); $dumpvars(-1, dut); $monitor("%d GIN=%b, OUT=%b", $stime, GIN, OUT); end initial begin tgnd = 1'b0; tvcc = 1'b1; #DELAY1 GIN = 3'b000; #CYCLE GIN = 3'b001; #CYCLE GIN = 3'b010; #CYCLE GIN = 3'b011; #CYCLE GIN = 3'b100; #CYCLE GIN = 3'b101; #CYCLE GIN = 3'b110; #CYCLE GIN = 3'b111; #CYCLE $finish; end endmodule //encoder_tb
実行結果
実行結果が以下に。000から110までの入力に対しては出力1、111の時だけ出力0となりました。OKだね。
CD4007レベルのコンポーネントをモデリングするということはまずないでしょうが、やれば出来る、と。