目次CPLD入門


開発言語仕様(VHDL)



CPLDの設計するための開発言語( HDL:Hardware Description Language )にはいくつかの種類があります。
ABEL-HDL、VerilogHDL、VHDLなどが代表的なものです。WebPACKのソフトウェアではこれらの言語のいずれでも使用できます。
私は記述が比較的容易であり、現在の主流であるVHDLを使うことにしました。
VHDLのフルスペルは"Very high speed integrated circuit Hardware Description Language"です。

ここに紹介する言語仕様はVHDLのほんの一部です。
詳しく知りたい方は専門書を見て下さい。

私は以下の本を参考にしました。

VHDLによるハードウェア設計入門
CQ出版 長谷川裕恭 著
ISBN4-7898-3287-2
A5判 236頁 定価2,345円(税込)
価格は2000年6月時点のものです。


以下にVHDLの基本構文を説明します。
実際にはもっと複雑で、奥が深いものです。ここで紹介する内容はほんの一部です。
記載している内容はXilinx Project Navigatorでの記述方法も含まれています。他のツールでは違う記述のものもあるかもしれません。




VHDLの基本構文
    エンティティー( Entity )とアーキテクチャー( Architecture )

      VHDLで回路構成を記述する際にエンティティーとアーキテクチャという概念が使われます。



エンティティーでは設計する回路ブロックの入力条件(ポート宣言)とかビット長などのパラメータ(ジェネリック宣言)を定義します。

アーキテクチャーでは設計する回路ブロックの中身を記述します。





    基本構文
library ieee;
use ieee.std_logic_1164.all;

entity (エンティティー名) is

(エンティティー文)

end (エンティティー名);

architecture (アーキテクチャ名) of (エンティティー名) is
begin

(アーキテクチャ文)
end (アーキテクチャ名);


青い文字の部分はVHDLで規定されている書式の文字を示しています。

大文字、小文字の区別はありません。


    コメント
      ハイフン(-)を2つ続けた後の文字は全てコメントとなり、処理には関係しません。
      コメントは1行のみに有効で、次の行もコメントにするためには先頭に(--)を付ける必要があります。
      Xilinx Project Navigatorでは日本語は使えません。

      library ieee;  -- Declaration of library
      -- comment
      赤字の部分がコメントです。



ライブラリ文( library )
    Library ではVHDLで使用する各種の定義群を宣言します。
    この宣言ではIEEEで規定されている標準ロジックの宣言の読み込みを指定します。
    いろいろな宣言がありますが、以下の2行を宣言すれば大部分はOKのようです。
    library ieee;
    use ieee.std_logic_1164.all;

    上記はIEEEのSTD_LOGIC_1164で規定されている定義を全て読み込むということになります。
    Xilinx Project Navigator を使用している場合には新規にソースファイルを作成した時点でこれらの宣言文が既に書かれています。複雑な回路を設計する場合にはもっと多くの宣言をする必要があります。

    処理の中で算術演算を使う場合にはSTD_LOGIC_UNSIGNEDを指定する必要があります。
      use ieee.std_logic_unsigned.all;


エンティティー文( entity )
    Entityではポート宣言、属性宣言、ジェネリック宣言などを行います。
    Entityの終了にはendを書きます。endの後のentity名は省略できます。
    ここではポート宣言と属性宣言のみを説明します。

    ポート宣言 ( port )
      Port宣言では全ての入出力ポートを指定します。

      構文
      port(ポート名:方向タイプ名;
          ポート名:方向タイプ名;



          ポート名:方向タイプ名);

      :スペース

      ポート名は方向、タイプが同じであればカンマ(,)で区切ってつなげて書くことができます。
      見やすさのためにセミコロン(;)の後で改行していますが、一行で書いてもかまいません。

      方向では以下の5種類が指定できます。
        in入力ポート
        out出力ポート
        inout入出力兼用ポート
        buffer出力(内部で再利用可)
        linkageどの方向でも結合可

      通常は in または out を使います。



      タイプ名ではロジックタイプを指定します。
      通常はstd_logicまたはstd_logic_vectorなどが使われます。vectorは同じロジックを複数作る(配列)場合に使用します。
      タイプを指定するためにはLibraryで" ieee.std_logic_1164.all "を指定している必要があります。

      例1
port (
  a,b,c : in  std_logic;
  y : out std_logic);
a、b、および c は標準ロジックの入力ポート
yは標準ロジックの出力ポート

      例2 ベクタ(配列)
port (
  a,b : in  std_logic_vector(2 downto 0);
  y : out std_logic_vector(2 downto 0));
a、b、および c はそれぞれ0から2までの組を持ちます。


    属性宣言( attribute )
      Xilinx Project Navigatorで使用できる属性( attribute )には多くの種類があります。
        attribute PIN_ASSIGN of object : object_type is "pin_name";
        attribute LOC of object_list : object_type is "function_block_name";
        attribute KEEP of object_list : object_type is "TRUE";
        attribute DONT_OPTIMIZE of object_list : object_type is "TRUE";
        attribute FAST | SLOW of object_list : object_type is "TRUE";
        attribute BUFG of object_list : object_type is "CLK" | "OE" | "SR";
        attribute INIT of object_list : object_type is "S" | "R";
        attribute PWR_MODE of object_list : object_type is "LOW" | "STD";
        attribute REG of object_list : object_type is "CE" | "TFF";
        attribute TNM of object_list : object_type is "string";

      これらの属性宣言をする前には必ず以下の宣言をしなければなりません。
        attribute attribute_name : string;

      ピン配置指定の属性宣言例を以下に示します。
      ポート名称( object )は事前にポート宣言で指定されている必要があります。

      A、B、Yポートをそれぞれ1、2、3番ピンにアサインした例
library ieee;
use ieee.std_logic_1164.all;

entity Ex1 is
  port( A : in std_logic;
        B : in std_logic;
        Y : out std_logic);
  attribute pin_assign : string;
  attribute pin_assign of A : signal is "1";
  attribute pin_assign of B : signal is "2";
  attribute pin_assign of Y : signal is "3";
end;

architecture SAMPLE of Ex1 is
begin
  Y <= A nand B;
end SAMPLE;

フィッティング結果のピン配置

      T  T  T           T  T  T  V  T  
      I  I  I           I  I  I  C  I  
      E  E  E  y  b  a  E  E  E  C  E  
      --------------------------------  
     /6  5  4  3  2  1  44 43 42 41 40 \
TIE | 7                             39 | TIE
TIE | 8                             38 | TIE
TIE | 9                             37 | TIE
GND | 10                            36 | TIE
TIE | 11         XC9536-5-PC44      35 | TIE
TIE | 12                            34 | TIE
TIE | 13                            33 | TIE
TIE | 14                            32 | VCC
TDI | 15                            31 | GND
TMS | 16                            30 | TDO
TCK | 17                            29 | TIE
    \ 18 19 20 21 22 23 24 25 26 27 28 /
      --------------------------------  
      T  T  T  V  T  G  T  T  T  T  T  
      I  I  I  C  I  N  I  I  I  I  I  
      E  E  E  C  E  D  E  E  E  E  E  

    Xilinx Project NavigatorではLock Pinsを行うと、ピン配置はUCFファイルに記録されます。ですから、Lock Pins以降にピン配置を変更するためにはProcesses for Current SourceウィンドウのEdit UCF fileを使用して記録データの変更を行う必要があります。


アーキテクチャー文( architecture )
    Architectureでは回路のロジックに関する指定を書きます。ここがCPLD設計の中心になるところです。
    非常に多くの規定があり、ここではとても全ては書けません。基本的な部分のみを記載します。

    構文
    architecture(アーキテクチャー名)of(エンティティー名)is
    
        <宣言文>
    
    begin
    
        <処理文>
    
    end(アーキテクチャー名)

    :スペース
    endの後のアーキテクチャー名は省略することができます。

    宣言文

    宣言文にはsignal宣言、component宣言などが書かれます。以下にsignal宣言のみ紹介します。

      信号宣言( signal )
      signal宣言は内部で使用する信号を定義します。


library ieee;
use ieee.std_logic_1164.all;

entity Ex2 is
  port( A : in std_logic;
        B : in std_logic;
        C : in std_logic;
        D : in std_logic;
        Y : out std_logic);
end;

architecture SAMPLE of Ex2 is
signal S0,S1 : std_logic;
begin
  S0 <= A nand B;
  S1 <= S0 nand C;
  Y <= S1 and D;
end SAMPLE;
S0およびS1は内部のロジックのみで使用する信号です。
信号宣言ではポート宣言と同様にデータタイプを指定します。


    処理文

    処理文では以下のような処理文を書くことができます。
    同時処理文
    ( concurrent )
    同時処理文では独立した論理処理文を書きます。
    S0 <= A and B
    Y <= S0 nand D
    上記の文はそれぞれ独立して処理され、S0の行とYの行を逆に書いても同じです。
    書く順番に関係なく、同時に処理しているように見えるので同時処理文と言われています。
    プロセス文
    ( process )
    プロセス文では記述した文を上から順番に処理されます。
    文の中では if とか case とかの条件文を記述することもできます。

    プロセス文の構文
      process(入力ポート名)
      
      begin
      
        < 順次処理文 >
      
      endprocess;

:スペース


    以下ではプロセス文で使用する if 文および case 文について説明します。

    IF 文
構文
(1)
if 条件 then
 <順次処理文>
end if;
(2)
if 条件 then
 <順次処理文>
else
 <順次処理文>
end if;
(3)
if 条件 then
 <順次処理文>
elsif 条件 then
   <順次処理文>
else
   <順次処理文>
end if;

    CASE 文
構文
case 条件 is
  when "条件1" => ポート名 <= "設定値1";
  when "条件2" => ポート名 <= "設定値2";



  when "条件n" => ポート名 <= "設定値n";
  when others => ポート名 <= "設定値x";
end case;




3 to 8 Demultiplexer ( 74138 相当 )
フィッティング結果のピン配置
                                    y  
      T  T  T           T  T  T  V  <  
      I  I  I           I  I  I  C  0  
      E  E  E  c  b  a  E  E  E  C  >  
      --------------------------------  
     /6  5  4  3  2  1  44 43 42 41 40 \
 g1 | 7                             39 | y<1>
g2a | 8                             38 | y<2>
g2b | 9                             37 | y<3>
GND | 10                            36 | y<4>
TIE | 11         XC9536-5-PC44      35 | y<5>
TIE | 12                            34 | y<6>
TIE | 13                            33 | y<7>
TIE | 14                            32 | VCC
TDI | 15                            31 | GND
TMS | 16                            30 | TDO
TCK | 17                            29 | TIE
    \ 18 19 20 21 22 23 24 25 26 27 28 /
      --------------------------------  
      T  T  T  V  T  G  T  T  T  T  T  
      I  I  I  C  I  N  I  I  I  I  I  
      E  E  E  C  E  D  E  E  E  E  E  

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
library ieee;
use ieee.std_logic_1164.all; 

entity DECODER1 is
  port ( A,B,C,G1,G2A,G2B : in std_logic;        -- INPUT and OUTPUT declaration
         Y : out std_logic_vector(7 downto 0));
  attribute pin_assign : string;                 -- Pin assign
  attribute pin_assign of A : signal is "1";
  attribute pin_assign of B : signal is "2";
  attribute pin_assign of C : signal is "3";
  attribute pin_assign of G1 : signal is "7";
  attribute pin_assign of G2A : signal is "8";
  attribute pin_assign of G2B : signal is "9";
  attribute pin_assign of
      Y : signal is "33,34,35,36,37,38,39,40";
end DECODER1;

architecture SAMPLE of DECODER1 is
  signal IN_DATA : std_logic_vector(2 downto 0); -- Internal signal declaration
begin
  IN_DATA <= C & B & A;                          -- Binding vector
  process( IN_DATA, G1, G2A, G2B ) begin
    if( G1='1' and G2A='0' and G2B='0' ) then    -- Judgement of gate condition
      case IN_DATA is                            -- Judgement of input data
        when "000" => Y <= "11111110";
        when "001" => Y <= "11111101";
        when "010" => Y <= "11111011";
        when "011" => Y <= "11110111";
        when "100" => Y <= "11101111";
        when "101" => Y <= "11011111";
        when "110" => Y <= "10111111";
        when "111" => Y <= "01111111";
        when others => Y <= "XXXXXXXX";          -- Illegal condition
      end case;
    else
      Y <= "11111111";                           -- Gate OFF condition
    end if;
  end process;
end SAMPLE;

    上記の記述は3ビットのバイナリ入力を8つの出力に展開するデコーダ回路です。74138というデコーダICと同じ機能です。
    これを作るだけなら74138を使用した方が経済的です。練習のために作ってみました。
    以下にこの記述でのいくつかのポイントを説明します。
内 容
006 出力(Y)は8つの配列(vector)を使用しています。
今回の指定では降順(7->6->5->4->3->2->1->0)としているので downto を使用しています。
昇順(0->1->2->3->4->5->6->7)にするために to を使うこともできます。
その場合、全ての配列の順番を意識して設定する必要があります。
015Yは配列なのでピンの割付も8つ指定しています。
019 内部の論理判定のための信号を定義しています。
3ビットなので3つの配列にしています。
021内部の信号に入力を接続しています。入力は1ビットづつなので、 & を使って結合しています。
022プロセス文の入力信号を指定しています。3ビットのIN_DATAおよびゲート入力(G1,G2A,G2B)です。
023ゲートの条件が全て'1'の場合023以下の処理となるようなロジックが組まれます。
024
-034
IN_DATAの条件により出力(Y)に状態を設定するロジックです。
035ゲート条件の一つでも'0'の場合の処理です。
036出力(Y)を全て'1'にするロジックです。