スパイス  組み込み制御装置の受注製作

小規模組み込み装置に向いたCPLD
平成26年9月 1日

 CPLDでのデータセレクタ実装
 (従来型の)CPLDは入力数/出力数の比が4対1を超えるデータセレクタの実装は苦手だと説明しました。
当然、出来ない訳ではないのですがツールの特性を知って、それに合わせたコードの記述が必要になります。
これは明らかに直感的ではない記述になります。
私のところでの実例を書いておきます。ザイリンクス社のXC9500XL(144ピン)に8ビット幅で16対1のデータセレクタを実装したときのことです。計算上全体の入力数は8x16=128本にもなります。が、実際には一部の出力に固定値(常に'1'を出力する)を含んでいるので、入力数は100本を少し越えた数字でした(デバイスの仕様からこんな実装は実現できないと言われないための説明です。特に重要ではありません)。

    最初の実装
 プログラムの記述は下記のようになります。ごく普通のコードです。このコードでデバイスへの書き込みファイルの作成まで問題なく完了します。
/* BUS_DATA, DATA0, ..., DATA15 は全て8ビット配列 */
        always @( BUS_SEL, DATA0, DATA1, DATA2, DATA3, DATA4, ... . DATA15 ) begin
                case (BUS_SEL)
                       4'b0000 :       BUS_DATA = DATA0;
                       (一部省略) 
                       4'b1111 :       BUS_DATA = DATA15
                endcase
        end
 ところが、実際に動作させて見ると入力に指定した特定のピンからおかしな信号出力が見られます。原因を探していくと、結果的にはツールのバグであることが分かりました。上記のようなコードでは8ビット分のデータセレクタ全体を一つのロジックエレメント(複数のマクロセルの集合で入力信号数の制限はほぼマクロセルと同じ)に割り当てています。すると単純計算で入力信号の数+データ選択信号数だけの入力が必要です。当然、標準の入力数では不足しますので隣接するマクロセルの機能を借用するすることで見かけ上のフィティングは問題なく正常終了していました。ところが、この隣接するマクロセルを使用する処理部分にバグがあるらしく、借用したマクロセルにデフォルトで対応しているピン(設定では入力に設定してある)が設定を無視して出力となっていました。どのマクロセルを借用するかはプログラムが決めますので、どのピンが強制的に出力になるかの予測は出来ません。
 これはプログラムのバグではあるのですが、間接的に多くの問題点を指摘しています。
 国内メーカーであれば見つかったバグは大抵次のVer.で対策されますが、海外メーカーではあまり多くを期待しない方が良いでしょう。
また、基本的にデバイスの構造上、苦手な機能は出来るだけ避けて使用するような配慮が必要です。

    苦肉の対応策
 この時は、対処方法としてプログラムの最適化機能の一部を禁止することで、何とかしのぎました。下図のように4対1のデータセレクタを2段直列にすることで16対1とします。XC9500XLの仕様なら4対1のデータセレクタの実装まではマクロセルの入力数制限以内に収まります。
しかし、このままではプログラムの最適化機能によって自動的に16対1のデータセレクタに最適化されるので、最適化の一部機能を禁止します。


    汎用的な対策方法
 実務中には気が付かなかったのですが、これは二つの問題が複合しています。
 単純に単一信号の16対1のデータセレクタならマクロセルに対する制約以内に収まるのですが信号を配列として一括代入したために、これが出来なくなっています。最終的な出力信号名を(OUT1, OUT2, ... . OUTnのような)非配列名にして個別に代入すれば、配置の検討は各信号名単位に行われるでしょう。あるいは配列名のままでも配列の各信号毎に代入を行うように記述するだけでも上手く行く可能性はあります。以下のプログラムは動作を検証していませんので、参考程度に見てください。
/* 4対1を超えるデータセレクタの記述方法(未検証のため使用には注意) */

module BUS_SELCT16( SEL, OUT, IN0, ... , IN15 );
        input   [3:0]   SEL;
        output  [7:0]   OUT;
        input   [7:0]   IN0,  ... , IN15;
        //個々の信号に順番に代入することで配置の検討を各信号単位に行わせる
        SELCT16 SEL_1( .SEL(SEL), .OUT(OUT[0]), .IN({IN1, IN0});
                                (一部省略)
        SELCT16 SEL_7( .SEL(SEL), .OUT(OUT[7]), .IN({IN15, IN14});
endmodule

module SELCT16( SEL, OUT, IN );
        input   [3:0]   SEL;
        output  [7:0]   OUT;    (H24/ 9/ 9, 記述ミス訂正)
        output          OUT;    (H24/ 9/ 9, 記述追加)
        input   [15:0]  IN;

        always @(SEL, IN) begin
                case (SEL)
                        2'b0000 :       OUT = IN[0];
                                (一部省略)
                        2'b1111 :       OUT = IN[15];
                endcase
        end
endmodule
  

 これらの対処な方法はあるものの、本来やりたい事を素直に記述できないのは大きなデメリットです。
 以上は従来型のCPLDでの話です。FPGA類似型の内部構成を持つデバイスには当てはまりません。

目次へ  前へ  次へ