$readmemh -- is there something better?

Regarding systemverilog file IO, $readmemh has been around a long time. Is there something better?

I would like to read the contents of a file into a queue, rather than a memory. I gave this (below) a shot, but now I have a queue of strings. The string values look like this: “0x1234”. What is the best way to convert “0x1234” to something that I can store in logic [15:0] hex_reg?

I am asking because I cannot change the format of the file that I am receiving. Perhaps I should pre-process the file using something like python, and then just use $readmemh?

Thanks!
Aaron

typedef string file_lines_queue[$];
 function automatic file_lines_queue get_file_lines(string file_name);
      int fd;
      string line;
      file_lines_queue ret;

      fd = $fopen(file_name, "r");
      if (fd)  begin
          $display("File %s was opened successfully", file_name);
          while (!$feof(fd)) begin
              $fgets(line, fd);
              ret.push_back(line);
              // $display ("Line: %s", line);
          end
      end else begin     
          $display("File %s was NOT opened successfully", file_name);
      end

      $fclose(fd);
      return ret;
  endfunction : get_file_lines

In reply to aale:

Use $fscanf instead of $fgets

typedef bit [15:0] uint16_t;
typedef uint16_t uint16q_t[$];
function automatic uint16q_t get_file_lines(string file_name);
      int fd;
      uint16_t value; 
      fd = $fopen(file_name, "r");
      if (fd)  begin
          $display("File %s was opened successfully", file_name);
          while ($fscanf(fd,"%x",value))
              get_file_lines.push_back(value);
      end else begin     
          $display("File %s was NOT opened successfully", file_name);
      end
      $fclose(fd);
  endfunction : get_file_lines

In reply to dave_59:

This almost worked. With $fscanf() as a while loop argument, the while loop hung. This tweak worked…

typedef bit [15:0] uint16_t;
  typedef uint16_t uint16q_t[$];
  uint16q_t gain_offset_queue; 

  function automatic uint16q_t get_file_lines(string file_name);
      int fd;
      uint16_t value;
      uint16q_t ret;
      int line_num = 0;


      fd = $fopen(file_name, "r");
      if (fd)  begin
          $display("File %s was opened successfully", file_name);
          while (!$feof(fd)) begin
              $fscanf(fd, "%x", value);
              ret.push_back(value);
              if (line_num < 10) begin
                $display ("Line[%04d]: 0x%04X", line_num++, ret[ret.size()-1]);
              end
          end
      end else begin     
          $display("File %s was NOT opened successfully", file_name);
      end

      $fclose(fd);
      return ret;
  endfunction : get_file_lines

Any idea why $fscanf as a while loop argument didn’t work?

Another interesting side note. Check out the $dsiplay and note the capital X in 0x%04X. The output looks like this:

File …/…/tb/raw_proc/c_model/output/grid.mem was opened successfully

Line[0000]: 0x00ca

Line[0001]: 0x00ac

Line[0002]: 0x00dc

Line[0003]: 0x0108

Line[0004]: 0x010a

Line[0005]: 0x0136

Line[0006]: 0x015e

Line[0007]: 0x0174

Line[0008]: 0x0146

Line[0009]: 0x015c

Why are the a-f characters not capitalized? I am using questa 10.7c.

Thanks!
Aaron

In reply to aale:

I see that my post has the no formatting. In the future, how can I keep the verilog formatted so that it is easier to read?

In reply to aale:

Code Tags I have added them for you.

Without all the code and a text file we can’t debug your problem.

SystemVerilog format specifiers are case insensitive; the output is always in lowercase except for certain conditions with unknowns.

In reply to dave_59:

Forgive the newbie questions. Okay, code tags are awesome. Got it. Next, in order to send you a complete code snippet, can I attach a file, or what do you recommend?

Tahnks!
Aaron

In reply to aale: