ModelSimで非同期回路を探索する





ajrecの記事FPGA / Asynchronous Decoder読みました



最初に読んだものの何も理解していませんでした。 実際、非同期回路に関するすべてのajrecの記事をすでに読んでおり、それが実際に何であるかを理解していないことを認めなければなりません(FPGAでの設計の経験があると思いますが)。



記事へのコメントでは、著者はほとんど短所を得て、人々はくすくす笑って、私ほど理解していないようです。



正直なところ、私は常に「他の人とは違う」プロジェクトに興味を持っています。 私は、そのようなプロジェクトだけが深く失敗するか、高く飛ぶ機会があると信じています。 他の何百人もの開発者と同じように何かをするなら、あなたは踏みにじられた道を行く、それはここで簡単で快適です。 誰もが一歩進んで自分の道をたどることができるわけではありません。



非同期デコーダプロジェクトを把握し、少なくともModelSimでコードの一時的なシミュレーションを実行しようとしました。 それがどうなったのかについて。



正直なところ、記事「 非同期デコーダー 」と「 石化自己同期回路合成システム:問題とその解決策 」で説明されている記事は、私の頭にひどく当てはまりました 。 私は徹底的に「同期設計技術に甘やかされています」。



さらに、この記事には目を痛める奇妙な点があります。 たとえば、引用:



出力信号:

q1-r1 = 1およびr2 = 1の場合に切り替えます。

q2-r1 = 1およびr2 = 0の場合に切り替えます。

q3-r1 = 0およびr2 = 1の場合に切り替えます。

q4-r1 = 0およびr2 = 0の場合に切り替えます。


私はおそらく間違いを見つけますが、1から始まるシグナル番号を書いてr1 = 0とr2 = 0のときにq4が切り替わるようなプログラマーはほとんど想像できません。 私の頭の中のすべては厳密にパターンに従っています:{0、0}-q0信号に対応します。 {0、1}-信号q1に対応します。 {1、0}-信号q2に対応し、{1、1}-信号q3に対応します。 しかし、これらはもちろん、無関係な些細なことです。



主な不満は私の側にあります。著者は、FPGAやその他の方法で彼の仮説/研究/プロジェクトをテストしません。 彼は次のように書いています。「実際の実施形態で回路をテストする方法はありません。」



実際、これにより、 ajrecで記述されたデコーダーのロジックをシミュレートしようと考えるようになりました。 一時的なシミュレーションは、実際のFPGAの回路の動作を示すのに十分なモデルです。 確かに、ニュアンスがあります-ModelSimが非同期回路を確実にシミュレートできるという確信はありません。ModelSimシミュレータは、主に「伝統的な」同期設計用に設計されています。



だから。 記事FPGA / Asynchronous Decoderのソースコードは、どの言語を使用しているかはわかりません。次のようになります。



e=NOT(o1); e1=AND(o1,j1); e2=AND(o2,h1); e3=NAND(e,i1);

e4=OR(o2,h1); f1=AND(d,r1); f2=AND(d,r2); g=NOT(d);

h1=NOR(g,r1); h2=NOR(g,r2); i1=NOR(f1,j1); i2=NOR(f2,j2);

j1=NOR(g,i1); j2=NOR(g,i2); k1=AND(e1,j2); k2=AND(e1,h2);

k3=AND(e2,j2); k4=AND(e2,h2); l1=AND(t1,i2); l2=NOR(t2,h2);

l3=AND(t3,i2); l4=NOR(t4,h2); m1=NOR(k1,n1); m2=NOR(k2,n2);

m3=NOR(k3,n3); m4=NOR(k4,n4); n1=NOR(l1,m1); n2=NOR(l2,m2);

n3=NOR(l3,m3); n4=NOR(l4,m4); o1=NOR(p1,p2); o2=NOR(p3,p4);

p1=NOR(m1,s1); p2=NOR(m2,s2); p3=NOR(m3,s3); p4=NOR(m4,s4);

s1=NOR(n1,l1); s2=NOR(n2,l2); s3=NOR(n3,l3); s4=NOR(n4,l4);

t1=NOR(e3,s1); t2=OR(e3,s2); t3=NOR(e4,s3); t4=OR(e4,s4);

q1=NOR(s1,k1); q2=NOR(s2,k2); q3=NOR(s3,k3); q4=NOR(s4,k4).








さらに記事にはこのことの等価回路があり、実際には、信号m1、m2、m3、m4を作業を開始する前に元の状態にリセットする必要があると述べています。 さて、これをすべてVerilogに次のように書き直します。



 module test( input wire d, input wire r1, input wire r2, input wire set0, output wire q1, output wire q2, output wire q3, output wire q4, output wire [3:0]qq ); wire e, e1, e2, e3, e4; wire f1, f2; wire g; wire i1, i2; wire j1, j2; wire h1, h2; wire k1, k2, k3, k4; wire l1, l2, l3, l4; wire m1, m2, m3, m4; wire n1, n2, n3, n4; wire o1, o2; wire p1, p2, p3, p4; wire s1, s2, s3, s4; wire t1, t2, t3, t4; function NOT; input s; begin NOT=~s; end endfunction function AND; input s1,s2; begin AND=s1&s2; end endfunction function NAND; input s1,s2; begin NAND=~(s1&s2); end endfunction function OR; input s1,s2; begin OR=s1|s2; end endfunction function NOR; input s1,s2; begin NOR=~(s1|s2); end endfunction assign e=NOT(o1); assign e1=AND(o1,j1); assign e2=AND(o2,h1); assign e3=NAND(e,i1); assign e4=OR(o2,h1); assign f1=AND(d,r1); assign f2=AND(d,r2); assign g=NOT(d); assign h1=NOR(g,r1); assign h2=NOR(g,r2); assign i1=NOR(f1,j1); assign i2=NOR(f2,j2); assign j1=NOR(g,i1); assign j2=NOR(g,i2); assign k1=AND(e1,j2); assign k2=AND(e1,h2); assign k3=AND(e2,j2); assign k4=AND(e2,h2); assign l1=AND(t1,i2); assign l2=NOR(t2,h2); assign l3=AND(t3,i2); assign l4=NOR(t4,h2); assign m1=NAND( set0, OR(k1,n1)); /* NOR(k1,n1); */ assign m2=NAND( set0, OR(k2,n2)); /* NOR(k2,n2); */ assign m3=NAND( set0, OR(k3,n3)); /* NOR(k3,n3); */ assign m4=NAND( set0, OR(k4,n4)); /* NOR(k4,n4); */ assign n1=NOR(l1,m1); assign n2=NOR(l2,m2); assign n3=NOR(l3,m3); assign n4=NOR(l4,m4); assign o1=NOR(p1,p2); assign o2=NOR(p3,p4); assign p1=NOR(m1,s1); assign p2=NOR(m2,s2); assign p3=NOR(m3,s3); assign p4=NOR(m4,s4); assign s1=NOR(n1,l1); assign s2=NOR(n2,l2); assign s3=NOR(n3,l3); assign s4=NOR(n4,l4); assign t1=NOR(e3,s1); assign t2=OR(e3,s2); assign t3=NOR(e4,s3); assign t4=OR(e4,s4); assign q1=NOR(s1,k1); assign q2=NOR(s2,k2); assign q3=NOR(s3,k3); assign q4=NOR(s4,k4); assign qq = 1 << {r2,r1}; endmodule
      
      





私が理解できないロジックを誤って壊さないように、ソースコードに最小限の変更を加えようとしました。 そこで、Verilogの関数AND、OR、NOR、NANDを定義して、必要なことを実行できるようにしました。 Verilogで信号値を割り当てるには、assignを使用します。 必要に応じて、 Verilog言語の簡単な説明を次に示します



したがって、テストモジュールには、デコードされたアドレスr1およびr2の入力信号と、リセット信号set0および信号d-アドレスを解読するためのコマンド(著者の用語で)があります。 出力信号q1、q2、q3、q4。



さらに、次のように、従来のデコーダーによって計算されるギャグ、4ビット出力qqを追加しました。assign qq = 1 << {r2、r1};



テストモジュールは、Cyclone IV E FPGAチップ用のIntel Quartus Prime Lite Edition v16.1プロジェクトに挿入されました。



プロジェクトがコンパイルされました。 まず、プロジェクト設定の割り当て=>設定=> EDAツール設定=>シミュレーションで、ツール名=> ModelSim-Alteraを選択します。 次に、コンパイル後に、一時的なシミュレーションに必要な* .sdoおよび* .voモジュールが配置されるシミュレーション/ modelsimフォルダーが作成されます。



ここでテストベンチが必要です。 私はそれを簡単な方法で書きました:



 `timescale 1ns / 1ns module tb(); reg r1_; reg r2_; reg d_; reg set_; wire q1_,q2_,q3_,q4_; wire [3:0]qq_; test test_inst( .d(d_), .r1(r1_), .r2(r2_), .set0(set_), .q1(q1_), .q2(q2_), .q3(q3_), .q4(q4_), .qq(qq_) ); initial begin $dumpfile("out.vcd"); $dumpvars(0,tb); //reset m1-m4 signals using "set_" r1_=0; r2_=0; d_=0; set_=0; #100; set_=1; #100; //check addr 00 r1_=0; r2_=0; #100; d_=1; #100; d_=0; #200; //check addr 01 r1_=1; r2_=0; #100; d_=1; #100; d_=0; #200; //check addr 10 r1_=0; r2_=1; #100; d_=1; #100; d_=0; #200; //check addr 11 r1_=1; r2_=1; #100; d_=1; #100; d_=0; #200; //-------------------- //check addr 00 r1_=0; r2_=0; d_=1; #100; d_=0; #200; //check addr 01 r1_=1; r2_=0; d_=1; #100; d_=0; #200; //check addr 10 r1_=0; r2_=1; d_=1; #100; d_=0; #200; //check addr 11 r1_=1; r2_=1; d_=1; #100; d_=0; #200; end endmodule
      
      





ここで、アドレス信号r1およびr2は、4つすべての可能な値2'b00、2'b01、2'b10および2'b11に交互に設定されますが、この信号dも生成され、デコードをアクティブにします。



これはすべて2回発生し、最初の4つの復号化アクティベーション信号dは定常状態信号r1およびr2で発生し、信号dの2番目のグループでは信号r1およびr2と同時に発生します。 正直なところ、著者が意図したとおりにどのようにすべきかはわかりません。 そのため、ここでは、信号r1とr2が確立された時点での起動信号dの到着という極端なケースを考えています。



現在、ModelSim-Altera(またはIntel)を起動しています。 プロジェクトとワークショップを作成します。 2つの既存のファイルを追加します。tb.vtestbenchと、quartusによってコンパイルされたasync_test.voプロジェクトです。







ModelSimを使用してコンパイルする必要があります。 右クリックして、メニューから「すべてコンパイル」を選択します。 各ファイルの横に緑色のチェックマークが表示されている必要があります。 時々奇妙で、ModelSimは、四分の一がそれらを見ていない構文エラーを見つけます。 ところで、これはそうです。



これで、メニューModelSim、シミュレーション->シミュレーションの開始からシミュレーションを開始できます...

ここで、必要な場所にダイアログボックスが表示されます。



1)一番上のモジュールを選択すると、テストベンチになります







2)アルテラライブラリの追加







3)コンパイル済みのSDFファイルを追加して、そこからすべての時間パラメーターを取得します







シミュレーションに必要なすべてのファイルとモジュールを正常にロードしたら、タイムダイアグラムのウィンドウに目的の信号を追加する必要があります。







[OK]をクリックしてから、[シミュレーション] => [実行] => [すべて実行]メニュー



それで判明した-それは働いた!







私が見るもの:



まず、プロジェクトはほとんど機能しているようで、約束どおりにアドレスをデコードします。4つのパルスの最初のグループについてのみd。 デコーダーの出力は何らかの形で混同され、{r2、r1} = 2'b01 q2が点火されます。 しかし、私はすでにこの奇妙さについて話しました。 正直なところ、私はこれが一般的にいくつかの条件下で機能することに非常に驚きました。



4つのパルスdの2番目のグループは正しく機能しません。 これは、信号dが変化するr1とr2と同時に到着する瞬間です。



ここで、シグナルdの役割をよりよく理解したいと思います。 同期論理では、組み合わせ機能を使用して、あるレジスタから別のレジスタに送られるデータをラッチするクロック周波数があることを知っています。 この場合、開発者は、いわゆる時間パラメーターtsuおよびtholdを提供する必要があります。 以下は、Googleのトピックに関する最初の写真です。





レジスタにラッチされた信号は、クロック周波数の前のtsu(セットアップ時間)とクロック周波数の前の時間thold(ホールド時間)の間安定している必要があります。 この条件が満たされない場合、同期回路は動作しないか、確実に動作しません(つまり、実際には動作しません)。





安定した信号とは何ですか? 入力データが保存されるレジスタがあります。 次は、入力データ(数桁の場合もあります)から次のレジスタに格納される次の値を計算する論理関数です。 したがって、論理関数は、クロック周波数期間の長さよりも短い時間で結果を計算する必要があります。 計算する時間があるだけではありません。 いくつかの放電があるため、結果には、それぞれの導体に沿ってそのラッチレジスタに間に合うように実行する時間があります。



さて、非同期回路と信号dに戻ると、シミュレーション中のこの非同期回路の4つのパルスの2番目のグループdは、同期回路が機能しないのとまったく同じ理由で、正しく機能しないようです。 つまり、tsuは持続しません。 信号dは、信号r1とr2がまだ到着していないか、安定していないときに到着します。



非同期回路の作成者は一時的な分析を避けられないようです。 dが到着する前に、信号r1とr2の安定性に注意してください。 これは何らかの形で管理され、考慮される必要があります。 正直なところ、パルスd自体はクロック周波数に似ています。 信号dには持続時間がありますか?そのため、この持続時間には何らかのジェネレーターが提供されますか? 非同期回路の動作には、信号dの持続時間と位置を決定する回路がすべて同じように、時間がかかることが必要であることがわかりました。 一般的に、この信号dの起源は非常に明確ではありません...



シミュレーションでさらにいくつかの点に注意を引きたいと思いました。 回路が動作している場合でも(シミュレーションのdの最初の4パルス)、出力信号q1、q2、q3、q4は信号dに対してシフトし、それぞれ異なる時間シフトします。 最も興味深いのは、パルス幅q1、q2、q3、q4が常にパルス幅dよりも大きく、すべての幅が異なることです。 著者がどのようにこのようなスキームを互いに組み合わせるのか私は知りません。 後続の回路の出力信号q1が信号dになると仮定すると、一連の回路を通して信号dがますます広くなることがわかりますが、これらは私の幻想です。 繰り返しますが、このようなスキームがどのように大きなスキームにアセンブルされるかはよくわかりません。



別の考えは私を去りません。



上記のような従来のデコーダーはqq = 1 << {r2、r1}を割り当てているように思えます。 著者が説明した非同期回路よりも、チップ内のトランジスタ数のスペースがはるかに少なくなります。 また、ASIC内のトランジスタ数はパフォーマンスに直接影響します。これは、チップの大きな領域が占有され、要素間のパスが長くなり、消費電力が増加するためです。 あなたはこれについて、それをどのように評価し、どのように計算するかを考える必要があります。



時々、私自身は、電子機器を高速化する方法や、仕事の「異なる原則」を使用する方法について、奇妙な「ブレークスルー」アイデアを持っています。 ムーアの法則はどういうわけかうまく機能せず、電子機器の速度を上げるには新しいアイデアが必要です。 マイクロプロセッサの場合、これは根本的に異なるアーキテクチャである可能性があります(うーん...私はそれを持っています)。 または、チップの基本的な要素のデバイスに関する新鮮な技術とアイデアが必要です。



Double-Edge-Triggerで回路を実装する実験をしたことがあります。 アイデアは、通常の同期ロジックに両方のクロックエッジを使用することでした。 DETトリガーを使用すると、チップの動作周波数が同じ計算速度に対して半分の速度になり、少なくとも消費電力が少なくなると考えました。 私は自分のプロジェクトのふりをして、それをFPGAで起動しました。 このプロジェクトの詳細はこちらです。



次に、必要なトランジスタの数を見積もってみて、残念な結論に達しました。DETトリガーを使用した回路では、通常よりもチップ内にはるかに多くのトランジスタが必要になるようです。



非同期ロジックは、アイデアとして興味深いものです。 しかし、残念ながら、それは深い研究が必要です。 実際のアプリケーションにとっては、まだ遠すぎて明らかではありません。 また、FPGAでも、シミュレーションでも、結果を確認する必要があります。難しくなく、高価でもありません。 ModelSimは、非同期回路を非常にシミュレートできるようです。



シミュレーションは無料です! 紳士を試してみてください!



All Articles