【注】本文为系列教程,使用同一个仿真代码,关注公众号“数字积木”,对话框回复“ modelsim_prj ”,即可获得。这是系列第一篇。
1,ModelSim软件介绍
Mentor 公司的 ModelSim 是工业界最优秀的语言仿真器,它支持 XP、Win7 和 Linux 系统,是单一内核支持 VHDL 和 Verilog 混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk 技术、单一内核仿真,不仅编译仿真速度业界最快、编译的代码与平台无关,而且便于保护 IP 核。它还提供了最友好的调试环境,具有个性化的图形界面和用户接口,为用户加快调试提供强有力的手段,它是 FPGA/ASIC 设计的首选仿真软件。
Modelsim 有几种不同的版本:SE(System Edition)、DE(Deluxe Edition)、PE(Personal Edition)和 OEM(Orignal Equipment Manufactuce,即原始设备制造商),其中 SE 是最高级的版本,而集成在 Actel、Atmel、Altera、Xilinx 以及 Lattice 等 FPGA 厂商设计工具中的均是OEM 版本。我们这里选择使用的是 Altera 公司提供的 OEM 版本,也就是我们常说的 ModelSim AE(即:ModelSim-Altera Edition)。下面我们给出 Altera 官方对 ModelSim AE 的介绍,如图 所示。
该图中我们可以看出,Modelsim Altera 是有两个版本的,一个是免费版本(ModelSim-Altera Starter Edition);一个是收费版本(ModelSim-Altera Edition)。由于图中给出了收费版本和免费版本的区别,所以我们就不在进一步介绍它们了,这里我们说一下,ModelSim-Altera 版软件与 ModelSim PE/DE 软件的区别,ModelSim-Altera 版软件仅支持 Altera 门级库。ModelSim-Altera 版软件包括 ModelSim PE 的基本特性,包括了行为仿真、HDL 测试台和Tcl 脚本。但是,ModelSim-Altera 版软件并不支持 ModelSim PE 的可选特性,ModelSimAltera 版的仿真性能要低于 ModelSim PE/DE 软件。
2,ModelSim使用流程
介绍完了 ModelSim 软件,接下来我们再来介绍一下 ModelSim 使用流程。在介绍 ModelSim的使用流程之前,我们需要对给大家说明一下仿真的两个概念,仿真一般分为前仿真与后仿真:(1) 前仿真也就是纯粹的功能仿真,主旨在于验证电路的功能是否符合设计要求,其特点是不考虑电路门延迟与线延迟。(2) 后仿真也就是时序仿真。是指电路已经映射到特定的工艺环境下,综合考虑电路的路径延迟与门延迟的影响,验证电路在一定时序条件下是否满足设计构想的过程。说完了仿真的两个概念,接下来我们在来说一说 ModelSim 的使用,ModelSim 的使用主要分为两种情况,第一种就是通过 Quartus II 软件调用我们的 ModelSim 来进行仿真,这种情况也就是我们通常所说的自动仿真。第二种情况就是直接打开 ModelSim 进行仿真,不经过我们的Quaruts II 软件,这种情况也就是我们通常所说的手动仿真。不管是自动仿真还是手动仿真,它们的都遵循以下 5 个步骤:
(1) 新建工程。
(2) 编写 Verilog 仿真文件。
(3) 编写 Testbench 仿真文件。
(4) 开始功能仿真。
(5) 开始时序仿真。
当我们执行了仿真以后,ModelSim 软件会根据我们的设计文件和仿真文件生成波形图,最后,我们观察波形并判断设计的代码功能是否正常。前仿真完成以后,接下来我们就需要进行后仿真了,后仿真与前仿真的步骤大体相同,只不过中间需要添加仿真库、网表和延时文件等步骤。这里我们要注意的是,对于时序要求不严格的小规模设计,我们一般只进行功能仿真。
【注】本系列教程使用的源码和testbench代码如下:
源码:
代码语言:javascript复制module Verilog_First
(
//输入端口
CLK_50M,RST_N,
//输出端口
LED1
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟的端口,开发板用的50M晶振
input RST_N; //复位的端口,低电平复位
output LED1; //对应开发板上的LED
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg [26:0] time_cnt; //用来控制LED闪烁频率的定时计数器
reg led_reg; //用来控制LED亮灭的显示寄存器
//设置定时器的时间为1s,计算方法为 (1*10^6)us / (1/50)us 50MHz为开发板晶振
//parameter SET_TIME_1S = 27'd49_999_999;
parameter SET_TIME_1S = 27'd49 ; //用于仿真
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//时序电路,实现1s的定时计数器
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
time_cnt <= 27'h0; //初始化time_cnt值
else if(time_cnt == SET_TIME_1S) //判断1s时间
time_cnt = 27'h0; //如果到达1s,定时计数器将会被清零
else
time_cnt = time_cnt 27'h1;//如果未到1s,定时计数器将会继续累加
end
//---------------------------------------------------------------------------
//时序电路,判断时间,控制LED的亮或灭
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
led_reg <= 1'b0; //初始化led_reg值
else if(time_cnt == SET_TIME_1S) //判断1s时间
led_reg = ~led_reg; //如果到达1s,显示寄存器将会改变LED的状态
else
led_reg = led_reg; //如果未到1s,显示寄存器将会将保持LED的原状态
end
assign LED1 = led_reg; //最后,将显示寄存器的值赋值给端口LED1
endmodule
testbench:
代码语言:javascript复制`timescale 1 ps/ 1 ps
module Verilog_First_vlg_tst();
reg CLK_50M;
reg RST_N;
// wires
wire LED1;
// assign statements (if any)
Verilog_First i1 (
// port map - connection between master ports and signals/registers
.CLK_50M(CLK_50M),
.LED1(LED1),
.RST_N(RST_N)
);
initial
begin
#0 CLK_50M = 1'b0;
#10000 RST_N = 1'b0;
#10000 RST_N = 1'b1;
#10000000 $stop;
end
always #10000
begin
CLK_50M = ~CLK_50M;
end
endmodule
欢迎关注,更精彩的内容等着你!