代码编织梦想

SYNOPSYS—SystemVerilog入门实验1


前言

该系列实验分为6大部分,每部分都会尽可能地还原我在每个实验中的思路与步骤,旨在记录我在学习SV验证道路上的点点滴滴,同时也希望能与众多志同道合的兄弟们多多交流在学习验证过程中遇到的问题,共同进步,大家加油。


一、验证平台(环境)的透明度

在搭建"测试平台(Testbench)"之前,首先要先确定拿到手项目验证的透明度。
可以按照激励的生成方式和检查的功能点分布将验证划分为三种基本方式:

  • 黑盒验证
    如果验证人员对DUT(Device Under Tset—待验证设计)的内部逻辑缺乏了解,黑盒验证无疑是一种合适的方式,因为验证环境只需要将激励给入设计的外部输入接口,检查设计的输出足矣,其判断的标准为根据一个输入是否能够得到一个正确的输出即可,而测试平台本身不会去关注设计内部具体的逻辑细节。但由此引发而来的问题包括:1.若测试失败则无法直接定位问题来源 验证人员只能判断测试结果是否成功,无法进一步定位到缺陷所在的位置进而与设计师不能很好的协作 2.难以发现一些较深的缺陷 验证人员无法通过设计代码给出更苛刻的随机约束从而定向地生成一些激励,而且这对后面的功能覆盖率收集也造成了不小的麻烦。

  • 白盒验证
    验证人员同设计人员一样,对设计内部的逻辑、信号等十分了解,测试失败时能够逐级追踪信号从而准确定位问题,另一方面也能结合设计需求文档检查设计内部的完整性。但白盒验证往往容易1.忽略设计整体的功能测试若甲方提供的设计需求文档描述的有缺陷,我们较难发现设计本身违规的错误 2.设计发现版本更新时,测试平台的维护较麻烦 白盒验证的测试用例通常是从设计内部细节提取的,例如某寄存器在某些条件下处于某些数值之类。这对于后期接手的工程师来说无疑是巨大麻烦,因此白盒测试的低复用性的缺点就显现出来了。

  • 灰盒验证
    个人认为,灰盒验证是目前验证领域使用最多的一种验证方式(黑盒与白盒的结合),也是笔者在入行以来唯一正在使用的验证方式,此种验证方式不仅能够弥补白盒测试对于整体功能验证的较低的把握程度,而且也能够将设计里的重点内部逻辑进行着重测试,yyds!

就拿目前Synopsys公司的这个小实验来说,旨熟悉基于SV的整套验证流程,因此采用黑盒验证的方式

二、测试平台(环境)结构

什么是测试平台?

1. 对DUT创建测试序列
2. 观察DUT的输入输出
3. 对DUT的输出数据与预期数据进行对比
4. 报告检查结果(对比相同PASS,否则FAIL)

1. 通用验证结构

Stimulator(激励发生器):它也被称为drive(驱动器),主要负责模拟与DUT的接口协议。其可分为两部分:1)initiator 主动发起接口数据传输;2)responder 对接口的数据发送请求做出响应,而它本身不会主动发送数据。
Monitor(监视器):观察DUT的边界或者内部信号,并且经过打包整理传送给其他验证平台的组件。
Checker(比较器):缓存各个monitor收集到的数据,通过数据比较的方法,检查实际收集到的DUT输出端接口数据是否同期望数据保持一致。

2. 针对该实验的验证结构

如下图所示,其整体验证结构同样也是基于通用验证结构搭建而成:
在这里插入图片描述

Stimulator(激励发生器) 对应Configure、Generator、Transactor、Driver四部分;
Monitor(监视器) 对应Monitor;
Checker(比较器) 对应Self Check。
搞清楚这些之后,接下来会对其中每个部件进行详细说明,首先我们先从interface、Test program、Top level harness file三大部分进行搭建。

三、组件说明

1. interface

该设计实现的具体功能为:某个具有16输入与16输出功能的路由器,其中任意输入可以对应任意输出。由于该实验我们采用的方法为黑盒测试,因此原设计的具体代码不做粘贴,只需知道输入输出端口即可。
创建一个名为router_io.sv的文件,以下为该文件中所有代码,这部分代码也可称为接口(interface)部分的代码:

`timescale 1ns/100ps
//---one--
interface router_io(input bit clock);
  logic			reset_n	;
  logic [15:0]	din		;
  logic [15:0]	frame_n	;
  logic [15:0]	valid_n	;
  logic [15:0]	dout	;
  logic [15:0]	valido_n;
  logic [15:0]	busy_n	;
  logic [15:0]	frameo_n
//---two---
		clocking cb @(posedge clock);
		//input  #1ns:采样时间相对时钟上升沿提前1ns
		//output #1ns:驱动时间相对时钟上升沿推后1ns		
		default input #1ns output #1ns;
				output 	reset_n	;
				output 	din		;
				output	frame_n	;
				output	valid_n	;
				input	dout	;
				input	valido_n;
				input	busy_n	;
				input	frameo_n;
		endclocking: cb
//---three---
		modport	TB(clocking cb,output reset_n);
endinterface: router_io

代码分析: one: 该部分代码中描述了该设计与外部连接的所有接口,该部分接口都是异步且没有方向的,之所以使用“logic”(四值逻辑)而非“bit”(二值逻辑)来定义信号的数据类型,是因为在SV中规定跟硬件所有连接的信号都应该为四值逻辑,我们可以直接使用logic来达到通用的存储硬件数据的目的。two: 我们需声明一个由时钟上升沿所驱动的时钟模块,简称cb。目的是采样和驱动DUT的信号,其中接口的方向应在此处被说明,需注意此时信号的方向应与DUT设计中定义的信号方向相反(若din信号相对于DUT为输入,则相对于时钟模块应为输出)。default input #1ns output #1ns 此句根据具体情况增添或删除,代表含义已注释在代码块中。three: 需创建modport用来连接测试代码,在它的参数列表中,应该引用之前创建的时钟模块与所有可能会用到的异步信号。


2. Test program

创建一个名为test.sv的文件,在这个文件中,声明一个带有参数的测试程序块,它连接到接口中的modport TB:

`timescale 1ns/100ps
	program automatic test(router_io.TB router_io);
	endprogram: test

代码分析: program中所有模块若要做驱动,必须经过modport,并且定义一个插口router_io。

个人拙见:时钟信号与复位信号是采样/驱动DUT的前提。在该文件中,需先将DUT的输入信号在复位阶段的状态进行重置,因此输入信号相对于复位与时钟之间的时序关系显得尤为重要,提供的时序图如下所示:
在这里插入图片描述
从上图可以看出:复位信号reset_n与frame_n信号均是相对与时钟的上升沿进行电平跳转,因此必须连接至由时钟上升沿所驱动的时钟模块(cb)中;复位信号reset_n与frame_n在第二个时钟上升沿时,分别为0与1,经2ns后,复位信号reset_n由低电平“0”跳转到高电平“1”;并在复位信号reset_n之后的15个时钟周期frame_n信号由高电平“1”跳转到低电平“0”。由于valid_n未在上图绘制出,先暂且认为valid_n复位前后始终为高电平“1”。代码如下:

`timescale 1ns/100ps
program automatic test(router_io.TB router_io);
	initial begin
	//----创建一个vcd+dump文件来产生可见波形
		// $vcdpluson;
		reset();
	end
	task reset();
			router_io.reset_n 		= 1'b0	;  //异步
			router_io.cb.frame_n 	<= '1	;  //同步
			router_io.cb.valid_n 	<= '1	;	//同步	
		#2 	router_io.cb.reset_n 	<= 1'b1	;   //同步
		repeat(15) @(router_io.cb);
			router_io.cb.frame_n 	<= 1'b0	;
	endtask: reset
endprogram: test

3. Top level harness file

创建一个名为router_test_top.sv的文件,其作用是将DUT接口实例化与验证环境相连接,同时生成DUT所需时钟,代码如下:

`timescale 1ns/100ps
//---one--
`include "router_io.sv"
module router_test_top;
//---two--
  parameter simulation_cycle = 100;
  bit SystemClock;
//---three---
	test t(top_io);
//---four---
  initial begin
	$timeformat(-9, 1, "ns", 10)
    SystemClock = 0;
    forever begin
      #(simulation_cycle/2)
        SystemClock = ~SystemClock;
    end
  end
//---five---
	router_io top_io(SystemClock); 
//---six---   
router dut(
    .reset_n	(top_io.reset_n),
    .clock		(top_io.clock),
    .din		(top_io.din),
    .frame_n	(top_io.frame_n),
    .valid_n	(top_io.valid_n),
    .dout		(top_io.dout),
    .valido_n	(top_io.valido_n),
    .busy_n		(top_io.busy_n),
    .frameo_n	(top_io.frameo_n)
  );
endmodule

代码分析: one: router_io.sv中所有的内容放到该文件中 two: 需定义系统时钟周期与系统时钟信号 three: 为了使test.sv与 router_test_top.sv 连接起来,我们需将test.sv在router_test_top.sv 中的例化t与router_io.sv(接口)在router_test_top.sv 中的例化top_io相连接 four: 生成DUT所需时钟SystemClock
Tip:($timeformat( Units, Precision, Suffix, MinFieldWidth )
1.Unit 是 0 到-15 之间的整数值,表示打印的时间的单位:0 表示秒,-3 表示毫秒,-6 表示微秒。-9 表示毫微秒; -12 表示微微秒; -15 表示毫微微秒;中间值也可以使用:例如-10表示100ps单位。
2.Precision 是在小数点后面要打印的小数位数。
3.Suffix 是在时间值后面打印的一个字符串。
4.MinFieldWidth 是打印的最小数量字符,包括前面的空格。如果要求更多字符,那么打印的字符更多。
five: 实例化系统时钟 six: 将DUT与验证环境的顶层连接起来(例化)。


四、总结

至此,整个测试平台的结构已经初步形成,通过接下来一步步的添砖加瓦与不断完善,最后,将会构建起一个基于SV的完整验证平台,大家继续努力,针对仿真(QuestaSim)部分,后续会继续更新,感谢大家支持。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42493102/article/details/120978815

【systemverilog】对小数的处理_lbt_dvshare的博客-爱代码爱编程_systemverilog 小数

在sv/verilog中,我们常用的是整数(int, longint),小数可以用(real),对小数的处理大致分为三种: 1. 四舍五入 2. 向上取整 3. 向下取整 这三种如何实现呢? 1.四舍五入        如果除数和被除数均为整数,可以通过乘以1.0来实现          i.e.  164*8*1.0/28 =47 bit

【system verilog】并发断言SVA bind RTL module的几种方式-爱代码爱编程

前言 https://blog.csdn.net/moon9999/article/details/97982140 学会了写断言还要学会将断言bind到环境中,因此总结归纳下bind sva_module到RTL上的方式; 正文开启 并发断言SVA的组织形式一般是,把断言组织在一个module中,之后将这个sva_module bind在对应的r

SystemVerilog的一个简单验证demo-爱代码爱编程

文后阅读原文附本文所有代码。 DUT:     是一个简单的memory。就六个信号,时钟信号clk,复位信号reset(高有效),读使能信号rd_en,写使能信号wr_en,写数据信号wdata,读数据信号rdata。     对于写操作:         address, wr_en和wdata 在同一时钟进行驱动。     对于读操作

synopsys svtb lab1:SystemVerilog Verification Flow-爱代码爱编程

前言: 这是路科的V0课程实验,就是路桑所说的“把大象装进冰箱里”,其实就是Synopsys公司的SV testbench lab(有英文的pdf,要是有这样的指导,就可以对sv验证有个清晰的感知了),如果需要pdf文档,去eetop下载,或者进企鹅群:11427一七989下载。  设计模块介绍 实验中的待测试模块(DUT)是一个16输入,16输出的

systemverilog实验之随机数验证-爱代码爱编程

1.简述 随机化验证在数字ic验证中十分重要,使用频率也比较高。为了比较直观地地使用随机数,我结合小工程来学习; 2.被测试代码 我以38译码器代码为例,做随机化验证,下面是源码: module decoder_38( //clk & rst input clk ,

System Verilog学习小结-爱代码爱编程

System Verilog课程小结 第一周 问题1:设计人员和验证人员他们的协作关系体现在哪些地方? 1.设计人员和验证人员都需要围绕功能描述文档开展工作 2.设计只有经过充分量化验证,才有信心去流片 3.验证人员需要懂设计才能很好地向设计人员反馈设计漏洞 4.设计初步实现后即需要验证工作的加入 5.在系统由低向高的集成过程中,验证与设计需在每一层

SystemVerilog高效仿真技巧-爱代码爱编程

做动态仿真验证通常会遇到要等待仿真结果的情况,特别是在调试某个测试用例的时候。很多时候,工程师们会自然地认为仿真速度大部分依赖于跑仿真任务的服务器本身的性能,以及EDA仿真工具的能力。而实际上,高效的验证环境以及代码质量也是影响仿真速度的关键因素。 另一方面,提高仿真速度这回事,对于芯片工程师来说本身就是“求人不如求己”。提高服务器机器性能意味着更大的资

SystemVerilog Testbench Lab1: verification flow-爱代码爱编程

个人认为自学最大的门槛在于:用怎样的形式来输出所学知识,以保证对所学知识的理解是深刻的。我选择写博客来记录自学过程中的疑惑和答案。 SystemVerilog Testbench Lab系列博客将作为我这段时间学习sv的输出,希望能够学会sv在验证中的使用。Synopsys的sv_lab是学习sv的入门资料(EETOP上可以搜到),这一系列的博客都将基于

SystemVerilog系列实验2-爱代码爱编程

SYNOPSYS—SystemVerilog入门实验2 文章目录 SYNOPSYS—SystemVerilog入门实验2前言一、实验思路二、实验步骤1.声明与调用gen()2.声明与调用send()1) 读懂时序图2) 用“代码”描述“时序图”三、知识点:随机变量赋值四、总结 前言 该实验的目的为:从DUT的输入端口(端口3)发送1包数据,

搭建一个SV验证环境(1)-爱代码爱编程

transaction transaction是验证平台内传输信息的基本单元,transaction会将信息从一个验证组件发送到另一个验证组件里面;transaction结构通常与协议帧结构相关; 在这里我们定义一个最简单的帧,帧包含header、payload; class simple_packet ; rand bit [31:0] he

SystemVerilog系列实验3-爱代码爱编程

SYNOPSYS—SystemVerilog入门实验3 文章目录 SYNOPSYS---SystemVerilog入门实验3前言一、Monitor是什么?1. 实验思路2. 实验步骤1)声明与调用recv()2)读懂时序图二、Checker是什么?1. 实验思路2. 实验步骤1)声明与调用check()2)创建compare()三、 总结 前

sv_labs学习笔记——sv_lab4(System Verilog)-爱代码爱编程

sv_labs学习笔记——sv_lab4(System Verilog) lab4 OOP encapsulation实验概述任务代码解析Packat实现与理解语法点解析randomize()extern`ifndef 宏定义的使用this.name = name;$sformatf随机约束主程序的实现与理解语法点解析`includeref 的理解