systemverilog 实验
systemverilog的例子

systemverilog的例子摘要:一、SystemVerilog 简介1.SystemVerilog 的发展历程2.SystemVerilog 在EDA 领域的应用二、SystemVerilog 的基本语法1.数据类型a.整型b.实型c.布尔型d.字符串型2.变量声明与赋值3.运算符与表达式4.控制结构a.顺序结构b.选择结构c.循环结构三、SystemVerilog 的模块与接口1.模块定义2.模块端口声明3.模块实例化4.接口定义与实现四、SystemVerilog 的行为描述1.过程声明2.连续赋值与事件驱动赋值3.函数声明与调用五、SystemVerilog 的仿真与测试1.仿真驱动2.测试序列3.波形查看与分析正文:SystemVerilog 是一种基于Verilog 的硬件描述语言,它被广泛应用于电子设计自动化(EDA)领域,特别是在验证和仿真方面具有显著优势。
本文将简要介绍SystemVerilog 的基本语法、模块与接口、行为描述以及仿真与测试方面的知识。
一、SystemVerilog 简介SystemVerilog 起源于Verilog,是在其基础上进行扩展的一种硬件描述语言。
自1995 年由Cadence 公司推出以来,SystemVerilog 逐渐成为业界标准,被广泛应用于EDA 领域,尤其在验证方面取得了显著成果。
二、SystemVerilog 的基本语法SystemVerilog 提供了丰富的数据类型,包括整型(integer)、实型(real)、布尔型(boolean)和字符串型(string)等。
此外,SystemVerilog 还支持变量声明与赋值、运算符与表达式、以及控制结构(顺序结构、选择结构和循环结构)。
三、SystemVerilog 的模块与接口模块是SystemVerilog 的基本组织单位,用户可以通过模块定义、模块端口声明、模块实例化以及接口定义与实现等方式组织代码。
systemverilog的例子

systemverilog的例子(原创版)目录1.SystemVerilog 概述2.SystemVerilog 的例子3.例子的解析4.总结正文SystemVerilog 是一种硬件描述语言,主要用于设计和验证数字电路和模拟混合信号电路。
它基于 Verilog,并添加了许多新的功能,如类、继承、多态和封装等,使得 Verilog 更加强大和灵活。
SystemVerilog 的一个关键应用是模块化设计和验证,可以将电路划分为多个模块,然后对每个模块进行验证,最后将所有模块组合在一起进行系统级验证。
下面是一个简单的 SystemVerilog 例子,用于演示如何使用SystemVerilog 进行模块化设计和验证。
假设我们要设计一个 4 位加法器,可以将其划分为两个模块:一个用于实现 4 位全加器,另一个用于实现进位处理。
首先,我们创建一个名为"full_adder"的模块,用于实现 4 位全加器。
```verilogmodule full_adder (input [3:0] A,input [3:0] B,input Cin,output [3:0] Sum,output Cout);assign Sum[0] = A[0] ^ B[0] ^ Cin;assign Sum[1] = A[1] ^ B[1] ^ (Cin << 1);assign Sum[2] = A[2] ^ B[2] ^ (Cin << 2);assign Sum[3] = A[3] ^ B[3] ^ (Cin << 3);assign Cout = (Sum[0] & Sum[1] & Sum[2] & Sum[3]) | (Sum[0] & Sum[1] & Sum[2] & (Cin << 1)) | (Sum[0] & Sum[1] & (Cin << 2)) | (Sum[0] & (Cin << 3));endmodule```接下来,我们创建一个名为"adder_module"的模块,用于实现进位处理。
system verilog 实例化参数模块

system verilog 实例化参数模块如何在SystemVerilog中实例化参数化模块在SystemVerilog中,模块是一种组织硬件描述的方式。
参数化模块是一种允许用户在实例化时为模块参数传递值的工具。
在本篇文章中,我们将详细介绍如何在SystemVerilog中实例化参数化模块,并展示一些示例代码来帮助读者更好地理解。
参数化模块允许用户在实例化时为模块的参数传递不同的值。
这样可以根据实例化时提供的参数值,生成不同的硬件描述。
这对于设计具有不同配置或不同功能的模块非常有用。
参数化模块也可以提供一种动态生成硬件描述的方式。
首先,我们需要定义一个参数化模块。
在模块声明中,我们可以使用`#`符号来定义一个或多个参数。
例如,下面是一个具有两个参数的参数化模块的声明:systemverilogmodule MyParameterizedModule #(parameter WIDTH = 8, parameter DEPTH = 16) (input logic [WIDTH-1:0] data, input logic [DEPTH-1:0] address, output logic [WIDTH-1:0] output);模块的具体实现endmodule在这个例子中,我们定义了两个参数:`WIDTH`和`DEPTH`。
这些参数被用于定义`data`,`address`和`output`端口的位宽。
接下来,我们可以使用实际的参数值来实例化此参数化模块。
要在SystemVerilog中实例化一个参数化模块,我们需要在实例化语句中为参数提供值。
以下是一个实例化带有具体参数值的参数化模块的示例:systemverilogmodule MyTopModule;实例化参数化模块MyParameterizedModule #(8, 32)myInst(.data(in_data), .address(in_address), .output(out_data));顶层模块的其余部分endmodule在这个例子中,我们使用`(8, 32)`作为参数值实例化了`MyParameterizedModule`模块。
system verilog 调用 python 案例

system verilog 调用 python 案例SystemVerilog是一种硬件描述语言,通常用于硬件设计和验证。
而Python是一种高级编程语言,常用于软件开发和自动化脚本编写。
结合这两种语言,可以实现硬件设计与验证过程中的自动化任务,提高工作效率和准确性。
在SystemVerilog中调用Python可以实现很多功能,比如数据处理、文件操作、测试生成等。
以下是一个简单的案例,演示了如何在SystemVerilog中调用Python脚本进行数据处理:假设我们有一个SystemVerilog模块,需要对一组数据进行求和操作。
我们可以编写一个Python脚本来实现这个功能,然后在SystemVerilog中调用这个脚本来完成数据处理。
首先,我们编写一个Python脚本,比如sum.py,实现对一组数据进行求和操作。
脚本内容如下:```python# sum.pydata = [1, 2, 3, 4, 5]result = sum(data)print(result)```接着,我们在SystemVerilog中调用这个Python脚本。
可以使用SystemVerilog中的system函数来执行外部命令,如下所示:```system("python sum.py")```当SystemVerilog执行到这一行代码时,会调用Python脚本sum.py,并输出结果。
在这个例子中,Python脚本会对数据[1, 2, 3, 4, 5]进行求和操作,最后输出结果。
通过这种方式,我们可以在SystemVerilog中调用Python脚本,实现数据处理、文件操作、测试生成等功能。
这种结合硬件描述语言和高级编程语言的方式,可以帮助工程师更高效地完成硬件设计与验证任务。
System-Verilog-与功能验证分析

功能验证技术和方法学概要
功能验证技术和方法学概要
激励产生形式 1)用户直接输入,即直接测试(direct test)。 2)种子随机生成,即随机测试(random test)。 3)用户可控的随机输入,即约束随机测试 (constraint random test)
实际项目中我们通常三者结合着去检查比对结果。
功能验证技术和方法学概要
功能验证流程 验证过程可以被分解成三个主要阶段: 1)制定验证策略和验证计划; 2)创建验证平台,运行和调试; 3)覆盖率分析和回归测试。
功能验证技术和方法学概要
制定验证策略和验证计划
功能验证技术和方法学概要
创建验证平台,运行和调试;
System Verilog 与功能验证
功能验证技术和方法学概要
为什么需要IC验证 IC设计复杂度巨大,规模已达上亿门级。 70%验证, 30%设计。 验证是IC设计的关键部分。
功能验证技术和方法学概要
功能验证技术和方法学概要
什么是验证 验证是确保设计和预定的设计期望一致(吻合) 的过程。
功能验证技术和方法学概要
覆盖率驱动验证 覆盖率驱动验证方法学涉及以下技术: 事务级验证、约束随机激励产生、自动化结果 比较、覆盖率统计分析和直接测试。
功能验证技术和方法学概要
事务级验证 事务级验证允许在一个更高的抽象层次来创建 验证场景。 信号级VS事物级:低效VS高效,简单VS复杂。
功能验证技术和方法学概要
功能验证技术和方法学概要
覆盖率分析和回归测试
功能验证技术和方法学概要
SystemVerilog验证方法实例 random_generator

testbench.in/TB_15_SYSTEM_FUNCTION_RANDOM_A_MYTH.html
2/18
13-12-17
WWW.TESTBENCH.IN - Verilog for Verification signed number. This can also be used to meet the requirements. The following example shows the usage of concatenation operator and $unsigned.
EXAMPLE: module Tb(); integer add_1;
initial begin repeat(5) begin #1; add_1 = $random % 10; end end
initial $monitor("add_1 = %d",add_1);
endmodule
RESULT:
add_1 = 8; add_1 = 4294967287; add_1 = 4294967295; add_1 = 9..... The results are not what is expected. The reason is $random generates negative numbers also. The following example demonstrates proper way of generating a random number between 0 to 10. Concatenation operator returns only bit vector. Bit vectors are unsigned, so the results are correct as we expected. Verilog also has $unsigned systemtask to convert signed numbers to
用SystemVerilog验证赛灵思 FPGA

但通常并不会提供特别具有挑战性的向 量对其进行有针对性的测试。这里需要 的是有用的测试激励。我们建议先从最 简单的测试开始,即先检查设计的基本 功能。具体来说,我们的最初测试实例 就是在每个方向仅发送一个封包。发送 单个封包可以验证逻辑和物理层之间的 通信是正确的,并且测试平台本身也能 够正常运行。
SystemVerilog接口对内核信号进 行抽象,从而可以在测试平台和待测器 件(DUT)之间提供简单的连接。唯 一与内核接口通信的类是将事务转换为 向量的驱动器和将向量转换回事务监视 器。图1中用黑色实线表示基于向量的 接口。所有其它单元之间的连接都用灰 色虚线,代表基于事务的通信。在处理 向量流时,驱动器和监视器利用内建在 事务中的函数实现域和数据流之间的转 换,并且还使用比较(comparison)等 成员函数。
coverpoint din1_s; coverpoint din2_s; combos: cross din1_s, din2_s; endgroup
// overflow not allowed // on dout wire [WIDTH:0] tmp = din1 + din2; property p_dout_over;
4
赛灵思中国通讯 31 期
信号增加对应的输入端口。
最后一步是编写封装(wrapper) 模块,用来将验证模块绑定到现有 RTL模块。 SystemVerilog的关键字绑 定和固有的按名字连接(connect-byname)能力使得创建封装模块非常简 单。请注意,SystemVerilog并不支持 参数的隐含连接,因此在这一级必须 明确地将其作为端口调用。分层引用 (Hierarchical references)允许访问子 模块中的信号和参数。
面向硬件仿真的SystemVerilog断言检查电路生成研究

据, 一个 长度为 3的移 位 寄存 器 记 录信 号 b的历史
算 法 1显示 了把线性 序列转换 为硬 件检查 电路
数据 , 再使用 一个 长度 为 1的移 位 寄存 器来 记 录信 号 e的历史数 据 。 以下介绍 线性 序 列 的硬 件 检查 电路 综合 方 法 。
的具体 算法 。算法 中 , 入信 号 首先 通 过 它们 的位 输 置来搜 索 , 后计 算 各个 信 号 的深 度 。各个 信 号 的 然 深 度表示 在检 查 电路 中其移 位寄存器 链使 用的寄存
Ab t a t I hi a e ,a meh d t e r t a d r he k rcr u t r m y t mVe i g a s rin sr c : n t sp p r t o o g neae h r wa e c c e ic i fo S se s rl s eto s o frh r wa e e l t n i r p s d Th i de s t o sr t t e c e k r crui b s d o hf— o ad r mu ai s p o o e . o e man i a i o c n t h c e ic t a e n s i uc h t rg se h i I lo i to u e a me o o mi i z he h r wa e e o r e c n u t n b h rn e itrc an. t as nr d c t d t n mie t a d r r s u c o s mp i y s a g h o i
效性 。
关键词 : yt V r g Ss m el 断言;硬件仿真;检查电路 e i o
Ch c e ic s r i n e k r c r u t g n r to o y t m rl s e t o o
systemverilog验证方法

systemverilog验证方法SystemVerilog验证方法引言在现代芯片设计中,验证是一个非常重要的环节。
SystemVerilog 是一种常用的硬件描述语言,有许多验证方法可以帮助设计人员有效验证设计的正确性。
本文将详细介绍一些常用的SystemVerilog验证方法。
1.仿真验证方法•使用仿真工具进行功能验证–利用Simulator工具来模拟设计行为以进行功能验证。
验证工程师可以编写testbench来生成输入数据,驱动设计的输出,并进行断言验证。
–通过创建各种激励来测试设计中的不同情况,包括边界情况、异常情况和极端情况等。
•波形分析验证–利用仿真工具生成波形,并分析波形来验证设计的正确性。
可以检查信号的时序关系、逻辑等,并比较期望结果和实际结果。
波形分析验证可以在不同抽象级别进行,包括电平验证、逻辑状态验证和功能验证等。
2.形式验证方法形式验证是一种使用形式工具来验证设计是否满足规范的方法。
形式工具基于设计的数学模型进行验证,可以全面而快速地验证设计的正确性。
•模型检查方法–使用形式工具对设计进行形式化建模,并使用模型检查器来验证设计是否满足特定的属性。
设计人员需要编写属性规范来描述设计的期望行为,并利用模型检查器来自动验证属性是否满足。
•定理证明方法–使用形式工具来进行数学定理的证明来验证设计的正确性。
设计人员需要将设计抽象为一个形式化的数学模型,并利用定理证明器来验证设计是否满足特定的性质。
3.边界扫描方法边界扫描方法是一种将设计周围的接口边界进行扫描以验证设计的方法。
•验证接口协议–针对设计中使用的接口协议,可以编写验证环境来验证接口协议是否正确地被设计所遵循。
验证环境可以利用随机算法生成各种接口交互情况,并验证设计的响应是否满足接口协议规定的规范。
•验证接口互连–针对设计中的各个接口之间的互连,可以编写验证环境来验证互连是否满足设计的要求。
验证环境可以生成接口交互的各种情况,并验证互连的正确性和稳定性。
合并数组 systemverilog 例子

合并数组 SystemVerilog 例子在SystemVerilog中,数组是一种常用的数据结构,它允许我们将相同类型的数据元素组织在一起,并在需要时进行操作。
有时,我们需要将两个数组合并成一个数组,这就是合并数组的概念。
本文将介绍如何使用SystemVerilog合并数组,并给出一些示例。
1. 合并数组的基本概念在SystemVerilog中,我们可以使用concatenation运算符`{}`来合并数组。
这个运算符可以把两个数组连接在一起,形成一个新的数组。
需要注意的是,被合并的数组必须是相同类型的,否则会导致编译错误。
2. 合并数组的语法使用concatenation运算符`{}`来合并数组的语法如下所示:```systemverilog{array1, array2}```其中,array1和array2是待合并的两个数组。
3. 合并数组的例子下面是一个简单的例子,演示了如何合并两个整数数组:```systemverilogmodule merge_arrays;int array1[3] = '{1, 2, 3};int array2[4] = '{4, 5, 6, 7};int merged_array[7];initial beginmerged_array = {array1, array2};$display("Merged array: p", merged_array);endendmodule```在这个例子中,我们首先定义了两个整数数组array1和array2,然后使用concatenation运算符`{}`将它们合并成一个新的数组merged_array。
我们使用$display函数打印出合并后的数组。
4. 运行结果当我们运行上述例子时,将会得到如下输出:```Merged array: {1, 2, 3, 4, 5, 6, 7}```可以看到,原先的array1和array2数组被成功合并成了一个包含所有元素的新数组merged_array。
SystemVerilog在interface中使用modport时的例化问题

SystemVerilog在interface中使⽤modport时的例化问题⼀、前⾔在systemverilog中有⼀个⾮常实⽤的功能,那就是interface。
在最近写⼀个⼩练习的时候,不仅使⽤到了interface,还在interface中使⽤了modport,但是在⼀开始例化的时候出了点问题,所以在这⾥说⼀下需要注意的地⽅。
下⾯举⼀个例⼦,这个例⼦主要展⽰了:如何在module中调⽤interface如何在testbench中正确例化interface和module,并将在testbench中定义的与module的输⼊输出信号对应的信号传⼊module代码功能不重要,⽽且我这个代码设计的有些问题,我也就不改了emmm!!!⼆、举例1、RTL代码interface ticket_if(input logic clk,rst_n,[5:0]m_in,output logic ticket_out,[5:0]m_out);logic [5:0]sum;task change(input logic [5:0]in_data,output logic [5:0]out_data );out_data = in_data - 6;endtask //automaticmodport ticket_ports(input clk,rst_n,m_in,output ticket_out,m_out,sum,import task change(input logic [5:0]in_data,output logic [5:0]out_data ));endinterface //interfacenamemodule ticket(ticket_if.ticket_ports ports);enum logic [1:0]{s0,s1,s2} state_c,state_n;always_ff @(posedge ports.clk or negedge ports.rst_n)if(!ports.rst_n)state_c <= s0;elsestate_c <= state_n;always_combcase(state_c)s0:beginports.sum = ports.m_in;ports.ticket_out = 0;if(ports.sum>=6)state_n <= s2;elsestate_n <= s1;ends1:beginports.sum = ports.sum + ports.m_in;if(ports.sum>=6)state_n <= s2;elsestate_n <= state_c;ends2:beginports.change(ports.sum,ports.m_out);//ports.m_out = ports.sum - 6;ports.ticket_out = 1;state_n <= s0;enddefault:state_n <= s0;endcaseendmodule2、仿真代码module tb_ticket;timeunit 1ns;timeprecision 100ps;logic clk,rst_n;logic [5:0]m_in;logic ticket_out;logic [5:0]m_out;initialbeginclk = 0;rst_n = '1;#5 rst_n = '0;#5 rst_n = '1;endinitialbegin#10 m_in=2;#10 m_in=3;#10 m_in=4;#10 m_in=5;#10 m_in=6;#10 m_in=7;#10 m_in=8;endalways #5 clk = ~clk;//ticket_if ports(.*);如果信号名称⼀样,你也可以直接按照这种⽅式来例化ticket_if ports(.clk(clk),.rst_n(rst_n),.m_in(m_in),.ticket_out(ticket_out),.m_out(m_out));ticket u_ticket(ports.ticket_ports);endmodule三、注意事项1、需要注意的是,我们在例化的时候,只能对interface进⾏实例化,并不能直接对modport进⾏实例化。
SystemVerilog验证方法学介绍

前言:芯片验证中虽然传统验证方法尽力保持技术更新步伐以适应设计尺寸以及复杂度的增加,但验证依然是当前SoC以及可重用IP模块设计中面临的最大挑战。
1 SystemVerilog验证方法学介绍芯片验证中虽然传统验证方法尽力保持技术更新步伐以适应设计尺寸以及复杂度的增加,但验证依然是当前SoC以及可重用IP模块设计中面临的最大挑战。
解决这个问题的方法是采用有丰富语义支持的标准语言,以及可重用,覆盖率为驱动的验证方法学。
这是文章中的第一部分:介绍由SystemVerilog硬件设计验证标准语言支持的验证方法学。
此方法学在《VMM for SystemVerilog》一书中有全面介绍。
《VMM for SystemVerilog》致力于如何建立一个可升级,可预期,可重用的验证环境,使得用户能充分利用断言性,重用性,验证平台自动生成,覆盖率,形式分析以及其他先进验证技术特点,从而帮助解决RTL以及系统级中验证技术问题。
如此一个环境能在芯片迈出成功第一步时增加用户验证信心。
《VMM for SystemVerilog》目的是针对所有SoC,IP项目建立一个高效,可控验证过程。
《VMM for SystemVerilog》来源于业界领先的ARM公司,Synopsys公司(新思科技)及其客户经验。
1.1 验证面临挑战随着SoC,IP验证复杂度持续增加,有相应的新验证技术产生,但设计能力与验证所能提供信心之间鸿沟仍然巨大。
多次调查显示有一半到三分之二的SoC项目在第一次流片失败,而功能缺陷的存在是其中主要原因。
这些统计显示了要验证当今设计所具有的固有难度。
复杂模块,尤其在集成到一起后,很难在验证中将芯片实际运用可能遇到的所有条件模拟执行。
预期到所有可能边界条件(corner cases),以及发现设计中深层次设计缺陷是验证面临的关键挑战之一。
非常紧迫的是在规定项目资源以及time-to-market需求情况下,项目过程中花费最小代价尽可能早发现设计缺陷。
system_verilog 验证小技巧与案例

system_verilog 验证小技巧与案例在SystemVerilog中,验证是非常重要的一步,可以帮助我们检查设计的正确性并确保其按预期工作。
以下是一些SystemVerilog验证的小技巧和案例。
1.使用断言(assertions)进行验证:断言是一种在代码中插入的逻辑语句,用于在运行时检查特定条件。
它们可以帮助我们捕捉设计中的错误和问题。
例如,对于一个FIFO设计,我们可以编写一个断言来检查写入和读取操作是否按照预期进行。
`assert (wr_en === (rd_en === 0));`这个断言会在写使能和读使能同时为1时进行验证,以确保读写操作不会同时进行。
2.使用模拟环境进行验证:在验证过程中,我们通常需要创建一个模拟环境来模拟设计的行为。
这个环境通常包括一个测试程序和设计的驱动程序、监听器和功能模型等。
测试程序主要用于生成输入和验证输出,而驱动程序则负责将测试向设计输入,监听器则用于捕获设计的输出并与期望值进行比较,功能模型则用于模拟设计的行为。
例如,对于一个简单的计数器设计,我们可以编写一个测试程序来递增计数器的值,并验证计数器的值是否按预期递增。
3.使用覆盖率分析:覆盖率分析是一种用于确定设计代码是否已被完全测试的方法。
SystemVerilog提供了覆盖率分析的功能,可以帮助我们确定代码的覆盖率,并找出未被完全测试的部分。
覆盖率分析可以使用covergroup和coverpoints来实现。
covergroup提供了用于组织和管理覆盖率数据的方法,而coverpoints则用于指定要测试的代码的特定部分。
例如,对于一个模块,我们可以使用covergroup来收集每个输入组合的覆盖率,并确定哪些输入组合尚未被测试到。
4.使用随机化测试:SystemVerilog提供了一些功能,例如randomize()和randomize_with(),可用于生成随机输入并对设计进行测试。
远程FPGA虚拟实验平台用SystemVerilogHDL实现计数器和分频器

远程FPGA虚拟实验平台⽤SystemVerilogHDL实现计数器和分频器远程FPGA虚拟实验平台⽤SystemVerilog HDL实现计数器和分频器原理计数器本实验中,材料给出的计数器是⼆进制来分频的,就搞得还挺⿇烦。
/** The input port is replaced with an internal signal **/wire reset =PB[0];wire clk;/************* The logic of this experiment *************/logic [23:0] count;always@(posedge CLOCK or posedge reset)beginif(reset)count <=0;elsecount <= count+1;endassign clk = count[22];//2^23,详解见下⽅logic [7:0]q;always @ (posedge clk or posedge reset)if(reset)q <=1;elseq <={q[6:0], q[7]};/****** Internal signal assignment to output port *******/assign L[7:0]= q[7:0];endmodule由代码可知,在CLOCK输出2个信号后,clk=1,然后CLOCK需要再输出2个信号,使clk=0。
这个过程的时间是2(次)/10M(次/秒),约为838毫秒。
测试界⾯的刷新间隔T实际上是,每隔T时间显⽰⼀下虚拟实验⾯板当前的情况,如果在测试时刷新间隔T=1000ms,会使得刷新不完全按照分频器转换后的频率来,所以刷着刷着就跳过了某⼏次,这个“某⼏次”是可以算的,但是我懒得算。
也就是说,只要刷新间隔T<=838ms就能让每个灯都亮了,但是如果不是838的倍数,灯亮的时候就不匀速,有点抽风。
systemverilog与验证方法

systemverilog与验证⽅法读书笔记⿊盒验证指的是只通过其边界信号来验证⼀个模块或者设计的功能。
在⽩盒验证中,可以不需要参考模型,因为可以通过在设计内部或者外部输出信号放置监控器和断⾔来保证设计操作的正确性。
形式验证技术主要有等价性检查和属性检查.验证⼀个设计需要回答两个问题:“Doesitwork?”(DUT能够正常⼯作么?)(在验证计划中可以分解成:测试什么功能点?怎么测?最后功能对不对?)和“Arewedone?”(我们做完了么?)。
第⼀个问题属于最基本的验证概念,也就是说设计能否符合设计者的意图;第⼆个问题就是问我们的验证是否充分和完备,验证是否达到收敛。
基于断⾔验证和覆盖率驱动验证就是解决这两个问题主要的⽅法学。
断⾔验证(AssertionBasedVerification,ABV)主要的⽬的是保证设计和设计期望之间是⼀致的。
覆盖率驱动验证的⽅法最重要的特点是基于随机激励产⽣。
随机激励⽣成是提⾼效率的最主要的原动⼒。
覆盖率驱动验证⽅法学把下⾯⼏个概念和技术融合到了⼀块::事务级验证、约束随机激励产⽣、⾃动化结果⽐较、覆盖率统计分析和直接测试。
⼀个覆盖率驱动的验证项⽬的开发周期包括下⾯⼏个阶段。
(1)开发验证计划(2)搭建验证环境(3)测试运⾏环境(4)运⾏随机测试⽤例(5)针对边界情况创建直接测试/s/blog_4bc2e9450100o9lt.htmlSystemVerilog还为Verilog加⼊了⼏个新的数据类型,以便能够在更抽象的层次上建模硬件。
char:可以是⼀个8位整数(ASCII)或short int(Unicode);int:⼀个两态的有符号变量,32位;shortint:⼀个两态的有符号变量,16位;longint:⼀个两态的有符号变量,64位;byte:⼀个两态的有符号变量,8位;bit:⼀个两态的可以具有任意向量宽度的⽆符号数据类型,可以⽤来替代Verilog的reg数据类型;logic:⼀个四态的可以具有任意向量宽度的⽆符号数据类型,可以⽤来替代Verilog的线⽹或reg数据类型,但具有某些限制;不能⽤在双向总线和多驱动的情况shortreal:⼀个两态的单精度浮点变量,与C语⾔的float类型相同;void:表⽰没有值,可以定义成⼀个函数的返回值,与C语⾔中的含义相同。
systemverilog struct 例化 例子

systemverilog struct 例化例子
在SystemVerilog中,你可以使用`struct`关键字定义一个结构体,然后使用`new`关键字来实例化这个结构体。
以下是一个简单的例子:
```systemverilog
// 定义一个结构体
struct Point {
int x;
int y;
};
// 在主函数中实例化这个结构体
module top;
Point p; // 实例化Point结构体
initial begin
p = new(); // 使用new关键字实例化Point结构体
= 10; // 设置x的值为10
= 20; // 设置y的值为20
$display("Point coordinates: (%0d, %0d)", , ); // 输出点的坐标
end
endmodule
```
在上述代码中,我们首先定义了一个名为`Point`的结构体,它有两个整型成员变量`x`和`y`。
然后,在主函数中,我们实例化了这个结构体,并设置了它的成员变量的值。
最后,我们使用`$display`系统任务输出了这个点的坐标。
7、systemverilog语法和验证相关流程

1、IC验证环境的基本框图测试平台发生器(generator)用来解释testcase,其实也就是把testcase 翻译成具体的数据包,或者数据码流。
代理这个东西就是把数据分配下去,他与记分板和检测器一起称为功能层。
记分板(scoreboard)用来临时存放一些数据,用于数据的比较。
常与检测器合在一起,共同完成数据的比较,查错。
他们要实现的一个与待测设计相同功能的模块,用于自动比较的。
其实也就是要设计一个能实现相同功能的模块,一般小的模块这部分设计都是由验证工程师自己完成的,如果是复杂的模块由于验证工程师还要关注其他的模块,这块功能可以由其他地方提供,比如一些现成的C语言代码,验证工程师把这个C代码嵌入的验证环境中就可以了,这个地方的实现方式比较多,也是验证的一个精华的地方吧。
主要的debug也就在这个地方实现的。
驱动层(driver)顾名思义,就是用来驱动我们的待测设计(DUT (device under test))。
就是把数据包处理成具体的操作激励,也就是那些波形了。
监测器(monitor)用来采集待测设计(DUT)的输出波形,然后传回scoreboard用于和标准结果比较,验证DUT工作是否正确。
断言(assert)是个好东西,但是如果紧紧依靠验证工程师这个东西是没办法用好的,这个东西非常需要设计人员配合。
Assert功能很强大,也很容易上手,能深层次的发掘设计错误,定位很准确,也正是由于这些优点,所以验证工程师不能非常容易的使用它,因为验证工程师一般可以不需要了解太多的设计细节就可以对设计模块进行验证,但是assert需要比较清楚的了解内部信号,才能将内部信号连接到相应的assert上。
建议IC设计工程师学习哦。
对debug很有帮助的哦。
这个模块在有的验证环境中是不使用。
最后说一下覆盖率的问题。
覆盖率分为功能覆盖率,代码覆盖率,还有人为添加的一些覆盖点的覆盖率。
这个其实就是用来衡量验证工作进行到什么程度了。
system verilog 调用 python 案例

system verilog 调用python 案例在SystemVerilog中直接调用Python脚本并不是标准的功能,因为SystemVerilog是一种硬件描述语言,主要用于描述和验证硬件系统,而Python 是一种通用的编程语言。
然而,你可以通过一些间接的方法实现这一目标。
一种常见的方法是使用外部工具或脚本来调用Python脚本,并将结果传递给SystemVerilog。
以下是一个简单的案例,展示了如何在SystemVerilog中调用Python脚本:创建一个Python脚本(例如script.py),该脚本执行你想要的操作并输出结果。
python# script.pydef calculate_sum(a, b):return a + bif __name__ == "__main__":result = calculate_sum(3, 4)print(result)在SystemVerilog中,你可以使用$system任务来调用外部命令。
你可以将Python脚本的输出重定向到一个文件中,然后在SystemVerilog中读取该文件。
systemverilog// testbench.svmodule testbench;initial begin// 调用Python脚本并将输出重定向到文件$system("python script.py > output.txt");// 等待一段时间,以确保Python脚本已经执行完毕#10;// 读取文件内容string line;int file = $fopen("output.txt", "r");if (file != 0) beginwhile (!$feof(file)) beginline = $fgets(file);$display("Python Output: %s", line);end$fclose(file);end// 结束仿真$finish;endendmodule在这个案例中,testbench.sv是SystemVerilog测试平台,它使用$system任务调用script.py Python脚本,并将输出重定向到output.txt文件。
基于System Verilog的IP验证方法的开题报告

基于System Verilog的IP验证方法的开题报告1. 研究背景和意义现今,芯片设计的规模越来越大,设计时间和成本也不断增加。
为了保证设计的正确性和可靠性,芯片设计中通常要进行大量的验证工作。
其中,IP验证是芯片验证中的重要工作之一。
IP(Intellectual Property)即芯片设计中的知识产权,具有一定的功能性和复用性,可以用于构建更复杂的芯片设计。
因此,验证IP的正确性和可靠性对于芯片设计的成功至关重要。
而基于System Verilog的IP验证方法,相较于传统的验证方法具有以下优势:1. 支持面向对象的设计方法,可以更方便地组织和管理验证代码。
2. 支持功能覆盖率分析,可以提高验证效率,减少验证时间和成本。
3. 支持随机测试方法,可以大大增加测试用例的多样性,提高验证的覆盖率。
本文将研究基于System Verilog的IP验证方法,探究其在芯片设计中的应用,旨在提高验证效率、减少验证成本、保证芯片设计的正确性和可靠性。
2. 研究内容和方法本研究将主要研究以下内容:1. System Verilog语言特性和验证方法,包括面向对象的设计方法、功能覆盖率分析和随机测试方法等。
2. IP验证的基本流程和方法,包括IP环境的搭建、验证计划的制定、测试用例的设计和实现、结果分析和bug的调试等。
3. 基于System Verilog的IP验证案例,包括常用IP的验证,如UART、SPI、I2C等。
本研究将采用以下方法:1. 文献研究法:对System Verilog语言和IP验证方法的相关文献进行深入研究,掌握其基本理论和应用方法。
2. 实验研究法:通过实验验证方法,验证验证的正确性和可靠性。
3. 数据统计分析法:对实验结果进行数据统计和分析,评估验证方法的有效性和可行性。
3. 论文结构和预期成果本研究的论文结构如下:第一章:绪论,介绍研究背景和意义、研究内容和方法。
第二章:System Verilog语言和验证方法,介绍System Verilog语言的特性和验证方法,包括面向对象的设计方法、功能覆盖率分析和随机测试方法等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
INTRODUCTIONIn this tutorial, we will verify the Switch RTL core. Following are the steps we follow to verify the Switch RTL core.1) Understand the specification2) Developing Verification Plan3) Building the Verification Environment. We will build the Environment in Multiple phases, so it will be easy for you to learn step by step.Phase 1) We will develop the testcase and interfaces, and integrate them in these with the DUT in top module.Phase 2) We will Develop the Environment class.Phase 3) We will develop reset and configuration methods in Environment class. Then using these methods, we will reset the DUT and configure the port address.Phase 4) We will develop a packet class based on the stimulus plan. We will also write a small code to test the packet class implementation.Phase 5) We will develop a driver class. Packets are generated and sent to DUT using driver.Phase 6) We will develop receiver class. Receiver collects the packets coming from the output port of the DUT.Phase 7) We will develop scoreboard class which does the comparison of the expected packet with the actual packet received from the DUT.Phase 8) We will develop coverage class based on the coverage plan.Phase 9) In this phase , we will write testcases and analyze the coverage report.SPECIFICATIONSwitch Specification:where the packet is driven out.Packet Format:Packet contains 3 parts. They are header, data and frame check sequence.Packet width is 8 bits and the length of the packet can be between 4 bytes to 259 bytes.Packet Header:Packet header contains three fields DA, SA and length.DA: Destination address of the packet is of 8 bits. The switch drives the packet to respective ports based on this destination address of the packets. Each output port has 8-bit unique port address. If the destination address of the packet matches the port address, then switch drives the packet to the output port.SA: Source address of the packet from where it originate. It is 8 bits.Length: Length of the data is of 8 bits and from 0 to 255. Length is measured in terms of bytes.If Length = 0, it means data length is 0 bytesIf Length = 1, it means data length is 1 bytesIf Length = 2, it means data length is 2 bytesIf Length = 255, it means data length is 255 bytesData: Data should be in terms of bytes and can take anything.FCS: Frame check sequenceThis field contains the security check of the packet. It is calculated over the header and data.Configuration:Switch has four output ports. These output ports address have to be configured to a unique address. Switch matches the DA field of the packet with this configured port address and sends the packet on to that port. Switch contains a memory. This memory has 4 locations, each can store 8 bits. To configure the switch port address, memory write operation has to be done using memory interface. Memory address (0,1,2,3) contains the address of port(0,1,2,3) respectively.Interface Specification:The Switch has one input Interface, from where the packet enters and 4 output interfaces from where the packet comes out and one memory interface, through the port address can be configured. Switch also has a clock and asynchronous reset signal.Memory Interface:Through memory interfaced output port address are configured. It accepts 8 bit data to be written to memory. It has 8 bit address inputs. Address 0,1,2,3 contains the address of the port 0,1,2,3 respectively.There are 4 input signals to memory interface. They areinput mem_en;input mem_rd_wr;input[1:0] mem_add;input[7:0] mem_data;All the signals are active high and are synchronous to the positive edge of clock signal. To configure a port address,1. Assert the mem_en signal.2. Asser the mem_rd_wr signal.3. Drive the port number (0 or 1 or 2 or 3) on the mem_add signal4. Drive the 8 bit port address on to mem_data signal.Input PortPackets are sent into the switch using input port.All the signals are active high and are synchronous to the positive edge of clock signal. input port has 2input signals. They areinput[7:0]data;input data_status;To send the packet in to switch,1. Assert the data_status signal.2. Send the packet on the data signal byte by byte.3. After sending all the data bytes, deassert the data_status signal.4. There should be at least 3 clock cycles difference between packets.Output Portport_* signal after one clock cycle.VERIFICATION PLANOverviewThis Document describes the Verification Plan for Switch. The Verification Plan is based on System Verilog Hardware Verification Language. The methodology used for Verification is Constraint random coverage driven verification.Feature ExtractionThis section contains list of all the features to be verified.1)ID: ConfigurationDescription: Configure all the 4 port address with unique values.2)ID: Packet DADescription: DA field of packet should be any of the port address. All the 4 port address should be used.3)ID : Packet payloadDescription: Length can be from 0 to 255. Send packets with all the lengths.4)ID: LengthDescription:Length field contains length of the payload.Send Packet with correct length field and incorrect length fields.5)ID: FCSDescription:Good FCS: Send packet with good FCS.Bad FCS: Send packet with corrupted FCS.Stimulus Generation Plan1) Packet DA: Generate packet DA with the configured address.2) Payload length: generate payload length ranging from 2 to 255.3) Correct or Incorrect Length field.4) Generate good and bad FCS.Coverage Plan1) Cover all the port address configurations.2) Cover all the packet lengths.3) Cover all correct and incorrect length fields.4) Cover good and bad FCS.5) Cover all the above combinations.Verification EnvironmentPHASE 1 TOPIn phase 1,1) We will write SystemVerilog Interfaces for input port, output port and memory port.2) We will write Top module where testcase and DUT instances are done.3) DUT and TestBench interfaces are connected in top module.4) Clock is generator in top module.NOTE: In every file you will see the syntax`ifndef GUARD_*`endif GUARD_*InterfacesIn the interface.sv file, declare the 3 interfaces in the following way.All the interfaces has clock as input.All the signals in interface are logic type.All the signals are synchronized to clock except reset in clocking block.Signal directional w.r.t TestBench is specified with modport.`ifndef GUARD_INTERFACE`define GUARD_INTERFACE//////////////////////////////////////////// Interface declaration for the memory/////////////////////////////////////////////interface mem_interface(input bit clock);logic[7:0] mem_data;logic[1:0] mem_add;logic mem_en;logic mem_rd_wr;clocking cb@(posedge clock);default input#1output#1;output mem_data;output mem_add;output mem_en;output mem_rd_wr;endclockingmodport MEM(clocking cb,input clock);endinterface////////////////////////////////////////////// Interface for the input side of switch.//// Reset signal is also passed hear. ////////////////////////////////////////////// interface input_interface(input bit clock);logic data_status;logic[7:0] data_in;logic reset;clocking cb@(posedge clock);default input#1output#1;output data_status;output data_in;endclockingmodport IP(clocking cb,output reset,input clock); endinterface///////////////////////////////////////////////// // Interface for the output side of the switch.//// output_interface is for only one output port/////////////////////////////////////////////////// interface output_interface(input bit clock);logic[7:0] data_out;logic ready;logic read;clocking cb@(posedge clock);default input#1output#1;input data_out;input ready;output read;endclockingmodport OP(clocking cb,input clock);endinterface//////////////////////////////////////////////////`endifTestcaseTestcase is a program block which provides an entry point for the test and creates a scope that encapsulates program-wide data. Currently this is an empty testcase which just ends the simulation after 100 time units. Program block contains all the above declared interfaces as arguments. This testcase has initial and final blocks.`ifndef GUARD_TESTCASE`define GUARD_TESTCASEprogram testcase(mem_interface.MEM mem_intf,input_interface.IP input_intf,output_i nterface.OP output_intf[4]);initialbegin$display(" ******************* Start of testcase ****************");#1000;endfinal$display(" ******************** End of testcase *****************");endprogram`endifTop ModuleThe modules that are included in the source text but are not instantiated are called top modules. This module is the highest scope of modules. Generally this module is named as "top" and referenced as "top module". Module name can be anything.Do the following in the top module:1)Generate the clock signal.bit Clock;initialforever#10 Clock =~Clock;2)Do the instances of memory interface.mem_interface mem_intf(Clock);3)Do the instances of input interface.input_interface input_intf(Clock);4)There are 4 output ports. So do 4 instances of output_interface.output_interface output_intf[4](Clock);5)Do the instance of testcase and pass all the above declared interfaces.testcase TC(mem_intf,input_intf,output_intf);6)Do the instance of DUT.switch DUT7)Connect all the interfaces and DUT. The design which we have taken is in verilog. So Verilog DUT instance is connected signal by signal.switch DUT(.clk(Clock),.reset(input_intf.reset),.data_status(input_intf.data_status),.data(input_intf.data_in),.port0(output_intf[0].data_out),.port1(output_intf[1].data_out),.port2(output_intf[2].data_out),.port3(output_intf[3].data_out),.ready_0(output_intf[0].ready),.ready_1(output_intf[1].ready),.ready_2(output_intf[2].ready),.ready_3(output_intf[3].ready),.read_0(output_intf[0].read),.read_1(output_intf[1].read),.read_2(output_intf[2].read),.read_3(output_intf[3].read),.mem_en(mem_intf.mem_en),.mem_rd_wr(mem_intf.mem_rd_wr),.mem_add(mem_intf.mem_add),.mem_data(mem_intf.mem_data));Top Module Source Code:`ifndef GUARD_TOP`define GUARD_TOPmodule top();///////////////////////////////////////////////////// // Clock Declaration and Generation /////////////////////////////////////////////////////// bit Clock;initialforever#10 Clock =~Clock;///////////////////////////////////////////////////// // Memory interface instance /////////////////////////////////////////////////////// mem_interface mem_intf(Clock);///////////////////////////////////////////////////// // Input interface instance /////////////////////////////////////////////////////// input_interface input_intf(Clock);///////////////////////////////////////////////////// // output interface instance /////////////////////////////////////////////////////// output_interface output_intf[4](Clock);///////////////////////////////////////////////////// // Program block Testcase instance /////////////////////////////////////////////////////// testcase TC(mem_intf,input_intf,output_intf);///////////////////////////////////////////////////// // DUT instance and signal connection ///////////////////////////////////////////////////////switch DUT(.clk(Clock),.reset(input_intf.reset),.data_status(input_intf.data_status),.data(input_intf.data_in),.port0(output_intf[0].data_out),.port1(output_intf[1].data_out),.port2(output_intf[2].data_out),.port3(output_intf[3].data_out),.ready_0(output_intf[0].ready),.ready_1(output_intf[1].ready),.ready_2(output_intf[2].ready),.ready_3(output_intf[3].ready),.read_0(output_intf[0].read),.read_1(output_intf[1].read),.read_2(output_intf[2].read),.read_3(output_intf[3].read),.mem_en(mem_intf.mem_en),.mem_rd_wr(mem_intf.mem_rd_wr), .mem_add(mem_intf.mem_add),.mem_data(mem_intf.mem_data)); endmodule`endif(S)Run the simulation:PHASE 2 ENVIRONMENTIn this phase, we will writeEnvironment class.Virtual interface declaration.Defining Environment class constructor.Defining required methods for execution. Currently these methods will not be implemented in this phase.All the above are done in Environment.sv file.We will write a testcase using the above define environment class in testcase.sv file.Environment Class:The class is a base class used to implement verification environments. Testcase contains the instance of the environment class and has access to all the public declaration of environment class.All methods are declared as virtual methods. In environment class, we will formalize the simulation steps using virtual methods. The methods are used to control the execution of the simulation.Following are the methods which are going to be defined in environment class.1) new() : In constructor method, we will connect the virtual interfaces which are passed as argument to the virtual interfaces to those which are declared in environment class.2) build(): In this method , all the objects like driver, monitor etc are constructed. Currently this method is empty as we did not develop any other component.3) reset(): in this method we will reset the DUT.4) cfg_dut(): In this method, we will configure the DUT output port address.5) start(): in this method, we will call the methods which are declared in the othercomponents like driver and monitor.6) wait_for_end(): this method is used to wait for the end of the simulation. Waits until all the required operations in other components are done.7) report(): This method is used to print the TestPass and TestFail status of the simulation, based on the error count..8) run(): This method calls all the above declared methods in a sequence order. The testcase calls this method, to start the simulation.We are not implementing build(), reset(), cfg_dut() , strat() and report() methods in this phase.Connecting the virtual interfaces of Environment class to the physical interfaces of top module.Verification environment contains the declarations of the virtual interfaces. Virtual interfaces are just a handles(like pointers). When a virtual interface is declared, it only creats a handle. It doesnot creat a real interface.Constructor method should be declared with virtual interface as arguments, so that when the object is created in testcase, new() method can pass the interfaces in to environment class where they are assigned to the local virtual interface handle. With this, the Environment class virtual interfaces are pointed to the physical interfaces which are declared in the top module.Declare virtual interfaces in Environment class.virtual mem_interface.MEM mem_intf ;virtual input_interface.IP input_intf ;virtual output_interface.OP output_intf[4];The construction of Environment class is declared with virtual interface as arguments.function new(virtual mem_interface.MEM mem_intf_new ,virtual input_interface.IP input_intf_new ,virtual output_interface.OP output_intf_new[4]);In constructor methods, the interfaces which are arguments are connected to the virtual interfaces of environment class.this.mem_intf = mem_intf_new ;this.input_intf = input_intf_new ;this.output_intf = output_intf_new ;Run :The run() method is called from the testcase to start the simulation. run() method calls all the methods which are defined in the Environment class.task run();$display(" %0d : Environment : start of run() method",$time); build();reset();cfg_dut();start();wait_for_end();report();$display(" %0d : Environment : end of run() method",$time); endtask: runEnvironment Class Source Code:`ifndef GUARD_ENV`define GUARD_ENVclass Environment ;virtual mem_interface.MEM mem_intf ;virtual input_interface.IP input_intf ;virtual output_interface.OP output_intf[4];function new(virtual mem_interface.MEM mem_intf_new ,virtual input_interface.IP input_intf_new ,virtual output_interface.OP output_intf_new[4]);this.mem_intf = mem_intf_new ;this.input_intf = input_intf_new ;this.output_intf = output_intf_new ;$display(" %0d : Environment : created env object",$time); endfunction:newfunction void build();$display(" %0d : Environment : start of build() method",$time); $display(" %0d : Environment : end of build() method",$time); endfunction:buildtask reset();$display(" %0d : Environment : start of reset() method",$time); $display(" %0d : Environment : end of reset() method",$time); endtask: resettask cfg_dut();$display(" %0d : Environment : start of cfg_dut() method",$time); $display(" %0d : Environment : end of cfg_dut() method",$time); endtask: cfg_duttask start();$display(" %0d : Environment : start of start() method",$time); $display(" %0d : Environment : end of start() method",$time); endtask:starttask wait_for_end();$display(" %0d : Environment : start of wait_for_end() method",$time); $display(" %0d : Environment : end of wait_for_end() method",$time); endtask: wait_for_endtask run();$display(" %0d : Environment : start of run() method",$time);build();reset();cfg_dut();start();wait_for_end();report();$display(" %0d : Environment : end of run() method",$time);endtask: runtask report();endtask: reportendclass`endifWe will create a file Global.sv for global requirement. In this file, define all the port address as macros in this file. Define a variable error as integer to keep track the number of errors occurred during the simulation.`ifndef GUARD_GLOBALS`define GUARD_GLOBALS`define P08'h00`define P18'h11`define P28'h22`define P38'h33int error =0;int num_of_pkts =10;`endifNow we will update the testcase. Take an instance of the Environment class and call the run method of the Environment class.`ifndef GUARD_TESTCASE`define GUARD_TESTCASEprogram testcase(mem_interface.MEM mem_intf,input_interface.IP input_intf,output_interface.OP output_intf[4]);Environment env;initialbegin$display(" ******************* Start of testcase ****************");env =new(mem_intf,input_intf,output_intf);env.run();#1000;endfinal$display(" ******************** End of testcase *****************");endprogram`endif(S)Run the simulation:(S)Log report after the simulation:******************* Start of testcase ****************0 : Environemnt : created env object0 : Environemnt : start of run() method0 : Environemnt : start of build() method0 : Environemnt : end of build() method0 : Environemnt : start of reset() method0 : Environemnt : end of reset() method0 : Environemnt : start of cfg_dut() method0 : Environemnt : end of cfg_dut() method0 : Environemnt : start of start() method0 : Environemnt : end of start() method0 : Environemnt : start of wait_for_end() method 0 : Environemnt : end of wait_for_end() method 0 : Environemnt : end of run() method******************** End of testcase *****************PHASE 3 RESETIn this phase we will reset and configure the DUT.The Environment class has reset() method which contains the logic to reset the DUT and cfg_dut() method which contains the logic to configure the DUT port address.NOTE: Clocking block signals can be driven only using a non-blocking assignment.Define the reset() method.1) Set all the DUT input signals to a known state.mem_intf.cb.mem_data <=0;mem_intf.cb.mem_add <=0;mem_intf.cb.mem_en <=0;mem_intf.cb.mem_rd_wr <=0;input_intf.cb.data_in <=0;input_intf.cb.data_status <=0;output_intf[0].cb.read <=0;output_intf[1].cb.read <=0;output_intf[2].cb.read <=0;output_intf[3].cb.read <=0;2) Reset the DUT.// Reset the DUTinput_intf.reset <=1;repeat(4)@ input_intf.clock;input_intf.reset <=0;3) Updated the cfg_dut method.task cfg_dut();$display(" %0d : Environment : start of cfg_dut() method",$time);mem_intf.cb.mem_en <=1;@(posedge mem_intf.clock);mem_intf.cb.mem_rd_wr <=1;@(posedge mem_intf.clock);mem_intf.cb.mem_add <=8'h0;mem_intf.cb.mem_data <=`P0;$display(" %0d : Environment : Port 0 Address %h ",$time,`P0);@(posedge mem_intf.clock);mem_intf.cb.mem_add <=8'h1;mem_intf.cb.mem_data <=`P1;$display(" %0d : Environment : Port 1 Address %h ",$time,`P1);@(posedge mem_intf.clock);mem_intf.cb.mem_add <=8'h2;mem_intf.cb.mem_data <=`P2;$display(" %0d : Environment : Port 2 Address %h ",$time,`P2);@(posedge mem_intf.clock);mem_intf.cb.mem_add <=8'h3;mem_intf.cb.mem_data <=`P3;$display(" %0d : Environment : Port 3 Address %h ",$time,`P3);@(posedge mem_intf.clock);mem_intf.cb.mem_en <=0;mem_intf.cb.mem_rd_wr <=0;mem_intf.cb.mem_add <=0;mem_intf.cb.mem_data <=0;$display(" %0d : Environment : end of cfg_dut() method",$time); endtask: cfg_dut(4) In wait_for_end method, wait for some clock cycles.task wait_for_end();$display(" %0d : Environment : start of wait_for_end() method",$time); repeat(10000)@(input_intf.clock);$display(" %0d : Environment : end of wait_for_end() method",$time); endtask: wait_for_end(S)Run the simulation:(S)Log File report******************* Start of testcase ****************0 : Environment : created env object0 : Environment : start of run() method0 : Environment : start of build() method0 : Environment : end of build() method0 : Environment : start of reset() method40 : Environment : end of reset() method40 : Environment : start of cfg_dut() method70 : Environment : Port 0 Address 0090 : Environment : Port 1 Address 11110 : Environment : Port 2 Address 22130 : Environment : Port 3 Address 33150 : Environment : end of cfg_dut() method150 : Environment : start of start() method150 : Environment : end of start() method150 : Environment : start of wait_for_end() method100150 : Environment : end of wait_for_end() method100150 : Environment : end of run() method******************** End of testcase *****************PHASE 4 PACKETIn this Phase, We will define a packet and then test it whether it is generating as expected.Packet is modeled using class. Packet class should be able to generate all possible packet types randomly. Packet class should also implement required methods like packing(), unpacking(), compare() and display() methods.We will write the packet class in packet.sv file. Packet class variables and constraints have been derived from stimulus generation plan.Revisit Stimulus Generation Plan1) Packet DA: Generate packet DA with the configured address.2) Payload length: generate payload length ranging from 2 to 255.3) Correct or Incorrect Length field.4) Generate good and bad FCS.1) Declare FCS types as enumerated data types. Name members as GOOD_FCS and BAD_FCS.typedef enum{GOOD_FCS,BAD_FCS} fcs_kind_t;2) Declare the length type as enumerated data type. Name members as GOOD_LENGTH and BAD_LENGTH.typedef enum{GOOD_LENGTH,BAD_LENGTH} length_kind_t;3) Declare the length type and fcs type variables as rand.rand fcs_kind_t fcs_kind;rand length_kind_t length_kind;4) Declare the packet field as rand. All fields are bit data types. All fields are 8 bit packet array. Declare the payload as dynamic array.rand bit[7:0] length;rand bit[7:0] da;rand bit[7:0] sa;rand byte data[];//Payload using Dynamic array,size is generated on the flyrand byte fcs;5) Constraint the DA field to be any one of the configured address.constraint address_c { da inside{`P0,`P1,`P2,`P3};}6) Constrain the payload dynamic array size to between 1 to 255.constraint payload_size_c {data.size inside{[1:255]};}7) Constrain the payload length to the length field based on the length type.constraint length_kind_c {(length_kind ==GOOD_LENGTH)-> length ==data.size;(length_kind ==BAD_LENGTH)-> length ==data.size+2;}Use solve before to direct the randomization to generate first the payload dynamic array size and then randomize length field.constraint solve_size_length {solve data.size before length;}8) Constrain the FCS field initial value based on the fcs kind field.constraint fcs_kind_c {(fcs_kind ==GOOD_FCS)-> fcs ==8'b0;(fcs_kind ==BAD_FCS)-> fcs ==8'b1;}9) Define the FCS method.function byte cal_fcs;integer i;byte result ;result =0;result = result ^ da;result = result ^ sa;result = result ^ length;for(i =0;i<data.size;i++)result = result ^data[i];result = fcs ^ result;return result;endfunction: cal_fcs10) Define display methods:Display method displays the current value of the packet fields to standard output.virtual function void display();$display("\n---------------------- PACKET KIND ------------------------- ");$display(" fcs_kind : %s ",fcs_());$display(" length_kind : %s ",length_());$display("-------- PACKET ---------- ");$display(" 0 : %h ",da);$display(" 1 : %h ",sa);$display(" 2 : %h ",length);foreach(data[i])$write("%3d : %0h ",i +3,data[i]);$display("\n %2d : %h ",data.size()+3, cal_fcs);$display("----------------------------------------------------------- \n");endfunction: display11) Define pack method:Packing is commonly used to convert the high level data to low level data that can be applied to DUT. In packet class various fields are generated. Required fields are concatenated to form a stream of bytes which can be driven conveniently to DUTinterface by the driver.virtual function int unsigned byte_pack(ref logic[7:0] bytes[]);bytes =new[data.size+4];bytes[0]= da;bytes[1]= sa;bytes[2]= length;foreach(data[i])bytes[3+ i]=data[i];bytes[data.size()+3]= cal_fcs;byte_pack = bytes.size;endfunction: byte_pack12) Define unpack method:The unpack() method does exactly the opposite of pack method. Unpacking is commonly used to convert a data stream coming from DUT to high level data packet object.virtual function void byte_unpack(const ref logic[7:0] bytes[]);this.da = bytes[0];this.sa = bytes[1];this.length = bytes[2];this.fcs = bytes[bytes.size-1];this.data=new[bytes.size-4];foreach(data[i])data[i]= bytes[i +3];this.fcs =0;if(bytes[bytes.size-1]!= cal_fcs)this.fcs =1;endfunction: byte_unpack14) Define a compare method.Compares the current value of the object instance with the current value of the specified object instance.If the value is different, FALSE is returned.virtual function bit compare(packet pkt);compare=1;if(pkt ==null)begin$display(" ** ERROR ** : pkt : received a null object ");compare=0;endelsebeginif(pkt.da !==this.da)begin$display(" ** ERROR **: pkt : Da field did not match");compare=0;endif(pkt.sa !==this.sa)begin$display(" ** ERROR **: pkt : Sa field did not match");compare=0;endif(pkt.length !==this.length)begin$display(" ** ERROR **: pkt : Length field did not match");compare=0;endforeach(this.data[i])if(pkt.data[i]!==this.data[i])begin。