下面是一个使用 systemverilog 从二进制文件读取的示例。
如 IEEE SV 标准文档中所示,"nchar_code" 将返回读取的字节数/字符数。如果在最后一次读取时已经达到 EOF,则此数字将为零。
请注意,“nchar_code”可以为零但尚未达到 EOF,如果数据文件末尾有空格或返回,则会发生这种情况。
您可以使用 $fread 函数控制要读取的字节数。这是通过以下示例的“data_write_temp”或“mem”的类型定义来完成的。如果 "data_write_temp" 变量的长度为 16 位,那么每次调用 $fread 时它将读取 16 位。此外,$fread 将返回“nchar_code=2”,因为 16 位是 2 字节。如果示例中的“data_write_temp”为 32 位,则 $fread 将读取 nchar_code=4bytes(32bits)。您还可以定义一个数组,$fread 函数将尝试填充该数组。
让我们定义一个多维数组mem。
logic [31:0] mem [0:2][0:4][5:8];
在示例单词内容中,wzyx,
-w shows the start of the word
-z corresponds to words of the [0:2] dimension (3 blocks).
-y corresponds to words of the [0:4] dimension (5 rows).
-x corresponds to words of the [5:8] dimension (4 columns).
文件的结构如下(注意@z 显示z 维度块):
@0 w005 w006 w007 w008
w015 w016 w017 w018
w025 w026 w027 w028
w035 w036 w037 w038
w045 w046 w047 w048
@1 w105 w106 w107 w108
w115 w116 w117 w118
w125 w126 w127 w128
w135 w136 w137 w138
w145 w146 w147 w148
@2 w205 w206 w207 w208
w215 w216 w217 w218
w225 w226 w227 w228
w235 w236 w237 w238
w245 w246 w247 w248
在前面的结构中,数字表示每个维度的索引。
例如w048 表示,索引 z = 0,索引 y= 4 和索引 x= 8 上的单词 w(32 位)值。
现在,您可以通过多种方式阅读本文。
您可以使用上面声明的类型“mem”在single shot 中读取所有内容,或者您可以执行while 循环,直到EOF 使用32 位的“data_write_temp”变量读取32 位的片段。如果您想对每个单词片做一些检查并且您对内存值不感兴趣,那么循环很有趣。
如果选择多维数组/单次读取,则可以使用 $fread 或使用 SV 标准中定义的特定函数 $readmemh。
$readmemh("mem.data", mem, 1, (3*5*4));
等价于
$readmemh("mem.data", mem);
$readmemh 让您无需打开/关闭文件。
如果您使用 $fread 进行单次读取
logic [31:0] mem [0:2][0:4][5:8];
register_init_id = $fopen("mem.data","rb");
nchar_code = $fread(mem, register_init_id);
if (nchar_code!=(3*5*4)*4)) begin
`uvm_error("do_read_file", $sformatf("Was not possible to read the whole expected bytes"));
end
$fclose(register_init_id);
如果您想使用 32b 字读取进行循环。然后看下面的例子。
该示例使用从文件中读取的数据使用 AHB 验证组件写入 AHB 总线。
logic [31:0] data_write_temp;
...
//DO REGISTER FILE
register_init_id = $fopen("../../software/binary.bin","rb");
if (register_init_id==0) begin `uvm_error("do_read_file", $sformatf("Was not possible to open the register_init_id file")); end
count_32b_words=0;
while(!$feof(register_init_id)) begin
nchar_code = $fread(data_write_temp, register_init_id);
if ((nchar_code!=4)||(nchar_code==0)) begin
if (nchar_code!=0) begin
`uvm_error("do_read_file", $sformatf("Was not possible to read from file a whole 4bytes word:%0d",nchar_code));
end
end else begin
tmp_ahb_address = (pnio_pkg::conf_ahb_register_init_file_part1 + 4*count_32b_words);
data_write_temp = (data_write_temp << 8*( (tmp_ahb_address)%(DATAWIDTH/(8))));//bit shift if necessary not aligned to 4 bytes
`uvm_create_on(m_ahb_xfer,p_sequencer.ahb0_seqr);
assert(m_ahb_xfer.randomize(* solvefaildebug *) with {
write == 1;//perform a write
HADDR == tmp_ahb_address;
HSIZE == SIZE_32_BIT;
HBURST == HBURST_SINGLE;
HXDATA.size() == 1; //only one data for single bust
HXDATA[0] == data_write_temp;
}) else $fatal (0, "Randomization failed"); //end assert
`uvm_send(m_ahb_xfer);
count_32b_words++;
end //end if there is a word read
end //end while
$fclose(register_init_id);