1)首先新建一个文件夹,把你需要仿真的设计文本和仿真文本全部放在同一个文件夹下面,注意,文件夹路径不能包含中文。
2)打开modelsim软件,选择“File > new >project,新建一个工程,工程保存在上述所建的文件夹中,点击ok。
3)点击add existing file,选择所要仿真的文件。
4)点击编译进行文本编译找错。
5)编译无错后,选择simulate>start simulate,进行仿真。
6)选择work中文件名为xx-tb的文件(只需仿真顶层文件,其他文件不用选择)
7)进入仿真界面。点击sim中顶层文件名,右击选择 Add Wave将所要观测的信号添加到Wave窗口,为便于查找观察信号点击Wave窗口左下角,如图;
8)在Transcript窗口输入 run 5000ns,仿真开始运行,运行5000ns。(5000ns为大致所需的仿真时间)若用run-all配置低的电脑容易卡死。
9)为便于观测data中数据,点击data右击选择hex模式。
10)仿真方法
Find prvious transition(寻找前一个传输)
Find next transition(寻找后一个传输)
11)若需改动Testbench代码,在不退出Simulation的前提下,右击文件窗口中,project中需改动的文本文档选择Edit进行保存改动编译。如下图方式可方便改动和编译。(有时候会遇见.v文件打开时不用modesim自带的编辑软件打开,这是笔者采用的一种方法是选中文件,点击菜单栏project中的edit打开)也可用其他编程软件直接打开修改。
12)编译后,点击modesim右上方,如下图,进行复位,然后重新点击simulate>start simulate,进行仿真进行重新仿真
13)Testbench如下(内含语法):
/***************************************************************************
一个testbench要包含时钟信号发生器,模块的例化,系统初始化,生成系统激励;
本例还要产生一个模拟总线时序。
//mcu spi interface
input spi_cs, //Chip select enable, default:L
input spi_sck , //Data transfer clock
input spi_mosi, //Master output and slave input
input spi_miso, //Master input and slave output
***************************************************************************/
`timescale 1ns/1ns
module MCU2FPGA_SPI_TB;
//------------------------------------------
//clock generate module
reg clk; //所要仿真的接口信号都要设置成reg类型
reg rst_n;
parameter PERIOD = 10; //时钟周期我为10ns
initial //inital 执行一次
begin
clk = 0;
forever #(PERIOD/2) //每半个时钟周期翻转一次
clk = ~clk;
end
task task_reset; //类似于子函数,调用方式为task_reset(接口信号)
begin
rst_n = 0;
repeat(2) @(negedge clk); //重复两个时钟下降沿执行下一步
rst_n = 1;
end
endtask //任务函数task要有endtask
wire clk_ref = clk;
wire sys_rst_n = rst_n;
//----------------------------------------------
//the target component instantiation
reg spi_cs; //接口信号
reg spi_sck;
reg spi_mosi;
//-----------------------------------
wire rxd_flag;
wire [7:0] rxd_data;
spi_receiver u_spi_receiver
(
//global clock
.clk (clk_ref), //100MHz clock
.rst_n (sys_rst_n), //global reset
//mcu spi interface
.spi_cs (spi_cs), //Chip select enable, default:L
.spi_sck (spi_sck), //Data transfer clock
.spi_mosi (spi_mosi), //Master output and slave input
// .spi_miso (spi_miso), //Master input and slave output
//user interface
.rxd_flag (rxd_flag),
.rxd_data (rxd_data)
);
//---------------------------------------
wire txd_flag;
spi_transfer u_spi_transfer
(
//global clock
.clk (clk_ref), //100MHz clock
.rst_n (sys_rst_n), //global reset
//mcu spi interface
.spi_cs (spi_cs), //Chip select enable, default:L
.spi_sck (spi_sck), //Data transfer clock
// .spi_mosi (spi_mosi), //Master output and slave input
.spi_miso (spi_miso), //Master input and slave output
//user interface
.txd_en (rxd_flag),
.txd_data (rxd_data),
.txd_flag (txd_flag)
);
//---------------------------------------------
//mcu spi data transfer
task task_mcu_spi_txd; //spi总线时序
input [7:0] mcu_data;
begin
spi_cs = 0; #100;
spi_sck = 0; spi_mosi = mcu_data[7]; #100; spi_sck = 1; #100; //Bit[7]
spi_sck = 0; spi_mosi = mcu_data[6]; #100; spi_sck = 1; #100; //Bit[6]
spi_sck = 0; spi_mosi = mcu_data[5]; #100; spi_sck = 1; #100; //Bit[5]
spi_sck = 0; spi_mosi = mcu_data[4]; #100; spi_sck = 1; #100; //Bit[4]
spi_sck = 0; spi_mosi = mcu_data[3]; #100; spi_sck = 1; #100; //Bit[3]
spi_sck = 0; spi_mosi = mcu_data[2]; #100; spi_sck = 1; #100; //Bit[2]
spi_sck = 0; spi_mosi = mcu_data[1]; #100; spi_sck = 1; #100; //Bit[1]
spi_sck = 0; spi_mosi = mcu_data[0]; #100; spi_sck = 1; #100; //Bit[0]
spi_cs = 1; spi_sck = 0; #100;
end
endtask
//---------------------------------------------
//system initialization
task task_sysinit; //spi总线时序chushihua
begin
spi_cs = 1;
spi_sck = 0;
spi_mosi = 0;
end
endtask
//---------------------------------------
//testbench of the RTL
initial //生成系统激励
begin //多个inital文件可以并行执行
task_sysinit;
task_reset;
#100;
task_mcu_spi_txd(8'h95);
#100;
task_mcu_spi_txd(8'hbe);
#100;
task_mcu_spi_txd(8'hab);
end
endmodule