0
votes

I am new to Verilog and I have to create a testbench file for a core I designed. In the testbench I need to read data from txt files and feed them in my design as inputs. Then, the design's output will be written in an output txt files. Already I managed to do that concerning one input file and one output file (reading from a file with fscanf, process the data and write the output to another file with fwrite).

Now I would like to further test my design by reading data from more than one files and write the output results in more than one output files.

For example, I would like to have 1000 input files, iteratively read data from them and feed it to my design, and write the output to 1000 output files (read the first file, process its data, write the first output file, read the second file, process its data, write the second output file, etc etc). Each one of the output files will concern the corresponding input file. Is it even possible in Verilog ? And, if so, in which way I have to implement it ? I searched in the net for that but I didn't found anything related to iterative read/write many files...

Thanks in advance!

The code I used to lead the file and read the data is:

fd_test = $fopen("C:/TEST_FILE.dat","r");
fd_out_test = $fopen("C:/TEST_OUT_FILE.dat","w");

while(cnt_test>0) begin
   if (fifo_read_request) begin
       cnt_test = $fscanf(fd_test,"%H",read_block);
       mpdu_block = read_block;
   end else begin
       cnt_test = cnt_test;
       mpdu_block = mpdu_block;
   end
   if (valid_enc_mpdu_block) begin
       $fwrite(fd_out_test, "%H\n", enc_mpdu_block);
   end
   #2;  @(posedge clk);
end
1

1 Answers

0
votes

The following should get you started, it loads 2 files and read the lines at the same time.

initial begin
  fd_test1 = $fopen("C:/TEST_FILE.dat","r");
  fd_test2 = $fopen("C:/TEST_FILE_2.dat","r");

  fd_out_test = $fopen("C:/TEST_OUT_FILE.dat","w");

  // Check lines left in file
  while((cnt_test>0) & !$feof(fd_test1) & !$feof(fd_test2)) begin
     if (fifo_read_request) begin
       cnt_test   = $fscanf(fd_test1,"%H",read_block);
       cnt_test2  = $fscanf(fd_test2,"%H",read_block);
       mpdu_block = read_block;
     end else begin
       cnt_test   = cnt_test;
       cnt_test2  = cnt_test2;
       mpdu_block = mpdu_block;
     end
     if (valid_enc_mpdu_block) begin
       $fwrite(fd_out_test, "%H\n", enc_mpdu_block);
     end
     #2;  @(posedge clk);
  end
end

This line is confusing #2; @(posedge clk); Why have a #2 and wait for the posedge of a clock. The #2 seems redundant.

When $fopen is called with only 1 argument 'filename' it returns a 32bit unsigned integer which is a MCD, multi-channel descriptor. each file gets 1 bit of the MCD alowing 32 files to be open at the same time, the advantage is that writing to many files at once the MCD for a file can just be OR'd together.

Since Verilog-2001 adding mode 'r', 'w', 'a' switches the output from MCD into a new format (fd, file descriptor) allowing many more files to be open at the same time. If bit 31 is set then it is a File Descriptor. This breaks backwards compatibility when verilog-95 opens it 32nd file.

Three fd's are defined by default:

32'h8000_0000 STDIN
32'h8000_0001 STDOUT
32'h8000_0002 STDERR

For covering multiple files, using a for loop might be a good idea.

integer i; // loop variable
integer j; // loop variable
string  list [0:99]; //100 Stings
reg [31:0] fd [0:99];

initial begin
  list[0]  = "C:/TEST_FILE1.dat";
  list[1]  = "C:/TEST_FILE2.dat";
  for( i=0; i<100; i=i+1) begin
    fd[i] = $fopen(list[i], "r");
  end

end

always @(posedge clk) begin
  // Every clock load the next sample from all files
  for( j=0; j<100; j=j+1) begin
    cnt_test[j]  = $fscanf(fd[j], "%H", read_block);
  end
end