HDL文件操作总结

VHDL  

文件操作都在tb中,因为涉及到操作系统,所以无法综合。

  在vhdl中,文件被看作 行 组成的一维数组。

  预先要把两个文件读写相关的库声明。

1 use STD.TEXTIO.all;

2 use ieee.STD_LOGIC_TEXTIO.all; 

  首先要声明用来存储文件数据的数组,以一个80X64的32位浮点图像数据为例。

1     type TYPE_MdlImgDat32_r is array (0 to 79) of std_logic_vector(31 downto 0);
2     type TYPE_MdlImgDat32 is array (0 to 63) of TYPE_MdlImgDat32_r;

  首先定义了一个80大小的一维数组类型,数组成员为32位std_logic_vector

  然后再定义了一个64大小的一维数组类型,数组成员类型为一维数组。

  这样我们就得到了一个二维数组类型,当然我们也可以用下面的方法来直接定义:

    type matrix is array(0 to 63, 79 downto 0) of std_logic_vector;

  在定义完用来存数的数组结构之后,我们需要申明文件句柄。

1     file FILE_MdlImg          : TEXT;
2     file FILE_MdlImg_rad      : TEXT;
3     file FILE_MdlImg_mag      : TEXT;
4     file FILE_RefImg          : TEXT;
5     file FILE_RefImg_Software : TEXT;
6     file FILE_MdlImg_Software : TEXT;

  申明完文件句柄之后,记得要把前面定义的数组初始化。、

 1 variable vMdlImgDat32 : TYPE_MdlImgDat32 := (others => (others => (others => '0')));      

   因为文件内部是一行一个数据,而且是32位的HEX表示,所以还需要声明行句柄

1         variable MdlL_OUT : LINE;
2 
3         variable RefL_OUT : LINE;
4 
5         variable RefL_OUT_Software : LINE;
6 
7         variable MdlL_OUT_Software : LINE;

  把文件读入二维数组中

  file_open,第一个参数是前面定义的文件句柄,后面是文件的绝对路径,最后是读或者写模式。

  readline,第一个参数还是文件句柄,第二个是前面定义的行句柄。

  hread,第一个参数是行句柄,第二个参数是二维数组里面的某个元素。

  file_close,关闭之前打开的文件。

1         FILE_OPEN(FILE_MdlImg_Software, "C:\Users\MekiX\Documents\Recorded_projects\cal_mag\mag_cal_ready_valid\Data\srcimg_oactave__80x64_hex.txt", READ_MODE);
2         ReadMdlImgFromFiles : for i in 0 to 63 loop
3             loopX               : for j in 0 to 79 loop
4                 READLINE(FILE_MdlImg_Software, MdlL_OUT_Software);
5                 HREAD(MdlL_OUT_Software, vMdlImgDat32(i)(j));
6             end loop;
7         end loop;
8         FILE_CLOSE(FILE_MdlImg_Software);

  总结一下就是,先把文件打开,再把文件的行读取,之后再把文件的行内元素依次写入到二维数组中。(readline应该可以放到loopx上面,还未验证)。

 

  对于写操作,基本类似。

  先也是file_open,

  HWRITE,第一个参数是行句柄,第二个数据,第三个是光标向右移动的位置,10是移动的长度。32位的HEX表示应该是8,写成10留了点余量。数据前面会有两个空格。写入方式也就是一个数据一行。

  WRITELINE,第一个参数是文件句柄,第二个是行变量。

  最后再把文件关闭。

  生成的文件在vivado工程的sim文件夹下.

 1         FILE_OPEN(FILE_MdlImg_rad, "MdlImg_rad.txt", WRITE_MODE);
 2         wait until rising_edge(aclk);
 3 
 4         while m_axis_rad_tuser = '0' loop
 5             wait until rising_edge(aclk);
 6             if (m_axis_rad_tvalid and m_axis_rad_tready) = '1'then
 7                 HWRITE(MdlL_OUT, m_axis_rad_tdata, right, 10); 9                 WRITELINE(FILE_MdlImg_rad, MdlL_OUT);
10             else
11                 wait until (m_axis_rad_tvalid and m_axis_rad_tready) = '1';
12                 wait until rising_edge(aclk);
13                 HWRITE(MdlL_OUT, m_axis_rad_tdata, right, 10);15                 WRITELINE(FILE_MdlImg_rad, MdlL_OUT);
16             end if;
17         end loop;
18         FILE_CLOSE(FILE_MdlImg_rad);

 Verilog

  以下都是task类型的.

  读文件一般使用$readmemb,$readmemh,分别是读二进制和16进制的文件。

  同样需要先建立一个数组

    

  但是不需要再打开文件

   1 $readmemb("file1.txt",mem); 

  这个可以按次序填充多维数组,即先79到0.

  

1  $readmemb("file1.txt",mem,1);//这个代表从mem[1]往后写
2  $readmemb("file1.txt",mem,1,2);//这个代表从mem[1]写到[2]

 

 

 

  上面的文件可以使用绝对地址,只需要把"\"换成"/".

  写文件一般是

  首先定义一个整数类型的文件指针,然后用$fopen打开文件.

  $fopen实际上可以有两个参数,中间用 , 隔开,后面一个是mode

  常用mode包括

  “w",“wb"              清除文件内容并从文件头开始写,如果不存在就创建文件,只写模式。(默认模式) .

  “w+",'w+b","wb+"清除文件内容并从文件头开始读写,如果不存在就创建文件,可读写模式.

  "a","ab"     从文件末尾开始写,如果不存在就创建文件,只写模式。

  “a+","a+b","ab+"  文件末尾开始读写,如果不存在就创建文件,可读写模式.

  "r","rb"       只读模式.

  "r+","r+b","rb+"    可读写方式.

  多一个b为binary

   1 integer hex_image_80X64; 2 hex_image_80X64 = $fopen("hex_image_80X64.txt") 

  然后我们向文件写入信息,常用的task有:

  $fdisplay, $fwrite,$fstrobe,$fmonitor. 格式控制有

      %c %C character (low 8 bits)
                    %d %D decimal  %0d for minimum width field
                    %e %E E format floating point %15.7E
                    %f %F F format floating point %9.7F
                    %g %G G general format floating point
                    %h %H hexadecimal
                    %l %L library binding information
                    %m %M hierarchical name, no expression
                    %o %O octal
                    %s %S string, 8 bits per character, 2´h00 does not print
                    %t %T simulation time, expression is  $time
                    %u %U unformatted two value data  0 and 1 
                    %v %V net signal strength
                    %z %Z unformatted four value data  0, 1, x, z

  %5d, %5b.前面的数字类似vhdl,也是长度控制.,也可以直接在task后面加b/h/o,也可以直接把默认格式切换成指定的格式,例如$fdisplayb,就是二进制.

  $fdisplay和 $fwrite在每次被执行的时候都会向文件中写入指定格式的数据,区别在于$fdisplay每次执行完毕会添加新的一行,而$fwrite不会.

  $fstrobe也是写入数据但是是在同一时刻所有语句执行完毕之后再执行,举例:

1 initial 
2 #1 a=1; 
3 b=0; 
4 $fstrobe(hand1,a,b); // 默认格式将ab写入
5 b=1;

  此时,文件名是hand1,写入的ab都是1;

  $fmonitor是在参数变化的时候往文件里写数.

  它们的具体格式非常类似c,这也是因为verilog开发的初衷就是为了比VHDL贴近C.举例如下:

  

1 f = $fopen("output.txt","w");
2 $fmonitor(f, "%h", acc_out);
3 $fclose(f);

  这些task前面的f去掉之后就是在屏幕上显示而非写入文件.而具体的语法区别在于最前面的参数从文件句柄(通过$fopen得到)换成了类似c的字符串输出,举例如下

 1 $monitor("monitor a:%h @ %0t", acc_out, $time); 

  分别将accout以16进制替换%h,time替换%0t. 同时,与c语言类似,也有

1                                                  \t   tab
2                                                  \\   backslash反斜杠
3                                                  \"   quote引号
4                                                  %%   percent

  如果这些task没有指定输出或者写入格式会怎么样?

  写入完成之后,调用$fclose关闭文件,参数是整数句柄变量而非文件名.

  读取和写入一般只执行一次,放在initial块中.

  task还有很多,下次用到再写.

posted @ 2020-08-03 21:12  天山明月  阅读(834)  评论(0编辑  收藏  举报