割り込みDMAコア
1.割り込み&DMAコアの概要
「割り込み&DMAコア(dmaint_user)」は、以下の機能を持ちます。
・DMAのターゲットアドレスの管理
・大きなサイズのDMAを、複数の細かいTLPに分割して発行
・割り込みステータスレジスタの保持
・最大16種類の割り込み要求の管理
ユーザの要求によるDMAは任意のサイズの可能性があり、数メガバイトの大きなサイズになることもあります。しかし、PCI Expressの仕様では、最大のパケットサイズは4096までであって、実際には最大ペイロードサイズ(ほとんどの場合、128バイトか256バイト)によってさらに小さなサイズに制限されてしまっています。
したがって、例えば1メガバイトのDMAを送りたい場合、4096個の小さな細切れのDMAに分割して送らなければなりません。

図 細切れDMAの概念
このコアは、ホストPC(アプリケーションソフトウェア)からの要求によって、任意のサイズのDMAを細切れに分割して発行する機能を持ちます。細切れのDMAパケットを送出する間に、ウェイトを挟むこともできます。
(※ なお、現在のバージョンではスキャッタ・ギャザーによるDMAには対応しておりません。)
このコアの内部にはDMA制御レジスタや、割り込み制御レジスタを含むため、BAR0空間に配置されるようにする必要があります。

図1 特電ラッパの役割
2.入出力ポートの説明
2.1 シンボル
割り込み&DMAコアの入出力ポートのシンボルを図2に示します。本コアの入出力信号は、システム用ポート、レジスタ読み書き信号、ユーザ用信号、コア接続用ポート、割り込み用システムポート、その他、に分けられます。
図2 割り込み&DMAコアの入出力ポート
2.2 システム用ポート
システム用のポートをリスト1に示します。
|
リスト1 システム用ポート |
|
pclk_i : in std_logic; reset_i : in std_logic; |
これらの信号には、コア(特電ラッパ)から出力されるpclk_oと、reset_oを接続してください。
2.3 レジスタ読み書き信号
csr_*で始まるポートは、レジスタ読み書き信号です。
|
リスト2 レジスタ読み書き信号 |
|
-- コントロール・ステータスレジスタを読み書きするための信号 csr_addr_i : in std_logic_vector(7 downto 0); csr_wdata_i : in std_logic_vector(31 downto 0); csr_wren_i : in std_logic_vector(63 downto 0); csr_be_i : in std_logic_vector(3 downto 0); csr_rdata_o : out std_logic_vector(31 downto 0);
|
csr_addr_i、csr_wdata_i、csr_be_i にはコアのuser_addr_o、user_wdata_o、user_be_oをそのままつなぎます。
csr_wren_iは64bitのバスですが、これはBAR0空間のどのアドレスに対して書き込みリクエストが行われたかを示す信号です。4バイト単位なので、例えば、csr_wren_i(4)は、BAR0+0x10番地に書き込みリクエストが発行されたことを示します。
csr_rdata_oは、このDMAコアから読み出されたステータスレジスタの値です。適切にマルチプレクスして特電ラッパのuser_wrdata_iに接続します。
|
リスト3 レジスタ読み書き信号と特電ラッパ(PCIeコア)との接続 |
|
-- bar0_wren信号の生成 LOOP_BAR0WR : FOR I in 0 to 63 generate bar0_wren(I) <= bar0_wr and user_dvalid end generate;
-- DMAコントローラの実装 inst_dmaint_user : dmaint_user generic map ( ・・・(中略) ・・・ csr_addr_i => user_addr(7 downto 0), csr_wdata_i => user_wdata, csr_wren_i => bar0_wren, csr_be_i => user_be, csr_rdata_o => dmaint_stat, ・・・(中略) ・・・ );
-- BAR0の読み出し信号のマルチプレクス ・・・(中略) ・・・ bar0_rdata <= gpio_in when (user_addr(7 downto 2) = 0) else dmaint_stat; ・・・(中略) ・・・
|
実際の記述は、サンプル・リファレンス・デザインを参照してください。
2.4 ユーザ用信号
ユーザ用信号ポートは、ユーザ回路とDMAコアを接続するためのポートです。
主に、DMAの転送にウェイトをかけるために用いられます。
このポートには以下の信号があります。
|
リスト4 ユーザ回路用ローカルポート |
|
-- ユーザ用信号 user_int_i : in std_logic_vector(15 downto 0); -- 書き込みデータ udma_in_start_o : out std_logic; -- DMA RD (IN:PC=>FPGA)が開始した udma_out_start_o : out std_logic; -- DMA WR (OUT:FPGA=>PC)が開始した udma_in_ready_i : in std_logic; udma_out_ready_i : in std_logic; udma_in_end_o : out std_logic; -- 細切れのDMA RD (IN:PC=>FPGA)が完了 udma_in_endack_i : in std_logic; -- 細切れのDMA RD (IN:PC=>FPGA)が完了
|
各信号の機能を以下に示します。
表1 ユーザ用ローカルポートの信号
|
信号名 |
方向 |
機能 |
|
user_int_i[15:0] |
入力 | ユーザ回路からコアに対して、割り込みの発生を要求します。16種類の割り込み要求の種類を使い分けることができます。 |
|
udma_in_start_o |
出力 |
IN動作のDMA転送(PC→FPGA方向)を開始しようとしていることを示します。細切れのDMAが送られる前に毎回アサートされます。 |
|
udma_out_start_o |
出力 |
OUT動作のDMA転送(FPGA→PC方向)を開始しようとしていることを示します。細切れのDMAが送られる前にに毎回アサートされます。 |
|
udma_in_ready_i |
入力 | 使われていません |
|
udma_out_ready_i |
入力 |
OUT動作(FPGA→PC方向)を実行する際に、1パケット(TLP)分のユーザデータの準備ができたことを示します。 OUT動作時に、この信号を'0'にすると、次のTLPを発行せずにWAITします。メモリからの読み出しなどで時間がかかる場合に、転送を一時中断させるために使います。 |
|
udma_in_end_o |
出力 |
IN動作(PC→FPGA方向)を実行した際に、1パケット(TLP)分のユーザデータの転送が完了したことを示します。 |
|
udma_in_endack_i |
入力 |
IN動作(PC→FPGA方向)において、1パケット分のデータを受信してユーザ回路に送信した後、ユーザ回路が次のデータを受け入れる準備ができたことを示すために用います。 IN動作時に、この信号を'0'にすると、次のTLPを要求せずにWAITします。メモリへの格納などで時間がかかる場合に、転送を一時中断させるために使います。 |
本コアは、任意のサイズの大きなDMAを、128バイト〜4096バイトの細切れのパケットに分割して、複数回の小さなDMAを発行します。
その際の、小さなパケットが発行される前に、udma_in_start_o もしくは udma_out_start_o がアサートされます。
ユーザ回路は、次のパケットを発行してもよければ、udma_in_endack_i もしくは udma_out_ready_i をアサートします。これらの信号がアサートされるまでは、コアはDMAを実行しません。
例えば、udma_out_start_oがアサートされた場合は、ホストPCがFPGAにデータを要求しています。FPGAが応答する準備ができていれば、udma_out_ready_iを'1'にして応えます。そうでなければ'0'に保ちます。例えば、DDR2メモリを他の回路が占有してしまっていたり、フラッシュメモリの読み出しに時間がかかるような場合は、udma_out_ready_iを'0'に保つことで、次の細切れのDMAを待たせることができます。
※ これらの信号は、pclk_iに同期させてから入力してください。コアの中でpclkへの同期は行っておりません。
※ ウェイトを行う必要がない場合は、udma_in_endack_i と udma_out_ready_i には固定値'1'を与えてください。
2.5 コア接続用ポート
以下の信号は、特電ラッパ(PCIeコア)へ接続するための信号です。
データバス、アドレスバス、DMA開始リクエストなど、実質的な信号があります。
これらの信号は、使用されていないものも含めて、すべて特電PCIeコア(ラッパ)に接続してください。
|
リスト5 コア接続用ポート |
|
-- 以下はコアと接続するための信号 -- DMA制御信号 dma_cfg_c : out std_logic_vector(15 downto 0); -- 定数出力 dma_sysaddr_o : out std_logic_vector(31 downto 0); -- PC内メインメモリの物理アドレス dma_lcladdr_o : out std_logic_vector(31 downto 0); -- ローカル(コア上)のアドレス dma_length_o : out std_logic_vector(9 downto 0); -- DW単位 dma_wr_req_o : out std_logic; -- DMA要求(FPGA->PC) dma_wr_ack_i : in std_logic; -- DMA応答 dma_rd_req_o : out std_logic; -- DMA要求(PC->FPGA) dma_rd_ack_i : in std_logic; -- DMA応答 dma_fin_o : out std_logic; -- DMA完了 dma_addr_i : in std_logic_vector(31 downto 0); dma_remain_i : in std_logic_vector(31 downto 0); dma_dvalid_i : in std_logic; -- DMA受信データ有効 dma_dreq_i : in std_logic; -- DMA送信データ要求 dma_corebusy_i : in std_logic; -- コアのDMA制御ステートマシンが実行中 dma_userrun_o : out std_logic; -- ユーザレベルのDMA制御ステートマシンが実行中 dma_pktsize_i : in std_logic_vector(3 downto 0); -- 分割するサイズ(未使用) -- 割り込み制御信号 int_reqline_o : out std_logic; -- レベル出力 Hで割り込み要求 int_available_i : in std_logic; -- 割り込み使用可能 int_ack_i : in std_logic; -- 割り込み要求を送信した(但し、現Verでは未使用)
|
表2 コア接続用ポートの信号
|
信号名 |
方向 |
機能 |
|
dma_cfg_c[15:0] |
出力 |
現在のバージョンでは使用されません。 |
|
dma_sysaddr_o[31:0] |
出力 |
小さな細切れのDMAを行う際のホストPC上のアドレス。 |
|
dma_lcladdr_o[31:0] |
出力 |
小さな細切れのDMAを行う際のFPGA内のローカルアドレス。 |
|
dma_length_o[9:0] |
出力 |
小さな細切れのDMAを行う際の転送長(DW単位)。 |
|
dma_wr_req_o |
出力 |
小さな細切れのDMAライトの発行をコアに要求する。 |
|
dma_wr_ack_i |
入力 |
コアがDMAライトの要求を受け付けたことを示す信号。 |
|
dma_rd_req_o |
出力 |
小さな細切れのDMAリードの発行をコアに要求する。 |
|
dma_rd_ack_i |
入力 |
コアがDMAリードの要求を受け付けた。 |
|
dma_fin_o |
出力 |
DMAがすべて完了した。 |
|
dma_addr_i[31:0] |
入力 |
現在、転送中のローカルアドレス。 |
|
dma_remain_i[31:0] |
入力 |
現在転送中の細切れDMAの残量。 |
|
dma_dvalid_i |
入力 |
DMAリード(PC→FPGA)を要求してコアがパケットを受信し、デコード結果がバス上に有効になったタイミングでアサートされる。 |
|
dma_dreq_i |
入力 |
DMAコア内では使われていません。 |
|
dma_corebusy_i |
入力 |
PCIeコアがDMAのTLPを送信中にアサートされる。 |
|
dma_userrun_o |
出力 |
DMAが実行中であることを示す。 |
|
dma_pktsize_i[3:0] |
入力 |
パケットを分割すべきサイズの設定。現在は未使用。 |
|
int_reqline_o |
出力 |
割り込み要求信号。 |
|
int_available_i |
入力 |
割り込みが使用可能であることを示す信号。 |
|
int_ack_i |
入力 |
割り込み要求の遷移が受け付けられたことを示す信号。 |
3.ユーザ回路の接続方法
DMAが行われるときの、FPGA内のローカルアドレスは、dma_lcladdr_oから得られます。
DMAのライト(FPGA→PC)方向の転送の際に、送信するデータはdma_wrdataに与えます。
ユーザ回路は、dma_dreqが'1'になったら次のデータを用意します。
DMAのリード(PC→FPGA)方向の転送の際に、受信したデータはdma_rddataに現れます。
ユーザ回路は、dma_dvalidが'1'になるタイミングでデータを取り込みます。
例えば、BlockRAMやFIFOに書き込み信号にdma_dvalidが使えます。
4.動作波形
DMAリード時の波形
DMAでリード(PC→FPGA方向)転送を行う際の各部の波形を示します。
? ソフトウェアがAPIのPcieWriteDMA関数を呼び出し、DMAコントロールレジスタにパラメータがセットされると、DMAコア(dmaint_user)が起動します。
? DMAコアは、dma_rd_req_oをアサートします。
? PCIeコア(特電PCIeラッパ(pciecore_sp6lxt.ngc))は、TLPが送信可能な状態になったら、dma_rd_ack_iをアサートます。そして、PCIeコアはMemory Readパケットを送信します。Memory Readパケット送信中はdma_corebusy_oが'1'になります。
図3 DMAリード(PC→FPGA)方向のDMA開始時の波形
? Memory Readパケットが送信されてからおよそ2μ秒後に、ホスト(PC)はコンプリーションパケットを返します。
? PCIeコアはその中に含まれるデータをデコードしてdma_rddata[31:0]から出力します。有効なデータが出力されているタイミングで、dma_dvalidがアサートされるので、ユーザ回路はそのデータを取り込みます。
図4 DMAリード(PC→FPGA)方向のDMAデータの取り込み時の波形
? 1回分の細切れDMAが終了すると、DMAコアはudma_in_end_oをアサートします。
? ユーザ回路は、次のDMAパケットを受け入れる準備ができていれば、udma_in_endack_iをアサートして応答します。
図5 DMAリード(PC→FPGA)方向の細切れDMA終了時の波形
? すべてのDMAが完了すると、dma_fin_oがアサートされ、dma_userrun_oが'0'に戻ります。
その後、int_reqline_oがアサートされDMA完了割り込みが送られます。
DMAリード(PC->FPGA方向)転送の全体の波形を次の図6に示します。
図6の波形は512バイトのDMA転送を行ったときのものです。DMAコアは、256バイトのMemory Read パケットを2個発行しています。1回のMemory Readに対し、ホストPCは64バイトのコンプリーションを4個返しています。それらが8個集まって合計512バイト分のデータが送られています。
Memory Read パケットを送信してからコンプリーションパケットを受信するまでの間に2μ秒程度の待ち時間が生じてしまっているため、バスの使用率が30%程度に落ちてしまっています。そのため、DMAリードの速度は約70MBytes/sec程度しか出すことができません。
図6 DMAリード(PC→FPGA)転送の全体像
DMAライト時の波形
DMAでライト(FPGA→PC方向)転送を行う際の各部の波形を示します。
? ソフトウェアがAPIのPcieReadDMA関数を呼び出し、DMAコントロールレジスタにパラメータがセットされると、DMAコア(dmaint_user)が起動します。
? DMAコアは、udma_out_start_oをアサートします。ユーザ回路は送信するデータが用意でき、準備完了となったら、udma_out_ready_iをアサートし応答します。
? DMAコアはdma_wr_req_oをアサートします。この信号はPCIeコアが受け取ります。
? PCIeコアがWrite Memoryパケットを送信している間、dma_corebusy_oがアサートされます。
図7 DMAライト(FPGA→PC)転送のDMA開始時の波形
? PCIeコアはdma_dreq_oをアサートしたタイミングで、dma_wrdata_iからデータを取り込みます。データのとりこみは2クロックごとに行われるので、ユーザ回路はdma_dreq_oがアサートされてから次のデータを用意するまで1クロックの余裕があります。
図8 DMAライト(FPGA→PC)転送のDMA開始時の波形
DMAライト(FPGA→PC)転送の全体の波形を次の図9に示します。
図9の波形は512バイトのDMA転送を行ったときのものです。DMAコアは、128バイトのMemory Read パケットを4個発行しています。1回のMemory Writeパケットには128バイトのデータが含まれています。それらが4個集まって合計512バイト分のデータが送られています。
Memory Writeは、コンプリーションを待つ必要がないので、待ち時間がなく連続で送られます。128バイトを送る時間は0.8μ秒程度なので、160MBytes/sec程度の速度が出ます。
図9 DMAライト(FPGA→PC)転送の全体像
Copyright(C) 2009 TokushuDenshiKairo Inc. All rights reserved.











