FPGA 设计_ModelSim 仿真流程简要
1. ModelSim简介
ModelSim分几种不同的版本:SE、PE和OEM,其中集成在 Actel(爱特公司)、Altera (阿尔特拉)、Xilinx(赛灵思)以及Lattice(莱迪思)等FPGA厂商设计工具中的均是其OEM版本,SE版本为最高级版本。ModelSim仿真分为功能仿真,门级仿真,时序仿真
◆ 功能仿真(前仿真,代码仿真)
主旨在于验证电路的功能是否符合设计要求,其特点是不考虑电路门延迟与线延迟,主要是验证电路与理想情况是否一致。可综合FPGA代码是用RTL级代码语言描述的,其输入为RTL级代码与Testbench.在设计的最初阶段发现问题,可节省大量的精力。
◆ 门级仿真和时序列仿真 (后仿真)
使用综合软件综合后生成的门级网表进行仿真,不加入时延文件的仿真就是门级仿真.可以检验综合后的功能是否满足功能要求,其速度比功能仿真要慢,比时序仿真要快。
◆ 在门级仿真的基础上加入时延文件(.sdf)的仿真就是时序仿真, 比较真实地反映了逻辑的时延与功能.综合考虑电路的路径延迟与门延迟的影响,验证电路能否在一定时序条件下满足设计构想的过程,是否存在时序违规。
2. ModelSim仿真的基本步骤
首次运行modelsim时,先建立一个工作库,一般将这个工作库命名为work。后面建立的仿真工程(project)一般都是在这个work下面工作的。在用户界面模式下,点 File->New->Library,选择 a new library and a logical mapping to it,如下图所示(ModelSim SE 10),
1)建立工程,启动ModelSim,选择菜单“File New Poject”,会打开“Creat Project”对话框,在“Creat Projec”t对话框中填写“Project Name”为“Test”,然后在“Project Location”栏中选择Project文件的存储目录,保留“Default Library Name”的设置为work,在弹出的对话框中选择Add Existing File,添加已经写好的源文件及测试文件(如果没有,可选择Create New File 进行创建)。
2) 在工作区中的Project标签页中可以看到新加入的文件,单击右键,选取“Compile Compile All”命令对加入的文件进行编译
3) 文件编译完后,用鼠标点击“Library”标签栏。在标签栏中用鼠标点击work库前面的“+”,展开work库,就会看到编译好的设计单元,点击测试文件选择仿真。
4) 调出窗口(View -> Structure,View -> object,View -> Wave),在object 窗口添加观察变量,运行仿真,在Wave中查看波形。
5) 在Run_Length中选择单步运行时间;鼠标在黄线不同端,按住Ctrl,移动滑轮可调整观察波形时间
3. ModelSim断点仿真
1) 选择View > Files打开文件窗口,单击sim前的+,双击block.v打开源文件
2) 滑动到21行,在行标的右侧单击。一个红色的球出现在行标的右边表示已经设置了一个断点(此断点可进行使能或移除)。
3) 点击Run-All 运行,可见程序执行到断点处
4. 命令行执行
force指令
指令格式:force item_name value time,value time(item_name为端口信号或内部信号,支持通配符号,但只能匹配一个;value不能默认,time,可选项,支持时间单元)
force din 10#40000000 //从当前时刻起给din赋值10进制40000000; force bus 10#F @100ns //在100ns时刻给bus赋值10进制F; force clr 0 //在当前仿真时间强制clr到0 force clr 1 100 //经历100个默认时间单元延迟后为clr赋值1; force clr 1,0 100 //表示clr赋值1后,经历100个默认时间单元延迟后为clr赋值为0;
force-repeat指令
指令格式:force
开始时间 开始电平值,结束电平值 忽略时间(即0电平保持时间)
-repeat 周期
force clk 0 0,1 20 -repeat 100 //表示强制clk从0时间单元开始,起始电平为0,结束电平为1,0电平保持时间为20个默认时间单元,周期为100个默认时间单元,占空比为80%
force-cancel指令
指令格式:force-cancel
period(执行period周期时间后取消force命令)
force clk 0 0,1 30 -repeat 60-cancel 1000 //强制clk从0时间单元开始,到1000时间单元结束;
run指令
指令格式:run
timesteps time_unit(timesteps时间步长,time_unit时间单元,可以是ps、ns等)
run 10 //表示运行10个默认时间单元; run 200ns //表示运行200ns; run -all //表示运行全过程; run -continue //表示继续运行
本例代码
1 `timescale 1ns / 1ps 2 module block( 3 input clk_i, 4 input rst_n_i, 5 output reg [4:0]result_o 6 ); 7 reg [3:0]A; 8 reg [3:0]B; 9 reg [4:0]C; 10 11 always @(posedge clk_i) 12 if(!rst_n_i) 13 begin 14 #2 A = 4\'d4; 15 #0.2 B = 4\'d12; 16 #0.2 C = 5\'d0; 17 #0.2 result_o = 5\'d0; 18 end 19 else 20 begin 21 #2 C = A + B; 22 #0.2 result_o = (C >> 1); 23 end 24 endmodule
block.v
1 `timescale 1ns / 1ps //仿真时间单位/时间精度 2 module unblock 3 ( 4 input clk_i, 5 input rst_n_i, 6 output reg [4:0]result_o 7 ); 8 reg [3:0]A; 9 reg [3:0]B; 10 reg [4:0]C; 11 always @(posedge clk_i ) 12 if(!rst_n_i) 13 begin 14 #2 15 A <= 4\'d4; 16 B <= 4\'d12; 17 C <= 5\'d0; 18 result_o = 5\'d0; 19 end 20 else 21 begin 22 #2 23 C <= A + B; 24 result_o <= (C >> 1); 25 end 26 endmodule
unblock.v
1 `timescale 1ns / 1ps 2 module tb_test(); 3 reg clk_i; 4 reg rst_n_i; 5 wire[4:0]result1_o,result2_o; 6 unblock unblcok_inst 7 ( 8 .clk_i(clk_i), 9 .rst_n_i(rst_n_i), 10 .result_o(result1_o) 11 ); 12 13 block blcok_inst 14 ( 15 .clk_i(clk_i), 16 .rst_n_i(rst_n_i), 17 .result_o(result2_o) 18 ); 19 20 initial 21 begin 22 clk_i =0; 23 rst_n_i =0; 24 #22 25 rst_n_i =1; 26 end 27 28 always #5 clk_i = ~clk_i; 29 endmodule
tb_test.v