[SystemVerilog] Motorola S-record 形式ファイルのリード

SystemVerilog では string 型が使え、文字列操作もできるよ、という話です。

Motorola S-record 形式ファイルは、 モトローラ S レコードフォーマット(Web アーカイブ) などを参照。

こういったファイルをリードしたい場面は、仕様にきちんと対応する必要性はおそらくほとんどなく、たまたま S レコードフォーマットのファイルがあり、ライトアドレスとデータさえ読めれば OK という感じだと思います。

次はファイルから、S1 レコードタイプからアドレスとデータの取得し、S9 で処理の終了だけ対応したものです(実際に使ったものじゃないので、万一使うときはチェックしてください)。

gistfile1.v
initial begin
    int fd, ret;
    string line;
    int type_no, size;

    bit [31:0] addr;
    bit [7:0] data []; // dynamic array

    fd = $fopen("./hexfile", "r");

    while (!$feof(fd)) begin
        ret = $fgets(line, fd); // 1行リード
        if (line.substr(0, 0) != "S") begin // S から始まらない場合次の行へ
            continue;
        end

        type_no = line.substr(1, 1).atoi(); // レコードタイプ
        size = line.substr(2, 3).atohex(); // レコード長

        case (type_no)
            1: begin // S1
                // アドレス
                addr = line.substr(4, 7).atohex();

                // データを 1byte ずつ処理
                data = new [size - 3]; // MEMO: データ長は (アドレス2byte + チェックサム1byte) を引いたサイズ
                for (int i = 0; i < size - 3; i++) begin
                    data[i] = line.substr(8 + i * 2, 9 + i * 2).atohex(); // MEMO: 9文字目から2文字ずつ
                end

                $display("S1 addr: %2h", addr);
            end
            9: begin // S9
                $display("S9");
                break;
            end
        endcase
    end

    $fclose(fd);
end

ポイントは、一部分の文字列の取得(substr)、文字列から数値へ変換(atoi、atohex など)や、$fgets で1行の長さ分だけの文字列が取得できてます(Verilog HDL では、string 型がなく固定長の reg 型変数を指定しかできません)。