Alveo U250でXPM_MEMORY_SPRAMを使いたい(2)

  • Mar 26, 2023
post-thumb

前回

ドキュメントを読んだ.

前回の記事:Alveo U250でXPM_MEMORY_SPRAMを使いたい(1)

githubのソースを使ってみる

githubでXPM_MEMORY_SPRAMを使っているモジュールを見つけたので,使ってみる.

Github:pulp-platform/tech_cells_generic
(https://github.com/pulp-platform/tech_cells_generic)

githubの該当のソースコードを書き換え

tech_cells_generic/src/fpga/tc_sram_xilinx.svを使ってみようと思う. ただこのままでは初期化用のファイルを指定できない. 設定できるようにしよう.

parameterInitFileで初期化ファイルを指定するようにする

次のように書き換える.

32
33
34
  parameter type         data_t    = logic [DataWidth-1:0],
  parameter type         be_t      = logic [BeWidth-1:0],
  parameter              InitFile  = "none"       // 追加:初期化ファイル

各モジュールのMEMORY_INIT_FILEInitFileを割り当て
Single Port RAMのモジュール

まずはxpm_memory_spram: Single Port RAM側を2箇所80,81行目を編集.

73
74
75
76
77
78
79
80
81
82
    // xpm_memory_spram: Single Port RAM
    // XilinxParameterizedMacro, version 2018.1
    xpm_memory_spram#(
      .ADDR_WIDTH_A        ( AddrWidth        ), // DECIMAL
      .AUTO_SLEEP_TIME     ( 0                ), // DECIMAL
      .BYTE_WRITE_WIDTH_A  ( ByteWidth        ), // DECIMAL
      .ECC_MODE            ( "no_ecc"         ), // String
      .MEMORY_INIT_FILE    ( InitFile         ), // 書き換え:String
      .MEMORY_INIT_PARAM   ( ""               ), // 書き換え:String
      .MEMORY_OPTIMIZATION ( "true"           ), // String

True Dual Port RAMのモジュール

次にxpm_memory_tdpram: True Dual Port RAM側を2箇所119,120行目を編集.

109
110
111
112
113
114
115
116
117
118
119
120
121
    // xpm_memory_tdpram: True Dual Port RAM
    // XilinxParameterizedMacro, version 2018.1
    xpm_memory_tdpram#(
      .ADDR_WIDTH_A            ( AddrWidth        ), // DECIMAL
      .ADDR_WIDTH_B            ( AddrWidth        ), // DECIMAL
      .AUTO_SLEEP_TIME         ( 0                ), // DECIMAL
      .BYTE_WRITE_WIDTH_A      ( ByteWidth        ), // DECIMAL
      .BYTE_WRITE_WIDTH_B      ( ByteWidth        ), // DECIMAL
      .CLOCKING_MODE           ( "common_clock"   ), // String
      .ECC_MODE                ( "no_ecc"         ), // String
      .MEMORY_INIT_FILE        ( InitFile         ), // 書き換え:String
      .MEMORY_INIT_PARAM       ( ""               ), // 書き換え:String
      .MEMORY_OPTIMIZATION     ( "true"           ), // String

これでよし.

テストベンチファイル作成

テストベンチを作る. まあ細かい動作確認はするつもりなくて,アドレスから正しい値を読めるかなあって確認だけ. それってテストベンチか?

とりあえず./test/tb_tc_sram_origin.svを作成.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
`timescale 1ns / 1ps
// ----- 定数たち -----
`define DATA_WIDTH  128
`define ADDR_WIDTH   10
// --------------------

module tb_tc_sram_origin;

// ----- クロックの動作 -----
logic                           clk_i;
initial begin
    clk_i <= 1'b0;
    #2;
    forever begin
        #1; clk_i <= (clk_i==1'b1)?1'b0:1'b1;
    end
end
// --------------------

// ----- メモリの動作 -----
// // モジュールの宣言 
logic                           rst_ni;
logic                           req_i;
logic                           we_i;
logic [ `ADDR_WIDTH     -1:0]   addr_i;
logic [ `DATA_WIDTH     -1:0]   wdata_i;
logic [ (`DATA_WIDTH/8) -1:0]   be_i;
logic [ `DATA_WIDTH     -1:0]   rdata_o;
// // モジュールの宣言 
tc_sram #(
    .NumWords   ( 2**(`ADDR_WIDTH)  ),
    .NumPorts   ( 1                 ),
    .DataWidth  ( `DATA_WIDTH       ),
    .SimInit    ( "random"          ),
    .InitFile   ( "hello_world.mem" )
) ram_0 (
    .clk_i  ( clk_i                                                                     ),
    .rst_ni ( rst_ni                                                                    ),
    .req_i  ( req_i                                                                     ),
    .we_i   ( we_i                                                                      ),
    .addr_i ( 10'h0 + addr_i[($clog2(2**10)+$clog2(`DATA_WIDTH/8))  -1:$clog2(`DATA_WIDTH/8)]   ),
    .wdata_i( wdata_i                                                                   ),
    .be_i   ( be_i                                                                      ),
    .rdata_o( rdata_o                                                                   )
);
// // 各信号の制御
initial begin
    $dumpfile( "result.vcd" );
    $dumpvars( 0, ram_0    );
    #10; //全信号の初期化
        rst_ni  <=   1'b1;
        req_i   <=   1'b0;
        we_i    <=   1'b0;
        addr_i  <=  10'h000;
        wdata_i <= 128'h00000000000000000000000000000000;
        be_i    <=  16'hFFFF;
    #10; // リセット:ON
        rst_ni  <=   1'b0;
    #10; // リセット:OFF
        rst_ni  <=   1'b1;
    #10; // 0x0000から値を読み取り
        addr_i  <=  10'h000;
        req_i   <=   1'b1;
    #10; // req_iを下げる
        req_i   <=   1'b0;
    #10; // 0x0010から値を読み取り
        addr_i  <=  10'h010;
        req_i   <=   1'b1;
    #10; // req_iを下げる
        req_i   <=   1'b0;
    #10; // おしまい
        $finish;
end
endmodule

テストベンチの実行

当然だけど,iverilogコマンドでは動作確認できない...まあVivadoでやりましょう.

次のtclファイルをtcl/test.tclって名前で作りましょ.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# -----変数-------------
set outputDir       "./output"                      ;   # プロジェクトのディレクトリを設定
set projectName     "vivado_prj"                    ;   # プロジェクト名を設定
set device_name     "xilinx.com:au250:part0:1.3"    ;   # デバイス名を設定
set part_name       "xcu250-figd2104-2L-e"          ;   # fpgaチップ名を設定

# -----前回の実行結果を削除-------------
file delete -force  $outputDir
file mkdir          $outputDir

# -----プロジェクトの作成-------------
create_project      -force      $projectName $outputDir -part $part_name    ;# プロジェクトファイル作成
set_property        board_part  $device_name [current_project]              ;# FPGA
update_ip_catalog                                                           ;

# -----シミュレーション時間の制限を削除-------------
set_property -name {xsim.simulate.runtime} -value {-all} -objects [get_filesets sim_1]

# -----ソースを追加-------------
add_file test/tb_tc_sram_origin.sv
add_file src/fpga/tc_sram_xilinx.sv
add_file test/hello_world.mem

# -----トップモジュールを設定-------------
set_property top tb_tc_sram_origin [current_fileset] 
set_property top tb_tc_sram_origin [get_filesets sim_1]

# -----シミュレーション実行-------------
update_compile_order -fileset sources_1
launch_simulation
source $outputDir/$projectName.sim/sim_1/behav/xsim/tb_tc_sram_origin.tcl

# ----プロジェクトを閉じる-------------
close_project

そのあと以下のコマンドを実行する.

0
vivado -mode batch -source test/test.tcl

最後に以下のコマンドを実行して作成したvcdファイルを確認.

0
gtkwave ./output/vivado_prj.sim/sim_1/behav/xsim/result.vcd

実行結果はこんな感じ

読めてそう.色々使えることがあるところがあると嬉しいな.