之前有一篇文章介绍过仿真测试文件编写的步骤:
1.给A模块写测试,其测试模块的模块名为A_tb,比如原模块模块名叫做led,测试模块名就叫 led_tb;
2.复制A模块的所有输入输出端口,也就是I/O声明部分(input和output信号),注意这里不包括中间变量(reg型和wire型信号);将所有的input 改为 reg, output 改为 wire;
3.再把A模块的端口定义部分复制过来,包括 模块名到分号结束,进行模块例化;
4.测试模块的意义就是模拟输入信号,来验证原模块的输出信号是否符合代码逻辑,所以在测试模块里面需要写一个initial块模拟所有的输入变量,进行赋值操作;
5.如果有时钟,需要再产生一个时钟信号;
6.最后添加时间标识。
这篇文章就详细说一下怎么做,举得例子是上一篇二选一数据选择器的例子,大家可以动手做一做。
设计背景:
测试文件在我们的项目中格外的重要,比如我们要验证你的模块的正确性难道要不停的下板来验证吗,如果你的项目小还可以,如果编译一下超过10分钟了你难道不停的等待,修改中循坏下去吗,所以如果我们可以设计出我们的测试文件,那么先验证我们的系统,如果我们的逻辑都正确了,我们就可以下班来查看,如果还不正确那么我们就可以用quartus 中的工具signaltap来捕捉我们信号来验证,这些都会在我们以后的文档中给大家说明。
设计原理:
我们的设计就是一个简单的2选一多路选择器,我们通过给这个简单的多路选择器来写测试文件,让大家对测试有一个简单的认识。
在架构中我们可以明白的看出我们设计的架构,我们的项目中有2个输入数据data_1,data_2,一个输入的选择位select,还有一个输出data_out。其实给这个架构写测试也就是激励,其实说白了就是给其写输入,当给其写好输入后,我们不就可以在仿真工具中验证其逻辑关系了。
设计架构图:
sel_1架构
总架构
设计代码:
我们写好的代码如下,大家看下,然后我们给大家讲解测试怎么写
模块
0 module sel_1(data_1, data_2, select, data_out);
1
2 input data_1, data_2; //数据输入
3 input select; //选择位
4
5 output reg data_out; //数据的输出
6
7 always @ (*)
8 begin
9 if(select) //如果选择位为高,输出data_1
10 data_out = data_1;
11 else //如果选择位为低,输出data_2
12 data_out = data_2;
13 end
14
15 endmodule
测试模块
测试的简单写法,测试中模块的输入定义为寄存器reg型,输出定义为wire型,然后加上我们的块 initial ,再加上我们的例化,如下:
0 `timescale 1ns / 1ps
1
2 module 模块名;
3
4 reg 模块输入;
5 wire 模块输出;
6
7 initial begin
8
9
10
11
12 end
13
14 模块名 例化名(
15 .端口(端口),
16 .端口(端口),
17
18 );
19
20 endmodule
在测试中我们也有许多的系统比如我们的系统任务$stop等,这些都属于语法知识了,大家可以买一本适合的书来看看,我们为我们的设计写好的激励如下:
0 `timescale 1ns / 1ps //这一行中1ns定义我们测试时的时间单位,后面的ps 是精度
1 //前面的timescale英文也就是时间量程的意思
2
3 module sel_1_tb; //module 后面跟上我们测试名字,一般我们都写成模块名
4 //加上_tb,如果我们对一个项目的多个模块写测试我们就能清楚的分清
5
6 reg data_1, data_2; //定义模块的输入输出
7 reg select; //模块中的输入定义为寄存器
8
9 wire data_out; //输出定义为wire型也就是线型
10
11 initial begin //initial 是一个串型执行的,在测试中被综合,
12 //如果你写到模块中,可是会报错的
13 data_1 = 0; //然后我们就可以定义我们的端口,给我们的端口赋初值
14 data_2 = 0;
15 select = 0;
16
17 #200 data_1 = 1; data_2 = 0; //延迟200ns给输入赋值
18 #100 select = 1; //延迟200ns后给选择位赋值
19 #100 select = 0; //延迟200ns后给选择位赋值
20
21 #200 data_1 = 0; data_2 = 1;
22 #100 select = 0;
23 #100 select = 1;
24
25 #300 $stop; //$stop 系统任务,也就是停止的意思,这句 就是延迟 300ns后,仿真停止
26 end
27
28 sel_1 sel_1_dut( //模块的例化,和端口的连接
29 .data_1(data_1),
30 .data_2(data_2),
31 .select(select),
32 .data_out(data_out)
33 );
34
35 endmodule
在测试中如果我们用到时钟了怎么办,我们可以这样写,如下
0 `timescale 1ns / 1ps
1
2 module 模块名;
3
4 reg 模块输入;
5 wire 模块输出;
6 reg clk,rst_n;
7
8 initial begin
9 clk = 1;
10 rst_n = 0;
11
12 #200.1 rst_n = 1;
13
14 end
15
16 always #10 clk = ~clk; //always 一直,这样可以写成一个 50M的时钟
17 //说的是延迟10ns翻转一次,也就是一 个周期20ns
18
19 模块名 例化名(
20 .端口(端口),
21 .端口(端口),
22
23 );
24
25 endmodule
仿真图:
在仿真中我们可以真实的看到,当数据data_1为1,data_2位0的时候,当选择位select为0的时候,输出data_out的值为0也就是data_2的值,当select为1的时候,data_out的值位1,也就是data_1的值,后面的仿真也一样我们可以清楚的看到。
以上就是对于二选一数据选择器的仿真测试文件的编写细节,大家可以动手去做一做,加油,各位。
全部0条评论
快来发表一下你的评论吧 !