Modelsim导出数据的两种方法

本文详细介绍了如何在Modelsim中使用Verilog系统函数和Modelsim指令来导出仿真数据,以便于进行后续的MATLAB分析和绘图。方法1通过Verilog的$fopen、$fwrite等函数将数据写入文本文件,方法2利用Modelsim的examine命令结合Tcl过程实现数据导出。提供了具体的代码示例和Tcl过程编写方法,帮助用户理解并应用这两种导出数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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 ] [-event

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   

用法:

  1. 首先在Modelsim脚本窗口输入过程定义。
  2. 然后设置好参数,调用脚本。
    在这里插入图片描述

输出:
在这里插入图片描述
在这里插入图片描述

3 附件

测试工程:
链接:https://pan.baidu.com/s/1wXj58zLa-_eq1KmOrMwuMA
提取码:open

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChipWeaver

觉得有用的话点个赞吧 :)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值