ASIC-WORLD Verilog(10)编写测试脚本Testbench的艺术

news2024/12/24 3:15:35

写在前面

        在自己准备写一些简单的verilog教程之前,参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。

        这是网站原文:Verilog Tutorial

        这是系列导航:Verilog教程系列文章导航


        编写Testbench(测试平台/测试脚本)和编写 RTL 代码一样复杂。随着如今ASIC 变得越来越复杂,验证ASIC的功能和性能已成为一项艰巨的挑战。通常情况下,ASIC项目开发所需的时间有 60~70% 都花在验证/确认/测试上。尽管上述事实为大多数 ASIC 工程师所熟知,但仍有工程师认为验证没有什么技术含量。

        在你开始编写Testbench之前,最重要的是要编写“被测设计(design under test,DUT)”的设计规范(design specification)。你需要清楚地理解设计规范并制定与之匹配的测试计划,该计划要详细规划测试平台的架构和测试场景(测试用例)。

        接下来,我们以一个简单的 4 位递增计数器的验证作为例子。该计数器会在使能信号(enable)为高电平时递增,并在同步复位信号(reset)为高电平时重置为零。


module counter (clk, reset, enable, count);

input clk, reset, enable;
output [3:0] count;
reg [3:0] count;                                   

always @ (posedge clk)
if (reset == 1'b1) begin
  count <= 0;
end else if ( enable == 1'b1) begin
  count <= count + 1;
end

endmodule  

测试计划(Test Plan

        接下来,我们将编写一个自检式的测试脚本。为了帮助您更好地理解自动化测试脚本的概念,我们将分步骤进行。测试脚本的框架类似下图。

        被测设计DUT (计数器)将在测试脚本中被例化,测试脚本包含一个时钟生成器(clock gen)、复位信号生成逻辑(reset logic)、使能信号逻辑生成逻辑(enable logic)和监控/比较逻辑(monitor/checker)。该测试脚本将计算计数器的预期计数值并将其与计数器的实际输出进行比较,以验证被测设计的功能是否满足设计预期。

测试用例(Test Cases

  • 复位信号测试(Reset Test):我们先取消复位信号,然后在数个时钟后重置复位信号,看看计数器是否将其输出设置为零。
  • 使能信号测试(Enable Test):使能信号有效/使能信号无效。
  • 复位信号和使能信号的随机的有效/无效(Random Assert/deassert of enable and reset)。

        我们可以添加更多的测试用例,但我们的重心不是来测试计数器,而是来学习如何编写测试脚本的。

编写测试台(Writing a TestBench

        任何测试脚本创建的第一步都是构建一个伪模板(dummy template),该模板基本上将被测设计DUT 的输入声明为 reg,输出声明为 wire,然后再实例化 DUT,如下面的代码所示。请注意,测试脚本没有端口列表。

最基本的测试脚本

module counter_tb;
  reg clk, reset, enable; 
  wire [3:0] count; 
    
  counter U0 ( 
  .clk    (clk), 
  .reset  (reset), 
  .enable (enable), 
  .count  (count) 
  ); 
    
endmodule 

        下一步是添加时钟生成器逻辑:这很好简单,因为我们知道如何生成时钟。在我们添加时钟发生器之前,我们需要将 DUT 的所有输入驱动到某个已知状态,如下面的代码所示。

带时钟生成逻辑的测试脚本

module counter_tb; 
  reg clk, reset, enable; 
  wire [3:0] count; 
    
  counter U0 ( 
  .clk    (clk), 
  .reset  (reset), 
  .enable (enable), 
  .count  (count) 
  ); 
    
  initial 
  begin 
    clk = 0; 
    reset = 0; 
    enable = 0; 
  end 
    
  always 
    #5 clk = !clk; 
    
endmodule 

          

        Verilog 中的initial block(初始块)只会执行一次,因此模拟工具会将 clk、reset 和 enable 的值置为 0;通过查看计数器代码可以发现驱动 0 会使这些信号失效。
        生成时钟的方法有很多种:可以在initial 块内使用foever循环作为上述代码的替代方法。您还可以添加参数或使用 `define 来控制时钟频率。你可能会写一个复杂的时钟发生器,我们可以在其中引入 PPM(百万分之一,时钟宽度漂移),然后控制占空比。

添加复位逻辑

        一旦我们有了基本的逻辑后,即可添加复位逻辑。如果我们查看测试用例,就会发现我们添加了一个约束条件 -- 在仿真期间应该可以随时激活复位。为实现这一目标,我们有很多方法。Verilog 中有一种叫做“事件(events)”的东西:事件可以被触发,也可以被监控,以查看事件是否发生。

        让我们用等待触发事件“reset_trigger”的方式编写我们的复位逻辑:当此事件发生时,复位逻辑在时钟的下降沿有效复位信号并在下一个下降沿无效复位信号,如下面的代码所示。此外,在无效复位后,复位逻辑会触发另一个名为“reset_done_trigger”的事件。然后可以在测试台的其他地方使用此触发事件进行同步。   

event reset_trigger; 
  event  reset_done_trigger; 
    
  initial begin 
    forever begin 
      @ (reset_trigger); 
      @ (negedge clk); 
      reset = 1; 
      @ (negedge clk); 
      reset = 0; 
      -> reset_done_trigger; 
    end 
  end

          
添加测试用例逻辑

        接下来,让我们添加逻辑来生成测试用例。

  • 复位信号测试(Reset Test):我们先取消复位信号,然后在数个时钟后重置复位信号,看看计数器是否将其输出设置为零。
  • 使能信号测试(Enable Test):使能信号有效/使能信号无效。
  • 复位信号和使能信号的随机的有效/无效(Random Assert/deassert of enable and reset)。

        重复一遍:编写测试用例“有很多种方法”,这完全取决于设计者的创造力。让我们采用一种简单的方法,然后慢慢地构建它。

测试用例 1 -- 有效/无效复位信号

        在这个测试用例中,我们将在 10 个仿真时间单位后触发事件 reset_trigger(即使复位信号有效再无效)。

 initial  
   begin: TEST_CASE 
      #10  -> reset_trigger; 
   end

测试用例 2 -- 在复位后,有效/无效使能信号

        在这个测试用例中,我们将触发复位逻辑并等待复位逻辑完成,然后将使能信号有效,并在10个时钟下降沿后将使能信号无效。

 initial  
  begin: TEST_CASE 
    #10 -> reset_trigger; 
    @ (reset_done_trigger); 
    @ (negedge clk); 
    enable = 1; 
    repeat (10) begin 
      @ (negedge clk); 
    end 
    enable = 0; 
  end  


测试用例 3 -- 随机地有效/无效复位信号和使能信号

        在这个测试用例中,我们将触发复位逻辑并等待复位逻辑完成,然后随机地有效/无效复位信号和使能信号。

 initial  
  begin : TEST_CASE 
    #10 -> reset_trigger; 
    @ (reset_done_trigger); 
    fork  
      repeat (10) begin 
         @ (negedge clk); 
        enable = $random; 
      end	
      repeat (10) begin 
        @ (negedge clk); 
        reset = $random; 
      end 
    join 
  end 


        好吧,你可能会问,这三个测试用例是否都存在于同一个文件中?答案是否定的。如果我们将这三个测试用例放在通一个文件中,那么由于三个initial块都会驱动复位信号和使能信号,就会导致出现竞争条件。所以通常情况下,测试用例会单独编写,然后使用“include”指令将其包含在测试脚本中。

        如果仔细观察这三个测试用例,你就会发现即使测试用例执行未完成,仿真也会终止。为了更好地控制,我们可以做的是添加一个“terminate_sim”的事件,只有在触发该事件时才执行$finish(结束仿真)。我们可以在测试用例执行结束时触发此事件。$finish 的代码现在可能如下所示。

  event terminate_sim;  
  initial begin  
  @ (terminate_sim); 
    #5 $finish; 
  end 

添加比较逻辑(自检)

        要使任何测试脚本自检/自动化,首先需要设计一个在功能上模仿 DUT 的模型。在我们的示例中很容易,因为我们的DUT很简单。但如果 DUT 很复杂,那么模仿它就会非常复杂,并且需要大量创新技术才能进行自检。

reg [3:0] count_compare; 

always @ (posedge clk) 
if (reset == 1'b1) begin
  count_compare <= 0; 
end else if ( enable == 1'b1) begin
  count_compare <= count_compare + 1; 
end

        一旦我们有了模拟 DUT 功能的逻辑,就需要添加检查逻辑,它会不断检查预期值与实际值的偏差。每当出现错误时,它都会打印出预期值和实际值,并通过触发事件“terminate_sim”来终止模拟。

        现在我们已经准备好了所有逻辑,我们也可以删除 $display 和 $monitor,因为测试脚本已经实现了自检化,并不需要手动验证输入和输出。你尝试更改 count_compare = count_compare +2,看看比较逻辑是如何工作的。这只是查看我们的测试平台是否稳定的另一种方式。

always @ (posedge clk) 
  if (count_compare != count) begin 
    $display ("DUT Error at time %d", $time); 
    $display (" Expected value %d, Got Value %d", count_compare, count); 
    #5 -> terminate_sim; 
  end 

  •  📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/610460.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

干货!来自北大、KAUST、斯坦福、达摩院的大模型前沿动态:表格推理、代码生成、MiniGPT-4、生成式推理...

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; ChatGPT的发布使得国内外众多的研究机构掀起了一股AI热潮&#xff0c;而这也进一步推动了人们对大语言模型的深入研究。2023年4月26日&#xff0c;AI TIME举办的大模型专场四活动邀请了阿里巴巴达摩院NLP研究员…

在 IDEA 中配置 JavaFX 11

因为从 Java8/openjdk 之后&#xff0c;javafx 从 jdk 中移除&#xff0c;如果进行 JavaFX 开发需要在 module 中添加 lib&#xff0c;并对 IDE 进行配置&#xff0c;确保 jdk 可以与 javafx 正常调用。 javafx 下载路径&#xff0c;主页网址&#xff1a;https://openjfx.io/ …

开发实践|程序员是如何刷抖音、玩快手、看头条进行赚米的?

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1a;[ https://www.weiyigeek.top ] 博客&…

【计算机组成原理与体系结构】数据的表示与运算

目录 一、进位计数制 二、信息编码 三、定点数数据表示 四、校验码 五、定点数补码加减运算 六、标志位的生成 七、定点数的移位运算 八、定点数的乘除运算 九、浮点数的表示 十、浮点数的运算 一、进位计数制 整数部分&#xff1a; 二进制、八进制、十六进制 --…

穿越认知峡谷

十年前&#xff0c;2013 年的这个时候&#xff0c;“互联网思维”在国内大火。我没有认真研究过这件事的来龙去脉&#xff0c;不过印象里 2012 年底《罗辑思维》视频栏目的开播&#xff0c;以及差不多同时小米手机的爆发&#xff0c;对“互联网思维”的大流行应该是起了重要的推…

【ABAP】数据类型(一)「数据类型概要及分类」

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后端的开发语言A…

Nginx正则表达式、location、rewrite

目录 一、常用的Nginx正则表达式 二&#xff1a;localtion 1、location 分类 2、 location 常用的匹配规则 3、location 优先级 4、 location 示例 5、优先级总结 6、实际网站使用中&#xff0c;至少有三个匹配规则定义 &#xff08;1&#xff09;第一个必选规则 &…

深入理解设计原则之接口隔离原则(ISP)【软件架构设计】

系列文章目录 C高性能优化编程系列 深入理解软件架构设计系列 深入理解设计模式系列 高级C并发线程编程 LSP&#xff1a;接口隔离原则 系列文章目录1、接口隔离原则的定义和解读2、案例解读3、如何判断一个接口是否符合接口隔离原则&#xff1f;小结 1、接口隔离原则的定义和…

CVPR 2023 医学图像分割论文大盘点

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【医学图像分割】微信交流群 被催了很久&#xff0c;CVer 正式开启 CVPR 2023 论文大盘点系列&#xff01;Amusi 一共搜集了13篇医学图像分割论文&#xff0c;这应该是目前各…

HTML 5中的文件处理之FileAPI

在众多HTML5规范中&#xff0c;有一部分规范是跟文件处理有关的&#xff0c;在早期的浏览器技术中&#xff0c;处理小量字符串是js最擅 长的处理之一。但文件处理&#xff0c;尤其是二进制文件处理&#xff0c;一直是个空白。在一些情况下&#xff0c;我们不得不通过Flash/Acti…

GPT国内的一些产品真的比国外的差吗?(篇幅较长,请收藏)

关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 计算机视觉研究院专栏 作者&#xff1a;Edison_G 本次讨论的话题仅限于计算机视觉研究院个人观点&#xff0c;若有说的不对的地方勿喷&#xff0c;有…

k8s之docker-扩展知识(八)

一.Docker的应用场景 Web 应用的自动化打包和发布。 自动化测试和持续集成、发布。 在服务型环境中部署和调整数据库或其他的后台应用。 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。 二.Docker 的优点 Docker 是一个用于开发&#…

【ChatGPT】Mr. Ranedeer:可定制个性化学习体验的 GPT-4 AI 导师提示

Mr. Ranedeer AI Tutor是一个可定制的提示&#xff0c;为具有不同需求和兴趣的用户提供个性化的学习体验。它使用GPT-4来释放AI的潜力&#xff0c;并允许您调整知识深度以匹配您的学习需求&#xff0c;自定义学习风格&#xff0c;沟通类型&#xff0c;语气和推理框架 。 当您使…

ISO21434 组织网络安全管理(二)

目录 一、概述 二、目标 三、输入 3.1 先决条件 3.2 进一步支持信息 四、要求和建议 4.1 网络安全治理 4.2 网络安全文化 4.3 信息共享 4.4 管理系统 4.5 工具管理 4.6 信息安全管理 4.7 组织网络安全审计 五、输出 一、概述 为了实现网络安全工程&#xff0c;该…

自动驾驶TPM技术杂谈 ———— 车辆分类

文章目录 机动车规格机动车结构机动车使用性质机动车和挂车分类接近角定义离去角定义纵向通过角定义离地间隙定义前后轴之间的离地间隙轴下离地间隙 机动车规格 机动车规格分类 分类 说明 汽车 载客汽车 大型 车长大于或等于 6000mm 或者乘坐人数大于或等于20 人的载客汽车。 …

【微信小程序开发】第 4 节 - 创建小程序项目

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、点击 “加号” 按钮 3、项目创建完成 4、在模拟器上查看项目效果 5、在真机上预览项目效果 6、主页面的 5 个组…

安卓调试|一文归纳总结adb调试工具常规命令

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1a;[ https://www.weiyigeek.top ] 博客&…

FPGA PAL视频BT656解码Video Processing Subsystem去隔行工程源码 TW2867采集4路视频拼接输出 提供技术支持

目录 1、前言2、我这里已有的PAL视频解码方案3、模拟视频概述4、模拟视频颜色空间5、逐行与隔行6、BT656数据与解码BT656数据格式BT656数据解码 7、TW2867芯片解读与配置TW2867芯片解读TW2867芯片配置TW2867时序分析 8、设计思路与框架9、vivado工程详解Block Design设计SDK设计…

chatgpt赋能python:Python奇偶数求和方法详解

Python奇偶数求和方法详解 在日常的编程开发中&#xff0c;经常需要对数字进行分类求和&#xff0c;其中“奇偶数求和”更是最常见的问题之一。而Python作为一种高效、可靠的编程语言&#xff0c;其在求解奇偶数的优秀性能备受瞩目。接下来本篇文章将详细介绍Python奇偶数求和…

Redis为什么会这么快?Redis到底有多快?

文章目录 一、redis到底有多快&#xff1f;二、redis为什么这么快1、内存存储&#xff08;1&#xff09;虚拟存储器&#xff08;虚拟内存Virtual Memory&#xff09;&#xff08;2&#xff09;用户空间和内核空间 2、单线程&#xff08;1&#xff09;进程切换&#xff08;上下文…