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:UsersMekiXDocumentsRecorded_projectscal_magmag_cal_ready_validDatasrcimg_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 tab
2 \ backslash反斜杠
3 " quote引号
4 %% percent
如果这些task没有指定输出或者写入格式会怎么样?
写入完成之后,调用$fclose关闭文件,参数是整数句柄变量而非文件名.
读取和写入一般只执行一次,放在initial块中.
task还有很多,下次用到再写.