【FPGA自学总结】Testbench测试代码推荐编写规范
Testbench介绍及其重作用
编写Testbench的主要目的是为了对使用硬件描述语言(HDL)设计的电路进行仿真验证,测试设计电路的功能、部分性能是否与预期的目标相符。
博主在刚开始入门FPGA时把写RTL代码当成重点,不愿写Testbench,仅仅使用Quartus II自带的仿真产生几个激励,然后观察一下最后输出的波形就完事了。有段时间甚至直接忽视仿真,拿单片机在线调试那一套来对付FPGA,直接把代码下载到板子里看效果,若与预期不符,再修改代码,再次下载到板子,如此反复,效率、效果都很低。
后来随着深入地了解,发现FPGA水很深,而且和单片机等有很大的不同。因此劝各位要管住自己、不去使用Quartus II自带的仿真。如果你立志从事FPGA行业,那么会写Testbench才你的敲门砖,才是去大厂的门票,别想着去公司写RTL代码了,公司一定是让你来写Testbench测试文件的。
Testbench作为Modelsim的激励文件,也是自成体系的,同样具有规范化的设计,需要完美的风格及苛刻的结构
本篇只讲Testbench测试代码的推荐编写规范,Modelsim仿真步骤请移步另一篇博客https://blog.csdn.net/zhaogoudan/article/details/111663758。
一个最基本的Testbench包含三个部分,信号定义、模块接口和功能代码。借用一下特权同学总结的编写Testbench的三个基本步骤:
对被测试设计的顶层接口进行例化;
给被测试设计的输入接口添加激励;
判断被测试设计的输出相应是否满足设计要求。
逐步解决编写Testbench的这三点:
对被测试设计的顶层接口进行例化
首先“对被测试设计的顶层接口进行例化”,这一步相对比较简单,就是简单的例化,但端口多时,也比较困难,而且要分wire、reg,有时会弄错。这里我推荐大家可以偷个懒,通过Quartus II自动生成一个Testbench的模板,里面会自动例化好顶层的接口。
步骤:选择Processing -> Start -> Start Test Bench Template Writer,等待完成后打开刚才生成的Testbench,默认是保存在simulation\Modelsim文件夹下的.vt格式文件。这一步就不多讲了,偷懒就挺好。
给被测试设计的输入接口添加激励
其次“给被测试设计的输入接口添加激励”,一般时序设计必然涉及到最基本的两个信号——clk、rst_n(时钟、复位)。肯定有朋友会讲可以没有rst_n,是可以没有,但让代码更丰富、更严谨没有错。下面来看看激励clk、rst_n的写法:
首先先讲一下timescale,因为想要进行仿真首先要规定时间单位,而且最好在Testbench里面统一规定时间单位,而不要在工程代码里定义,因为不同的模块如果时间单位不同可能会为仿真带来一些问题,而timescale本身对综合也就是实际电路没有影响。 `timescale 1ns/ 1ps表示仿真的单位时间为1ns,精度为1ps。
系统时钟的三种写法 :
`timescale 1ns/1ps
initialclk = 0;
always#10 clk <= ~clk;
`timescale 1ns/1ps
initial beginclk = 0;forever#10 clk = ~clk;
end
`timescale 1ns/1ps
always begin#10 clk <= 0;#10 clk <= 1;
end
上述三种代码的目的就是产生系统时钟,给clk一个初值后,不断重复执行:每10ns翻转一次clk,从而生成一个周期为20ns,频率50MHz的方波信号。第一、二种基本类似,第三种比较简单,少了一个initial,放在了always里初始化。
三种方法都无一例外地给clk赋了初值,因为信号的缺省值为Z,如果不赋初值,则反相后还是Z,时钟就一直处于高阻Z状态。
复位信号rst_n的两种写法
根据复位方式的不同,rst_n一般有两种写法:
`timescale 1ns/1ps
initial beginrst_n = 1;#100 rst_n = 0;#500 rst_n = 1;
end
//同步复位
`timescale 1ns/1ps
initial beginrst_n = 1;@(negedge clk) //等待时钟下降沿repeat(3) @(negedge clk);rst_n = 1;
end
上述两种代码的目的基本都是延时复位,但一个异步复位,一个同步复位,用途不同。
一种推荐的时钟发生器编写规范
推荐!
//clock generate moudle
initial
begin clk = 0;forever #(PERIOD/2)clk = ~clk;
end //将复位信号封装在Task(任务)当中
task task_reset;
beginrst_n = 0;repeat(2) @(negedge clk); //等待clk出现两个下降沿之后,才继续执行后续语句rst_n = 1;
end
endtask
判断被测试设计的输出相应是否满足设计要求
最后“判断被测试设计的输出相应是否满足设计要求”。首先介绍最常用的两个系统任务函数 $ stop和$ finish。$ stop代表暂停仿真后返回软件操作主窗口,将控制权交给user;$ finish代表终止仿真后关闭软件操作主窗口。其他任务函数如$ monitor、$ display 、$ time、$ fwrite等也比较重要,用到的时候再一一介绍。
RTL代码:
* All rights Reserved, Designed By https://blog.csdn.net/zhaogoudan* @projectName :led* @title : * @description :LED自加 * @author :zhaodongliang* @date :21/01/07 * @version :V1.0.0* @copyright ${YEAR} https://blog.csdn.net/zhaogoudan*/
module led(input clk,input rst_n,output reg [3:0] led_data
);//---------------------------
//Delay for 0.3s
localparam DELAY_TOP = 24'd15_000_000;
//localparam DELAY_TOP = 24'd4; //just for testreg [23:0] delay_cnt;
always @(posedge clk or negedge rst_n) beginif(!rst_n)delay_cnt <= 24'd0;else if(delay_cnt < DELAY_TOP) delay_cnt <= delay_cnt + 1'b1;elsedelay_cnt <= 24'd0;
endwire delay_done = (delay_cnt == DELAY_TOP) ? 1'b1 : 1'b0;//----------------------------
always @(posedge clk or negedge rst_n) beginif(!rst_n)led_data <= 4'd0;else if(delay_done) beginif(led_data < 4'd15)led_data <= led_data + 1'b1;elseled_data <= 4'd0;end
end
endmodule
testbench代码
`timescale 1 ns/ 1 ns
module led_vlg_tst();localparam PERIOD = 20;reg clk;
reg rst_n;
// wires
wire [3:0] led_data;// assign statements (if any)
led i1 (
// port map - connection between master ports and signals/registers .clk(clk),.led_data(led_data),.rst_n(rst_n)
);initial
begin clk = 0;forever #(PERIOD/2)clk = ~clk;
end task task_reset;
beginrst_n = 1'b0;repeat(2) @(negedge clk)rst_n = 1'b1;
end
endtask//-------------------
//systerm initialization
task task_sysinit;
begin
end
endtask//--------------------
//testbench of the RTL
initial
begintask_sysinit; //必须先进行系统初始化task_reset; //再进行复位//然后才能进行其他的激励
endendmodule
Testbench可以通过设计Task功能来实现任务的模块化编写及调用,而这些部分的目的就是为了在最后生成待测试的测试激励。
在测试激励生成的代码编写规范中,要遵守以下几点:
- 采用initial设计,生成现成的激励
- 为了可移植性,激励都通过Task编写调用
- 必须先进行系统初始化,接着进行复位,然后才能进行其他的激励
如下所示:
//testbench of the RTLinitial
begintask_sysinit; //必须先进行系统初始化task_reset; //再进行复位//然后才能进行其他的激励
end
输入
必须为reg,因为对于testbench来说输入其实是要输出给测试模块的,也就是相当于需要一个东西来存储,所以是register类型
输出
必须为wire,因为对于testbench来说输出其实是测试模块的输入,也就是需要通过wire来进行连接
—————————————————————————————————
【FPGA自学总结】Testbench测试代码推荐编写规范相关推荐
- junit编写测试代码_编写数据访问代码测试-不测试框架
junit编写测试代码 当我们向数据访问代码编写测试时,是否应该测试其公共API的每种方法? 一开始听起来很自然. 毕竟,如果我们不测试所有内容,那么如何知道我们的代码可以按预期工作? 这个问题为我们 ...
- junit编写测试代码_编写数据访问代码测试–绿色建筑不够好
junit编写测试代码 开始为数据访问代码编写集成测试之前,我们要做的第一件事是决定如何配置测试用例. 我们有两种选择:正确的一种和错误的一种. 不幸的是,许多开发人员选择错误. 我们如何避免犯同样的 ...
- 03_MyBatis基本查询,mapper文件的定义,测试代码的编写,resultMap配置返回值,sql片段配置,select标签标签中的内容介绍,配置使用二级缓存,使用别名的数据类型,条件查询ma
1 PersonTestMapper.xml中的内容如下: <?xmlversion="1.0"encoding="UTF-8"?> < ...
- Emmet:HTML/CSS代码快速编写规范(转发)
Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生.它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示: ...
- VS2010 测试功能之旅:编码的UI测试(4)-通过编写测试代码的方式“.NET研究”建立UI测试(下)...
回顾 最近比较忙,距离上次更新的时间较久,见谅. 在本章上部分,介绍了"添加用户"窗口的测试代码编写.想必大家也看到了,在UIMap.cs文件中实现自定义编码是一件很轻松的事情,接 ...
- Modelsim联合Matlab进行FPGA图像处理仿真与测试的学习总结(以RGB转Ycbcr转Gray为例)
文章目录 一.Modelsim联合Matlab进行FPGA图像仿真的步骤 二.具体实现方法 2.1 新建一个Modelsim项目并编写测试代码 2.2 新建v文件来编写待测试代码 2.3 建成项目后, ...
- 领导让我重写测试代码,我该怎么办?
我有一个朋友,有一天问我这样的一个问题:"说现在他们公司有五个 python 测试工程师.但是有一天领导要求他把所有的自动化测试代码,全部都转化成 Java 语言." 虽然说他们在 ...
- S3C6410开发板adc驱动代码分析及测试代码分析
在本文中,我们对S3C6410开发板adc驱动代码的实现过程进行分析,然后通过一个实例对adc功能进行测试.在本文的资源中包含了设备驱动的源码和测试的源码. 一.设备驱动源码分析 adc的设备驱动主要 ...
- S3C6410开发板LED驱动代码分析及测试代码分析
在本文中,我们对S3C6410开发板LED驱动代码的实现过程进行分析,然后通过一个实例对LED进行控制.在本文的资源中包含了设备驱动的源码和测试的源码. 一.设备驱动源码分析 设备驱动主要实现了模块的 ...
- S3C6410开发板按键驱动代码分析及测试代码分析
在本文中,我们对S3C6410开发板按键驱动代码的实现过程进行分析,然后通过一个实例对按键功能进行测试.在本文的资源中包含了设备驱动的源码和测试的源码. 一.设备驱动源码分析 按键的设备驱动主要实现了 ...
最新文章
- 【杂谈】为什么邀请大家加入硬核知识星球有三AI
- 1020 月饼 (25 分)(c语言)
- 王彪20162321 2016-2017-2 《程序设计与数据结构》第5周学习总结
- camvid数据集使用方法_使用PyTorch处理CIFAR10数据集并显示
- 在 Gitee 上使用 GPG公钥(Beta版)
- rabbitmq rpc
- ArcGIS Desktop10.2与CityEngine2012兼容问题
- 【图像处理算法】直方图均衡化
- Pandas实战-Series的方法
- 2019年终总结2020个人规划和目标
- licecap免费+轻量+使用简单的录屏制作gif工具
- 计算机网络基础——网络的性能
- 角度转度分秒lisp函数_自改小程序,提示错误,运行另一个lisp后就不会出错,求帮忙!...
- 图像对齐讲座—旷世成都研究院 数据策略产品经理——阿里讲座
- 开启Fluter基础之旅三-------Material Design风格组件、Cupertino风格组件、Flutter页面布局篇...
- office提示为什么要冒险的解决办法
- kettle使用过程记录(详细)
- Linux下挂载移动硬盘和USB的方法
- Concepts:Stateful Stream Processing
- 反射内存卡读写测试(RFM2gRead和RFM2gWrite)-- C++