無償ツールで実践する「ハード・ソフト協調検証」(4) ―― SystemVerilog側のDPI-Cの記述を作成する

Verification Enginnerの戯言

tag: 半導体

技術解説 2009年12月28日

無償のSystemVerilog対応シミュレータと無償のFPGA用オンチップ・バス・モデルを用いて,ハードウェア・ソフトウェア協調検証の一手法について解説する連載の第4回である.今回はAvalon BFMをC言語のテスト・プログラムから使えるようにするため,SystemVerilog側にDPI-Cのコードを記述する.tb_prog.svというサンプル・コードを示し,その概要を説明する.(編集部)

技術解説シリーズ「無償ツールで実践する『ハード・ソフト協調検証』」
第1回 SystemVerilogのDPI-C機能
第2回 テスト・プログラムはC言語で書く
第3回 Avalonインターフェースと検証用モデル
 

 

9.Avalon BFMをC言語のテスト・プログラムから使えるようにする

 Avalon BFMをC言語のテスト・プログラムから使えるようにするため,SystemVerilog側にDPI-Cのコードを記述する必要があります.Avalon BFMのコードにはいっさい手を加えることなしに実現するため,tb_prog.svというSystemVerilogコードを作成します.なお,SystemVerilogコードのファイル拡張子は,.vではなく,.svにします.一部のEDAツールは,.svという拡張子のファイルをVerilog HDLではなく,SystemVerilogであると自動認識します.

 リスト6にtb_prog.svを示します.また,tb_prog.svのファイルはこちらからダウンロードできます.

 

リスト6 SystemVerilog側のDPI-Cのコード

module tb_prog;

  timeunit      1ns;
  timeprecision 1ns;
 
`define BFM        test_bench.DUT.the_mm_master_bfm_0.mm_master_bfm_0

  // =====================================================
  // DPI-C
  // =====================================================

`ifdef DPI_C

`ifndef TEST_BFM
  import "DPI-C" context task dpi_main();
`endif // TEST_BFM

  export "DPI-C" task bfm_write32;
  export "DPI-C" task bfm_read32;
  export "DPI-C" task bfm_write16;
  export "DPI-C" task bfm_read16;
  export "DPI-C" task bfm_write8;
  export "DPI-C" task bfm_read8;
  export "DPI-C" task bfm_nop;

  // =====================================================
  // Main
  // =====================================================

  initial begin

    `BFM.init();
   
`ifdef TEST_BFM
    test_bfm;
`else
    dpi_main();
`endif // TEST_BFM

    #100;
    $finish(2);
  end

  // =====================================================
  // Task
  // =====================================================

  import avalon_mm_pkg::*;

  task automatic bfm_run( Request_t request, int addr, int byte_enable, inout int data );

    `BFM.set_command_request(request);
    `BFM.set_command_address(addr);
    `BFM.set_command_byte_enable(byte_enable,0);
    `BFM.set_command_idle(0,0);
    `BFM.set_command_init_latency(0);
    `BFM.set_command_burst_count(1);
    `BFM.set_command_burst_size(1);

    if( request == REQ_WRITE )
      `BFM.set_command_data(data, 0);

    `BFM.push_command();

    while(1) begin
      @(posedge `BFM.clk);
      if(`BFM.get_response_queue_size() > 0)
        break;
    end
   
    `BFM.pop_response();

    if( request == REQ_READ )
      data = `BFM.get_response_data(0);
 
  endtask : bfm_run 

  task automatic bfm_read32(  int unsigned addr, output int unsigned data );
    int byte_enable;

    if( addr & 'h3 ) begin // address check
        data = 'hffff_ffff;
        return;
    end
   
    byte_enable = 'hf;
   
    bfm_run( REQ_READ, addr, byte_enable, data );
    $display("bfm_read32  : addr = 0x%h, data = 0x%x", addr, data );
     
  endtask : bfm_read32
 
  task automatic bfm_write32( int unsigned addr, input int unsigned data );
    int byte_enable;

    if( addr & 'h3 ) begin // address check
        return;
    end

    byte_enable = 'hf;
   
    bfm_run( REQ_WRITE, addr, byte_enable, data );
    $display("bfm_write32 : addr = 0x%h, data = 0x%x", addr, data );

  endtask : bfm_write32

  task automatic bfm_read16(  int unsigned addr, output shortint unsigned data );
    int byte_enable;
    int unsigned word;
 
    if( addr & 'h1 ) begin // address check
        data = 'hffff;
        return;
    end
   
    case ( addr & 'h2 )
      0 : byte_enable = 'h3;
      2 : byte_enable = 'hc;
    endcase
     
    bfm_run( REQ_READ, addr, byte_enable, word );
   
    case( addr & 'h2 )
      0 : data = (word & 'h0000_ffff) >>  0;
      2 : data = (word & 'hffff_0000) >> 16;
    endcase

    $display("bfm_read16  : addr = 0x%h, data = 0x%x", addr, data );
     
  endtask : bfm_read16

  task automatic bfm_write16( int unsigned addr, input shortint unsigned data );
    int byte_enable;
    int unsigned word;
 
    if( addr & 'h1 ) begin // address check
        return;
    end
   
    case ( addr & 'h2 )
      0 : begin byte_enable = 'h3; word = (data <<  0) & 'h0000_ffff; end
      2 : begin byte_enable = 'hc; word = (data << 16) & 'hffff_0000; end
    endcase

    bfm_run( REQ_WRITE, addr, byte_enable, word );
    $display("bfm_write16 : addr = 0x%h, data = 0x%x", addr, data );

  endtask : bfm_write16
 
  task automatic bfm_read8(  int unsigned addr, output byte unsigned data );
    int byte_enable;
    int unsigned word;
   
    case ( addr & 'h3 )
      0 : byte_enable = 'h1;
      1 : byte_enable = 'h2;
      2 : byte_enable = 'h4;
      3 : byte_enable = 'h8;
    endcase
   
    bfm_run( REQ_READ, addr, byte_enable, word );

    case ( addr & 'h3 )
      0 : data = (word & 'h0000_00ff) >>  0;
      1 : data = (word & 'h0000_ff00) >>  8;
      2 : data = (word & 'h00ff_0000) >> 16;
      3 : data = (word & 'hff00_0000) >> 24;
    endcase

    $display("bfm_read8   : addr = 0x%h, data = 0x%x", addr, data );
     
  endtask : bfm_read8

  task automatic bfm_write8( int unsigned addr, input byte unsigned data );
    int byte_enable;
    int unsigned word;
 
    case ( addr & 'h3 )
      0 : begin byte_enable = 'h1; word = (data <<  0) & 'h0000_00ff; end
      1 : begin byte_enable = 'h2; word = (data <<  8) & 'h0000_ff00; end
      2 : begin byte_enable = 'h4; word = (data << 16) & 'h00ff_0000; end
      3 : begin byte_enable = 'h8; word = (data << 24) & 'hff00_0000; end
    endcase

    bfm_run( REQ_WRITE, addr, byte_enable, word );
    $display("bfm_write8  : addr = 0x%h, data = 0x%x", addr, data );

  endtask : bfm_write8

  task automatic bfm_nop( int no );
 
    for( int n=0 ; n<no ; n++ )
      @(posedge `BFM.clk);
 
  endtask : bfm_nop
 
  task test_bfm;
    int unsigned addr;
   
    addr = 'h0000_0000;

    for ( int n=0 ; n<4 ; n+=4 ) begin : int_loop   
      int unsigned a, b;
   
      a  = 'h1234_5678;
      bfm_write32( addr, a );
      bfm_read32 ( addr, b );
      $display("addr = 0x%h, exp = 0x%h, data = 0x%h", addr, b, a ); 
    end
 
    addr = 'h0000_1000;
    for ( int n=0 ; n<4 ; n+=2 ) begin : short_loop
      shortint unsigned a, b;
     
      a  = 'h4567 + n*2;
      bfm_write16( addr + n, a );
      bfm_read16 ( addr + n, b );
      $display("addr = 0x%h, exp = 0x%h, data = 0x%h", addr, b, a ); 
      a += a;
    end
   
      addr = 'h0000_2000;
    for ( int n=0 ; n<4 ; n++ ) begin : byte_loop
      byte unsigned a, b;
     
      a  = 'h12 + n*4;
      bfm_write8( addr + n, a );
      bfm_read8 ( addr + n, b );
      $display("addr = 0x%h, exp = 0x%h, data = 0x%h", addr, b, a );
      a += a;
    end

  endtask : test_bfm
 
`else  // DPI_C
`endif // DPI_C 

endmodule : tb_prog

 

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日