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

将Verilog中的二进制文件数据读取到2D数组中,verilog,system-verilog,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

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

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位?我觉得应该没那么复杂。

试试这个

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
f_bin=$fopen(s_文件名,“rb”);
对于(r=0;r

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

我意识到了我的错误。应该是:

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

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

下面是一个使用systemverilog从二进制文件读取的示例

如IEEE SV标准文档所示,“nchar_代码”将返回读取的字节数/字符数。如果上次读取时已达到EOF,则该数字将为零。 请注意,“nchar\u code”可以为零,但未达到EOF,如果数据文件末尾有空格或返回,则会发生这种情况

您可以使用$fread函数控制要读取的字节数。这是通过以下示例中“数据写入临时”或“mem”的类型定义来完成的。如果“data\u write\u temp”变量的长度为16位,则每次调用$fread时它都将读取16位。此外,$fread将返回“nchar_code=2”,因为16位是2字节。如果“data_write_temp”是32位,如示例中所示,$fread将读取nchar_代码=4字节(32位)。您还可以定义一个数组,$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尺寸块):

在前面的结构中,数字显示每个维度的索引。 e、 g.w048表示索引z=0、索引y=4和索引x=8上的字w(32位)值

现在,你有很多方法来阅读这篇文章。 您可以使用上面声明的类型“mem”在单次激发中读取所有数据,也可以使用32位的“data\u write\u temp”变量执行while循环,直到EOF读取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);
逻辑[31:0]数据写入温度;
...
//注册文件
register_init_id=$fopen(“../../software/binary.bin”,“rb”);
如果(register_init_id==0)开始'uvm_error(“do_read_file”、$sformaf(“无法打开register_init_id文件”);结束
计数32b个单词=0;
而(!$feof(register\u init\u id))开始
nchar\u代码=$fread(数据写入临时、寄存器初始化id);
如果((nchar_代码!=4)|(nchar_代码==0))开始
如果(nchar_代码!=0)开始
`uvm_错误(“do_read_file”、$sformaf(“无法从文件中读取整个4字节字:%0d”,nchar_代码));
结束
结束,否则开始
tmp_ahb_地址=(pnio_包装::conf_ahb_寄存器_init_文件_part1+4*计数_32b_字);

data_write_temp=(文本模式“r”下的data_write_temp读取可能失败,因为它在您的文件中遇到一个字节,相当于它响应的换行符或其他控制字符。什么不起作用?。代码是一个剪贴画,只是为了向您展示如何使用systemverilog方法吗
    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);