PCIバス向けテストベンチ用サブプログラム

PCIバスターゲット用テストベンチを簡単に作成する


1.はじめに
SMDクランプバナー  PCIバスは 2002年頃から PCI Expressバスに置き換えられる様になり、近年は余り使用されなくなった様でが、製品寿命が比較的長い産業用システムでは現状でも現役です。
 しかし技術テーマとしては古い為か、ネットでの情報は乏しい印象です。

 例えば、PCIバス用IPをFPGAに載せてPCIバス用ターゲットデバイスを製作する際のテストベンチを簡単に作成できる様なライブラリをネットで探しても見つかりませんでした。
 IPメーカさんにはあるのでしょうが、現状はサポートしていないか、有償PCI-IPの正式ユーザしかサポートされない模様です。

 そこでPCIバスターゲット用テストベンチのライブラリを作成しました。
 PCIバスの現状では使用する機会はそう多くはなさそうですが、皆無でもなさそうなので、機会があれば利用してみて下さい。
 なお、ソースの改造等は構いませんが、本稿のオリジナルソースに関しては弊社に著作権があるものとし、ご利用の際はその旨を記載して下さい。
 また結果についての責任を弊社は負えませんので、ご利用は自己責任で行なって下さい。

 添付するソースファイルはASIAN記法(HDLにおける信号名称決定方法)によります。

 なお、本稿はPCIバスとModelSimについての知識を有している事を前提とし、詳細説明は省きます。

2.PCIバスライブラリ使用例
 PCIバスの利用者であればライブラリの使用方法は、細かい説明より使用例を見るのが最も理解と応用がし易いと思われるので、 ここでは基本的で簡単な使用例を記してユーザーズマニュアルの代替えとします。

●システム構成
 図1にテストベンチのシステム構成を示します。
テストベンチシステム構成
(クリックで拡大)


   図1.テストベンチのシステム構成 

●使用ファイル
ファイル名 ファイル内容
pci_master_access_2target.vht
テストベンチ本体
ターゲットのコンフィギュレーション、SRAMのライト/リード、I/Oライト/リードを行なう。 IDSELの使用方法と機能を判り易くする為にターゲットを2つのシステムにした。
pci_master_access_pac.vhd
テストベンチ用ライブラリ
この中の pci_config_write 等各種サブプログラムをテストベンチ中に記述する事で、PCIバスを動かす。
TGT8_plus.VHD
テストベンチ用ライブラリの動作を確認する為のターゲット用PCI-IP
ユーザ用テストベンチを作成する際には本IPをユーザ使用のPCI-IPに置き換える。
以下のソースファイルを一部編集したもの

Interface増刊 TECH I Vol.3 PCIデバイス設計入門 (CQ出版) 付属CDの VHDLソース
ターゲット8 (バースト転送対応) TGT8.VHD
著作権者:来須川智久 氏

編集者による変更箇所は 「--px0」を付記。
主な変更は以下の通り。
@DI、DO 各8点分のI/Oレジスタ追加。
 ベースアドレス +4 番地:DO[7..0] WR/RD
 ベースアドレス +6 番地:DI[7..0] RD ONLY
A受信データのパリティチェックを追加。
 パリティエラー時は PERR_n を'0'にする。
 PERR_n は受信動作が終了したら自動クリアされる。
sram_8_model.vhd
テストベンチ用8ビットSRMモデル
SRAMのアドレス幅は RAM_ADR_WIDTH で定義するが、使用するパソコンの環境(メモリ量)によってはコンパイル時にパソコンがハングする。

pci_master_access_2target.vht では Note1 の箇所で以下の様に'10'にしているが、パソコン環境によってはさらに小さい値にしなければならないかもしれない。

 constant SET_RAM_ADR_WIDTH : integer := 10;   -- sram address bit
圧縮ファイル一式
rtl_pci_test_bench.zip
上記の全ファイル一式を一括して圧縮したもの
ダウンロードして解凍すればソースファイルとして利用可能。


●ModelSim画面
付加機能付きユニバーサル基板_バナー  図2は、 ModelSim ALTERA STARTER EDITION 10.1e Revision: 2013.06 (ALTERA)のプロジェクト画面です。
modelsim画面
(クリックで拡大)

図2.ModelSim ALTERA STARTER EDITIONのプロジェクト画面

●シミュレーション結果
 図3は、 ModelSim ALTERA STARTER EDITION 10.1e Revision: 2013.06 (ALTERA)によるシミュレーション結果です。
シミュレーション図(クリックで拡大)
     図3.シミュレーション結果

●応用方法
SMD用ユニバーサル基板バナー  以下の手順で比較的容易にユーザのPCIバスを制御できます。
@圧縮ファイル一式をダウンロードする。

ATGT8_plus.VHDをユーザ使用のPCI-IPに置き換える

Bpci_master_access_2target.vht をユーザシステム用テストベンチに改造する。
 その中で pci_master_access_pac.vhd を以下の様にパッケージ宣言する。
  use work.pci_master_access_pac.all;

Cpci_master_access_2target.vht 中のサブプログラム使用部分をコピーしてカスタマイズする。

●参考資料
 PCIバステストベンチ作成に当たり、以下の資料を参考にしました。
@OPEN DESIGN No.7 PCIバスの詳細と応用へのステップ (CQ出版社)
AC&E TUTORIAL VHDLによるハードウェア設計入門(初版) 長谷川裕恭 (CQ出版社)
BTECHI Vol.3 インーフェイス増刊 PCIデバイス設計入門 (初版)(CQ出版社)


***********************************************
 本稿の主題である「PCIバスターゲット用テストベンチ」の作成方法は以上です。
 以下は補足説明として関連事項を記載したものなので、ご興味をお持ち頂けたらご覧下さい。


【補足説明】
オペアンプ基板バナー ●サブプログラムの改造
 PCIバス用テストベンチの目的は以下の2つです。
@使用するPCI-IPの動作確認
 各種タイミング変更、パリティエラー発生、32ビットバウンダリ以外のアドレスでのアクセス等、 PCIバスの正常アクセス以外のイリーガルなアクセスも必要。

APCI-IPの動作は正常であり、それを用いたターゲットの動作確認
 PCIバスは正常アクセスさせるだけで良く、パリティエラー等は発生させる必要はない。

 本稿のPCIバス向けテストベンチ用サブプログラムは@、Aの何れにも容易に対応できます。
 あるいはパリティエラー生成を取り除く等で、容易にA専用の設定要素が少ないサブプログラムに改造する事もできます。

 また、バースト転送時の最大データ数を増やす事も pci_master_access_pac.vhd の
 constant MAX_DATA  : integer := 4;
の値と、関連する行列を変更する事で容易にできます。

 さらに、大量のデータをライト/リードする場合に便利な、データファイルを用いたテストベンチへの改造も比較的容易にできます。

●サブプログラムの説明
 各サブプログラムは procedure としているので、所要の情報をセットしてテストベンチ中に埋め込むだけでPCIバスが簡単に制御できます。

(1)コンフィギュレーション・ライト pci_config_write
    procedure pci_config_write (
                set_dev_no      : in    integer range 0 to 31;              --  --px1
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_wr_data     : in    std_logic_vector(31 downto 0);      --
                set_be_n        : in    std_logic_vector(3 downto 0);       --     
                set_data_perr   : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  v_idsel         : out   std_logic_vector(31 downto 0);      -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic                           -- 
    );

設定項目 設定内容
set_dev_no
integer range 0 to 31
コンフィギュレーション対象のターゲットを選択する信号線 IDSELを整数 0 〜 31で指定。
set_address
std_logic_vector(31 downto 0)
ライト対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_wr_data
std_logic_vector(31 downto 0)
ライトするデータを設定。
set_be_n
std_logic_vector(3 downto 0)
ライトデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
set_data_perr std_logic
ライトデータに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。


(2)コンフィギュレーション・リード pci_config_read
    procedure pci_config_read (
                set_dev_no      : in    integer range 0 to 31;              --  --px1
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_be_n        : in    std_logic_vector(3 downto 0);       -- 
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  v_idsel         : out   std_logic_vector(31 downto 0);      -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic;                          -- 
        signal  perr_n          : out   std_logic;                          -- 
        signal  sv_read_data    : out   std_logic_vector(31 downto 0)       -- for test
    );

設定項目 設定内容
set_dev_no
integer range 0 to 31
コンフィギュレーション対象のターゲットを選択する信号線 IDSELを整数 0 〜 31で指定。
set_address
std_logic_vector(31 downto 0)
リード対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_be_n
std_logic_vector(3 downto 0)
リードデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。
なお、sv_read_data はリードしたデータを判り易く値として波形表示する為のものである。


(3)メモリ・ライト pci_memory_write
    procedure pci_memory_write (
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_wr_data     : in    std_logic_vector(31 downto 0);      -- 
                set_be_n        : in    std_logic_vector(3 downto 0);       --     
                set_data_perr   : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic                           -- 
    );

設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
ライト対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_wr_data
std_logic_vector(31 downto 0)
ライトするデータを設定。
set_be_n
std_logic_vector(3 downto 0)
ライトデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
set_data_perr std_logic
ライトデータに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。


(4)メモリ・リード pci_memory_read
    procedure pci_memory_read (
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_be_n        : in    std_logic_vector(3 downto 0);       --     
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic;                          -- 
        signal  perr_n          : out   std_logic;                          -- 
        signal  sv_read_data    : out   std_logic_vector(31 downto 0)       -- for test
    );

設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
リード対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_be_n
std_logic_vector(3 downto 0)
リードデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。
なお、sv_read_data はリードしたデータを判り易く値として波形表示する為のものである。


(5)I/O・ライト pci_io_write
    procedure pci_io_write (
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_wr_data     : in    std_logic_vector(31 downto 0);      -- 
                set_be_n        : in    std_logic_vector(3 downto 0);       --     
                set_data_perr   : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic                           -- 
    );

設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
ライト対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_wr_data
std_logic_vector(31 downto 0)
ライトするデータを設定。
set_be_n
std_logic_vector(3 downto 0)
ライトデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
set_data_perr std_logic
ライトデータに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。


(6)I/O・リード pci_io_read
    procedure pci_io_read (
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_be_n        : in    std_logic_vector(3 downto 0);       -- 
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic;                          -- 
        signal  perr_n          : out   std_logic;                          -- 
        signal  sv_read_data    : out   std_logic_vector(31 downto 0)       -- for test
    );

設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
リード対象のアドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_be_n
std_logic_vector(3 downto 0)
リードデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。
なお、sv_read_data はリードしたデータを判り易く値として波形表示する為のものである。


(7)メモリ・バースト・ライト pci_memory_burst_write
    type    SET_DATA is record 
                WR_DATA : std_logic_vector(31 downto 0);
                BEn     : std_logic_vector(3 downto 0);
                PERR    :  std_logic;                   -- 1: ng_parity, 0: ok_parity
                LAST    :  std_logic;                   -- 1: last data, 0: non-last data
    end record;
    type    SET_DATA_ARRAY is array (0 to (MAX_DATA-1) ) of SET_DATA;

    procedure pci_memory_burst_write (
                set_address         : in    std_logic_vector(31 downto 0);  -- 
                set_ad_perr         : in    std_logic;                      -- 1: ng_parity, 0: ok_parity
                set_data_array      : in    SET_DATA_ARRAY;
        ----
        signal  clk                 : in    std_logic;                      -- 
        signal  trdy_n              : in    std_logic;                      -- 
        signal  devsel_n            : in    std_logic;                      -- 
        signal  frame_n             : out   std_logic;                      -- 
        signal  ad                  : inout std_logic_vector(31 downto 0);  -- 
        signal  c_be_n              : out   std_logic_vector(3 downto 0);   --
        signal  irdy_n              : out   std_logic;                      -- 
        signal  par                 : inout std_logic                       -- 
    );


設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
ライト対象の先頭アドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_wr_data
std_logic_vector(31 downto 0)
ライトするデータを設定。
set_data_array
ライトデータ数分のデータレコードの配列
pci_memory_burst_write を発行する直前に予め準備して置く。
これはVHDLが、データレコードの内容を pci_memory_burst_write 内に直接記述できない仕様になっているので、別途用意するものとした為である。
本サブプログラムでは最大バーストデータ数(MAX_DATA)を4にしているので、4個のレコードの配列とする。
具体的な使用例は後出のテストベンチの例参照。

下表に1レコードの内容を示す。
設定項目 設定内容
WR_DATA
std_logic_vector(31 downto 0)
ライトするデータを設定。
BEn
std_logic_vector(3 downto 0)
ライトデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を設定。
PERR
std_logic
ライトデータに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
LAST
std_logic
最終ライトデータかどうか設定。
1: 最終データ、 0: 非最終データ
4個のライトデータのレコード配列でLASTに1が設定されたデータ迄ライトする。
但し、4個全てのLASTが0の場合は4個のデータをライトする。
その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。


(8)メモリ・バースト・リード pci_memory_burst_read
    subtype BEn is std_logic_vector(3 downto 0);
    type    BEn_ARRAY is array (0 to (MAX_DATA-1) ) of BEn;

    procedure pci_memory_burst_read (
                set_address     : in    std_logic_vector(31 downto 0);      -- 
                set_ad_perr     : in    std_logic;                          -- 1: ng_parity, 0: ok_parity
                set_data_no     : integer range 1 to MAX_DATA;              -- 
                set_be_n_array  : in  BEn_ARRAY;                            -- 
        ----
        signal  clk             : in    std_logic;                          -- 
        signal  trdy_n          : in    std_logic;                          -- 
        signal  devsel_n        : in    std_logic;                          -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic;                          -- 
        signal  perr_n          : out   std_logic;                          -- 
        signal  sva_read_data   : out   DATA_ARRAY                          -- for test
    );


設定項目 設定内容
set_address
std_logic_vector(31 downto 0)
リード対象の先頭アドレスを指定。
set_ad_perr
std_logic
アドレスに対するパリティエラーを設定。
パリティ線 PAR を 正常パリティ(OK)にするかエラーパリティ(NG)にするかを選択する。
0:OK、 1:NG
set_data_no
integer range 1 to MAX_DATA
バーストリードするデータ数を指定。
本サブプログラムでは最大バーストデータ数(MAX_DATA)を4にしているので、データ数は1〜4個で設定する。
set_be_n_array
BEn_ARRAY
リードデータに対する C/BE[3:0]# 信号のバイトイネーブル信号 be_n の値を BEn(std_logic_vector(3 downto 0)) の配列で設定。
本サブプログラムでは最大バーストデータ数(MAX_DATA)を4にしているので、配列の要素数は1〜4個。

その他の信号 clk 以下の信号は本procedure と外部信号を接続する為のもの。
ユーザの編集禁止。
なお、sva_read_data はリードしたデータを判り易く値として波形表示する為のものである。

(9)PCIイニシャライズ pci_init
    procedure pci_init (
        signal  v_idsel         : out   std_logic_vector(31 downto 0);      -- 
        signal  frame_n         : out   std_logic;                          -- 
        signal  ad              : inout std_logic_vector(31 downto 0);      -- 
        signal  c_be_n          : out   std_logic_vector(3 downto 0);       --
        signal  irdy_n          : out   std_logic;                          -- 
        signal  par             : inout std_logic;                          -- 
        signal  lock_n          : out   std_logic;                          -- 
        signal  req_n           : out   std_logic;                          -- 
        signal  perr_n          : inout std_logic;                          -- 
        signal  serr_n          : out   std_logic;                          -- 
        signal  inta_n          : out   std_logic;                          -- 
        signal  intb_n          : out   std_logic;                          -- 
        signal  intc_n          : out   std_logic;                          -- 
        signal  intd_n          : out   std_logic                           -- 
    );


設定項目 設定内容
無し
PCIバス信号の signal定義部分で各信号の値を初期化する代わりに、本サブプログラムで'Z'や'1'にイニシャライズするもので、使用は必須ではない。
シミュレーション波形の信号レベル不定部分(赤色)を無くし、見栄えを良くする為に用意した。
全信号が本procedure と外部信号を接続する為のものであり、ユーザの編集禁止。


 以上
 (初版 2018/11/28)

−−−−− 本ページはここまで −−−−−