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

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



[第69回]


●VHDLサンプルプログラム1 82C55(2)

VHDLプログラムについては、今までいくつか作成してきました。
その都度プログラムリストをお見せして、それをもとに簡単な説明も書いてきました。
これからもCPLDトレーニングボード用のサンプルプログラムを作成してそのプログラムリストをもとに説明を書いていくことになります。
文法的なことについては今までにも書いてきていますので、それはまあいいかな、とも思いましたが、CPLDトレーニングボード用のサンプルプログラム第1号ということでもありますので、私自身のための復習といいますか、学んできたことの整理を兼ねて、今までの記事と重複するところもありますけれど、文法的な基本ルールについてもあらためて必要な要点を書いておくことにします。
ということで、まずはVHDL版82C55のプログラムリストです。

●VHDL版82C55プログラムリスト

--cpld training i/o interface 82c55
--19/5/25 5/26 6/14 6/15 6/16

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library ARITHMETIC;
use ARITHMETIC.std_logic_arith.all;

entity trngio1d is
        PORT (
                        ADRSIN:in std_logic_vector(7 downto 0);
                        DINOUT:inout std_logic_vector(7 downto 0);
                        PA:inout std_logic_vector(7 downto 0);
                        PB:inout std_logic_vector(7 downto 0);
                        PCL:inout std_logic_vector(3 downto 0);
                        PCH:inout std_logic_vector(3 downto 0);
                        IOR:in std_logic;
                        IOW:in std_logic);
end trngio1d;

architecture rtl of trngio1d is

        signal ainout:std_logic;
        signal binout:std_logic;
        signal clinout:std_logic;
        signal chinout:std_logic;
        signal paout:std_logic_vector(7 downto 0);
        signal pbout:std_logic_vector(7 downto 0);
        signal pclout:std_logic_vector(3 downto 0);
        signal pchout:std_logic_vector(3 downto 0);
--
begin
--82c55 address F0,F1,F2,F3
-- in out set
process(IOW)
begin
        if IOW='0' then
                if ADRSIN="11110011" and DINOUT(7 downto 5)="100" and DINOUT(2)='0' then
                        clinout<=DINOUT(0);-- '0' out,'1' in
                        binout<=DINOUT(1);
                        chinout<=DINOUT(3);
                        ainout<=DINOUT(4);
                end if;
        end if;
end process;
-- portC out
process(IOW)
begin
        if IOW='0' then
                if ADRSIN="11110010" then
                        if chinout='0' then
                                pchout<=DINOUT(7 downto 4);
                        end if;
                        if clinout='0' then
                                pclout<=DINOUT(3 downto 0);
                        end if;
        -- bit out
                elsif ADRSIN="11110011" and DINOUT(7)='0' then
                        if clinout='0' then
                                if DINOUT(3 downto 1)="000" then
                                        pclout(0)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="001" then
                                        pclout(1)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="010" then
                                        pclout(2)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="011" then
                                        pclout(3)<=DINOUT(0);
                                end if;
                        end if;
                        if chinout='0' then
                                if DINOUT(3 downto 1)="100" then
                                        pchout(0)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="101" then
                                        pchout(1)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="110" then
                                        pchout(2)<=DINOUT(0);
                                elsif DINOUT(3 downto 1)="111" then
                                        pchout(3)<=DINOUT(0);
                                end if;
                        end if;
                end if;
        end if;
end process;
--portA out
process(ainout,paout)
begin
        if ainout='0' then
                PA<=paout;
        else
                PA<="ZZZZZZZZ";
        end if;
end process;
--portB out
process(binout,pbout)
begin
        if binout='0' then
                PB<=pbout;
        else
                PB<="ZZZZZZZZ";
                
        end if;
end process;
--portCL out
process(clinout,pclout)
begin
        if clinout='0' then
                PCL<=pclout;
        else
                PCL<="ZZZZ";
        end if;
end process;
--portCH out
process(chinout,pchout)
begin
        if chinout='0' then
                PCH<=pchout;
        else
                PCH<="ZZZZ";            
        end if;
end process;
--
--out data PORTA,PORTB
process(IOW)
begin
        if IOW='0' then
                if ADRSIN="11110000" and ainout='0' then
                        paout<=DINOUT;
                elsif ADRSIN="11110001" and binout='0' then
                        pbout<=DINOUT;
                end if; 
        end if;
end process;
--in data from port
process(IOR)
begin
        if IOR='0' then
                if ADRSIN="11110000" then
                        if ainout='1' then
                                DINOUT<=PA;
                        else
                                DINOUT<=paout;
                        end if;
                elsif ADRSIN="11110001" then
                        if binout='1' then
                                DINOUT<=PB;
                        else
                                DINOUT<=pbout;
                        end if;
                elsif ADRSIN="11110010" then
                        if chinout='1' then
                                DINOUT(7 downto 4)<=PCH;
                        else
                                DINOUT(7 downto 4)<=pchout;
                        end if;
                        if clinout='1' then
                                DINOUT(3 downto 0)<=PCL;
                        else
                                DINOUT(3 downto 0)<=pclout;
                        end if;
                else
                        DINOUT<="ZZZZZZZZ";
                end if;
        else
                DINOUT<="ZZZZZZZZ";
        end if;
end process;
--
        
end rtl;

こうして見ると結構長いプログラムです。
しかしやっていることは割と単純です。

このリストを眺めていて、今思いついたのですが、CPLDトレーニングボードの説明書では、いきなり82C55プログラムなどという大きなプログラムから入るのではなくて、それよりももっと前の段階、たとえばLED出力の1個に1、または0を出力して点灯、消灯を確認してみるだけのプログラムとか、プッシュスイッチにつながっている入力端子からスイッチの状態を読み込んで、それをLEDにつながっている出力端子に出力してみる、というような超簡単プログラムから入るといい、と思います。
しかしそれはここには書きません。

そのリストをここで書いたとしても、ただ、ふーん、そうか、という程度で終ってしまいます。
手元にCPLDトレーニングボードがあって、そこに書き込んで実際にLEDが点灯する様子を確認できて、はじめてなるほどこう書くとこうなるのか、と納得がいくことだと思うからです。
今ここでそういうことまで書き出しますと、なかなか次へ進んでいくことができなくなってしまうという、私の側の理由からでもあります。

●VHDLプログラムの先頭部分

さてそれではプログラムの説明に入ります。
全体のプログラムを前から少しずつ切り取りながら説明していきます。
まずはVHDLプログラムの最初の部分です。

--cpld training i/o interface 82c55
--19/5/25 5/26 6/14 6/15

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library ARITHMETIC;
use ARITHMETIC.std_logic_arith.all;

VHDLプログラムは全て半角で記述します。
カナ、全角文字は使えません。
あとでも説明しますが、ファイルはプレーンテキスト(notepad、メモ帳などで作成するファイル形式)です。
Word、Exelなどでは作成できません。
TXTファイルですが、拡張子はVHDを使います。
ファイル名も半角英数と一部の記号のみ許されます。
ちなみに今回のサンプルプログラムのファイル名は、trngio1d.vhdです。

行の先頭に−−(マイナス記号)2個を並べて書くと、その行はコメント行になります。
行(文)の終わりには;(セミコロン)を書きますが、;の後ろに−−を書いてその後ろにコメントを書くことができます。
空白行はコンパイルで無視されます。
見易さを考えてプログラムの適当な区切りに、−−行または空白行を置くのもよいでしょう。

library IEEE;以下の4行は「おまじない」だと思ってください。
普通のVHDLプログラムは先頭にこのように書いておけば問題はありません。
面倒なので詳しくは調べていません(どうせ調べてもすぐに忘れてしまいます)。
興味のあるかたはネットで調べてみてください。

●信号端子(entity)の記述

entityの部分で、以下のプログラム本体の中で使う信号端子名を定義します。
ここで定義した端子名はコンパイルのあと、Pin Plannerで実際の入出力端子に1対1で割り当てます。
Pin Plannerで実際に割り当てを行なうまでは、実際の端子配列を余り意識する必要はないと思います。

entity trngio1d is
        PORT (
                        ADRSIN:in std_logic_vector(7 downto 0);
                        DINOUT:inout std_logic_vector(7 downto 0);
                        PA:inout std_logic_vector(7 downto 0);
                        PB:inout std_logic_vector(7 downto 0);
                        PCL:inout std_logic_vector(3 downto 0);
                        PCH:inout std_logic_vector(3 downto 0);
                        IOR:in std_logic;
                        IOW:in std_logic);
end trngio1d;

entityの記述は、
entity ファイル名 is
で始まって、
end ファイル名;
で終ります。
ここに書くファイル名は、このプログラムファイルのファイル名(から.VHDを取ったもの)と一致していなければなりません。

entityとendの間に
PORT(   );
を記述します。
( )の中に信号端子名を記述します。
信号端子名は大文字でも小文字でも構いません。
コンパイルでは大文字と小文字は区別されません。
数字や_も使えますが先頭はアルファベットで始まらなければいけません。
最後を_で終ることや_を続けて使うこともできません。
VHDLの予約語を信号名に使うことはできません。
私は外部入出力端子であることを強調するため、ここで記述する信号端子名には大文字を使うことにしています。

信号端子名のうしろには:(コロン)を置いてそのうしろにその端子が入力であるか、出力であるか、または入出力(双方向)であるか、などの端子の特性を記述します。
inは入力を、outは出力を、inoutは入出力兼用であることを示します。
通常の入出力端子は、in、out、inoutの後ろにstd_logicと記述します。
最後に;(セミコロン)を書きます。
I/Oポートなどのように複数の端子がひとまとまりであるようなときはstd_logic(7 downto 0);のように記述します。
これは8ビットの場合で、std_logic(3 downto 0);は4ビットです。
ビット長はハードウェアの制約の範囲内で自由に決められます(と思います。上限があるかどうか試していません)。

忘れがちな重要なことがあります。
PORT (  );の中は、各信号端子記述の最後に;を置くことで複数の端子について記述しますが、最後の信号、上のリストではIOW:in std_logic には ; がないことに注意してください。

説明が長くなってしまいましたので、今回はここまでにします。

CPLD入門![第69回]
2019.6.16upload

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