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

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

 本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处

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 复位。

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

相关文章:

  • SpringBoot 使用Rabbitmq
  • rust嵌入式开发零基础入门教程(一)
  • FSHNet:高效目标检测新突破
  • rust嵌入式开发零基础入门教程(五)
  • Python应用指南:构建和获取全球地铁线路数据及可视化
  • HarmonyOS学习记录5
  • 【形态学变换】——图像预处理(OpenCV)
  • (nice!!!)(LeetCode 每日一题) 1717. 删除子字符串的最大得分 (贪心)
  • 昨天去看了电科金仓的发布会,有点东西!
  • AI营销核心技术解析:运作机制与行业应用实例
  • 【软件系统架构】系列七:嵌入式系统性能深入解析
  • 华为云中,列表中的镜像无法删除可能由多种原因导致
  • 华为云开发者空间 × DeepSeek-R1 智能融合测评:云端开发与AI客服的协同进化
  • WPF的一些基础知识学习记录
  • 设计模式 八:原型模式 (Prototype Pattern)
  • Spring Boot全局异常处理:一网打尽Controller层异常,@RestControllerAdvice解析
  • 设计模式(单例)
  • 界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?
  • Linux下SVN常用指令
  • 设计模式代码总结
  • Android MediaCodec 的使用和源码实现分析
  • 路由器与交换机的区别
  • 从入门到精通:Windows右键菜单管理全解析
  • 为什么 Linux 启动后还能升级内核?
  • Jmeter的函数助手使用
  • 基于Dapr Sidecar的微服务通信框架设计与性能优化实践
  • 【软件系统架构】系列七:物联网云平台系统性能深入解析
  • HTTP性能优化终极指南:从协议原理到企业级实践
  • 视频、音频录制
  • 操作系统:系统调用的分类(Types of System Calls)