Spartan-3A スタータキット

〜LCDパネル表示〜


2007/04/18

あなたは 人目のお客様です.

とりあえず,LCDパネルを利用できるようにしたい. というのは,今後PS/2やシリアル通信の実験をする際に, デバッグ出力としてLCDくらいが使えないとつらいので.

LCDの使いかたは,こちらで説明した ユーザーガイド(ug330.pdf)に詳細がある. Spartan-3Eスタータキットのユーザーガイドの日本語版(j_ug230.pdf)も参考になる.

ただ,Spartan-3AスタータキットとSpartan-3Eスタータキットでは,LCDに関して, 以下の点が違っているので注意.

Spartan3AとLCDパネルはLCD_DB0〜7,LCD_E,LCD_RS,LCD_RWという信号線で 接続されている.

あとはLCDに対してのコマンド発行のタイミングについて書かれている. 簡単に説明するとこんな感じ.
  1. LCD_DB,LCD_RS,LCD_RW(これは常にゼロだが)をセットする.
  2. LCD_Eを1にする.
  3. LCD_Eを0にする.
  4. LCD_DB,LCD_RS,LCD_RWをもとに戻す(べつに戻さなくてもいいけど一応).
LCDパネルは,LCD_Eが1になったときにLCD_DBからコマンドなどを読み込んで 動作する. で,1〜2は40ns以上の余裕が無ければならない. 2〜3は230ns以上保持しなければならない. 3〜4は10nsの余裕が必要. 50MHzだと1クロックで20nsなので, 1〜2は2クロック, 2〜3は12クロックということになる. 3〜4は1クロック未満だし,どうせコマンド後にウエイトが入るので, あんまし考える必要無し.

さらに,コマンドやデータは常に8bitで扱われるが, 4bit制御の場合には,8bitを2回に分けて, 上記1〜3のシーケンスを2回行うことで送信する. 最初の1回で上位4bitを送信し,1usのウエイト(50クロック)を置き, 次の1回で下位4bitを送信する.

またコマンド送信したら, 次のコマンドまで40us(50MHzで2000クロック)のウエイトが必要. ただしコマンド(ディスプレイのクリアなど)によっては, もっとウエイトが必要な場合もあるので注意.まあこのへんの細かいことは ユーザーガイドに書いてある.

あと,ユーザーガイドには実際に4bit接続で初期化して文字を表示するまでに 必要なシーケンスが一通り載っている. しかし残念ながら ug330.pdf で説明してあるシーケンスは ug230.pdf に8bitの説明をちょこっと加えたくらいのもので, 8bitで操作する場合のことがあまり書いていない. (シーケンスも4bitの場合についてのみ説明されていて,8bitの場合の説明は無い)

LCDの動作に関しては, こちらで試したデモ(s3ask_demo.zip) のソースが参考になる. このデモは実際にはpicoblazeで実行されているので, デモの実体は picoblaze のアセンブラとして書かれているのだけど, コメントもきちんと入っているし,まあ見ればだいたい想像つくように書かれている. ちなみにデモは,LCDは4bitでなく8bitで制御している.

s3ask_demo.zip を解凍すると, demo/source/boarddemo.v というファイルが作成される. これがデモのためのボードのI/O制御の記述になっている. LCDの制御は demo/source/boarddemo.v を見ると, I/Oポートの0x22がデータ用ポート,0x23が制御用ポートに割り当てられている ことがわかる. つまりpicoblazeから見れば,0x22と0x23のI/Oポートに出力することで, LCDが制御できるわけだ.っていうことはpicoblazeはメモリマップドI/Oではなく, I/Oポートアクセス用の命令を持つ, いわゆるI/OマップドI/Oになっているのだろうと見当がつく(Z80みたいだね). ていうかCPUのI/Oポート制御部分ってこーいうふうに書くんだねー. 非常に参考になる.

デモのための picoblaze アセンブラは,demo/source/picocode/picocode.psm にある.このファイルの中の lcd_reset_8bit というラベルの付近で, LCDの初期化などを行っている. このあたりでOUTPUTというアセンブラ命令を使っている部分があるので, これがおそらくI/Oポート出力命令だと見当がつく.

で,アセンブラを見たところ,8bitで制御したい場合には, Function Set コマンドの発行時に0x28でなく0x38を送信すればいいらしい (LCD_DB4が0のとき4bit制御,1のとき8bitになる). このへんのことは残念ながらユーザーガイドには書かれていなくて, ユーザガイドでは,Function Set コマンドの LCD_DB4 は常にゼロ (Function Set コマンドの値は常に0x28)と書かれてしまっているので注意.

で,ユーザーガイドとデモのアセンブラを参考にして作ったサンプルプログラムが 以下.ゲートサイズの効率とかはまったく無視して書いているので注意. デモは8bit制御なのだけど,とりあえず4bit制御で書いてみた. lcd.ucf(Constraints File:制約ファイル)については, こちらを参照.

lcd.v
lcd.ucf

lcd.vではクロックをカウントすることで必要なだけウエイトし, 状態遷移しながらLCDパネルにコマンドを送る,という動作をしています. こーいうシーケンシャルな制御は,VerilogHDL で(回路として)処理するよりも, CPU使って処理したほうがやりやすいと思った (picoblazeやZ80のような,単純な8bitCPUでも十分). まあでも勉強としてやっているのでいいのだけど.

以下は実行したところ.注意として, ボードの電源ON時にフラッシュROM上に書き込んであるデモが起動してしまうと, デモプログラムがLCDの初期化を行ってしまうので, その後FPGAにテストプログラムをダウンロードしなおしても, LCDの初期化も含めたちゃんとしたテストが行えない. デモが起動しないようにジャンパの設定を変更(画像中央参照)して実行した.

A,B,C,Dの文字が,1秒おきに左上から表示されます. LEDは状態遷移に合わせて点灯します. 4つボタンの下を押すことでリセットがかかり,再表示します.


メールは kozos(アットマーク)kozos.jp まで