2019.6.1
前へ
次へ
ホームページトップへ戻る

[新連載]CPLD入門!
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
いつか使うことになるだろうと思ってはいたのですが。
何を今頃になって、というようなものですが。
ようやく本気で、CPLDと四つに取り組みます。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜



[第54回]


●CRTIF用VHDLプログラム

VGAIF用のVHDLプログラムは[第49回]でお見せしました。
そして前回見ていただきましたようにCRTIF用のVHDLプログラムもできております。
CRTIF用のVHDLプログラムはVGAIF用のVHDLプログラムをもとにして、相違しているところのみを変更する形で作成し、次にそれをもとにして80字/40字表示切り換え機能部分を追加して作成しました。
最終的には先に作成したVGAIF用プログラムとCRTIF用プログラムを合体させて、VGAIF/CRTIF両用のVHDLプログラムとして仕上げました。
そのようにして、VGAIF/CRTIF両用のVHDLプログラムとして完成させたのは、もうかれこれ3週間も前のことでした。

その過程でいろいろ悩ましい現象にぶつかり、悩みながらクリアしてきました。
VHDLプログラムはロジック回路をソフトウェアで記述するものです。
考え方はロジック回路を回路図として描くことと理屈の上では同じことです。
回路図ならば間違ったことを描かなければよいわけですが、VHDLの場合にはそこに文法上の制約が加わります。
回路図の場合でも実際にそれをTTLICなどを使って具体化するときにはゲートの遅延時間を考慮しないと誤動作につながります。
CPLD(MAX7000S)の内部回路は非常に高速(100MHz以上)ですが、それでもゲートの遅延時間は存在します。
VHDLプログラムの場合には、ソフトウェアのみを意識して、結局はハードウェアなのだということを、つい忘れてしまいます。
文法的には正しいのだけれど、書き上げたVHDLプログラムを実際にCPLDに書いて実行させてみると、気持ちの悪い誤動作に出会う、ということを何回も経験しました。
そのたびに原因、理由がわからずに、半日、1日あるいは数日間も苦闘してしまうことも再三経験しました。
中には単なる文法上の約束だけではなくて、記述の順序とかまとめ方といった、ひょっとするとMAX7000Sのいわばクセのようなものもあるらしいこともわかってきました。
そういうひとつひとつをクリアしながら、プログラムの完成にこぎつけたのですが、その過程ではなかなかメモをとるゆとりもなくて、あとでノートを見てみると、肝心のところが抜けていたりします。

悲しいことに3週間も前のことになると細かいことはほとんど記憶がありません。
ノートを見るといい加減な走り書きしかありません。
これはやはり後々のために備忘録として残すべきでありましょう。
とは言いながら、なにしろ相変わらず時間に追われる毎日です。
懇切丁寧に書くことなど、とてもとても出来そうにありません。

結局のところ、読者の皆様には、なんだかわけがわからんぞう、ということになってしまうかもしれません。
まま、できるだけ解説を加えて書きたいと思います。
最終的にVGAIFとCRTIFをあわせたプログラムとして仕上げたのですが、いきなりそこに行くのは飛ばしすぎです。
まずは製作の過程を追いながら、とりあえずCRTIF用のVHDLプログラムについて説明を進めたいと思います。

VGAIF回路とCRTIF回路は基本的にはほとんど同じです。
異なっているのは
1)水平同期周波数、垂直同期周波数が違う
2)垂直表示ラインの本数が違う
3)映像信号、同期信号の出力が違う
というあたりのところです。
水平表示文字数80字、垂直方向の文字数25行はVGAIFもCRTIFも同じです(まずは水平40字表示は考えないものとします)。
ということで、両者の異なるところは主として同期周波数の違いに基くところになります。

●VGAIFの信号規格

VGAIFの信号規格は「CRTインターフェースボードの製作」[第17回]に書きました。
以下に再掲します。
垂直同期周波数  70Hz
水平同期周波数  31.46875KHz
ドット表示周波数  25.175MHz

水平表示期間    640ドット(80CHR)
フロントポーチ    16ドット(2CHR)
水平同期パルス幅 96ドット(12CHR)
バックポーチ     48ドット(6CHR)
総ドット数/行    800ドット(100CHR)

垂直表示期間    400行
フロントポーチ    12行
垂直同期パルス幅 2行
バックポーチ     35行
総ライン数      449行

●CRTIFの信号規格

CRTIFの信号規格は「CRTインターフェースボードの製作」[第21回]の前後に書きました。
フロントポーチ 8文字(4.568μs)
水平同期パルス 8文字(4.568μs)
バックポーチ 16文字(9.136μs)
水平表示期間 80文字(45.68μs)
水平1走査期間 112文字(63.952μs)

あれ?
垂直表示関係についての説明がありません。
なにしろ書くべきことが多くて、うっかり飛ばしてしまったようです。
「CRTインターフェースボードの製作」[第16回]に図があります。
それを見ながら下にまとめました。

垂直表示期間    200行
フロントポーチ    16行
垂直同期パルス幅 8行
バックポーチ     32行
総ライン数      256行

●VHDLプログラムの変更部分

VGAIFとCRTIFでは1ドットを表示するためのクロックが異なるのですが、CPLDの外部でジャンパーピンで切り換えてそれを入力CLKとするので、プログラムとしては変更する必要はありません。
VGAIFのVHDLプログラムは[第49回][第51回]にあります。
そのうち水平1行の総文字数の部分は[第50回]で説明しています。

--cntr2
process(cntr1)  
begin                   
                if cntr1(2)'event and cntr1(2) = '0' then
                cntr2 <= cntr2 +"0000001";
                end if;         
                if cntr2="1100100" then 
                cntr2<="0000000";
                end if;
end process;

CNTR2は水平同期信号と、VRAMをスキャンするためのアドレスを出力するための7ビットのカウンタです。
CNTR2はCNTR1が111から000になるタイミングでカウントアップします。
CNTR2は1100100(64H)のときに0000000になります。
これによってブランキング期間と表示期間を合わせた水平1ラインの期間(100文字=64H)を作り出しています。

この部分をCRTIF用に変更します。
変更したのは(1)の行だけです。

--cntr2
process(cntr1)  
begin                   
                if cntr1(2)'event and cntr1(2) = '0' then
                cntr2 <= cntr2 +"0000001";
                end if;         
                if cntr2="1110000" then --(1)
                cntr2<="0000000";
                end if;
end process;

CRTIFは水平総文字数は112文字(70H)ですから、CNTR2は1110000(70H)のときに0000000になります。

次は水平ブランキング期間と水平同期信号です。

--hblnk,hsync
process(cntr2)
begin
--hblnkwk               
                if cntr2="0000000" then
                        hblnkwk<='1';
                --elsif cntr2="0000001" then see note 5/6
                        hblnkwk2<='1';
                elsif cntr2="1010000" then
                        hblnkwk<='0';
                elsif cntr2="1010001" then
                        hblnkwk2<='0';
--hsynkwk               
      elsif cntr2="1010011" then
                        hsyncwk<='0';
                elsif cntr2="1011111" then
                        hsyncwk<='1';
                end if;
end process;

hblnkwk、hblnkwk2は水平表示期間と水平ブランキング期間を決定する信号です。
1の期間は表示期間です。
0の期間はブランキング期間です。
表示期間は80文字(50H)ですからその期間を’1’にします。
hblnkwkはこのあとの垂直同期信号を作成するための「ズレのない」信号です。
hblnkwk2は1文字遅延させた信号です。
elsifがコメント行になっていますが、そのことについては次回に説明する予定です。

hsynkwkは水平同期信号です。
ここは説明か必要です。
CNTR2が50Hでブランキング期間になったあと、水平同期パルスまでがフロントポーチ(2文字)で、そのあとが水平同期パルス(12文字)で残りがバックポーチ(6文字)です。
するとhsynkwkは1010010(52H)〜1011101(5DH)のはずなのに、開始が1010011(53H)で終わりが1011110(5EH)になっています。
独立化セットのこの部分の回路図を調べましたら、開始が57Hで終わりが5FHになっています。
おそらく回路を簡単にするためにそのようにしたのだと思います(全く記憶にありません)。
少しアバウトですが、特に問題なく表示されていることを考えると、その程度のずれはディスプレイ側で調整してくれるようです。
今回のプログラムで開始を53H、終わりを5EHにしたのは1文字の表示遅れを考慮したためだと思います(記憶にありませんが)。

さて。
それで、この部分をCRTIF用に変更します。
hblnkwkとhblnkwk2については変更はありませんが、理由があって、processをそれぞれ別にしました。
このことについては次回に説明します。
CRTIF用に変更が必要なのはhsynkwk(水平同期信号)の部分です。

--hblnk,hsync
process(cntr2)
begin
--hblnkwk               
                if cntr2="0000000" then
                        hblnkwk<='1';
                elsif cntr2="1010000" then
                        hblnkwk<='0';
                end if;
end process;
--
process(cntr2)
begin
--hblnkwk2              
                if cntr2="0000001" then
                        hblnkwk2<='1';
                elsif cntr2="1010001" then
                        hblnkwk2<='0';
                end if;
end process;
--
process(cntr2)
begin
--hsynkwk               
      if cntr2="1011001" then
                        hsyncwk<='0';
                elsif cntr2="1100000" then
                        hsyncwk<='1';
                end if;
end process;

CRTIFでは、CNTR2が50Hでブランキング期間になったあと、水平同期パルスまでがフロントポーチ(8文字)で、そのあとが水平同期パルス(8文字)で残りがバックポーチ(16文字)です。
するとhsynkwkは1011000(58H)〜1011111(5FH)のはずなのに、開始が1011001(59H)になっています。
ここは1文字の表示遅れを考慮したためだと思います(記憶にありません)。
すると最後の
elsif cntr2=”1100000” は
elsif cntr2=”1100001”
にすべきなのでしょうが、ま、ここはこのままでもいいかなと思います。

CPLD入門![第54回]
2019.6.1upload

前へ
次へ
ホームページトップへ戻る