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

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



[第63回]


●”0111000”の写真です

前回の終わりにお見せした写真は、−−cntr2 の40字表示のところ(elsif SW80_40=’0’ and cntr2=”0110111” then のところ)でのcntr2の波形です。
それだけでは、プログラムの記述が”0110111”でよいのか、”0111000”にすべきではないのか、というあたりの判別ができないことに気がつきましたので、elsif SW80_40=’0’ and cntr2=”0111000” then にして、cntr2の出力をオシロで観測してみました。
下はその写真です。



上(CH1)がcntr2(5)で下(CH2)がcntr2(3)です。
cntr2のビット5〜ビット3が”000”から”110”までカウントアップして、”111”になってから”000”になる様子が確認できます。
[第61回]に書きましたように、”111”であることが確認できるのは”111”になってから1クロック後です。
そのためプログラムのelsifの記述を”0111000”にすると、そのことが確認できるのは実際には”0111001”のときなので、上の写真のように1クロック遅れてcntr2がクリアされます。
写真ではcntr2(3)に幅の狭いパルスが見えます。
その後でcntr2(5)がLになっています。
CNTR2(5)〜(3)が”111”になったあと1クロック後にcntr2がクリアされたことが推測できます。

たった1文字分の遅れなのですが、それ以後の回路の動作に影響してしまうため、まともな表示にはなりません(下の写真)。



以上のことから、プログラムの記述は”0111000”ではなくて、それよりも1クロック前の”0110111”にしなければならないことが確認できました。
ぴったり理屈通りですので、納得です。

●そのほかの修正箇所(2)

前回に続いて直していただいたそのほかの修正箇所です。
−−ramadrs のところなのですが、ここは何回も書いていますように、考え方がちょっと複雑で、そのためVHDLプログラムの記述もちょっと複雑な書き方になっています。
ですからここに手を入れるのはちょっと難しいなあと思っていました。
下は修正前のプログラムです。

--ramadrs
process(cntr1,cntr2,cntr3,vblnkwk)
begin
      if vblnkwk='0' then
           ramadrswk<="0000000";   
           ramadrswk0<="0000000";
      elsif cntr3(2 downto 0)="111" and hblnkwk = '0' then
           ramadrswk0 <= ramadrswk;
      elsif SW80_40='1' and cntr2="1010000" and cntr1(0)='1' then
           ramadrswk <= ramadrswk0;
      elsif SW80_40='0' and cntr2="0101000" and cntr1(0)='1' then
           ramadrswk <= ramadrswk0;
      elsif cntr2(3)'event and cntr2(3)='0' and hblnkwk='1' then
           ramadrswk<=ramadrswk+"0000001"; 
      end if;                    
end process;

そして下がメールでお送りいただいた修正後の、その部分です。
今までと同じ考え方で、event文のなかに、そのほかの文が含められています。

--ramadrs
process(cntr2)
begin
     if cntr2(3)'event and cntr2(3)='0' then
          if hblnkwk='1' then --(A)
               if vblnkwk='0' then
                    ramadrswk<="0000000";   
                    ramadrswk0<="0000000";
               elsif cntr3(2 downto 0)="111" and hblnkwk = '0' then --(B)
                    ramadrswk0 <= ramadrswk;
               elsif SW80_40='1' and cntr2="1010000" and cntr1(0)='1' then --(C)
                    ramadrswk <= ramadrswk0;
               elsif SW80_40='0' and cntr2="0101000" and cntr1(0)='1' then --(D)
                    ramadrswk <= ramadrswk0;
               else
                    ramadrswk<=ramadrswk+"0000001"; 
               end if;
          end if;
    end if;
end process;
ここはちょっと…と思いつつ、とりあえずはこのままをEPM7128SLC84に書いてテストしてみたのですが。
やっぱりだめでした。
画面がめちゃくちゃになってしまいます。
これはto…様のせいではありません。
ここはちょっと複雑で、ここを直すのは無理なのです。
ここはさわらないでおきましょう。

と一度はそのように思ったのですけれど。
うーん。
やっぱり面白くないのですよねえ。
なんとかできないものか。

上のリストを眺めているうちに、おかしいところがあることに気が付きました。
(A)のなかに(B)がありますから、これだと(B)は実行されません。
(A)が必要なところはここではありません。
もっとも(A)を外してみても画面は乱れたままです。
どうやら(C)(D)のところでも1クロックあとで確認が行なわれるのでは、という疑いが出てきました。
うーん。
cntr2(3)での1クロックはちょっと大変です。
16文字に相当するクロックです。
ここはこのままでは補正するのは無理のようです。

なんとかしたいと考えているうちに、だんだん考えが整理されてきました。
やっぱりevent文のクロックとしてcntr2を使うのはどだい無理という結論に行き着きました。
もともとここは横方向の文字数が80字または40字でいずれも2ではないため、線形に変化するRAMアドレスとの間を補正するためのところで、その場合補正が必要なのは80字の場合RAMアドレスのビット4から上で、ビット3〜ビット0は補正する必要はありません。
それでもとのプログラムではcntr2(3)をeventクロックとして使っていたのです。

実は今回の問題以前の問題として、元のプログラムでも40字表示の場合には正しく表示されないことに気が付いていませんでした。
今回の問題を考えていくなかで、そもそも40字表示の場合にはeventのクロックがcntr2(3)ではだめではないか、ということに気が付きました。
40字の場合には、RAMアドレスの補正の必要がないのは、ビット2〜ビット0の下位3ビットになります。
元のプログラムであらためて40字での表示を確認してみたところ、やはり2行目以降で正しい表示にならないことが確認できました。
元のプログラムのままで、40字表示の場合に正しい動作にしようとすると、eventのクロックはcntr2(3)ではなくてcntr2(2)にしなければなりません。
と同時にramadrswk、ramadrswk0を7ビットから8ビットにする必要があります。
それにともなってAHout、AHinも7ビットから8ビットに、ALout、ALinは4ビットから3ビットに変更が必要です。

これは大改造です。
そこまでやるか、ということなのですが。
まあ、せっかく乗りかかった船ですから、やるしかありませんでしょう。
しかしこれはホネな作業です。
どうするか?

考え付いたのは、eventクロックとして1文字単位のクロックcntr1_2(cntr1(2)と同じ)を使うという方法です。
これならいけるのでは?
そう考えて書いたのが下のプログラムです。

--ramadrs
process(cntr1_2)
begin
     if cntr1_2'event and cntr1_2='0' then
          if vblnkwk='0' then
               ramadrswk<="00000000";  
               ramadrswk0<="00000000";
          elsif cntr3(2 downto 0)="111" and hblnkwk = '0' then
               ramadrswk0 <= ramadrswk;
          elsif SW80_40='1' and cntr2="1010000" then
               ramadrswk <= ramadrswk0;
          elsif SW80_40='0' and cntr2="0101000" then
               ramadrswk <= ramadrswk0;
          elsif cntr2(2 downto 0)="111" and hblnkwk='1' then --(E)
               ramadrswk<=ramadrswk+"00000001";        
          end if;
    end if;
end process;
各変数の桁数を7ビットから8ビットに変更しています。
40字表示と80字表示を同じ土俵で行なえるようにするためです。
ここでのポイントは(E)のelsif文です。
ここでもとのプログラムと同じようにramadrswkのカウントアップを行なっています。
この場合1つだけ心配だったのは、eventクロックにcntr1_2を使うことで1文字のずれが生じるのではないか、ということでした。
幸い実際に動作テストをしてみた結果、特に問題なく正しく表示されました。

下の写真はそのようにプログラムを変更して、動作テストを行ない、正しく表示された画面です。
これは80字表示です。



下の写真は40字表示に切り換えたときの画面です。



CPLD入門![第63回]
2019.6.10upload

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