前言 :
人生不如意十之八九,调试代码也是如此,对题意理解的偏差、语法错误亦或是单纯的粗心都可能导致失败。在一次次的编译(compile)中,我们固然可以将 bug 逐个消除,但这只保证了程序的可运行性,并不能确保实物的正确性,就还需要映射到开发板上加以验证。对于简单程序,直接下载至开发板来实物验证并不困难,但对于复杂电路则不现实,这时引入验证语言仿真自然就非常必要了。
对于大型电路的验证过程会非常复杂,甚至在行业内具体划分出设计工程师和验证工程师来针对性工作,不过对于简单电路的仿真工作则轻松简单很多,在这个系列中只针对简单电路的仿真工作。在后续的开发中会使用 Questasim 软件为仿真平台,相关的下载流程可在网上查找。
知识点 :
仿真是对电路模块进行动态的全面测试。通过观察测试模块的输出信号是否符合要求,可以调试和验证逻辑系统的设计和结构准确与否,并发现问题及时修改。
编写 testbench (仍然是用 Verilog 语言编写)的目的是为了对使用硬件描述语言设计的电路进行仿真验证,测试设计电路的功能、性能与设计的预期是否相符。通常,编写测试文件主要过程如下:
产生模拟激励(波形);
将产生的激励加入到被测试模块中并观察其响应;
将输出响应与期望值相比较。
当然更为复杂的设计,激励部分也会更加复杂。根据自己的验证需求,选择是否需要自校验和停止仿真部分。
在 testbench 代码中的变量设置需要与待检测代码中变量保持一致,但变量类型发生了改变! 可以记为颠倒过来,待测代码中 input 为 wire 类型,output 为 reg 类型(也可以为 wire,但方便对比,设置为 reg),因为 output 往往需要存储下来以供他用;但 testbench 代码中 input 必须为 reg,output 为 wire,因为作为激励的 input,将会受到各种操作(下文详述),故要能将这些操作“记下来”,而此时的 output 就显得不那么重要,过客而已。
Testbench 中对于 input 的各种操作包含但不局限于设置初始量、生成波形激励、延时赋值等,下面将会介绍几个必须要掌握的操作:
语句 initial:
正如其名,此语句用来对变量赋初值,即初始化,注意:此初始化并不占用任何仿真时间! 在 0 ns 时间内,即可完成初始化(仿真时间即仿真中的延时非常重要),且一个程序中可以含有多个 initial 语句,它们是并行的(实际上这是 Verilog 语言的特点,在没有延时操作的情况下,所有模块都是并行运行的),但是 initial 在整个仿真中只运行一次,即初始时刻。如果 initial 内含有多个语句,则需要用 begin 起,end 做结尾,比如同时初始化 A=1,B=2,C=3:
initial
begin
A=1'd1;
B=1'd2;
C=1'd3
end
#
符号:
延时符号,在希望掩饰的语句前增加 # xxx
,即执行将该语句延时 xxx 时刻,但需注意延时的参照量是上一个语句的执行时刻。
时钟生成:
一般此用于时钟周期信号的产生,在针对时序逻辑电路的仿真是绕不开的任务。
在测试时钟生成中,上文的 initial 不可缺少,需要用它来为时钟赋初值,并通常采用取反实现,代码如下:
initial clk = 0 ;
always #(T/2) clk = ~clk;
`timescale
命令:
`timescale
用来说明跟在该命令后的模块的时间单位与时间精度。并且在一个 testbench 中可以多次使用 `timescale
,每一次使用都是对其和下一个 `timescale
之间模块们的描述(如果没有下一个,则是对剩下所有的模块),它的书写格式如下:
`timescale <时间单位>/<时间精度>`
(<>符号在正式代码的书写中并不需要写),在 `timescale
中,说明时间单位和时间精度的数字必须为整数。可以形象理解为,此时钟在走路,每一步的步长是规定死的,即时间单位,但是每一步总归有一些误差,那么在此范围误差内可以认为是走一步或者没走,那这个误差范围即时间精度。
`include `
命令:
此命令为“文件包含”处理,实现了在当前文件中调用另一个源文件的全部内容,在 testbench 的模块例化中可以使用,当然也可以不用此命令,直接在仿真时,将需要调用的文件和 testbench 文件放在同一个 project 也能实现该目标。
这一代码在VS code与Icarus Verilog的联动仿真中需要使用。VS code与Icarus Verilog联动
上述的几种操作是编写 testbench 的必备手段,可以实现基础的仿真,根据题目的难度和仿真的要求,我们还可以再进一步地使用更多有趣的命令来优化 testbench。更多的命令操作以及在仿真软件上具体的操作将争取在之后的实例仿真中一一演示。
温习 tips:
- 更多命令的学习“调试用系统任务和常用编译预处理语句”——《Verilog 数字系统设计教程·第四版·夏宇闻》第七章 P 100
- 更多相关总结 基于SparkRoad的《Verilog数字系统设计教程·第三版(夏宇闻)》学习(8)——第7章 - 江左子固 - 博客园 (cnblogs.com)
- Hdlbits 上的 Testbench 练习,因为网站是放在最后的,所以涉及了许多其他知识,所以先列出答案,以后再说基于SparkRoad的Hdlbits学习(12) - VeriMake