西洲渡

一只还没迈入IC领域的小菜鸡

使用SystemVerilog对Router进行验证

前言

在学习了SystemVerilog之后,检验学习成果最有效的方式就是真正的去实验一个项目,以下就是我的一个关于Router的验证过程。实验代码我会上传到我的GitHub仓库中,有需要的可以下载。

设计模块介绍

实验中的待测试模块(DUT)是一个16输入,16输出的路由器,这个路由器的功能是把数据通过各个输入端(Input)发送到任意输出端(Output)。下面是最终完成的整个验证平台示意图。

我们需要建立的几个文件:

  • 顶层(Top)文件:router test top.sv
  • 接口(Interface)文件:router_io.sv
  • 待测试(DUT)文件:router.v
  • 测试(Test)文件:test.sv

Do文件实现调试

在做验证的时候,每次修改完代码后都要经历一遍编译仿真,鼠标要点击数次,作为一个懒人,肯定是要想实现自动化实现这个流程了,网上一搜果真可以实现,只需要编译一个do文件,看了看参考的文章,动手写了一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
vlib work
#创建一个lib名叫work

vmap work work
#将新建的work映射到虚拟的空间

vlog router.v test.sv router_test_top.sv
#编译当前工程中的文件,注意被include的文件就不要放进来了

vsim work.router_test_top -t 1ns -sv_seed random
#开始设定仿真参数以及仿真work库中的顶层模型,顺便随机初始化随机种子

add wave -position insertpoint \
sim:/router_test_top/intf_io/clock \
sim:/router_test_top/intf_io/reset_n \
sim:/router_test_top/intf_io/din \
sim:/router_test_top/intf_io/frame_n \
sim:/router_test_top/intf_io/valid_n \
sim:/router_test_top/intf_io/dout \
sim:/router_test_top/intf_io/valido_n \
sim:/router_test_top/intf_io/busy_n \
sim:/router_test_top/intf_io/frameo_n
#添加波形查看器,并将需要查看的波形导入其中

run -all
#运行

实验一

准备

  • 自学关于V0实验指导视频(腾讯课堂)的Lab1/Lab2/Lab3指导内容,了解VO实验是如何构建测试平台、发送激励和完成数据监测的。
  • 完成第一次、第二次在线实验直播指导,学习实验的思路和培养目标,即在构建一个干净简洁的验证结构基础上,实现对DUT的激励和监测。

要求

  • 可自行根据VOLab1-3的实验代码内容,参考并且完成属于自己的验证环境(coding by yourself)。
  • 应该利用task/function来完成对DUT的激励和监测。
  • 利用struct作为激励的发送和监测数据类型。
  • 利用不同类型的数组来生成或者保存激励数据和监测数据。
  • 利用module和interface作为验证平台的层次结构以及与DUT之间的媒介。
  • 利用参数传递、或者函数调用等来完成接口(interface)从测试顶层(top)到验证组件的传递。
  • 利用$display函数来将每次激励的数据信息和监测的数据信息都打印出来。
  • 在所有的数据发送给DUT,并且由DUT全部发送完毕之后,调用$finish0来结束仿真。以上验证结构中,应该至少包括stimulator组件(module)、monitor组件(module)、接口和DUT,以及你认为需要的其它组件,并且利用结构绘制工具(Microsfot Visio,或者draw.io等结构框图绘制工具均可)绘制验证环境的结构框图,并且作为稍后第6周的打卡作业来提交。

结果

实验二

准备

  • 提前学习V0的实验4-5,掌握如何转换这些类(数据包packet,验证环境组件generator、driver、monitor、checker/scoreboard)。

要求

  • 需要让整个验证环境结构变得完整(补充上checker),从module的硬件层次转为由类来构成的对象之间的软件层次,即完成验证环境中各个组件从module转为class。用任何一种办法,相继发送多个数据包,前后实现遍历所有的入口,以及所有的出口,组合次数、效率都不限制。
  • (选做)实现一个测试场景,即同时给两个不同的channel(入口)发送数据至不同的目标端(出口),同时检查设计是否能够支持该激励,如果设计可以支持,那么验证环境的checker也应该支持相应的数据检查。

结果

实验三

准备

  • 能够有完整的验证组件包括generator、stimulator、monitor、scoreboard
  • 验证环境能够将数据比对的信息及时打印出来,并且控制仿真的结束和最后的测试结果统计打印(例如比较数目、测试是否通过)

要求

  • 能够实现验证环境可以同时对router的16个输入端口进行激励输入。
  • 能够实现多个通道的随机输入(目标地址DA随机)。
  • 能够解释清楚scoreboard的执行逻辑。
  • 能够解释清楚测试代码结束测试的逻辑(仿真何时停止、如何停止)。
  • 能够绘制自己验证环境的结构(在接下来的第10周打卡作业中提交实验3的验证结构框图)
  • (选做)根据自己的验证环境结构,独立实现你自己的scoreboard代码。
  • (选做)避免从generator或stimulator将激励数据直接发往scoreboard,而创建独立的monitor监测router的输入端数据,并且将监测的数据发往scoreboard。

结果

实验四

准备

  • 按照第4次实验的视频指导,能够使用手动编译的方式或者使用Tcl脚本命令完成单步编译和仿真执行,并且收集覆盖率。
  • 同样根据第4次实验的指导,能够理解提供的用来执行回归测试的脚本(从编译、仿真、覆盖率收集以及合并)。

要求

  • 将路桑提供的接口文件替换掉你环境中的接口文件,该接口文件具备收集功能覆盖率的功能呢。
  • 使用单步Tcl指令来收集覆盖率,或者提供的回归测试脚本来批量化收集覆盖率和测试结果。
  • 使用Questasim的verification management功能中的browser,来查看覆盖率数据文件(UCDB)、并且分析设计的代码覆盖率和验证环境的功能覆盖率,使其能够尽可能达到100%。
  • 对于没有达到100%的部分覆盖率,能够给出合理解释,为什么无法达到该覆盖率,是否激励不够需要更新测试(请继续更新测试用例,提升覆盖率),或者由于设计自身的原因,无法达到100%覆盖率,需要剔除该部分数据(exclude)。
  • (选做)对于一些时序部分的检查和覆盖,我们还可以交给断言assertion或者任务task去实现(检查和覆盖),所以你还可以进一步分析断言的覆盖率,并且通过修改stimulator、test验证组件,继而提高断言覆盖率。请对以下设计的接口时序描述,采用SV property (属性)去描述,实现检查或者覆盖。

注意:请在调试断言时,添加有关的仿真选项,即在vsim的命令选项中,添加-assertdebug -assertcounts
1.1.输入时序检查
1.1.1.framen拉低后,持续为低的第4拍,din应该保持为高持续5拍。
1.1.2.frame n拉低后,持续为低的第4拍,valid n应该保持为高5拍(不一定再拉低,如果下一拍可以发送无效数据的话)。
1.1.3.valid n保持为高超过5拍,接下来valid n应该保持为低,且持续的周期数应该是8的整数倍(有效字节周期,目前设计只支持接受byte即8-bits的整数倍)。
1.1.4.frame n拉高后的下1拍,valid应该拉高。
1.2.输入时序覆盖
1.2.1.frame_n拉低后,持续为低的前4拍,valid_n的取值可能为{0,1}(不关心valid_n信号的高低)。
1.3.输出时序检查
1.3.1.frameon拉低的下1拍,validon保持为高(下1拍不一定立即拉低,如果有无效数据的话)。
1.3.2.frameon拉高的下1拍,validon拉高。
1.3.3.当!validon&&!frameon第一次满足时(输出包的DO),到valido_n拉高且frameo_n为高时,中间经过valido_n为低的周期数,应为(8*N)。
1.4.输出时序覆盖
1.4.1.当!validon&&!frameon第一次满足时(输出包的DO),到valido_n拉高且frameon为高时,validon还可以拉高和拉低(输出数据包时,可以在frame有效期中,不连续发送数据,即valido_n可以为高)。

结果

参考文章

路科V0实验指导
Modelsim之 DO文件简介