LoginSignup
13
9

More than 5 years have passed since last update.

Verilogで外部テキストファイル読み込み

Posted at

まえおき

Verilog-HDLのシミュレーションを行う際に、テストデータを外部ファイルに書いておき、(コンパイル時ではなく)シミュレーション実行時に読み込ませる手法はよく使われている手段です。

ファイルの読み込み方法として代表的なのは

  • ファイルをまとめて読み込む($readmem)
  • 1行づつ読み込む($fscanf)

の2パターンかと思いますが、今回は$fscanfを使用したケースを紹介します。

$fscanfを使用すべきテストパターン

  • テストファイルの行数がテスト条件により可変長
  • テストデータにランダムアクセスしない(頭から流すだけ)
  • 1行に複数のデータがある
  • bin/hex/decフォーマットが混在している

基本的な流れ

  1. $fopenを使用してファイルを開く
  2. $fgetcで1文字読み出す
  3. EOF(ファイル終端か否か判定する)
  4. $fscanfで1行分を書式付で読み出す

使用するシステムタスク

$fopen (ファイルオープン)

項目 内容 説明
戻り値 ファイルディスクリプタ 0:オープン失敗
その他:オープン成功
(戻り値は、以後ファイルにアクセスする為に必要)
第一引数 ファイルパス 開きたいファイルのパスを指定
(実行ディレクトリからの相対パスでも可)
第二引数 アクセスモード "r":リード専用
(その他のアクセスモードについては今回は割愛)

$feof(ファイル終端か調べる)

項目 内容 説明
戻り値 ファイル終端に達したか否か 0以外の値が帰ってきたらファイル終端に達したことを示す
第一引数 ファイルディスクリプタ $fopenの戻り値を渡す

$fscanf

項目 内容 説明
戻り値 実行結果 -1が帰ってきたらエラー
第一引数 ファイルディスクリプタ $fopenの戻り値を渡す
第二引数 出力フォーマット %b:2進数
%h:16進数
(その他は説明割愛)
第三引数以降 信号 読み込んだ値を反映させるreg変数を渡す

サンプルコード

ファイルを読み込んで値を出力する"モジュール"として紹介します。
このモジュールをテストベンチTop階層で呼び出して使用します。

【モジュール仕様】

  • クロック同期で動作する
  • i_start入力ピンにHighを入力するとテキストデータの内容を出力する
  • 出力が完了するとo_end出力ピンを1サイクルだけHighにする
  • テキストデータは ”バイナリ6bit” + "Hex8bit"を1行に書く
FILE_READER.v
//  =================================================================
//  テストパターンファイル読み込みモジュール
//      未知の行数のテキストファイルを読み込み
//      テキスト内容を出力する
//  =================================================================
module FILE_READER #
    (parameter  TERGET_FILE_PATH="file.txt" //読込むファイルのパス
    ,parameter  BIT_WIDE        =4                      //bit幅
    )
    (input  wire                i_clk       //クロック
    ,input  wire                i_start     //開始トリガ(1で開始)
    ,output wire                o_end       //終了トリガ
    ,output wire[BIT_WIDE-1:0]  o_bin_dat   //読み込みデータ
    ,output wire[7:0]           o_hex_dat   
    );

    integer             fd      =0  ;//ファイルディスクリプタ
    integer             cb      =0  ;//キャラクタバッファ
    integer             rtn     =0  ;//システムタスク戻り値
    reg[BIT_WIDE-1:0]   bin_dat =0  ;//テキストファイルの中身を受け取るFF
    reg[7:0]            hex_dat =0  ;//テキストファイルの中身を受け取るFF
    reg                 end_trg =0  ;//終了トリガ

    //出力ポートへ接続
    assign  o_end       =end_trg    ;
    assign  o_bin_dat   =bin_dat    ;
    assign  o_hex_dat   =hex_dat    ;
    //スタートトリガをクロック立上りで監視
    always@(posedge i_clk) begin:FILE_READ_SEQ
        if(i_start)begin    //開始条件

            //ファイルオープン
            //-------------------------------
            fd=$fopen(TERGET_FILE_PATH,"r");

            if(fd==0)begin
                //オープン失敗
                $display("File Open Error!!!!!");
                //イベントから抜ける
                disable FILE_READ_SEQ;
            end else begin
                //オープン成功
                $display("File Open OK");
            end

            //ファイル読出しループ
            //-------------------------------
            begin:FILE_LOOP
                forever begin                   
                    //ファイル終端に達したらループを抜ける
                    if($feof(fd) != 0)begin
                        $display("File End !!");
                        disable FILE_LOOP;
                    end

                    //クロック同期
                    @(posedge i_clk);

                    //書式付読出し
                    rtn=$fscanf(fd,"%b %h\n",bin_dat,hex_dat);
                end
            end

            //ファイルを閉じで終了トリガを出す
            //-------------------
            $fclose(fd);
            @(posedge i_clk);
            end_trg <=1'b1;
            bin_dat <={BIT_WIDE{1'b0}};
            hex_dat <=8'h0;
            @(posedge i_clk);
            end_trg <=1'b0;

        end
    end

endmodule

動作環境

テストベンチTopと読み込むテキストファイルを紹介します。

FILE_READER_tb.v
`timescale 1ns/1ps

module FILE_READER_tb();

    parameter           BIT_WIDE    =6  ;
    reg                 i_clk       =0  ;
    reg                 i_start     =0  ;
    wire                o_end           ;
    wire[BIT_WIDE-1:0]  o_bin_dat       ;
    wire[7:0]           o_hex_dat       ;

    FILE_READER #
    (.TERGET_FILE_PATH  ("./TestPattern.txt")
    ,.BIT_WIDE          (BIT_WIDE           )
    )
    dut
    (.i_clk     (i_clk      )//
    ,.i_start   (i_start    )//
    ,.o_end     (o_end      )//
    ,.o_bin_dat (o_bin_dat  )//
    ,.o_hex_dat (o_hex_dat  )
    );

    //クロック
    always#5 i_clk=~i_clk;

    //
    initial begin
        #160;
        @(posedge i_clk);   i_start=1'b1;
        @(posedge i_clk);   i_start=1'b0;
        @(posedge o_end);

    end

endmodule

TestPattern.txt
100000 00
010000 01
001000 02
000100 03
000010 04
000001 05
000000 06
000000 07
000000 08
000001 09
000010 0A
000100 0B
001000 0C
010000 0D
100000 0E
010000 0F
001000 10
100100 20
010010 30
001001 40
000100 50
000010 60
000001 70
100000 80
010000 90
001000 A0
001001 B0
010010 C0
100010 D0
010001 E0
001000 F0

実行結果

image.png

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9