Verilog Testbench 编写初步
在编写Verilog程序时,一般有两部分内容是必不可少的。一个是实体程序,就是可用于综合的,能形成逻辑电路的部分,如前面介绍的由module关键字引导的具有名称,输入、输出端口以及行为、逻辑等内容构成的模块。如例1:
例1:
module add ( input [3:0] a, input [3:0] b, output [4:0] c ); assign c = a + b; endmodule
另一个就是仿真程序,主要用来对实体程序提供激励;仿真程序按步骤和时间顺序对实体程序的输入提供可能的组合,并观察输出结果是否符合预期。这种用来仿真的程序又叫仿真平台程序(testbench),简称tb。
- Testbench的简单结构
- 时间尺度定义
`timescale 1 ns / 1 ps
-
- 关键字module 引导,后跟模块名称
- 空的输入、输出(没有输入、输出)
仿真程序的输入、输出部分为空,即只有一个空括号作为占位符,如:
`timescale 1 ns / 1 ps
module tb
(
);
- 变量定义,如:
reg [3:0] ta, tb;
wire [3:0] tc;
- 仿真实体如initial ,always等过程使用。
- 实体例化,如将例1例化如下:
add add_inst ( .a (ta), .b (tb), .c (tc) );
- 仿真程序testbench的特点:
- 在仿真程序中可以使用wire,reg,integer,real, time等数据类型。
- 在实体程序中使用的任何语法结构这里都可以使用,如initial ,always,assign,模块例化等
- 在实体模块中不能参与综合的或不支持的语法结构这里也可以使用,如:延迟语句,实数,文件操作,以及专门用于观察输出结果的monitor,display等函数。
- 仿真程序可以配合工具软件一起使用,常用软件工具有 mentor graphic的modelsim , Vivado 的Xsim等。
- 仿真程序模块不参与综合,即最终不会成为实体电路的一个部分,只是用来提供仿真激励和仿真结果验证。
例2:
`timescale 1 ns / 1 ps module tb ( ); reg [3:0] ta, tb; wire [4:0] tc; initial begin ta = 0; tb = 0; #10 ta = 1; #10 ta = 2; #10 ta = 3; tb = 1; end add add_inst ( .a (ta), .b (tb), .c (tc) ); endmodule
Modelsim下的仿真波形如图1:
图 1
上面提供initial 提供的仿真更适合用于初始化,被仿真的模块在遍历仿真中由于要求所有的输入组合都能得到激励输入,因此一般用两种办法解决;第一种办法采用循环的方式,如for循环的结构在initial过程中使用;另一种办法采用always过程提供激励;在always过程中,可以使用循环结构,也可以使用时钟驱动的结构。
- 循环结构在initial 过程中的使用
例3:
`timescale 1 ns / 1 ps module tb_test ( ); reg [3:0] ta,tb; wire [4:0] tc; integer i, j; initial begin ta = 0; tb = 0; i = 0; j = 0; #10 for(i = 0; i < 16; i = i + 1) begin for(j = 0; j < 16; j = j + 1) #10 tb = tb + 1; ta = ta + 1; end end add add_inst ( .a (ta), .b (tb), .c (tc) ); endmodule
仿真结果如图2所示:
图2:
- always过程的使用
- 在always过程中,可以利用循环结构:
`timescale 1 ns / 1 ps module tb_test ( ); reg [3:0] ta,tb; wire [4:0] tc; integer i, j; initial begin ta = 0; tb = 0; i = 0; j = 0; end always@(*) begin for(i = 0; i < 16; i = i + 1) begin for(j = 0; j < 16; j = j + 1) #10 tb = tb + 1; ta = ta + 1; end end add add_inst ( .a (ta), .b (tb), .c (tc) ); endmodule
仿真结果
图3:
3.利用时钟提供仿真激励
`timescale 1 ns / 1 ps module tb_test ( ); reg CLK; initial begin CLK = 1'b0; #5; forever #5 CLK = ~CLK; end reg [3:0] ta,tb; wire [4:0] tc; //integer i, j; initial begin ta = 0; CLK = 0; tb = 0; //i = 0; //j = 0; end always@(posedge CLK) begin if(tb == 15) begin tb = 0; if(ta == 15) ta = 0; else ta = ta + 1; end else tb = tb + 1; end add add_inst ( .a (ta), .b (tb), .c (tc) ); endmodule
仿真结果如图4所示:
图4:
以上提供了几种激励实现方式,以及在modelsim下的仿真结果。更深入的应用如函数,文件操作等将会在后续课程中介绍。