当前位置: 首页 > news >正文

【盘古100Pro+开发板实验例程】FPGA学习 | Modelsim 的使用和 do 文件编写

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

1. 实验简介

实验目的:

      了解 PDS 软件的使用,在线 Debugger 工具的使用请看 uart 实验章节的工程说明部分章节。 实验环境:

      Window11 PDS2022.2-SP6.4

硬件环境: 

      MES2L676-100HP

2. 实验原理

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

3. 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 #1module tb_led_test();reg clk;reg rst_n;wire [7:0] led;reg [7:0] data;initial beginrst_n <= 0;clk <= 0;#20;rst_n <= 1;#2000;$display("I am stop");$stop;endalways #10 clk = ~clk; // 20ns 50MHzled_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);endalways @(posedge clk or negedge rst_n) beginif (!rst_n)data <= 8'd0;else begindata <= {$random} % 256;$display("Now data is %d", data);endend
endmodule

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

4. 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,之后会弹出如图 2.5-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 消除信号名称的前缀,如图 所示:

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

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

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

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

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

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

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

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

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

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

5. 文件的编写

5.1. 基本命令介绍

前文其实也有提到,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。(关闭整个软件)

5.2. 文件示例

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

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

vlib work
vmap work ./work
vmap usim "D:/modelsim/pg_sim_lib/usim" 
vmap adc_e2 "D:/modelsim/pg_sim_lib/adc_e2" 
vmap ddc_e2 "D:/modelsim/pg_sim_lib/ddc_e2" 
vmap dll_e2 "D:/modelsim/pg_sim_lib/dll_e2" 
vmap hsstlp_lane "D:/modelsim/pg_sim_lib/hsstlp_lane" 
vmap hsstlp_pll "D:/modelsim/pg_sim_lib/hsstlp_pll" 
vmap iolhr_dft "D:/modelsim/pg_sim_lib/iolhr_dft" 
vmap ipal_e1 "D:/modelsim/pg_sim_lib/ipal_e1" 
vmap ipal_e2 "D:/modelsim/pg_sim_lib/ipal_e2" 
vmap iserdes_e2 "D:/modelsim/pg_sim_lib/iserdes_e2" 
vmap oserdes_e2 "D:/modelsim/pg_sim_lib/oserdes_e2" 
vmap pciegen2 "D:/modelsim/pg_sim_lib/pciegen2" 
vlog -work work \
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/Desktop/01_led_test.v" \- 34 -
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/Desktop/tb_led_test.v" \
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/source/Desktop/01_led_test.v"

      以上是 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 -novopt -L work -L usim -L adc_e2 -L ddc_e2 -L dll_e2 -L hsstlp_lane -L hsstlp_pll -L iolhr_dft -L ipal_e1 -L ipal_e2 -L iserdes_e2 -L oserdes_e2 -L pciegen2 tb_led_test usim.GTP_GRS
add wave * view wave
view structure
view signals
run 1000ns

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 文件如下所示:

cd D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/sim/behav
vlib work
vmap work ./work
vmap usim "D:/modelsim/pg_sim_lib/usim" 
vmap adc_e2 "D:/modelsim/pg_sim_lib/adc_e2" 
vmap ddc_e2 "D:/modelsim/pg_sim_lib/ddc_e2" 
vmap dll_e2 "D:/modelsim/pg_sim_lib/dll_e2" 
vmap hsstlp_lane "D:/modelsim/pg_sim_lib/hsstlp_lane" 
vmap hsstlp_pll "D:/modelsim/pg_sim_lib/hsstlp_pll" 
vmap iolhr_dft "D:/modelsim/pg_sim_lib/iolhr_dft" 
vmap ipal_e1 "D:/modelsim/pg_sim_lib/ipal_e1" 
vmap ipal_e2 "D:/modelsim/pg_sim_lib/ipal_e2" 
vmap iserdes_e2 "D:/modelsim/pg_sim_lib/iserdes_e2" 
vmap oserdes_e2 "D:/modelsim/pg_sim_lib/oserdes_e2" 
vmap pciegen2 "D:/modelsim/pg_sim_lib/pciegen2" vlog -work work \
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/Desktop/01_led_test.v" \
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/Desktop/tb_led_test.v" \
"D:/ziguan_demo/MES2L100Hv2/MES2L100Hv2/2_Demo/01_led_test/01_led_test/source/source/Desktop/01_led_test.v" 
vsim -novopt -L work -L usim -L adc_e2 -L ddc_e2 -L dll_e2 -L hsstlp_lane -L hsstlp_pll -L iolhr_dft -L ipal_e1 -L ipal_e2 -L iserdes_e2 -L oserdes_e2 -L pciegen2 tb_led_test usim.GTP_GRS
add wave * 
add wave -position insertpoint sim:/tb_led_test/u_led_test/* 
view wave
view structure
view signals
restart
run 1000ns

可以看到,基本上就是把两个文件给合并起来,然后多添加了 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 即可。

http://www.dtcms.com/a/294864.html

相关文章:

  • 如何通过内网穿透,访问公司内部服务器?
  • 企业选择将服务器放在IDC机房托管的优势
  • Python 程序设计讲义(7):Python 的基本数据类型——整数类型
  • 什么是HTTP长连接、短连接?谁更能抗DoS攻击?
  • Vue 中 :value 和 :value.sync 的区别
  • La Création du C++ : Une Épopée dans l‘Évolution de la Programmation
  • Encore.ts:下一代高性能 TypeScript 后端框架的崛起
  • 后仿之 SDF优先级和相关概念
  • Kubernetes 服务发布进阶
  • 大模型开发
  • 图的BFS和DFS
  • 优化 Elasticsearch JVM 参数配置指南
  • 网安-SQL注入-sqli-labs
  • 前端Web性能核心指标全解析与优化实战指南
  • Mermaid流程图
  • netstat -tunlp | grep的作用
  • day 33打卡
  • 位运算在算法竞赛中的应用(基于C++语言)_位运算优化
  • SAP亚太区借力Business AI加速云转型,第二季度客户扩展势头强劲
  • 【Lucene】leafreadercontext逻辑段与segment物理磁盘段的关系
  • 牛油果褐变的成因与食用安全
  • 天津大学陈亚楠教授团队 ACS AEM:焦耳热超快合成非平衡态能源材料——毫秒级制备与跨体系性能突破
  • 本地运行C++版StableDiffusion!开源应用StableVerce发布
  • GTSuite许可问题解决方法
  • Flask框架全面详解
  • Python 程序设计讲义(9):Python 的基本数据类型——复数
  • 如何减少冷库能耗,1种降低冷库能耗的方法
  • 元宇宙产业生态全景:从基础设施到未来趋势的深度解析
  • 什么是RWA?它与传统资产和数字资产的区别
  • 【LeetCode刷题指南】--随机链表的复制