前言
记录一下自己仿真过程中用到过的一些用于testbench的系统命令,根据自己用到的情况不定时进行补充。
文件操作
$fopen
用于打开文件的命令,格式如下
file = $fopen("file_name","mode")
file_name:要打开的文件名,注意文件路径中要使用 " / ",例如 " D:/test/file.txt "
mode:要对打开的文件进行的操作,通常记住读写两种就可以
r:只读打开一个文件,只允许读数据
w:只写打开一个文件,只允许写数据,如果文件存在,原数据会被删除,文件不存在则新建文件
注意:
- 这里file创建的是一个指向文件的指针
- file这个参数在仿真中会显示一个固定值,与读取的文件内容无关。如图,file_r显示ffffb1e0,file_w显示ffffb1e1,这是个固定的值,与打开的文件无关
$fscanf
该函数每次读取打开的文件中的一行数据,格式如下
$fscanf(file,"datatype",data)
file:由$fopen创建的指针,即 file=$fopen(‘xxx.txt’,'r') 中的返回值file,指向文件的开头
datatype:'%b'、'%d'、'%h',即二进制、十进制以及十六进制
data:用于存放从xxx.txt读取的数据的数组,要提前创建
注意:
- 只会读取数字,用空格(多个空格等同一个)或换行符隔开每个数字
- 超过数据位数的截取低有效位,如图中12345以及23456只读取了低位的45和56
- 遇到不能识别的符号(数字以及十六进制用到的字母以外的字母或符号)会停止读取,如图中只读取到了23456,jk以及后面的1234都没有读取
$fwrite
想打开的写格式的文件内写入数据,格式如下
$fwrite(file,"datatype",data)
file:由$fopen创建的指针,即 file=$fopen(‘xxx.txt’,'r') 中的返回值file,指向文件的开头
datatype:'%b'、'%d'、'%h',即二进制、十进制以及十六进制
data:向xxx.txt内写入的数据
注意:
- 数据的写入会无间隔的写在同一行,需要在格式内手动添加 \n (例如·$fwrite(f_r,"%h\n",data)) 进行换行。如下图,所有写入数据都写到了同一行
- 数据的高位为0时,会写入0。如图,读取时,文件内数据是1,但是存储时是8位的十六进制,显示的是01,写入文件时就会写入01
$fclose
关闭打开的文件,格式如下
$fclose(file)
file:由$fopen创建的指针,即 file=$fopen(‘xxx.txt’,'r') 中的返回值file,指向文件的开头
注意:
- 仿真结束后会自动的关闭文件,但是如果没有结束仿真,也没有关闭文件,则无法用别的程序读取该文件,该文件大小也会显示为0k
使用示例
`timescale 1ns/1ns
module pic_tb();
reg clk,rst_n ;
reg [7:0] data_in ;
reg [7:0] data_out ;
initial begin
clk = 1;
rst_n = 0;
#20 rst_n = 1;
end
always #10 clk = ~clk;
integer file_r;
integer file_w;
initial begin
file_r = $fopen("D:/BaiduNetdiskDownload/1.txt","r");
file_w = $fopen("D:/BaiduNetdiskDownload/2.txt","w");
end
reg [7:0] r_cnt;
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
r_cnt <= 0;
data_in <= 0;
end
else if(r_cnt<20)begin
$fscanf(file_r,"%h",data_in);
r_cnt <= r_cnt +1;
end
else begin
r_cnt <= 0;
$fclose(file_r);
end
end
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
r_cnt <= 0;
data_out <= 0;
end
else if(r_cnt<20)begin
data_out <= data_in;
$fwrite(file_w,"%h",data_out);
r_cnt <= r_cnt +1;
end
else begin
r_cnt <= 0;
$fclose(file_w);
end
end
endmodule
数据操作
$readmemb/$readmemh
从文件中读取数据,格式如下
$readmemb("file_name",data,addr_start,addr_end)
file_name:要读取的文件名,注意文件路径中要使用 " / ",例如 " D:/test/file.txt "
data:用于存储读取的数据的数组,要注意大小需要足够容纳要读取的数据
addr_start:开始地址,非必须参数
addr_end:结束地址,非必须参数
注意:
- $fscanf是一个数据一个数据的对文件进行扫描读取,$readmemb是一次性读取
- data需要是数组,即 reg [7:0] mem [255:0] 格式创建的,大小要足够容纳一次性读取的数据
- 除了$readmemb,还有$readmemh,最后的b和h表示读取数据的进制类型,readmemb以二进制读取数据,readmemh以十六进制读取数据
系统函数
$finish
结束仿真,testbench运行到该行会停止运行,格式如下
$finish
$display
在tcl输出内容,相当于printf,格式如下
$display("hello")