CPLDで作る回路について
SPI をパラレルに変換して LCD にアクセスするような回路をCPLD で作ろうとしている。そのことは前記事のCPLDの回路設計で書いた。シフトレジスタで組む単純な シリアルパラレル変換と違うのは、制御バイト を前置することで、SPI だけで 他の信号線 を制御できることだ。
そして、LCD だけ制御するのではなく、ラッチの制御や プリスケーラの機能も付けようと思っている。
そろそろ、具体的な仕様を決めていこうと思う。
入出力
先に基板を設計したので、入出力の信号(名)とピンアサインは既に決めた。
ピンアサインを定義する "spi2par.ucf" の内容は、次のようにした。
//
#PINLOCK_BEGIN
#Fri Mar 05 01:38:45 2010
NET "EXTCLK" LOC = "S:PIN1";
NET "LEOUT" LOC = "S:PIN20";
NET "OEOUT" LOC = "S:PIN19";
NET "EVOUT" LOC = "S:PIN28";
NET "EVIN" LOC = "S:PIN27";
NET "CS" LOC = "S:PIN30";
NET "MOSI" LOC = "S:PIN31";
NET "SCK" LOC = "S:PIN43";
NET "DB<0>" LOC = "S:PIN12";
NET "DB<1>" LOC = "S:PIN13";
NET "DB<2>" LOC = "S:PIN14";
NET "DB<3>" LOC = "S:PIN16";
NET "DB<4>" LOC = "S:PIN29";
NET "DB<5>" LOC = "S:PIN36";
NET "DB<6>" LOC = "S:PIN37";
NET "DB<7>" LOC = "S:PIN38";
NET "MISO" LOC = "S:PIN33";
NET "RD" LOC = "S:PIN23";
NET "RS" LOC = "S:PIN21";
NET "WR" LOC = "S:PIN22";
#PINLOCK_END
GTS とか GTK という機能を持ったピンがあるので、CS と SCK,EXTCLK をそれらに割り当て、あとは配線するのに都合が良いように割り当てている。
それぞれのピンの機能について
- CS,SCK,MOSI,MISO -- SPIポート
マスターとの接続。CS を H にしたら 通信 関係のレジスタを 初期化することで、バイト単位の同期は取れるようにする。通信フォーマットは後述。
あと、CS はプルアップしている。MISO は、CS が H のとき Hi-Z にした方が良いかも知れないが(今は)未サポート。 - DB[7..0], RD,WR,RS -- LCD 制御
LCD の制御線。(LCD の)RESET と CS がない。
RESET は、ソフトRESET を使う。(ソフトRESET が使えるか確認必要)。LCD の RESET はプルアップしている。
LCD の CS は、CS と接続。 - OEOUT -- ラッチのトライステート制御ピン
ラッチの OE に接続。状態は SPI で設定する。OE = H にすると Hi-Z (初期状態)。Hi-Z にすることで、ポートを別の目的に使えるようにする。 - LEOUT -- ラッチ制御ピン
ラッチの LE(CLK) に接続。↓で取り込み。 設定によって制御方法を変えられる。 - EXTCLK
ラッチを取り込むトリガ用の信号線(外部)。他に 周波数カウンタ用の入力ピンにも使う。CPLD で作るプリスケーラを通すことで、高い周波数もカウント出来るようにする。 - EVIN
ラッチを取り込むトリガ用の信号線(マスター)。定期的に取り込む場合などは、マスター側で制御する。
XMEGA の事象出力を接続することで、すべての事象をトリガにできる。事象は、タイマーを使っての定期的な取り込み だけに使う予定。 - EVOUT
XMEGA への事象入力用。この信号でデータを取り込む。事象は、タイマーのクロック元にもできるので、周波数カウンタの入力としても使う。
ついでに XMEGA のボード L28A3 の XMEGA(A3) への接続を書いておくと ..
MOSI PD7(DTXD1)
MISO PD6(DRXD1)
SCK PD5(DXCK1)
CS PD4
※ USART の SPI マスタ機能を使う
EVOUT PE6
EVIN PE7(EVOUT)
( ラッチ出力 PORTF )
通信プロトコル
制御バイトを前置すろことと、I2Cキャラクタディスプレーの仕様の拡張にすることは既に決めた。どのように拡張するか検討することにする。
基本のプロトコル
- 送信:
CS を L にして [制御バイト] [データ] [制御バイト] [データ] ... と 交互に送る。制御バイトの bit7 は CONT で これを一旦 0 にすると、以降データのみになる。
CS を H にすると CONT の状態はリセットされる。 - 受信:
CS を L にして [制御バイト] [ダミーデータ] [制御バイト] [ダミーデータ] ... と 交互に送る。
制御バイトに READ を指示するビットがあり、ダミーデータ送信のときに READ したデータを返す。
CONT を 0 にすると 以降無効なデータが返る。この様にしたのは、先読みをするが 終了を指示できないため 1 バイト余計に READしてしまうため。 - RS の制御
RS は、LCD にデータかコマンドかを指示する信号線。1bit のアドレス線と思っても良い。
制御バイトの bit6 は RS で、READ または WRITE する前に RS線に出力する。
以上は基本。これを拡張して機能を付ける。
注意点としては、LCD の制御ルーチンでは、他の機能を考慮したくない .. ということ。-- 制御バイトに 他の機能の情報を混ぜないと LCD が制御できないような仕様はダメ。
- 現状案
制御バイト
bit7 CONT (前述)
bit6 RS (前述)
bit[5..4] CMD
"00" WRITE
"01" READ
"10" 装置制御
"11" 未定義
bit[3..0] アトリビュート
装置制御:
bit[3..2] EVOUT 選択
"00" EXTCLK
"01" not EXTCLK
"10" EVIN
"11" 1/64 EXTCLK (プリスケーラ)
bit1 LEOUT 選択
'1' EVOUT
'0' '1' (透過モード)
bit0 OEOUT 選択
'1' '0' (ラッチ有効)
'0' '1' (ラッチ無効 - Hi-Z)
補足:
装置制御では、続くデータは使用しないが、基本どおりにダミーデータを付ける。CONT を '0' にすると、READ と同じく以降無効になる。
EXTCLK は、外部入力との間にインバータを入れる予定で、"01" not EXTCLK で正論理。"00" は負論理でこれを選択すると ↑ でデータ採取。
さらなる拡張:
装置制御で、続くデータも使用する拡張は簡単にできる。CONT を 0 にして 連続でデータを送るのもあり。
ただし、LCD のような 独立した装置だとその仕様では使いにくい。"11" 未定義 を使って 4bit のアトリビュートで装置を選択したり 動作を指定するのが良さそう。
ちなみに、RS は LCD 用で出力されてしまうが READ か WRITE しないと意味がないので、拡張用に使える。
デバッグの方法
好きなことを書いたが、実をいうと、どうやってデバッグするのか知らないレベルだったりする。
とりあえずググってしらべて見ると、FreeHDL が Linux でも使用できて良さそうな感触。
コマンドラインで使えるのが実は嬉しい。あと GUI で使いたいときは、qucs で使えるらしいのだが .. qucs は 教育用回路シミュレータ的な使い方が多く 論理シミュレータでどう使えるのかイマイチわからなかった。
ただ、セットで使うものなので、qucs に FreeHDL がもれなくついてくる。-- ソースは ここ。Windows バイナリは ここ。
FreeHDL Windows バイナリを インストールして見たのだが、gvhdl は perl スクリプトだった。perl は入れていないし freehdl-v2cc.exe を直接使うしかなさそう。
普通はこんな風に使えるらしいのだが...
gvhdl -c testbench.vhdl
gvhdl spi2par.vhdl testbench.o --libieee
FreeHDL の使い方が皆目見当がつかなかったのだが、このページを見たら理解できた。
あとは、ファイルから状態を読み込みできれば、デバッグできる。.. とりあえず このページを見たら、なんとなく分かった。
あと、VHDL Tutorial: Learn by Example がいろいろあって参考になりそう。
MinGW+MSYS環境での FreeHDLビルド
qucs のところにある FreeHDL をインストールしてみたが全然動かないので、ビルドしてみた。
MinGW も MSYS も少々古いうえ、ちょっと変則的な環境なので、あまち参考にはならないかも。
- 1. MinGW バイナリの追加インストール
Source Forge の http://sourceforge.net/projects/mingw-install/files/mingw_dir/current/ から
libtool-2.2.6b-20100118-1.tar.gz
pkg-config-0.23-20100118-1.tar.gz
libiconv-1.13.1-20100119-1.tar.gz/download
gettext-0.17-20100119-2.tar.gz/download
glib-bin-2.22.3-1-win32.tar.gz
glib-dev-2.22.3-1-win32.tar.gz
と http://sourceforge.net/projects/mingw/files/MinGW%20expat から
libexpat-2.0.1-1-mingw32-dll-1.tar.gz
をダウンロードして /mingw に展開する。
実は、glib-dev, gettext, libiconv, libexpat は、必須ではない。が、glib や pkg-config をビルドするのに必要なので、入れておいた方が良い。 - 2. regex のインストール
http://gnuwin32.sourceforge.net/packages/regex.htm から
regex-2.7-bin.zip
をダウンロードして "c:/Program Files/Regex" に展開する。
良く分からないのだが、 /mingw の方にもコピー。 - 3. Strawberry Perl のインストール
perl を入れてなかったので、Strawberry Perlを入れて見ることにした。
実をいうと MSYS を最新にすれば、regex も perl もパッケージがある。それを使えばもっと楽だと思う。MinGW も同様で手動でインストールしなくて良い。
次は、FreeHDL のビルドとインストール。
$ ./configure --prefix=/mingw
$ make
$ make install
だけで、インストール自体はできる。環境変数の設定が必要で、
$ export FREEHDL=/mingw
して使う。
ただ、環境が変則的なので、少々変更が必要。
- /mingw/bin/gvhdl の編集 と libtool のコピー
- 1. FreeHDL の libtool を /mingw/bin/freehdl-libtool に名前を変えてコピー
- 2. /mingw/bin/gvhdl の以下のところを変更
my $libtool = "libtool";
↓
my $libtool = "c:/msys/1.0/bin/sh c:/MinGW/bin/freehdl-libtool";
gvhdl は perl スクリプトで その中で libtool を実行するのだが、libtool は、シェルスクリプトで sh 自体は MSYS のコマンド。この環境のため、普通に libtool としても実行できない。
あと、どうもビルドしたときの libtool を使わないと上手く動かないようだ。
追記:
仮の環境で 最新の MSYS をインストールしてみた。MSYS のファイルはみな lzma で圧縮されているが、MSYS の base に lzma が含まれている。
MSYS のバイナリは、/usr にインストールする。perl と libregex の bin と dev 、あと libcrypt の dll をインストールすれば OK 。上記の 設定の問題はなくなり make install した状態で動作する。 - 1. FreeHDL の libtool を /mingw/bin/freehdl-libtool に名前を変えてコピー
実行できるかのテスト
上のリンクの easy.vhd を作り
$ gvhdl easy.vhd --libieee
とすると....
gvhdl: FreeHDL root path is 'c:/MinGW'.
gvhdl: executing 'c:/MinGW/bin/freehdl-v2cc -m easy._main_.cc -L c:/MinGW/share/freehdl/lib -o easy.cc easy.vhd'
easy.vhd:26: unit easy (IIR_EntityDeclaration)
gvhdl:
gvhdl: ================================
gvhdl: Compiling 'easy.cc'...
gvhdl: ================================
gvhdl: g++ -I c:/MinGW/include -c easy.cc
gvhdl:
gvhdl: ================================
gvhdl: Compiling simulator main file 'easy._main_.cc'...
gvhdl: ================================
gvhdl: g++ -I c:/MinGW/include -c easy._main_.cc
gvhdl: Linking simulator 'easy'...
gvhdl: c:/msys/1.0/bin/sh c:/MinGW/bin/freehdl-libtool --mode=link g++ easy._main_.o easy.o -lm c:/MinGW/lib/libfreehdl-kernel.la c:/MinGW/lib/libfreehdl-std.la c:/MinGW/lib/freehdl/libieee.la -o easy
linker: g++ easy._main_.o easy.o -o .libs/easy /mingw/lib/libfreehdl-kernel.a c:/progra~1/Regex/lib/libregex.dll.a -LD:/Progra~1/GnuWin32/lib /mingw/lib/libintl.dll.a -lwsock32 -lole32 -luuid -lmsvcp60 /mingw/lib/libfreehdl-std.a /mingw/lib/freehdl/libieee.a -Lc:/progra~1/Regex/lib -L/mingw/lib
linker: creating easy
gvhdl: ================================
gvhdl: Simulator 'easy' created.
gvhdl: ================================
とメッセージが出て easy.exe が出来る。
実行すると ...
default component instantiation for unit ':tb_arch:tb_q:e0'. Using 'work.easy'!
Available commands:
h : prints list of available commands
c: execute cycles = execute simulation cycles
n : next = execute next simulation cycle
q : quit = quit simulation
r
というメッセージが出て、プロンプトが出る。
> dc -f wave.vcf
> d
> r 60ns
> q
で、結果が出力された。
wave.vcf は、テキストファイルだが、まぁ読めるような感じではない。GtkWave で見ることが出来るらしい。Windows 版もある。(参考)
あと、dump しないで、show コマンドで見ていくという使い方もできるし、見やすいフォーマットで標準出力に出す テストベンチを作っても良さそう。
追記:

ようやく、spi2par の回路(のベース)をシミュレーションできた。
このチャートは、2 バイトのデータを WRITE するときのもの。CMD = 0xff だと、CONT=0 で 以降 WRITE データ。あと RS=0 。
結局 GtkWave が便利ということが分かった。あとデータのパターンは 直接書いている。ファイルからの読み込みをすると、パターン変更のとき便利ではある。... が 基本的なところが動いてから。
- ソース : spi2par-01.zip