« FPGAの言語の習得で最初からつまづく | トップページ | FPGAのUARTで7セグLEDを動かすことに成功 »

2010年3月29日 (月)

FPGAで7セグLEDのカウンターがやっと動く

7セグLEDが点灯した(3/26/10)
 VerilogHDLで書いた自前の7セグLED表示回路にタクトスイッチの回路を組み込む。生意気にシステムクロックを使ったチャタリング防止回路を入れる。always節の中の処理は順序処理なのでソフト屋にはコーディングしやすい。

 ただサブモジュール間のデータの受け渡しは、まだ完全に理解できていない。手探りである。基本は、regでデータを作り、ネット(wire)で受けるというのだが、サブモジュール間のデータの受け渡しのとき、メインモジュールに変数を定義しておかなくてもよいのか、サブモジュールでwireで受けた変数をそのまま変化させてよいのか、まだ確信がない。エラーになったところは、適当に定義をいじってNo Errorにするという対症療法でしのぐ。

 やっとのことで、タクトスイッチを押すと、その回数を99まで数えて7セグLEDに表示する練習課題のソースが論理合成でNo Errorとなった。次は、いよいよピンアサインである。おっと、まだFPGA基板の配線をすましていない。バラックでも良いが、デバッグに専念したいので、ベース基板にテスト用のソケットをつけてFPGA基板とLED基板の間を接続することにする。

 これが結構、時間がかかる。たかが10数本の配線だが、ピンアサインを良い加減にするとあとでひどいことになるので、なるべく元の基板の配置と同じで、しかも流用したストレートの電光掲示板のコネクターが入るようにピンアサインを決めようと苦心する。 7セグのエレメントの接続も気を抜いてハンダ付けするとすぐ間違える。メモをとり何度もテスターで導通を確かめながらの作業だ。2列20ピンのソケットは印をつけておかないとすぐ間違える。

A3292782

 基板のハンダ付けも終わった。今度こそピンアサインだ。雑誌記事の基板回路図を何度も確認しながら慎重にピン配置の.ucfファイルを作る。 Xilinxの開発環境ISEは操作性に問題があり余り評判が良くないが、このピン配置を決めるucfファイルの編集もやりにくい。

 一旦作ったucfファイルはUser Constraints(ユーザー制約定義)のGUI画面では編集できない。知らずに入力すると新たな制約定義を追記してしまう(ISE 10.1 )。編集はucfファイルをテキストエディターで開いて修正しないといけない(追記:GUIメニューにPre-SynthesisとPost-Synthesisの2つがあり、後者で修正が出来ることがわかった)。

 まあ、この開発環境はすべて無料なので(登録が必要だが)余り文句は言えない。しかし、これは統合環境というより、それぞれが別の仕事をするバッチジョブのランチャーに近い。ではバッチジョブとして独立しているかと思うと、沢山の中間ファイルが相互のジョブの途中経過を引き継いでいるので油断がならない。うまく行っているときは良いが、どこかのステップを失敗すると、とたんにご機嫌を損ねて先に進んでくれない。

 このときも二重に追記されたucfファイルを消したのだが、これに関係する内部ファイルが残っていて、新規にucfファイルを作っても同じエラーを吐いて動かない。結局、一旦そのプロジェクトをご破算にし、ソースコードだけ取り出して新しくプロジェクトを作り直したら先に進んだ(Clear Projectというのをやれば良いらしい)。

 ピンアサインが無事終わった。しかしFPGAを動かすまでの道は遠い。このあともまだたくさん手順がある。付録基板の号には詳しい手順が出ているのでもう一度おさらいし、慎重に進める。以前に1回通したというのが自信になっている(2008/8/8「FPGAでLEDピコピコ」記事)。幸い、Imprement Design(これがコンパイルにあたる)、Generate Programing File(実行可能ファイルを作る。リンカーか)は順調に終わった。

 残るは問題のiMPACTを使ったファーム書き込み(コンフィギュレーション)である。「鬼のように使いにくい」「難解きわまる」とWebで評判(?)のライターである。前回は、コンフィギュレーションROMをバイパスする手順を抜かして大はまりした。

Impact

 手順どおりiMPACTを始動させる。この始動方法にも色々な方法があるようで、おっかなびっくりである。ROMとFPGAのアイコンが出るConfigurationの画面が出た。手順どおりProgramの矢印アイコンをダブルクリックして書き込みを開始する。おお、順調のようだ。やった、やった、ブルーのSucceeded(出来たよ)のメッセージが出た。7セグLEDが点灯した。

 良かった。とりあえずはLEDが点いた。見ると、4つのLEDとも同じ形で激しく点滅しているだけだが、全くの無反応ではない。少なくとも暴走もせず(FPGAは暴走しないか)、何か動いている。タクトスイッチを押してみる。うん、何か変わった。数字にはなっていないが2番目の桁の形が変わったようだ。よーし、一歩前進したぞ。達成感で体が軽い。

A3272773

FPGAのデバッグは確かに大変だ(3/27/10)
 最初のFPGA自作プログラムは、無茶苦茶な点滅だけれど、とりあえず目的の7セグLEDを光らせることには成功した。次はデバッグである。全くの黙(だんま)りと違って何か動いている。手がかりは十分だ。

 激しく点滅するというのはダイナミック点灯の時間間隔が長すぎるからだろう。テレビのフレーム1/60秒に合わせて20msにしたが遅すぎるようだ。LEDが文字になっていないのはエレメントのアサインがおかしいからに違いない。

 LEDのピンアサインとソースコードをもういちど照合する。ああ、わかった。7セグ以外のエレメント、ドットポイントの位置を間違えている。ucfファイルでピンアサインを変える。ダイナミック点灯の間隔を1/10の2msに変更し、また最初の論理合成から始まる5つのステップを実行する。

 予想通り点滅は止まった。しかしまだ文字にならない。それにタクトスイッチを押して変わるLEDが一番右の桁にならない。ここも間違えているか。もういちどピンアサインを確認する。おやビットの定義がこれまでと違う。A[0] 、A[1]、A[2]はMSB(左から)からじゃないのか。そうなのだ。ここの配列はLSB(右)から数えるらしい。

 アサインを逆にして、やっと7セグLEDに数字が戻った。タクトスイッチを押すと数字が変わる。しかし、1づつ増えていかない。それに桁の位置がおかしい。うーむ、今日はこれくらいにしておこう。

同時に動くという仕組みを少し理解する(3/28/10)
 FPGAのデバッグは難しい。考えてみたらロジアナでは内部変数を外から見ることが出来ない。シミュレーターを入れれば良いのだろうが、そう簡単には入らない。それに7セグLEDくらいのアプリケーションで余りおおげさにしたくないという気持ちもある。まずは冷静になって最初からHDLコードを調べ直すことにする。

数字が大きく変わる不具合は新しく入れたスイッチのロジックが怪しい。スイッチがONになった直後、ただちにフラグをあげて、それ以上カウンターが動かないようにしているが、そのフラグが効いていないように見える。すると気になるところが見つかった。

if(A)       //begin endは文が単文のときは省略できるので
  if(B) begin     //この文は単文
    C;             //
    D;             //
  end             //
else begin  //このelseはif(A)のelseのつもり
  E;
  F;
end

Aが成立してBが成立すれば、CとD、そうでなければ何もしない。Aが成立しなければEとFを実行するという文だ。beginとendは複文の時だけ必要で単文のときはいらないので省略してあるが、よーく見ると、次のif(A)のつもりのelseは、字下げはしてあっても、if(B)の方のelseになってしまっている。

あーこれだ、これだ。昔々PASCALに凝っていた頃、さんざんやったミスだ。ここは面倒でも

if(A)  begin   //単文でもelseを取り違えないために必要   
   if(B) begin
     C;            
     D;          
   end
end                 //面倒だが、このbegin endがいる         
else begin  //これでやっとこのelseはif(A)のelseになる
  E;
  F;
end

としなければいけない。数字が大きく増える原因はここにちがいない。あせる気持ちでコンパイルしなおす。長い手順がもどかしい。コンフィギュレーションが出来たので動かしてみる。よーし、数字の増え方がひとつづつになった。

 おやあ、まだ時々1以上増える時があるぞ。うーむ、何故だ。スイッチの押し方で様子が変わる。チャタリング防止が機能していないようだ。どれくらい待っている? 300カウント待って同じならONとしている。待てよ、クロックは33Mhzだ。これでは少なすぎるのではないか。そうだ、10マイクロ秒しか待っていない。単位を間違えていた。千倍の300000(10ms)にしてチャタリングは完全に防止できた。

 表示される桁がおかしいのはもっと深い理由があった。ソフト屋はどうしてもステートメントが表記の順序で実行され、それが終わってから次のステートメントが実行されるという意識が頭から抜けない。always節の中は、順序回路だと言っても、実際の動作はわずかな遅延を伴って同時に処理される。

A3282780

 ダイナミック点灯のデータの指示をしたあと点灯する位置をシフトしているが、実際に点灯の処理がすんでからシフトが行われる保証はない。回路の具合で点灯する前に表示桁が移動するかもしれない。桁のずれがシフトの方向にずれているのが何よりの証拠だ。

 これは、シフトをブロッキング代入で最初にやり、点灯のデータの指示をノンブロッキング代入(always節の最後で一括変更)すれば解決するはずだ。ソースを組みなおす。これで遂に7セグLEDは正しい桁で数字が表示された。

 いやいや、良い勉強になった。参考書や雑誌に書いてあるブロッキング代入とノンブロッキング代入の違いをデバッグを通して肌で理解することができた。だいぶコーディングに自信がついてきた。次はUARTだ。

|

« FPGAの言語の習得で最初からつまづく | トップページ | FPGAのUARTで7セグLEDを動かすことに成功 »

FPGA」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1089557/33992382

この記事へのトラックバック一覧です: FPGAで7セグLEDのカウンターがやっと動く:

« FPGAの言語の習得で最初からつまづく | トップページ | FPGAのUARTで7セグLEDを動かすことに成功 »