目录
- 1 方法1:使用Verilog系统函数
- 1.1 需要用到的系统函数
- 1.2 例子
- 2 方法2:使用Modelsim指令
- 2.1 需要用到的Modelsim命令
- 2.2 Tcl过程编写
- 3 附件
Modelsim保存与打开仿真波形的方式介绍了怎么保存波形,但是有时候我们需要保存仿真过程的数据进行matlab分析绘图。
Modelsim导出数据的几中方法:
1 方法1:使用Verilog系统函数
1.1 需要用到的系统函数
- $fopen
multi_channel_descriptor = $fopen("file_name") ;
fd = $fopen("file_name",type) ;
- $fclose
$fclose(multi_channel_descriptor) ;
$fclose(fd) ;
- $fwrite/$fdisplay/$fdisplayb/$fdisplayh/$fdisplayo
file_output_task_name(multi_channel_descriptor [,list_of_arguments]);
file_output_task_name(fd [,list_of_arguments]);
file_output_task_name ::= $fwrite|\$fdisplay|\$fdisplayb|\$fdisplayh|\$fdisplayo
- $signed/$unsigned
$signed - returned value is signed
$unsigned - returned value is unsigned
1.2 例子
以输出无符号整数这个需求为例,RTL设计:
`timescale 1ns/1ps
module top(
input I_sys_clk,
input I_reset_n
);
//--- internal signal Definitions ---
//=== parameter define= ==
parameter P_SIM_MODE = 0;
//=== reg define ===
reg [9:0] R_data_cnt;
//=== wire define ===
//--- Main body of code ---
always @(posedge I_sys_clk or negedge I_reset_n)
begin
if(~I_reset_n)
begin
R_data_cnt <= 10'd0;
end
else
begin
if(~(&R_data_cnt))
begin
R_data_cnt <= R_data_cnt + 10'd1;
end
end
end
//--- save data ---
generate
if(P_SIM_MODE)
begin
integer f_id;
initial begin
f_id = $fopen("./data/data.txt","w");
end
always @(R_data_cnt)
begin
if (~(&R_data_cnt))
begin
$fwrite(f_id,"%d\n",$unsigned(R_data_cnt));//$unsigned可省略
end
else
begin
$fwrite(f_id,"%d\n",$unsigned(R_data_cnt));
$fclose(f_id);
end
end
end
endgenerate
endmodule
testbench
`timescale 1ns/1ps
module top_tb ();
parameter T = 10;
reg I_sys_clk;
reg I_reset_n;
initial begin
I_sys_clk <= 1'b1;
I_reset_n <= 1'b0;
#(T*10)
I_reset_n <= 1'b1;
end
always #(T/2) I_sys_clk <= ~I_sys_clk;
top #(
.P_SIM_MODE(1)
)top_u(
.I_sys_clk(I_sys_clk),
.I_reset_n(I_reset_n)
);
endmodule
仿真结果:
程序为一个R_data_cnt从0加到1023。
在save data代码段,首先打开一个“data.txt”文本文件,然后每次R_data_cnt改变时将R_data_cnt转换为有符号整数写入txt文件中,写完1023后关闭文件。
如果想要输出其他格式,则使用$fdisplayb/$fdisplayh/$fdisplayo,分别对应2进制,16进制,8进制。另外涉及到是否自动添加换行,需要微调一下。
2 方法2:使用Modelsim指令
ModelSim导出数据至.txt文件介绍了这种方法,现在补充一下基本原理以及怎么拓展。
2.1 需要用到的Modelsim命令
- examine
两种形式:examine和exa
功能:它检查一个或多个对象,并在Transcript窗口中显示当前值(或指定以前时间的值)。
语法:examine … [-delta ] [-env ] [-handle] {[-in] [-out]
[-inout] | [-ports]} [-internal] [-maxlen ] [-expr ] [-name]
[-<radix_type>] [-radix [<radix_type>][,<radix_flag>][,…]]
[-radixenumnumeric | -radixenumsymbolic] [-showbase] [-time ] [-value]
- -env: (可选)指定查找对象名称的路径。
- -name: 指定HDL或SystemC的目标
- -radix:(可选)进制。ascii,binary, decimal, fpoint, hexadecimal, octal, sfixed, symbolic, time, ufixed, unsigned,default, and user- defined radix names (refer to the radix define command).
- -time: (可选)指定从0到$now的某一个时间值,用于检查对象。
2.2 Tcl过程编写
我认为我们一般直接导出所有仿真时间段的需要的变量,所以稍微在之前的基础上稍微修改了一版:
Tcl过程:
proc write_sim_data {env name radix cycle file} {
set fid [open $file w]
for {set i 0} {$i <= $::now} {incr i [expr $cycle * 1000]} {
set str [exa -env $env -radix $radix -time ${i}ps {*}$name]
puts $fid $str
}
close $fid
}
说明:
line1
: 定义一个名为write_sim_data的过程,参数列表为:{env name radix cycle file}
- env:指定查找对象名称的路径。如top_tb/top_u。
- name:需要导出的变量列表。如{I_reset_n R_data_cnt}。
- radix:进制。可选:ascii,binary, decimal,hexadecimal,unsigned等
- cycle:时钟周期,单位ns。本例为:10
- file:输出文件。如./1.txt。
-
line2
:打开一个文档,返回文件描述符。 -
line3
: 分别获得从0到仿真结尾时间,按时钟周期间隔对数据进行取样输出。 -
line4
: 获得具体数据。 -
line5
: 将数据写入文件。 -
line7
: 关闭文件。
调用示例:
write_sim_data top_tb/top_u {I_reset_n R_data_cnt} unsigned 10 1.txt
用法:
- 首先在Modelsim脚本窗口输入过程定义。
- 然后设置好参数,调用脚本。
输出:
3 附件
测试工程:
链接:https://pan.baidu.com/s/1wXj58zLa-_eq1KmOrMwuMA
提取码:open