【紫光同创国产FPGA教程】——Modelsim的使用和do文件编写

发布于:2025-02-19 ⋅ 阅读:(27) ⋅ 点赞:(0)

本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com)

一:​​​​​​​实验简介

实验目的:

了解Modelsim的基本使用方法,完成do文件的编写,提高仿真效率。

实验环境:

Window11

PDS2022.2-SP6.4

Modelsim10.6rc

二:​​​​​​​​​​​​​​实验原理

将Modelsim的命令编写到一个do文件中,这样每次仿真时,只需运行这个do文件脚本即可自动执行其中的所有命令,从而显著提高重复仿真的效率。

三:​​​​​​​​​​​​​​接口列表

暂无

四:​​​​​​​​​​​​​​Testbench文件的编写

Testbench文件其实就是模拟信号的生成,给我们所设计的模块提供输入,以便测试。因为我们上板去生成比特流,尤其是比较复杂的算法,往往是需要耗很多时间的。所以要快速验证我们的设计逻辑是否正常,还得是用仿真来验证,不管是模拟图像的生成还是信号的生成,都可以通过Testbench来完成,但是,要注意一点,仿真通过了只能说明百分之80上板没问题,剩下的可能就要看实际的时序了,毕竟仿真是理想状态,实际总是不太理想。

接下来介绍Testbench的基本编写方法:

`timescale 1ns/1ns 该语句 第一个1ns表示时间单位为1ns,第二个1ns表示时间精度为1ns。注意的是,时间单位不能比时间精度还小。时间单位表示运行一次仿真所用的时间。时间精度表示仿真显示的最小刻度。

#10 表示延时10个单位时间,比如`timescale 1ns/1ns,#10表示延时10ns。

initial 对信号进行初始化,只会执行一次。

{$random}%x,表示随机取[0,x-1]之间的数字。x为正整数。如果是$random%x,则是[-(x-1),x-1]的数。

$display 打印信息,会自动换行。

$stop 暂停仿真。

$readmemb读取文件函数。

$monitor 为监测任务,用于变量的持续监测。只要变量发生了变化,$monitor 就会打印显示出对应的信息。

输入信号一般用reg定义,方便后续用always块生成想要模拟的值,输出一般直接wire引出即可。

例如生成时钟,always#10 sys_clk = ~sysclk; 表示每10个单位时间就翻转一次,如果时间单位是ns,那就是每10ns翻转一次,就是生成了50MHZ的时钟。周期是20ns。

接下来给出一个参考的testbench,如下所示:

`timescale 1ns / 1ns  

`define UD #1  

module tb_led_test();  

  

reg         clk     ;  

reg         rst_n   ;  

wire[7:0]   led     ;  

reg [7:0]   data    ;   

  

initial begin  

    rst_n <= 0;  

    clk   <= 0;   

    #20;  

    rst_n <= 1;  

    #2000  

    $display("I am stop"); //  

    $stop;  

end  

always#10 clk = ~clk;//20ns  50MHZ  

  

led_test   

#(  

    .CNT_MAX    (10)  

)u_led_test(  

 .clk       (clk    ),// input            

 .rstn      (rst_n  ),// input            

 .led       (led    ) // output [7:0]    

);                 

  

initial begin  

    $monitor("led:%b", led);  

end  

  

always@(posedge clk or negedge rst_n)    begin  

    if(!rst_n)  

        data    <=    8'd0;  

    else  

    begin  

data    <=    {$random}%256;  

        $display("Now data is %d",data);  

    end  

end  

  

endmodule  

代码第一行定义了仿真的时间单位和精度,均为1ns;第二行宏定义了延时的时间UD,可根据个人代码习惯使用。第10-18行对复位和时钟进行初始化,并且延时2020ns后用$display打印出暂停仿真的字样,之后停止仿真。注意$stop仅仅是暂停仿真,不是完全结束仿真,还可以通过run指令继续运行仿真。第19行每10ns翻转一次,完成了50MHZ时钟的生成。21-28行例化了流水灯模块,用来做仿真测试,该代码主要完成每隔一段时间对输出的数据完成一次移位。进而实现了流水灯。30-32行用$monitor监测led变量,一旦改变就打印出来。第34-42行主要是产生测试数据并打印出来,该数据仅仅用来观察random函数的测试。

五:​​​​​​​Modelsim的使用

该部分主要介绍Modelsim的基本使用方法。

当我们的设计文件没有使用到任何平台的IP核时,我们可以直接打开Modelsim新建工程,然后进行仿真,具体步骤如下所示:

点击左上角File->New->Library,新建一个工作库,一般取名为work,因为Modelsim运行时都会在这个work下面工作,所以第一次运行Modelsim我们需要新建一个叫work的库,如果打开发现已经有work的工作库时,则不用新建。 

输入work,点击OK即可。新建完成后就可以看到有个work的库在Modelsim里面。接下来新建工程。

 

左上角File->New->Project,新建工程。

 

工程名注意不要出现中文,其余保持默认即可,可以看到Default Library Name其名字默认指向work。

 

新建完后可以看到下方多了一个叫Project的选项卡,鼠标右键该界面空白部分,选择Add to Project->Existing File,或者Add to Project->New File。添加我们要仿真的文件,这里用一个比较简单的来演示。 

点击Browse,添加要仿真的文件。

 

选择上方Compile或者鼠标右键空白部分,选择Compile->Compile,该步骤主要对verilog文件进行编译,检查是否有语法错误等。

 

当看到Status是个绿色的√,或者下方打印输出区间没有任何errors,显示successful,表示我们的文件编译通过,可以进行下一步操作了。

 

选择上方Simulate->Start Simulation,之后会弹出如图 3.2-10所示的界面,把work展开,选择我们的testbench文件,可以看到Design Unit显示的是我们的testbench文件就没问题了。然后点击OK,开始仿真。 

 

可以看到会弹出一个新的选项卡叫”sim”,然后看红框部分,当点击OK后,实际上Modelsim自动输入一句命令vsim -gui work.tb_led_test。这其实和后面我们的do文件编写是有联系的,do文件的编写实际上就是在写这些命令,这里我们先铺垫一下。

 

接下来添加我们要观察的信号,这里我是直接右键u_led_test这个模块,然后选择Add Wave或者crtl+w,即可将该模块的全部信号都加入到波形窗口中。

 

可以看到,波形窗口已经添加该模块的全部信号,之后我们按下快捷建,crtl+a全选全部信号,crtl+g,对信号进行分组,该分组是按照不同模块进行分组,crtl+h消除信号名称的前缀,如图 3.2-14所示: 

鼠标右键信号,Radix可以修改该信号显示的格式,比如二进制显示,16进制显示等。Properties可以修改该信号波形显示的颜色,这两个是比较常用的。接下来开始来运行我们的仿真。

 

点击上方这个地方,对信号全部进行Restart复位。

 

红框旁边的100 ps是一次仿真运行的时间,红框内从左往右看,第一个是表示运行一次仿真,其时间为100ps,100ps并不是固定的,我们可以修改为1ms,100us等。第二个基本比较少用。第三个是让仿真不断运行,直到用户点击停止为止,如图 3.2-18所示: 

按下后,当用户点击stop,仿真才会停止。

 

上图为操作后显示出来的波形。

点击红框部分那个按钮,将缩小波形。我们也可以按住crtl键,然后鼠标滚轮上下,可以对波形进行缩放。到这里,基本的使用方法就结束了,更多操作大家可以去看视频操作,或者网上百度,或者自己摸索一下。

再铺垫一下,完成这些操作后,我们回去打印输出区间观察一下

可以看当我们添加波形时,Modelsim自动执行了一句add wave -position xxxxxxx的命令,执行了restart,也就是复位,run就是运行仿真,这些都和后续do文件的编写息息相关。所以其本质就是编写这些命令,我们就不需要用鼠标去点每个功能,每次我们只需要运行do文件就可以完成全部操作,大大提高我们的效率。

如果大家不小心把某些选项卡关了,可以在上方View选择要查看的窗口,如图 3.2-22所示:

比如Library前面有个√,就是显示Library选项卡的意思。大家可以在这里找找需要显示的界面。

六:​​​​​​​​​​​​​​文件的编写

​​​​​​​基本命令介绍

前文其实也有提到,Modelsim实际上是通过输入命令来执行相应功能的,比如add wave xxxxx,就是把信号添加到波形窗口。那接下来就是教大家如何使用这些命令来提高我们的开发效率。

首先先介绍常用的命令。

vlib:该命令为创建一个目录。例如 vlib work。即在当前路径下创建一个名字叫work的文件夹。

vmap: 映射逻辑库到物理目录。其格式为vmap work work     第一个work逻辑库名称,第二个work是表示在PC里实际的库文件的路径。

注意:前面所说的通过File->New->Library的方法建立了一个work的库,其实就是运行了vlib和vmap,具体可以看教程视频讲解。本质就是vlib work   vmap work work。

vlog:该命令用来编译verilog源码。例如vlog -work work ./src/test.v  第一个work表示文件夹的名称 、第二个work表示modelsim中library的库的名称、第三个就是要编译的文件的路径。

vsim:表示启动仿真。

add wave:表示添加波形到波形窗口(add wave -divider 会添加分割线)。

view wave:打开波形窗口。

view structure:打开结构窗口。

view signals:打开信号窗口。

restart:重新仿真,复位仿真时间,并清空之前的仿真数据。(如果修改了verilog文件 需要重新编译再仿真才行,restart只是在当前这个仿真下重新开始仿真而已)。

run x:运行x时间。例如run 1ms  run1ns  run 1us   run 250ms 均可。

quit -sim:退出仿真。

quit:退出Modelsim。(关闭整个软件)

​​​​​​​文件示例

如果从0开始写,相信是比较陌生的,其实当我们使用紫光联合仿真的时候,他会在sim的文件夹下生成一个后缀为tcl的脚本,每次运行联合仿真,实际就是打开Modelsim然后运行该tcl脚本,具体路径都在工程目录下的sim文件夹下,如下图所示:

主要是运行run_behav_compile.tcl和run_behav_simulate.tcl这两个文件。我们可以打开来参考一下。

 

 

以上是run_behav_compile.tcl的内容,大家可以结合视频教程一起分析一下,该文件主要完成工作区间的建立和一些库的映射以及对代码的编译。

vlib:该命令创建一个文件夹。例如 vlib work。

vmap:映射逻辑库到物理目录。其格式为vmap work work     第一个work逻辑库名称,第二个work是表示在PC里实际的库文件的路径。

vlog:该命令用来编译verilog源码。例如vlog -work work ./src/test.v  

第一个work表示文件夹的名称。  

第二个work表示Modelsim中library的库的名称。

第三个就是要编译的文件的路径。

所以大家其实可以参考demo的脚本来编写我们的do文件,我们的do文件本质上也是写这些命令,只不过后缀不一样,但其运行方法是一致的,均为do+空格+文件名。所以到此,大家应该都知道我们的do文件是怎么去编写了,其实就是把这些Modelisim的运行指令,写成一个脚本,然后用do指令直接完成我们想要的所有操作,可以大大提高我们的效率。在展示如何使用Modelsim的时候也介绍了,每一步操作实际上都是软件工具自动帮我们输入命令,现在就是把这些命令给拿出来。接下来我们看run_behav_simulate.tcl的内容。

vsim:表示启动仿真。vsim -L +逻辑库的名字。

add wave:表示添加波形到波形窗口。(add wave -divider 会添加分割线)

view wave:打开波形窗口。

view structure:打开结构窗口。

view signals:打开信号窗口。

run x:运行x时间。例如run 1ms  run1ns  run 1us  run 1s  run 250ms 均可。

再顺带介绍一下一些常用的。

restart:重新仿真,复位仿真时间,并清空之前的仿真数据。(如果修改了verilog文件 需要重新运行do文件才生效,restart只是在当前这个仿真下重新开始仿真而已)

quit -sim:退出仿真。

quit:退出Modelsim。

该脚本主要是完成仿真,以及一些仿真完成后的操作,比如添加波形,观察波形,设置运行时间。

所以,其实我们可以把这两个文件合起来,变成一个文件,做成我们自己的do文件就行了,如此,以后修改代码重新仿真都不需要去PDS软件里面去点联合仿真,我们直接在Modelsim里面直接do就行了。合并后的do文件如下所示:

可以看到,基本上就是把两个文件给合并起来,然后多添加了restart语句。至于添加波形的语句add wave -position insertpoint sim:/tb_led_test/u_led_test/* ,如果大家不熟悉这样的格式,可以直接在Modelsim里面手动添加,然后看其打印区间,输出的指令格式,复制下来就行了。一开始,大家不熟悉的话可以这么操作,等熟悉了后,就可以完全编写了,因为使用了紫光的联合仿真,所以中间会用vmap映射很多的紫光的仿真库。包括vsim也调用了很多紫光相关的库。所以,如果大家并没有用到紫光的IP核或者原语等,只是单纯的验证逻辑的话,其实没有这么麻烦。与紫光的仿真库有关的都可以删了,所以主要就是一个vlib work,然后vmap work work,然后vlog我们要仿真的文件的路径,注意需要写好testbench。然后vsim,然后添加要查看的波形,然后restart,然后run即可。 


网站公告

今日签到

点亮在社区的每一天
去签到