[原创]利用system verilog快速构建单元仿真

在一些单元模块仿真时,往往需要构建一定格式的数据激励,如某个处理TCP报文的单元模块,需要构建符合TCP报文格式的激励。基于verilog的激励生成,大致有两种方法:

  1. txt文件法。将符合需求的数据记录于txt,仿真时调用。
  2. 直接合成法。利用verilog在tb中直接合成激励。

这两种方法的优点是直观,但不够灵活。其一,当激励的数据结构复杂时,构建起来比较麻烦;其二,当被测对象的输入协议改动时,往往牵一发而动全身,需要对tb做整体的检查。

利用system verilog构建单元测试可以克服上述缺点,同时还具备其它优秀特性,如带约束的随机激励生成、测试覆盖率分析。

本人根据实践,总结出基于system verilog的单元测试解决方法,希望对大家有帮助,并共同探讨。

下面以msgx_cfg模块的测试说明该方法,重点讲述如何从原来的基于verilog测试tb转为基于system verilog的测试tb。这个过渡包括四个步骤:

  1. 修改tb文件类型。由.v改为.sv。
  2. 在tb.sv中增加一个class。
  3. 在tb.sv中写一个数据转信号的task。
  4. 调用task,享受sv带来的测试快感。

1 单元仿真的激励要求

该模块结构

本文重点讲述激励产生,因此省略模块所有输出接口。该模块数据输入接口信号如下:


信号名


位宽(bit)


描述


i_data_valid


1


电平,为高表示数据有效


i_data


64


数据


i_eop_p


1


脉冲,数据尾标志

对于i_data的格式要求如下:

 
63:56


55:48


47:40


39:32


31:24


23:16


15:8


7:0


beat1


msg_type


pld_len


b

c[47:16]

beat2


c[15:0]

payload

beat3


payload


其中各字段说明:


名称


长度(byte)


说明


msg_type


1


消息类型


pld_len


1


payload的byte数,最小6


b


2

 

c


6

 

payload


pld_len


长度取决于pld_len

2 修改tb

根据上述输入激励要求,利用sv快速构建单元仿真激励。

2.1 修改tb文件类型

原来msgx_cfg_tb.v的内容如下:

 1 module msgx_cfg_tb;
 2
 3 reg clk;
 4 reg    rst_n;
 5 reg i_data_valid;
 6 reg [63:0]    i_ data;
 7 reg    i_eop_p;
 8
 9 msgx_cfg DUT(
10 .clk            (clk    ),
11 .rst_n          (rst_n    ),
12
13 .i_data_valid    (i_data_valid    ),
14 .i_rdfifo_data    (i_ data ),
15 .i_eop_p        (i_eop_p    ),
16
17 //其它接口,省略
18
19 );
20
21 initial begin
22    clk = 0;
23    forever #5ns clk = ~clk;
24 end
25
26 initial begin
27    rst_n = 0;
28    #50ns;
29    rst_n = 1;
30 end
31
32 endmodule

将文件名改为msgx_cfg_tb.sv。

2.2 在tb.sv中增加一个class

在msgx_cfg_tb.sv头部,增加一个class,其作用是产生“输入激励要求”描述的数据。

 1 class msg_data_class;
 2
 3 //声明data中的所有字段
 4 rand bit[7:0] msg_type;
 5 rand bit[7:0] pld_len;
 6 rand bit[15:0] b;
 7 rand bit[47:0] c;
 8 rand bit[7:0] payload[];
 9
10 //用于存储最终数据data
11 bit[63:0] data[];
12
13 //随机约束
14 constraint legal_payload_size_c {pld_len > 6;  payload.size == pld_len;}
15
16 //自定义pack()函数,将字段打包进动态数组data
17 function void pack();
18     data = {>>{msg_type, pld_len, b, c, payload}};
19 endfunction
20
21 //重写class内置函数: post_randomize(),该函数在class随机化后会自动调用
22 function void post_randomize ();
23     pack(); //打包
24 endfunction : post_randomize
25
26 endclass

2.3 在tb.sv中增加一个task

现在,我们的msgx_cfg_tb.sv中有一个描述数据组成的class,一个module,接下来,需要在module内把数据转化为接口信号。我们在module内写一个task,完成这个任务。

 1 module msgx_cfg_tb;
 2
 3 reg             clk;
 4 reg            rst_n;
 5
 6 reg             i_data_valid;
 7 reg [63:0]        i_ data;
 8 reg            i_eop_p;
 9
10 //声明class
11 msg_data_class msg;
12
13 msgx_cfg DUT(
14     .clk            (clk            ),
15     .rst_n          (rst_n        ),
16
17     .i_data_valid    (i_data_valid    ),
18     .i_rdfifo_data    (i_ data         ),
19     .i_eop_p        (i_eop_p        ),
20
21     //其它接口,省略
22 );
23
24 initial begin
25     clk = 0;
26     forever #5ns clk = ~clk;
27 end
28
29 initial begin
30     rst_n = 0;
31     #50ns;
32     rst_n = 1;
33 end
34
35 //新增task
36 task data2signal(msg_data_class msg);
37     @(posedge clk);
38     i_data_valid <= 1;
39     i_data <= 64’h0;
40     for(int i=0; i<msg.data.size; i++) begin
41         i_data <= msg.data[i];
42         i_eop_p <= i==msg.data.size-1 ? 1:0;
43         @(posedge clk);
44     end
45     i_data_valid <= 0;
46     i_data <= 64’h0;
47 endtask
48
49 endmodule
50     

当data2signal task写好后,在测试case编写过程中专注于数据层构建就可以了。

2.4调用task,享受sv带来的测试快感

让我们在module内写第一个测试case。为了便于case的可重现性,我们把每一个case封装成一个task,在主过程中调用各个task,这样做的好处是测试后期一旦有改动可以将前期case方便的再做测试。

 1 //主过程
 2 initial begin
 3         test_case1();
 4 end
 5
 6 //第一个测试case
 7 task test_case1();
 8         $display(“------------- start of test_case1 -------------”);
 9         msg = new();
10         wait(rst_n);
11         @(posedge clk);
12
13         //随机化
14         assert (msg.randomize with {msg_type == 8’d1;});
15
16         //调用task: data2signal()
17         data2signal(msg);
18         $display(“------------- end of test_case1 -------------”);
19 endtask

在test_case1的task中,通过assert()语句控制随机产生msg_type字段为1的数据包,而其它一些字段(pld_len和payload的长度),由msg_data_class中的constraint约束。注意,当assert()中的约束与constraint中约束冲突时,仿真器会给出告警,此时产生的数据是不受控、没有意义的,因此仿真时需要留意告警信息,写tb时也注意做好约束规划和分配,避免产生冲突

时间: 2024-10-07 04:40:29

[原创]利用system verilog快速构建单元仿真的相关文章

如何利用docker快速构建MySQL主从复制环境

在学习MySQL的过程中,常常会测试各种参数的作用.这时候,就需要快速构建出MySQL实例,甚至主从. 考虑如下场景: 譬如我想测试mysqldump在指定--single-transaction参数的情况下,对于myisam表的影响. 本来想在现成的测试环境中进行,但测试环境中,有大量的数据,执行mysqldump进行全备,产生的SQL文件,很难基于表进行搜索. 这个时候,就特别渴望能有一套干净的实例进行测试. 此刻,快速构建能力就显得尤为必要,很多童鞋可能会问,通过脚本不就能实现么?为什么要

vue2.x利用脚手架快速构建项目并引入bootstrap、jquery

要使用vue-cli脚手架搭建项目,首先需要安装node.js Node.js官网:https://nodejs.org/en/download/ 选择你对应的系统即可下载,下载完成后傻瓜式安装即可. 安装完成之后打开cmd,输入node -v 出现版本号即安装成功 接下来便可使用脚手架快速构建你的项目了: npm install -g vue-cli                   全局安装vue-cli vue init webpack test                 生成项目

使用eclipse和JavaFX Scene Builder进行快速构建JavaFX应用程序

http://blog.csdn.net/wingfourever/article/details/7726724 使用eclipse和JavaFX Scene Builder进行快速构建JavaFX应用程序 2012-07-08 18:25 18641人阅读 评论(11) 收藏 举报  分类: JavaFX(52)  版权声明:本文为博主原创文章,未经博主允许不得转载. 了解过JavaFX的都知道,JavaFX自从2.0版本开始,已经完全抛弃了之前的script语言,才用纯java来实现.这样

基于Bluemix快速构建部署一款Java小程序——微博影响力分析器

一.前言 近年来IT界风云际会,各种新概念如大数据.云平台.虚拟化等,如雨后春笋般层出不穷.而云平台,可以说是近些年来引领时代新潮的边缘概念之一,各大厂商竞相推出各种云产品,抢占云市场高地.近期,IT百年老厂IBM也推出了其花费重金打造的基于CloudFoundry开放标准的云平台Bluemix.本文就旨在从一位普通Java开发者角度,尝鲜Bluemix云平台及其提供的Cloudant服务,快速构建并部署一款Java小程序"微博影响力分析器". 二."微博影响力分析器&quo

利用MVVM设计快速开发个人中心、设置等模块

我们在做iOS开发过程中,静态页面的开发比开发动态页面更让我们开发者抓狂.因为动态页面通常是一个页面一种cell样式,作为开发者只需要专注于定制好一种样式之后,就可以使用数据填充出较好的界面.而静态cell,则可能因为一个页面有多种cell样式,而且很有可能不是标准的cell样式,需要我们自定义,因此容易写出来的代码容易臃肿和重复.可读性差.这不符合开发者的代码优化原则(不主动重复).我时常会因为开发这种页面抓狂,因为会纠结到底怎么写会让代码可读性好点,写重复代码的机会少点.本文就是我做过的几个

node快速构建express项目

1.首先,到node官网,下载node安装.我的电脑是windows系统,所以下载的是windows版本的,下载完成之后,一路下一步安装就可以了.node中文网:http://nodejs.cn:node官网:https://nodejs.org/en/: 2.node安装完成之后,会自动安装npm包管理器.打开CMD,(windows系统,点击开始-->运行-->输入cmd回车):输入命令 node -v 如果输出信息,表示node安装成功;接着输入 npm -v 如果输出信息,表示npm安

System Verilog Assertion for debug

System Verilog Assertion是非常好的验证方法,通过SVA可以显式描述需要验证的电路逻辑,并且仿真工具可以在仿真的过程中自动输出波形出错信息,从而替代传统的看波形调试方法,提高前端设计验证效率. RTL代码结构 `ifdef SVA module m_sva(input wire signal); property p1; expression; endproperty a: assert property(p1); endmdule bind m m_sva m_sva_i

Centos6.4下快速构建基于用户名密码验证的openvpn服务器

如今VPN应用已经非常广泛了,之前就写过一篇关于PPTPD的博文.链接是http://cyr520.blog.51cto.com/714067/1161788. 家里最近新换了一个宽带.居然没办法用拨上公司的PptpdVPN,一直拨号状态一直停留在正在验证用户名和密码这一步.百度谷歌了一大圈,也没解决这个问题.貌似是因为宽带运营商屏蔽GRE协议的原因.作为运维人员,不能及时的连上公司的内部网络是一件很让人不爽的事情. 干脆再搞一套OpenVPN吧,据说OpenVPN非常强大,可以适应很复杂的网络

C#利用System.Net发送邮件(带 抄送、密送、附件、html格式的邮件)

net2.0后,C#可以利用System.Net发送邮件了. 代码整理如下: 3. 增加IProcessMessage类,定义了一个消息方法,用于消息传递 1 /************************************** 2 * <copyright file="SendEail.cs"> 3 * Copyright(c)2014 LeeStudio All rights reserved. 4 * CLR版本:4.0.30319.17929 5 * 开发