Posts Tagged with "Design"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on October 25, 2021 #442

BoktechにオーダーしていたV9基板が届いたので、組み立て火を入れたところ、JoystickスイッチONのタイミングで垂直同期にノイズが乗る現象が再発しました。

図442.1の上側黄色トレースが、X_RIGHT_SW信号(ボードへの入力、負論理)、下側青色トレースがVSYNC(ボードからの出力、負論理)です。スイッチのチャタリングが、本来無関係のはずの同期信号にクロストークしています。

実際にこのVSYNCのノイズにより、外付けモニタが誤動作しています。具体的には同期が乱れるため、それを自動的に検知し、一定期間ブランキングしています。

図%%.1
図442.1 オシロスコープ波形

レベコンICのVSYNCの隣接端子であるX_RIGHT_SW信号からノイズが回り込んでおり、一つ離れたX_LEFT_SW信号からの回り込みはありません。

この現象は、開発初期のV4で起きていたため、V5からスイッチ信号と同期信号を同じレベコンICに入力しないようにしていました。その後、配線に近い場所があったため、ロジカルには大丈夫だろうと、V9で同じレベコンICに入れたのですが再発しました。論理的には問題ないはずなので、あとは以下の2つ程度が考えられます。

  • チャタリング⇒レベコンICの電源・グラウンドの揺れ⇒同期信号にノイズ
  • レベコンICの内部でのクロストーク

ところが、4chオシロで観測したところ、電源・グラウンドの揺れはありませんでした。従って、原因はレベコンIC内部でのクロストークと考えられます。修正がここまでかかった原因は、メーカー製ICを信用し過ぎていたことに依るものです。

以上より、信号を入れ替え、ズイッチ信号と同期信号のレベコンICを別々に変更しました。これをV10とします。V10の基板図を図442.2及び3に示します。

図%%.2
図442.2 Ultra96toPMODV10ボード基板図(表面)

図%%.3
図442.3 Ultra96toPMODV10ボード基板図(裏面)

左矢前のブログ 次のブログ右矢

posted by sakurai on September 21, 2021 #437

改版中のV9ボードの基板図を図437.1及び2に示します。

図%%.1
図437.1 Ultra96toPMODV9ボード基板図(表面)

図%%.2
図437.2 Ultra96toPMODV9ボード基板図(裏面)

左矢前のブログ 次のブログ右矢

posted by sakurai on September 20, 2021 #436

V8基板が到着しました。今回も実装が安いBokTechに依頼しました。

図%%.1
図436.1 Ultra96toPMODV8基板

部品を並べたものが図436.2です。

図%%.2
図436.2 Ultra96toPMODV8ボード及び部品

組み立てたものが図436.3です。

図%%.3
図436.3 Ultra96toPMODV8ボード完成

正常に動作したものの、デバッグ途中で修正箇所を発見したため、V9として改版中です。具体的には、

  • Dip SWの入力がレベル変換ICにより1.8Vに変換されて入力されていた(Dip SWはスタティック信号のため、レベル変換ICの必要無し)⇒Dip SWの電源を1.8Vに変更し、ダイレクト入力に変更
  • Joy SWの入力が3.3Vダイレクト入力だった⇒1.8Vにレベル変換して入力(ラッチアップの可能性有るため)

Joy SWはV3において、1.8Vへのレベル変換ICを通すように変更したのですが、その際にSW信号が水平・垂直同期信号に悪影響を与えたため、V4以降で元に戻したものです。ただし動作しているとはいえ、1.8V入力に3.3Vを加えています。今回は再度V3と同様に修正します。ちなみにV3での悪影響の理由は、レベル変換ICで混信したのではなく、図436.4のように、レイアウト上同期信号がSW信号の間を通っていたためのようです。 【追記】レベル変換ICの端子間もしくはIC内部での混信のようでした。

図%%.4
図436.4 V3でのHSYNC/VSYNCのSWとの混信

V9ではV3と同様、再度JoySW信号を1.8Vへのレベル変換ICに入れるように修正しました。合わせて、レイアウト上SWの間を水平・垂直同期信号が通らないように注意して配線しています。


左矢前のブログ 次のブログ右矢

posted by sakurai on September 3, 2021 #434

Qiitaに「BSVによるSpaceInvaderのソースを公開」という記事を書きましたが、それに合わせてUltra96toPMOD基板の再設計(V8)を実施しました。現行のV7との変更点は、以下の2点です。

  • UltraZedボードインタフェースの削除
    UltraZedからは能動素子無しにUltraZedボード⇒Ultra96toPMODボード⇒PMODインタフェースボードと経由して信号を通していました。今回評価したところ、反射が起きて正常に動作しませんでした。Ultra96toPMODボード内でバッファを通す必要があったようです。設計変更も考えましたが、あまり需要が無さそうであるため、このインタフェースは削除することにしました。これに伴いZenarダイオードによる電源のOR回路も省略でき、電源まわりがすっきりしました。

  • 4層から2層に変更
    4層基板を2層としました。理由は、以前はそれほど高額でない料金で4層板が設計できたものが、EAGLEがAutodeskに買収されたため、高額なサブスクリプションでなければ4層板が設計できなくなったことです。無償で設計できるのが2層までとなったため、設計変更しました。

図%%.1
図434.1 Ultra96toPMODV8ボード表面図

データの場所は、https://github.com/mocapapa/Ultra96toPMODV8です。

今回もPCBA(SMD実装込み)を依頼しましたが、SeedFusionだと1万5千円以上だったので、BokTechに依頼しました。費用内訳は、

  • 基板代 1.0 USD
  • アセンブリ費用(部品代込み) 29.83 USD
  • DHL送料 34.0 USD

合計64.83 USDでした。


左矢前のブログ 次のブログ右矢

posted by sakurai on July 24, 2021 #425

BSVによるSpaceInvaderのVerilogソースを公開」と題する記事をQiitaに投稿しました。

図%%.1
図425.1 Qiita投稿

ボードの説明、Verilogソースの入手法、VivadoによるFPGAの配置配線までをガイドしています。


左矢前のブログ 次のブログ右矢

デザインのボード間移植

posted by sakurai on June 18, 2021 #424

ArtyボードからUltra96ボードへ

RTLにはボード依存性はありませんが、トップモジュールやIPにはボード依存性があるため、その移植が必要となります。まずトップ配線(ブロック間配線)は、Export Block Designにより、配線情報がTCLにより得られるので、それを入力したいところです。しかし、ボード依存性があるようで、新ボードを設定した上で旧ボードのTCLを読み込むとエラーになってしまいます。そのため、

  • 旧ボードの環境でデザインを構築しておき、新規ボードに変換する

方法により、デザインのボード間移植を実施しました。

新規プロジェクトの生成

最初に旧ボードでプロジェクトを生成します。この段階で必要なものはVerilogソースが全て含まれているsrcディレクトリ、ブロックデザインのTCL、新ボードのXDCのひな形です。

  1. Vivadoの下にプロジェクトフォルダを作成します。その下に、Verilogソースが全て含まれているsrcディレクトリ、ブロックデザインのtcl及び、xdcを配置します。
  2. Vivadoを起動し、Create Project⇒Next⇒RTLプロジェクトを選択し、Verilogソースフォルダを選択します。
  3. 次にconstraintファイルとしてxdcを設定します。
  4. Boardsとして旧ボードを選択します。
  5. FinishによりProjectが生成されます。
  6. IP Integrator⇒Create Block Designを実行します。
  7. BLOCK DESIGN⇒Sources⇒Design sourcesのトップデザインであるdesin_1に対してラッパを生成します。
  8. design_1を選択して右クリックでCreate HDL wrapperを実行するとダイアログが現れます。
  9. Let Vivado ...を選択してOKをクリックします。
  10. オレンジの階層だったものが、design_1_wapperというグリーンの階層が生成されます。
  11. それを右クリックし、Set as topにより、トップ階層とします。
  12. 最下段のTCL Console内で、source C:/Users/<ユーザ名>/Vivado/<プロジェクト名>/design_1.tclを実行します。
  13. ブロックが配置され、ブロック間に配線されます。Diagramを右クリックしてExpand Allし、Regenerate Layoutをクリックします。
  14. タイトルコメントのText sizeを64、Box fill colorを204,255,255とします。

新ボードへ移行

  1. ボードが旧ボードになっているので、PROJECT MANAGER⇒Settingsでダイアログを立ち上げ、Project Settings⇒General⇒Project device:によりボードを新ボードに変更します。
  2. BLOCK DESIGNに、IPのアップグレードを促す指示が出るため、個数をクリックします。Show IP Statusをクリックします。
  3. 最下段のUpgrade SelectedをクリックしIPのアップグレードを実施します。
  4. IPによっては結線が外れていることがあるため、良く見直して、外れていれば接続しなおします。

注意点

coeファイルは相対ディレクトリで記録されますが、tclスクリプトからうまく参照できないようなので、全て絶対ディレクトリ(例:e:\file.coe)として参照できるようにしました。


左矢前のブログ 次のブログ右矢

敵弾の貫通度の修正 (3)

posted by sakurai on June 17, 2021 #423

実行結果

このように修正した結果、以下の図423.1に示すように、敵弾の種類により貫通度を変えることができました。

図%%.1
図423.1 貫通度の違い

図423.1の下部中央のバリケードの

  • 右側に当たったのは、"Rolling"ショットで貫通度=3
  • 左側に当たったのは、"Plunger"ショットで貫通度=7

と深さが異なります。

以下の図はFPGAボードの動画です。最初に右側にRollingショット、次に左側にPlungerショットが着弾しています。

図%%.2
図423.2 貫通度の違い(動画)

以下の図は前記事のオリジナル動画です。最初に左側にPlungerショット、次に右側にRollingショットが着弾しています。

図%%.3
図423.3 貫通度の違い(オリジナル動画)

左矢前のブログ 次のブログ右矢

敵弾の貫通度の修正 (2)

posted by sakurai on June 16, 2021 #422

敵弾種類

敵弾名はインベーダゲームソースの研究から引用しています。図422.1の左から、Squiggly (抵抗器のようなジグザグ)、Rolling、Plunger (パイプつまり直し)と名前がついています。

図%%.1
図422.1 敵弾の種類

図422.2において、敵弾の貫通度は左からそれぞれ3, 3, 7としています。

BSVコードの修正

元々敵弾をランダム(風)に出現させるため、カウンタの値により敵弾タイプを決めていますが、同じように貫通度を決めるテーブルです。

UInt#(3) invBullet_pdval[8] =   { 7,  3, 3,  7, 3,  3,  7, 3}; // pd = penetrating depth

次は貫通度を記憶するためのレジスタであり、敵弾数だけ持つ必要があります。

Reg#(UInt#(3)) invBullet_pd[`INV_BULLET_MAX];

このレジスタを各敵弾にひとつ持たせるために敵弾の同時最大数だけインスタンシエートします。

for (int ii = 0; ii < `INV_BULLET_MAX; ii = ii + 1) begin
 :
   invBullet_pd[ii] <- mkRegU;
 :
end

敵弾発生部において、タイプを決定するのと同じロジックにより、上記の表を引きます。

            invBullet_type[idx] <= invBullet_rand[truncate(counter) & 3'h7];
            invBullet_pd[idx] <= invBullet_pdval[truncate(counter) & 3'h7];

敵弾衝突の一部です。この2つのseq - endseqブロックは元は一つでしたが、base(バリケード)の時だけこの貫通度を使用するように分離します。他の場合は最深(貫通度=7)固定とします。

                endseq else if (fbase) seq
                    eraseInvBullet(invBullet_x[idx], invBullet_y[idx]);     // 現敵弾消去
                    explodeInvBullet(invBullet_x[idx], invBullet_y[idx], invBullet_pd[idx]);   // 次敵弾爆発
                    invBullet_expTimer[idx] <= 1;           // 敵弾爆発タイマスタート
                    voff <= 5; // break 'for'
                 endseq else if (fobj || invBullet_y[idx] >= 225) seq
                    eraseInvBullet(invBullet_x[idx], invBullet_y[idx]);     // 現敵弾消去
                    invBullet_pd[idx] <= 7; // 最深
                    explodeInvBullet(invBullet_x[idx], invBullet_y[idx], 7);   // 次敵弾爆発
                    invBullet_expTimer[idx] <= 1;           // 敵弾爆発タイマスタート
                    voff <= 5; // break 'for'

コール先の爆発ルーチンです。爆発は、爆発マークを表示することで開始します。

// 敵弾爆発
function Stmt explodeInvBullet(
              UInt#(8) destx,
              UInt#(8) desty,
              UInt#(3) pd);
   return (seq
      orArea(43, 16, destx - 3, desty + extend(pd), 8, 8);
   endseq);
endfunction

爆発マーク消去コール部分です。爆発開始から一定時間後に、保存してある貫通度を使用して爆発マークを消去します。

       expEraseInvBullet(invBullet_x[idx], invBullet_y[idx], invBullet_pd[idx]);        // 敵弾爆発マーク消去

コール先の爆発マーク消去ルーチンです。

// 敵弾爆発マーク消去
function Stmt expEraseInvBullet(
              UInt#(8) destx,
              UInt#(8) desty,
              UInt#(3) pd);
   return (seq
      eraseAreaSP(43, 16, destx - 3, desty + extend(pd), 8, 8);
   endseq);
endfunction

左矢前のブログ 次のブログ右矢

敵弾の貫通度の修正

posted by sakurai on June 15, 2021 #420

Youtubeの動画の分析

この動画を観察すると、バリケード(シールド)への貫通度が、敵弾の種類によって異なるように思われます。

下図は左端のインベーダからT字型(Plunger)の敵弾が発射されたところです。

図%%.1
図420.1 敵弾1

敵弾が左端のバリケードに着弾しました。深く潜って(貫通度=7)爆発しています。

図%%.2
図420.2 敵弾1爆発

同じく左端のインベーダからジグザグ型(Squiggly)の敵弾が発射されたところです。

図%%.3
図420.3 敵弾2

敵弾が左端のバリケードに着弾しました。浅く潜って(貫通度=3)爆発しています。明らかに敵弾の種類により貫通度が異なっています。

図%%.4
図420.4 敵弾2爆発

動画を観察した限りでは、T字型の敵弾が7、他の敵弾は貫通度=3で爆発するようでした。一方、最下端では7で爆発するようなので、バリケードで爆発する際にのみ、貫通度(penetration distance)を設定することにします。


左矢前のブログ 次のブログ右矢

オープニングアニメーション (3)

posted by sakurai on June 11, 2021 #418

呼び出し側

前々稿に個別ファンクションを掲載したので、それをオープニングアニメーションとしてまとめるファンクションです。オープニングアニメーション時を示すようにfoaというフラグをTrueにしています。これがTrueの場合は、ウエイトルーチンにおいてボタンが押された場合にウエイトを中止する仕様となっています。

function Stmt openingAnimation;
   return (seq
      // Opening Animation
      foa <= True;
      eraseArea( 0, 41, 255, 199); // erase screen
      eraseArea(25,242, 5, 7); // erase zanki
      stringS1; // PLAY ...
      if (sbutton) break;
      wait_timer(`TICK_WAIT64);
      if (sbutton) break;
      stringS2; // *SCORE ...
      if (sbutton) break;
      wait_timer(`TICK_WAIT32);
      if (sbutton) break;
      stringS3; // =? MYSTERY ...
      if (sbutton) break;
      wait_timer(`TICK_WAIT64);
      if (sbutton) break;
      replaceY; // ^ -> Y
      if (sbutton) break;
      wait_timer(`TICK_WAIT64);
      if (sbutton) break;
      foa <= False;
   endseq);
endfunction 

実行結果

図418.1に実行結果の動画を示します。

図%%.1
図418.1 オープニングアニメーション

左矢前のブログ 次のブログ右矢


ページ: