Testbench的文本文件写入操作
文件打开$fopen
- 功能:用于打开指定文件名的文件并返回一个32位的多通道描述符或者32位文件描述符,取决于 文件操作类型 的设置(包括"r"、“w”、“a”、“r+”、“w+”、"a+"等读、写等操作类型),虽然会创建 .txt 文件但不会创建文件夹,所以要在相应目录下提前创建对应的文件夹
- 语法结构:有以下两种
- 指定文件类型:
integer 文件描述符 = $fopen("打开相应.txt文件的路径包括.txt","文件操作类型");
- 不指定文件类型:
integer 多通道描述符 = $fopen("打开相应.txt文件的路径包括.txt");
- 指定文件类型:
两者区别在于不指定文件操作类型时,文件打开后处于写入状态并且返回一个32位的多通道描述符,此时最多能同时打开31个文件进行操作,而在指定的路径下则没有该限制
文件关闭$fclose
- 语法结构:
$fclose(文件描述符或者多通道描述符);
文件写入$fwrite
- 功能:用于向指定文件写入数据,写入后不自动换行(注意需要的情况下加换行符)
- 语法结构:
$fwrite(文件描述符或者多通道描述符,字符串或数据格式,寄存器等);
实例
以前面杂记5中的格雷码转换快速算法为前提,我们需要把输出的数据保存在一个txt文件中,具体代码写在testbench中(前面省略):
...
//测试激励产生
initial begin
i_en <= 'b0;
i_data <= 'b0;
$display("The value of GRAY_MSB is %0d",GRAY_MSB);
@(posedge rst_n); //等待复位完成
@(posedge clk);
i_en <= 'b1;
i_data <= 'b0;
repeat(2**(GRAY_MSB+1)-1) begin
@(posedge clk);
i_en <='b1;
i_data <= i_data + 1;
end
@(posedge clk);
i_en <='b0;
#100;
$fclose(w_file); //关闭文件
$stop;
end
integer w_file; //文件操作符
initial begin
w_file = $fopen("./output_file/result_data.txt","w"); //在本目录下打开文件夹output_file并创建result_data.txt文件
end
always@(posedge clk) begin
if(o_vld) $fwrite(w_file,"%b\n",o_gray); //数据写入文件
end
endmodule
写入程序不要放在第一个initial里面的repeat语句的循环叠加里面,因为最后容易出现输出数据不完整的情况,还要考虑时序问题,得不偿失。写在外面会将寄存器中的数据一一输出,直到全部输出为止。其实时序问题是最难的,这里恕笔者太菜不能说得明明白白就不再赘述,但希望都能多点思考,才能让结果更加完美
输出结果将在output_file文件夹下出现.txt文件,里面的内容正是格雷码的正确转换,这里就不再赘述。
Testbench的文本文件读取操作
十六进制文件读取 $readmemh :将文件的数据一次性的读入到某个数组中,然后可以依次从数组中取出单个的数据进行处理,读取的内容只包括空白位置(空格、换行、制表格)、注释行、十六进制的数字,语法结构中的起始位置与终止位置可忽略
语法结构:$readmemh("相应文件位置信息",存储器名,起始地址,终止地址);
二进制文件读取为 $readmemb
测试脚本(部分,延续上一部分):
//文本文件的读取
reg[7:0] data_mem[255:0];
initial $readmemb("./output_file/result_data.txt",data_mem); //读取result_data文件的信息并存入data_mem中
//测试激励产生
initial begin
i_en <= 'b0;
i_data <= 'b0;
$display("The value of GRAY_MSB is %0d",GRAY_MSB);
@(posedge rst_n); //等待复位完成
@(posedge clk);
i_en <= 'b1;
i_data <= 'b0;
repeat(2**(GRAY_MSB+1)-1) begin
@(posedge clk);
i_en <='b1;
i_data <= i_data + 1;
end
@(posedge clk);
i_en <='b0;
#100;
//$fclose(w_file);
$stop;
end
integer cnt;
always @(posedge clk) begin
if(!rst_n) cnt <= 'b0;
else if(o_vld) cnt <= cnt + 'b1;
end
always@(posedge clk) begin
if(o_vld) $display("%b\n%b\n\n",o_gray,data_mem[cnt]); //上面一行显示实际程序运行的输出结果,下面一行显示读取的结果
else ;
end
endmodule
结果(相同):