この文書では入出力ボードにあるドットマトリクスディスプレイの制御方法について説明します.
1:概要
入出力ボードにある8個のドットマトリクスディスプレイは,7セグメントLEDと同様にダイナミック点灯方式で制御されており,垂直方向にある16個のLEDに表示するパターンをFPGAから32回送るようになっています.ただし7セグメントLEDよりやや複雑な制御を行っております.その一番の要因は32回送るとき,7セグメントLEDではそれぞれFPGAと制御されていましたが,ドットマトリクスディスプレイの場合にはFPGAの外部にあるシフトICを使っていることが挙げられます.各シフトレジスタはシリアルイン8ビットパラレルアウトになっており,それを4個使って32個の信号にしているのです.詳しくは後ほど説明します.
2:インタフェース
下にドットマトリクスディスプレイのインタフェースを示すとともに,各端子の説明を図の下にある表で示します.
端子名 | 入力/出力 | バス幅 | 説明 |
iColumn | 入力 | 16 | 描画する垂直方向(列)のパターンです.作成する回路ではこの信号をあらかじめ設定しておくと,それを記憶しておきます.1にすると点灯,0にすると消灯します. |
iColumnId | 入力 | 5 | iColumnを表示する列の番号です.左端が0,右端が31とします. |
iClk | 入力 | 1 | クロック.ダイナミック点灯をするために用います. |
iClrN | 入力 | 1 | 表示(1'b0)/非表示(1'b1)します. |
iLoad | 入力 | 1 | 立ち上がりエッジでiColumnからの信号をiColumnIdに表示します. |
iRst | 入力 | 1 | この信号が1'b1のときリセットされます. |
oColumn | 出力 | 16 | このドットマトリクスはダイナミック点灯方式を利用しており,目には見えませんが高速で1列ずつ描画しています.その1列のパターンを表しているのがこの信号です. |
oSeg | 出力 | 4 | 4個のシフトレジスタのシリアルインと接続されており,同じくシフトレジスタに接続されているoClkの立ち上がりエッジのタイミングで,oSsgの信号をシフトレジスタは取り込みます. |
oClk | 出力 | 1 | 4個のシフトレジスタのクロックに接続されています. |
oClrN | 出力 | 1 | ドットマトリクスディスプレイを表示する(1'b0)か非表示(1'b1)にするか出力します. |
3:外部回路構成
下に示す回路図はDMDに関係する回路図です.上部にPNP型トランジスタがあり,これで32列のLEDをON/OFFしています.その下側に8個のドットマトリクスディスプレイがあります.右側には行を制御する3ステートバッファ(74541)とトランジスタアレイ(TD6208)があり,右下には3ステートバッファによりハイインピーダンスにすることができるスライドスイッチがあります.なお,3ステートバッファにはもうひとつハイインピーダンスにすることができる信号はFPGAと接続されています.最後に,下側には列を制御するシリアルインパラレルアウトの8ビットシフトレジスタ(74164)があります.
PDF版はこちらからダウンロードできます.
動作の流れを簡単に説明します.ここでは1列分のパターンを表示することを例とします.
表示する列を指定するには,回路図の下側にあるシフトレジスタ(SR)の中の1個だけから1個だけLow,他をすべてHighにした信号を出します.これらの信号は回路図上側にあるPNP型トランジスタに接続されており,このトランジスタのエミッタに3.3[V]が接続されていますから,Lowにしたトランジスタのみを列だけが点灯し,それ以外の列は消灯します.
1列分の信号をFPGAから3ステートバッファを介してトランジスタアレイに接続しています.このトランジスタアレイはNPN型であり,ベースをHighにするとドットマトリクスディスプレイからの電流をグランドへ流すことができます.
以上のように,1列のパターンを変えつつ,かつシフトレジスタ(SR)にクロックを与えていけば,残像現象でパターンが表示されたように人間の目には見えます.ただし,SRとドットマトリクスディスプレイが順番に並んでいないため,順番を変換する必要があります.
4:ピンアサイン
ピンアサインを下表で示します.この表をもとにISE WebPACKのPlanAheadでピンを割り振ってください.なお,この表にはドットマトリクスディスプレイとは別に,スイッチ類のピン番号も掲載しておきます.
端子の役割 | 回路図上の名称 | FPGAのピン番号 | 信号の種類 | ポート名 |
上から1行目 | ROW0 | P79 | LVCMOS33 | oColumn[0] |
上から2行目 | ROW1 | P80 | LVCMOS33 | oColumn[1] |
上から3行目 | ROW2 | P83 | LVCMOS33 | oColumn[2] |
上から4行目 | ROW3 | P82 | LVCMOS33 | oColumn[3] |
上から5行目 | ROW4 | P85 | LVCMOS33 | oColumn[4] |
上から5行目 | ROW5 | P84 | LVCMOS33 | oColumn[5] |
上から7行目 | ROW6 | P87 | LVCMOS33 | oColumn[6] |
上から8行目 | ROW7 | P81 | LVCMOS33 | oColumn[7] |
上から9行目 | ROW8 | P75 | LVCMOS33 | oColumn[8] |
上から10行目 | ROW9 | P78 | LVCMOS33 | oColumn[9] |
上から11行目 | ROW10 | P64 | LVCMOS33 | oColumn[10] |
上から12行目 | ROW11 | P74 | LVCMOS33 | oColumn[11] |
上から13行目 | ROW12 | P61 | LVCMOS33 | oColumn[12] |
上から14行目 | ROW13 | P66 | LVCMOS33 | oColumn[13] |
上から15行目 | ROW14 | P62 | LVCMOS33 | oColumn[14] |
上から16行目 | ROW15 | P67 | LVCMOS33 | oColumn[15] |
左から1~8列目を 制御するSRの シリアルイン |
COLUMN_SEG0 | P97 | LVCMOS33 | oSeg[0] |
左から9~16列目を 制御するSRの シリアルイン |
COLUMN_SEG1 | P92 | LVCMOS33 | oSeg[1] |
左から17~24列目を 制御するSRの シリアルイン |
COLUMN_SEG2 | P55 | LVCMOS33 | oSeg[2] |
左から25~32列目を 制御するSRの シリアルイン |
COLUMN_SEG3 | P46 | LVCMOS33 | oSeg[3] |
すべてのSRに つながっているクロック |
COLUMN_CLK | P99 | LVCMOS33 | oClk |
点灯/消灯 | DMD_CLR1 | P100 | LVCMOS33 | oClrN |
トグルスイッチ1 | SW1 | P98 | LVCMOS33 | iColumn[0] |
トグルスイッチ2 | SW2 | P93 | LVCMOS33 | iColumn[1] |
トグルスイッチ3 | SW3 | P95 | LVCMOS33 | iColumn[2] |
トグルスイッチ4 | SW4 | P88 | LVCMOS33 | iColumn[3] |
トグルスイッチ5 | SW5 | P59 | LVCMOS33 | iColumn[4] |
トグルスイッチ6 | SW6 | P58 | LVCMOS33 | iColumn[5] |
トグルスイッチ7 | SW7 | P57 | LVCMOS33 | iColumn[6] |
トグルスイッチ8 | SW8 | P41 | LVCMOS33 | iColumn[7] |
トグルスイッチ9 | SW9 | P40 | LVCMOS33 | iColumn[8] |
トグルスイッチ10 | SW10 | P38 | LVCMOS33 | iColumn[9] |
トグルスイッチ11 | SW11 | P48 | LVCMOS33 | iColumn[10] |
トグルスイッチ12 | SW12 | P47 | LVCMOS33 | iColumn[11] |
トグルスイッチ13 | SW13 | P45 | LVCMOS33 | iColumn[12] |
トグルスイッチ14 | SW14 | P44 | LVCMOS33 | iColumn[13] |
トグルスイッチ15 | SW15 | P43 | LVCMOS33 | iColumn[14] |
トグルスイッチ16 | SW16 | P56 | LVCMOS33 | iColumn[15] |
トグルスイッチ17 | SW17 | P51 | LVCMOS33 | iLoad |
トグルスイッチ18 | SW18 | P50 | LVCMOS33 | iClrN |
タクトスイッチ | SW22 | P101 | LVCMOS33 | iRst |
発振器 | CLK | P94 | LVCMOS33 | iClk |
5:内部信号
ドットマトリクスディスプレイを制御するには,下記の内部信号が必要となります.
名称 | reg/wire | ビット幅 | 個数 | 初期値 | 備考 |
oSeg | reg | 4 | 1 | 4'b0000 | ポート宣言の信号をregにしている. |
drawingColumnPattern | reg | 16 | 1 | 16'b0000_0000_0000_0000 | 描画している列のパターン |
drawingColumnId | reg | 5 | 1 | 5'b00000 | 描画している列のID. |
pattern1 | reg | 16 | 8 | 別記 | 左から1~8列目のパターン |
pattern2 | reg | 16 | 8 | 別記 | 左から9~16列目のパターン |
pattern3 | reg | 16 | 8 | 別記 | 左から17~24列目のパターン |
pattern4 | reg | 16 | 8 | 別記 | 左から25~32列目のパターン |
disSt | reg | 1 | 1 | 1'b0 | 表示の状態.0:非表示,1:表示 |
dividedClk | wire | 1 | 1 | - | 分周したクロック |
上記以外に,制御変数としてinteger型のiとjがあります.
初期状態で8個のドットマトリクスディスプレイに下記のように表示することにします.
長野高専
電子情報
左端1列がpattern1[0]で表現され,その列から右側に進むにつれてpattern1[1],[2]…[7],pattern2[0],…,pattern4[7]となります.1列を表すpatternx[y]は16ビットであり,最上位ビットが下,最下位ビットが上になります.従いまして,パターンとpattern1~pattern4の関係は下の図のようになります.
上の図をもとに,pattern1~pattern4を初期化すると下のようになります.
initial begin pattern1[0] = 16'b00000110_00010000; pattern1[1] = 16'b00111010_01010000; pattern1[2] = 16'b00101111_01111111; pattern1[3] = 16'b00111111_01010101; pattern1[4] = 16'b01101011_00110101; pattern1[5] = 16'b01111110_01010001; pattern1[6] = 16'b01000110_01010000; pattern1[7] = 16'b00000000_00000000; pattern2[0] = 16'b00001000_01011111; pattern2[1] = 16'b00001001_01010101; pattern2[2] = 16'b01001001_01111111; pattern2[3] = 16'b01111101_01011111; pattern2[4] = 16'b00001011_01001001; pattern2[5] = 16'b00001001_01111101; pattern2[6] = 16'b00001000_00011011; pattern2[7] = 16'b00000000_00000000; pattern3[0] = 16'b00000110_01110010; pattern3[1] = 16'b01111111_00010010; pattern3[2] = 16'b00001000_01111110; pattern3[3] = 16'b01111010_01011011; pattern3[4] = 16'b00101111_01111110; pattern3[5] = 16'b01111010_00010010; pattern3[6] = 16'b00001000_01110010; pattern3[7] = 16'b00000000_00000000; pattern4[0] = 16'b00010100_00010010; pattern4[1] = 16'b00111110_00010010; pattern4[2] = 16'b01110111_00111110; pattern4[3] = 16'b00111110_01011111; pattern4[4] = 16'b01011111_01111110; pattern4[5] = 16'b00101001_00010010; pattern4[6] = 16'b01011011_00010010; pattern4[7] = 16'b00000000_00000000; end
次に各信号を説明します.
drawingColumnPattern:ある時点で描画している1列のパターンを表しています.従って,pattern1[0]~[7],pattern2[0]~[7],pattern3[0]~[7],pattern4[0]~[7]のいずれかということです.
drawingColumnId:ダイナミック点灯方式では,1列ごとにパターンを表示していきます.このときの列を表すのがこの信号です.すべてで32列あるため,この信号は5ビット(=0~31)となっています.0が左端の列,31が右端の列です.
disSt:7セグメントLEDを制御した時と同様に,ドットマトリクスディスプレイを制御するときにも隣り合う列を同時に表示させないため,列の切り替え時に消灯を行うことにしています.そのための信号がdisStです.この信号が1のときには点灯し,0のときには消灯するようにしています.
dividedClk:FPGAボードにはマスタクロックとして40[MHz]の発振器が備えられていますが,ドットマトリクスディスプレイをダイナミック点灯させるには速すぎます.そこで,およそ10[kHz]に分周したクロックを使うことにします.このクロック信号がdividedClkです.dividedClkはシフトレジスタのクロック(COLUMN_CLK)としても使用されます.
6:FPGAに作成する回路の構成
ここでは作成する回路の概略を示します.
- iClrNもしくはiRstがHigh(=押された)のときにoClrNをHigh(=非表示)にします.
- およそ10[kHz]に分周し,その信号をdividedClkとします.
- oClkをdisStとつなげます.
- iLoadが立ち上がる,もしくはiRstボタンが押されたとき,次の動作をする回路を作成します.
- iRstボタンが押されていたら,パターンを初期状態にします.初期状態にするには,pattern1~4に初期信号を入れればよいです.
- iRstボタンが押されていなかったら,つまりiLoadが立ち上がったら次の動作をする回路を作成します.
- もしiColumnIdの上位2ビットが0であったら,pattern1[y]にiColumnを代入します.このときのyは,iColumnIdの下位3ビットです.
- もしiColumnIdの上位2ビットが1であったら,pattern2[y]にiColumnを代入します.このときのyは,iColumnIdの下位3ビットです.
- もしiColumnIdの上位2ビットが2であったら,pattern3[y]にiColumnを代入します.このときのyは,iColumnIdの下位3ビットです.
- もしiColumnIdの上位2ビットが3であったら,pattern4[y]にiColumnを代入します.このときのyは,iColumnIdの下位3ビットです.
- 1列のパターン(oColumn)と描画している列パターン(drawingColumnPattern)とをつなげます.
- 周波数がおよそ10[kHz]のクロックの立ち上がりエッジが現れたら,表示状態(disSt)を表示なら非表示,非表示なら表示にします.
- 周波数がおよそ10[kHz]のクロックの立ち下がりエッジが現れたら,次の動作をする回路を作成します.
- disStが表示状態(=1'b1)なら,次の動作をする回路を作成します.
- 描画する列番号(drawingColumnId)をインクリメントします.
- もし描画する列番号が0~7であったら,描画している列パターンをpattern1[y]にします.ここでyはdrawingColumnIdの下位3ビットをColumnConvert関数で列番号を変換したものとします.
- そうではなく,もし描画する列番号が8~15であったら,描画している列パターンをpattern2[y]にする.ここでyはdrawingColumnIdの下位3ビットをColumnConvert関数で列番号を変換したものとします.
- そうではなく,もし描画する列番号が16~23であったら,描画している列パターンをpattern3[y]にする.ここでyはdrawingColumnIdの下位3ビットをColumnConvert関数で列番号を変換したものとします.
- そうではなく,もし描画する列番号が24~31であったら,描画している列パターンをpattern4[y]にする.ここでyはdrawingColumnIdの下位3ビットをColumnConvert関数で列番号を変換したものとします.
- 以上ですべての列番号を網羅したのでIF文を終了します.
-
もしdrawingColumnIdが31のとき,左端から1列目から8列目までのドットマトリクスディスプレイを制御するシフトレジスタに0を入力し, それ以外のシフトレジスタには1を入力します.
- そうではなく,もしdrawingColumnIdが7のとき,左端から9列目から16列目までのドットマトリクスディスプレイを制御するシフトレジスタに0を入力し, それ以外のシフトレジスタには1を入力します.
- そうではなく,もしdrawingColumnIdが15のとき,左端から17列目から24列目までのドットマトリクスディスプレイを制御するシフトレジスタに0を入力し, それ以外のシフトレジスタには1を入力します.
- そうではなく,もしdrawingColumnIdが23のとき,左端か259列目から32列目までのドットマトリクスディスプレイを制御するシフトレジスタに0を入力し, それ以外のシフトレジスタには1を入力します.
- それ以外の場合にはすべてのシフトレジスタに1を入力します.
- そうでない(disStが非表示状態)なら,drawingColumnPatternを16'b0000_0000_0000_0000にします.
- disStが表示状態(=1'b1)なら,次の動作をする回路を作成します.
- 3ビットのパラメラsrcを持ち,3ビットの戻り値であるColumnConvert関数を次のように作成する.
- srcが3'b000なら3'b111を返します.
- srcが3'b001なら3'b110を返します.
- srcが3'b010なら3'b001を返します.
- srcが3'b011なら3'b010を返します.
- srcが3'b100なら3'b000を返します.
- srcが3'b101なら3'b100を返します.
- srcが3'b110なら3'b101を返します.
- srcが3'b111なら3'b011を返します.
次にColumnConverter関数について説明します.下の図は左から1列目から8列目を制御するシフトレジスタです.右側がパラレル出力であり,それらのうち一番上が最下位ビット,一番下が最上位ビットとなっています.下の図のように,一番上の端子にはcolumn7が接続されており,次にcolumn6,1と続いていきます.このため,クロックをシフトレジスタに与えても,順番にシフトしてはくれません.そこでColumnConverterで列の入れ換えをしているのです.他のシフトレジスタも同じような順番にアサインされていますから,8ビットずつこの関数で変換します.なお,なぜこのようになっている理由は,回路パターンを引き回す上でこちらの方がうまく引き回せたからです.
以上でドットマトリクスディスプレイを制御する回路の説明を終わります.