透过 Verilog 完成一个具有特定功能的电路後,并不代表你的工作已经完成了,TestBench(tb) 在电路设计中也是一个非常重要的环节,往往验证电路所花的时间还会比较开发来的多。
而 TestBench 则是另一个 .v 档,TestBench 的工作就是产生待测模块的输入信号,用这些讯号模拟真实的情况,接着透过波型来观察输出结果是否如自己预期,如果不如预期,也可以再透过把待测电路中的各个讯号叫出来观察,以此 debug 也会比自己一直盯着程序码来除错来的有效率唷!
我们可以先来看[Day15]中的范例程序
module testFSM(
clkSys,
rst_n,
en,
out
);
/*--------localparam--------*/
localparam one = 2'd0;
localparam two = 2'd1;
localparam three = 2'd2;
localparam four = 2'd3;
/*--------ports declarations--------*/
input clkSys;
input rst_n;
input en;
output [2:0]out;
reg [2:0]out;
/*--------variables--------*/
reg [1:0]fstate;
.
.
.
.
endmodule
可以看到这个模块有三个输入,分别是 clkSys, rst_n, en,那麽我们在 testbench 那边就会需要有对应这三个讯号的 register(通常我名字会取一样),而输出则是一个 3 bit的 out,那麽对应 testbench,就会有一个 3 bit 的 wire 对应它。
再来稍微解释一下为甚麽 testbench 那边一定要模块的输入用 reg,而输出用 wire,因为 reg 属於过程性赋值(Procedural Assignment),意思是值是可以一直随心所欲变动的,而 wire 则属於连续性赋值(Continuous Assignment),通常用於连接讯号用。
所以就会有对应的这区块程序:
`timescale 10ns/1ns
module tb_testFSM();
reg clkSys;
reg rst_n;
reg en;
wire [2:0]out;
testFSM UUT(
.clkSys(clkSys),
.rst_n(rst_n),
.en(en),
.out(out)
);
先来谈谈最上面那行 timescale 10ns/1ns
timescale 是 Verilog 中的一种时间预编译指令,它用来定义模组模拟的时间单位以及时间精度。
格式长这样:
`timescale 时间单位 / 时间精度
需要注意到的是:
以上两者的数字只能是 1 or 10 or 100,而且时间单位必须大於时间精度。
以下来举个例子:
`timescale 1ns/10ps
reg clk_50M;
initial begin
clk_50M = 0;
end
always #10 clk_50M = ~clk_50M;
现在时间单位设为 1ns 那麽 #1 就会 delay 1ns,#10 则是 delay 10 个 ns,所以 delay 10 个 ns 则 clk_50M 会反向一次,所以反向两次可以得到 1 周期的 clk,所以一个 clk 总共 delay (1ns)x(delay 10 个)x(反向 2 次) = 20 ns,得到此频率为 50 MHZ。
现在回到 testBench 那个程序,宣告完 reg 以及 wire 後,剩下的就是以 by name 的方式来引用模组了。
注: TestBench 中引用的测试模块通常命名为 UUT(Unit Under Test)
再接着:
initial begin
clkSys = 0;
rst_n = 0;
en = 0;
repeat(2)@(posedge clkSys)rst_n = 0;//push rst_n
rst_n = 1;//release rst_n
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#100 $stop;
end
always #10 clkSys = ~clkSys;
endmodule
initial begin 是用於 TestBench 中初始化变数值的语法,而且 initial block 中的程序只会执行一遍,并不会像 always 一直重复执行,在 initial block 内初始化讯号後,就要开始对输入讯号的变数赋值了,而 $stop 语法则可以停止波形的模拟(否则会一直跑下去,会一直占用电脑的资源)。
Assignment/setting
Simulation/Compile test bench --->点选右侧 Test Bench.. 按钮
New...
上面两行打上 module 名称,下方选择 tb 的 .v 档并 add
接着连串的 ok ok...
tools/options
EDA Tool Options,并选择路径
Tools/Run Simulation Tool/RTL Simulation
这样好好看的波形就会出来罗!!
顺带解释一下 RTL 与 Gate-level Simulation 的差异:
RTL模拟是所谓的功能上的模拟,也就是不考虑硬体电路中实际的 delay,所有情况皆为理想,所以适合拿来纯测功能,而 Gate-level 模拟则是时序上的模拟,此时会考虑到所有的不理想因素,因此会有 delay 的情况发生,所以跑模拟的顺序都会是先跑 RTL 再跑 Gate-level。
<<: Day 16: 物件导向设计、函数式设计 (待改进中... )
>>: 110/16 - 整合Android 6到Android 11
这篇的主题是因为有朋友提到 Database vs Data warehouse 的差别,所以就开始...
CredentialsFileView 今天就来认识 CredentialsFileView 这个工...
前言 今天这篇要进入到资料视觉化 在前几篇的文章里,资料的形式多半是呈现在表格化的资料表上 为了让数...
元件介绍 Upload 是一个上传元件。帮助我们能够发布文字、图片、影片、档案到後端服务器上。 参考...
串列基本定义 串列可以储存不同的资料型态,如:整数、字串、浮点数,基本格式如下: List = [...