从二进制文件中读取 n 个字节,直到 verilog 中的文件结尾

reading n bytes from a binary file until end of file in verilog

我有一个二进制文件。我每次都需要从中读取 512 位,直到文件结束并将其作为输入传递给我的设计。我正在使用 readmemh/readmemb 从文件中读取。但是我们必须在 readmemh 之前指定内存数组的大小以作为其参数传递。所以如果我们不知道寄存器的深度,我们怎么能读取完整的二进制文件。

reg [511:0]packet[1:0]; 
$readmemh("abc.bin",packet); //this abc.bin has 237kb size

内存深度应该是多少'packet'?

$readmemh 方法不适合此类连续数据处理。

相反,我会使用与标准编程语言相同的方法: 打开一个文件,从中读取你需要的数据,关闭文件。通过这种方式,您可以处理许多兆字节大小的文件,但不需要太多兆字节的存储空间。

fd = $fopen(filename,"rb");
if (fd==0)
begin
   $display("%m @%0t: Could not open file '%s'",$time,filename);
   $stop;     
end
else
begin
   $display("%m @%0t: Opened %s for reading",$time,filename);
   file_is_open = 1'b1;
end

if (file_is_open)
  value= $fgetc(fd);

警告:
这使用二进制文件。您的 $readmemh 使用 ASCII 文件。如果需要,您可以读取 ASCII 文件,但随后您必须自己编写一个小的 Verilog 函数将 ASCII 转换为十六进制。

你有几个选择

  • 如果文件有最大可能大小,只需声明具有所需最大大小的数组即可。 $readmemh.
  • 将保留剩余元素未初始化 (X)
  • 编译设计时,在命令行中通过数组大小传递参数或宏定义。命令将取决于您使用的工具。
  • 不是将整个文件读入数组,而是使用 $fscanf(fd,"%h", value) 一次读取一行。 value 可以根据需要应用于您的输入。

do begin
  repeat (64) begin
    code = $fscanf(fd,"%h", value); // get byte
    pattern = {pattern,value};      // shift into pattern
  end
  send_to_dut(pattern);
end while (code == 1);