'Writing value 0 to a binary file

I am generating a binary file from a SystemVerilog simulation environment. Currently, I'm doing the following:

module main;
  byte arr[] = {0,32, 65, 66, 67};
  initial begin
    int fh=$fopen("/home/hagain/tmp/h.bin","w");
    for (int idx=0; idx<arr.size; idx++) begin //{
      $fwrite(fh, "%0s", arr[idx]);
    end //}
    $fclose(fh);
    $system("xxd /home/hagain/tmp/h.bin | tee /home/hagain/tmp/h.txt");
  end
endmodule : main

The problem is, that when b has the value of 0, nothing is written to the file. xxd output is:

0000000: 2041 4243                                 ABC

Same result when casting to string as follows:

$fwrite(fh, string'(arr[idx]));

I tried to change the write command to:

$fwrite(fh, $sformatf("%0c", arr[idx]));

And then I got the same value for the first two bytes ('d0 and 'd32):

0000000: 2020 4142 43                               ABC

Any idea on how to generate this binary file?



Solution 1:[1]

You cannot have a null(0) character in the middle of a string, it is used to terminate the string.

You should use the %u format specifier for unformated data.

module main;
  byte arr[] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
   int fh, c, tmp;
   initial begin
     fh = $fopen("h.bin","wb");
     for (int idx=0; idx<arr.size; idx+=4) begin
       tmp = {<<8{arr[idx+:4]}};
       $fwrite(fh, "%u", tmp);
      end
      $fclose(fh);
      fh  = $fopen("h.bin","r");
      while ((c = $fgetc(fh)) != -1)
        $write("%d ",c[7:0]);
    $display;
   end
endmodule : main

Note that %u writes a 32-bit value in least-significant bytes first order, so I reversed the bytes being written with the streaming operator {<<8{arr[idx+:4]}}. If the number of bytes is not divisible by 4, it will just pad the file with null bytes.

If you need the exact number of bytes, the you will have to use some DPI C code

#include <stdio.h>
#include "svdpi.h"
void DPI_fwrite(const char* filename,
           const svOpenArrayHandle buffer){
  int size = svSize(buffer,1);
  char *buf = (char *)svGetArrayPtr(buffer);
  FILE *fp = fopen(filename,"wb");
  fwrite(buf,1,size,fp);
}

And then import it with

import "DPI-C" function void DPI_fwrite(input string filename, byte buffer[]);
...
DPI_fwrite("filename", arr);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1