無償ツールで実践する「ハード・ソフト協調検証」(7) ―― DMAの割り込み機能を確かめられるようにする

Verification Enginnerの戯言

tag: 半導体

技術解説 2010年1月20日

●テスト用のDMAを追加する

 次に,割り込みのテストを行うためにDMAを追加します.「Memories and Memory Control」の下の「DMA」の下にある「DMA Controller」を選択し,[Add]ボタンをクリックします(図32).



図32 DMAを選択する

 

 すると,図33のようなウィンドウが表示されるので,[Finish]ボタンをクリックします.




図33 DMA Controllerの追加画面

 

 図34のように,右側にdmaが追加されます.



図34 DMA Controllerが追加された


 ここで,dma_0のread_masterとwrite_masterをmemoryのs1に,dma_0のcontrol_port_slaveをcpuのavalon_masterに接続します(図35).




図35 dma_0の各ポートをcpuとmemoryに接続する

 

 最後にdma_0のcontrol_port_slaveのBaseアドレスを「0x00000000」から「0x10000000」に変更し(図36),[Generate]ボタンをクリックし,HDLファイルを生成します.




図36 dma_0のcontrol_port_slaveのBaseアドレスを変更する

 

●シミュレーションの準備を行う

 テストベンチをCPUモデルに変更したので,setup_dpi_sim.doファイルの

  vlog -sv prog/tb_prog.sv ;

の部分を

  vlog -sv +define+DPI_C+DEBUG+ ../avalon_cpu.sv ;

に変更します.

●テスト・プログラムを用意する

 DMA Controllerのテスト・プログラムをリスト14に示します.

リスト14 テスト・プログラム(dpi_main)

int test_dma( void )
{
  unsigned int addr, data, exp, irq, n;

  addr = 0x00000000;
  data = 0x12345678;
  for( n=0x00; n<0x40; n+=4)
    bfm_write32( addr+n, data );
       
  addr = DMA_READ_REG;
  data = 0x00000000;
  bfm_write32(addr, data);

  addr = DMA_WRITE_REG;
  data = 0x00000800;
  bfm_write32(addr, data);

  addr = DMA_LENGTH_REG;
  data = 0x00000040;
  bfm_write32(addr, data);
 
  addr = DMA_CONTROL_REG;
  data = (DMA_CONTROL_LEEN | DMA_CONTROL_I_EN
        | DMA_CONTROL_GO   | DMA_CONTROL_WORD);
  bfm_write32(addr, data);

  wait_for_interrupt( &irq );
  printf("Interrput = 0x%x\n", irq );
   
  addr = DMA_STATUS_REG;
  bfm_read32(addr, &data);
  bfm_write32(addr, data);
   
  exp = (DMA_STATUS_LEN | DMA_STATUS_DONE);
  if( data != exp ) {
    printf("DMA Status = 0x%x\n", data );
    return 1;
  }
   
  addr = 0x00001000;
  exp  = 0x12345678;
  for( n=0x00; n<0x40; n+=4) {
    bfm_read32( addr+n, &data );
    if( data != exp ) {
        printf("Compare Error at 0x%x : data(0x%x) != exp(0x%x)\n",
               addr+n, data, exp );
        return 1;
    }
  }
   
  return 0;
}
 
int dpi_main( void ){

  test_dma();
   
  return 0;
}


 ソース・アドレスのメモリを初期化したあと,DMA ControllerのReadレジスタ(DMA_READ_REG),Writeレジスタ(DMA_WRITE_REG),Lengthレジスタ(DMA_LENGTH_REG),Controlレジスタ(DMA_CONTROL_REG)の順に設定し,DMAを起動します.

 wait_for_interrupt関数で割り込み待ちを行い,そのあとでStatusレジスタ(DMA_STATUS_REG)をチェックし,ディスティネーション・アドレスのメモリの内容をチョックしています.

 ポイントはwait_for_interrupt関数の部分です.ここで割り込みを待ちます.

 HDLファイルのコンパイル,C言語のテスト・プログラムのコンパイル,およびシミュレーションは割り込み機能がないCPUの場合と同じです.シミュレーション結果は図37のようになります.

# bfm_write32 : addr = 0x00000000, data = 0x12345678
# bfm_write32 : addr = 0x00000004, data = 0x12345678
# bfm_write32 : addr = 0x00000008, data = 0x12345678
# bfm_write32 : addr = 0x0000000c, data = 0x12345678
# bfm_write32 : addr = 0x00000010, data = 0x12345678
# bfm_write32 : addr = 0x00000014, data = 0x12345678
# bfm_write32 : addr = 0x00000018, data = 0x12345678
# bfm_write32 : addr = 0x0000001c, data = 0x12345678
# bfm_write32 : addr = 0x00000020, data = 0x12345678
# bfm_write32 : addr = 0x00000024, data = 0x12345678
# bfm_write32 : addr = 0x00000028, data = 0x12345678
# bfm_write32 : addr = 0x0000002c, data = 0x12345678
# bfm_write32 : addr = 0x00000030, data = 0x12345678
# bfm_write32 : addr = 0x00000034, data = 0x12345678
# bfm_write32 : addr = 0x00000038, data = 0x12345678
# bfm_write32 : addr = 0x0000003c, data = 0x12345678
# bfm_write32 : addr = 0x10000004, data = 0x00000000
# bfm_write32 : addr = 0x10000008, data = 0x00000800
# bfm_write32 : addr = 0x1000000c, data = 0x00000040
# bfm_write32 : addr = 0x10000018, data = 0x0000009c
# Interrput = 0x1
# bfm_read32  : addr = 0x10000000, data = 0x00000011
# bfm_write32 : addr = 0x10000000, data = 0x00000011
# bfm_read32  : addr = 0x00001000, data = 0x12345678
# bfm_read32  : addr = 0x00001004, data = 0x12345678
# bfm_read32  : addr = 0x00001008, data = 0x12345678
# bfm_read32  : addr = 0x0000100c, data = 0x12345678
# bfm_read32  : addr = 0x00001010, data = 0x12345678
# bfm_read32  : addr = 0x00001014, data = 0x12345678
# bfm_read32  : addr = 0x00001018, data = 0x12345678
# bfm_read32  : addr = 0x0000101c, data = 0x12345678
# bfm_read32  : addr = 0x00001020, data = 0x12345678
# bfm_read32  : addr = 0x00001024, data = 0x12345678
# bfm_read32  : addr = 0x00001028, data = 0x12345678
# bfm_read32  : addr = 0x0000102c, data = 0x12345678
# bfm_read32  : addr = 0x00001030, data = 0x12345678
# bfm_read32  : addr = 0x00001034, data = 0x12345678
# bfm_read32  : addr = 0x00001038, data = 0x12345678
# bfm_read32  : addr = 0x0000103c, data = 0x12345678
# ** Note: Data structure takes 6553768 bytes of memory
#          Process time 1.22 seconds
#          $finish    : ../avalon_cpu.sv(101)
#    Time: 3590 ns  Iteration: 0  Instance: /test_bench/DUT/the_cpu/cpu

図37 シミュレーション結果

 

 「Interrupt = 0x1」の部分が,wait_for_interrupt関数で割り込みが発生したことを示しています.波形の画面を使って,CPUモデルのポートをモニタすることでDMAからの割り込みを確認することもできます.

 CPUモデルを割り込みに対応させたことにより,DMAのステータス・レジスタにおいて,ポーリングではなく割り込みによって転送の終了を確認できるようになりました.

 

==== 

19.他のBFMに適用する(PCI,PCI Express,AMBAなど)

 SOPC Builderは,Avalon 関連だけでなく,PCIやPCI Express(PCIe)などのIPコアもサポートしています.SOPC BuilderでこれらのIPコアを使った場合,SOPC Builderが生成するVerilog HDLコードに,関連するインターフェースのBFMを使ったテストベンチが含まれています.Avalon BFMのDPI-C対応と同じ作業をこれらのBFMに施せば,C言語によるテスト・プログラムを書けます.

 また,SOPC BuilderのIPコアでなくても,BFMを提供しているものならば同じような方法でDPI-C対応を行い,C言語によるテスト・プログラムを書けます.システムLSIのオンチップ・バスとして一般的なAMBA(AXI,AHB,APB)やOCP(Open Core Protocol)などについても,BFMさえあれば同じことが行えます.ぜひトライしてみてください.


(第8回,最終回へ続く)

Verification Enginnerの戯言
http://blogs.yahoo.co.jp/verification_engineer

«  1  2
組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日