将Verilog中的二进制文件数据读入2D数组

时间:2014-07-29 20:50:11

标签: verilog system-verilog

我有一个数组,我想从二进制文件加载:

parameter c_ROWS = 8;
parameter c_COLS = 16;
reg [15:0]  r_Image_Raw[0:c_ROWS-1][0:c_COLS-1];

我的输入文件是二进制数据,256字节长(与r_Image_Raw相同的总空间)。我尝试使用$fread来完成此任务,但它只适用于最后一行的第4列:

n_File_ID = $fopen(s_File_Name, "r");
n_Temp = $fread(r_Image_Raw, n_File_ID);

我也尝试使用$fscanf,但是在打开综合工具时我收到有关打包类型的错误:

while (!$feof(n_File_ID))
  n_Temp = $fscanf(n_File_ID, "%h", r_Image_Raw);

我觉得这应该很容易。我是否创建了一个2D for循环并循环遍历r_Image_Raw变量,一次读取16位?我觉得它不应该那么复杂。

3 个答案:

答案 0 :(得分:2)

我意识到自己的错误。它应该是:

n_File_ID = $fopen(s_File_Name, "rb");
n_Temp = $fread(r_Image_Raw, n_File_ID);

我正在使用" r"而不是" rb"指定它是二进制文件。有趣的是," r"确实适用于大多数数据,但它无法从文件的最后~13个位置读取。

答案 1 :(得分:0)

试试这个。

f_bin       = $fopen(s_File_Name,"rb");

for (r = 0; r < c_ROWS; r = r+1) begin
    for (c = 0; c < c_COLS; c = c+1) begin
        f = $fread(r16,f_bin); 
        r_Image_Raw[r][c] =  r16;   
    end
end

看到$ fread(r16,f_bin)第一个参数是reg,第二个 - 文件!

答案 2 :(得分:0)

示例下面,用于从带有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位是2bytes。如果“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(32bits)值。

现在,您有很多方法可以阅读。 您可以使用上面声明的类型“mem”在单次拍摄中读取所有内容,或者您​​可以执行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);