Synopsys SV Lab Guide—lab3
目录
0.前言
1.全局变量声明
2.高层次级函数的确定
3. 接收数据函数
4.检查函数
5.仿真结果
6.完整test代码
0.前言
该lab目标有以下几点:
- 随机化输入端口和输出端口以全面测试DUT
- 写一个monitor接收DUT的输出
- 写一个checker自动检查DUT的输出与预期结果是否一致
该lab新添加的所有的操作都是在lab2中的test.sv文件中添加。
1.全局变量声明
首先由于我们要随机化输入端口和输出端口,所以如果按照前面lab的只随机21次肯定是无法把16×16个端口都遍历到的,因此我们创建一个变量来存放随机的次数,以便后面修改
其次,我们要接收到DUT的输出并核对是否正确,而在lab2中我们发送的数据是8bits的数据,而DUT的功能只是把数据交换到输出端口,因此我们需要创建一个每个元素为8bits的队列来存放数据,以便check
int run_for_n_packets;//声明一个整形变量来存放随机激励生成的次数
logic[7:0] pkt2cmp_payload[$];//声明一个每个元素为8bits的队列来存放DUT输出数据,以便用于check
2.高层次级函数的确定
该router输入与输出直接没有内部时延,因此我们需要同时发送和接收数据,而initial块儿内线程是顺序执行的,因此我们需要用到fork...join块儿来并行运行发送和接收线程。再接收完毕一次数据后,检查数据是否正确。因此代码在lab2基础上修改如下:
initial begin$display("Hello World!"); $vcdpluson; reset ();repeat (run_for_n_packets) begingen ();fork//同时发送一次数据和接收一次数据send();//lab2中的发送数据函数recv();//即将定义的接收数据函数joincheck();//接收完一次数据后检查数据是否正确endend
3. 接收数据函数
定义recv接收任务如下,在其中再定义接收数据任务(不清楚为何要套一层,可能是在后续lab中在该task中还有定义其它功能)。
task recv();get_pay1oad();
endtask
需要重点强调的是我们的TB是按照协议写的,协议规定frameo_n下降沿开始时输出数据;如果DUT的frameo_n出现异常没有下降沿,而我们的TB又一直等待它下降,就会造成仿真无限运行,而我们还在傻傻等待;因此我们必须采取行动防止这种情况的出现,所以定义了第一个fork join块儿来预防,其功能就是如果等frameo_n信号等了1000个时钟上升沿还没等到其下降,就报错并停止仿真!
task get_pay1oad();pkt2cmp_payload.delete();//由于要接收n次数据,因此在本次接收数据前必须把上一次的数据清空fork//我们的TB是按照协议写的,协议规定frameo_n下降沿开始时输出数据;如果DUT的frameo_n出现异常没有下降沿,而我们的TB又一致等待它下降,就会造成仿真无限运行,我们还傻傻等待;该fork join块儿就是为了出现这种情况时及时报错并停止仿真!beginfork//并行执行2个线程,要么等到frameo_n下降沿后结束,要么等了1000个clk后等不到报错@(negedge rtr_io.cb.frameo_n[da]);//线程1begin//线程2repeat(1000) @(rtr_io.cb);$display ("\n%m\n [ERROR] %t Frame signal timed out!\n", $realtime);$finishendjoin_any disable fork;//线程1先执行完后,跳转到这里结束fork join_any线程 endjoinendtask
使用上述的方法等到frameo_n下降沿后开始准备采集数据,根据输出时序协议要frameo_n和valido_n同时拉低后才是有效数据,并且frameo_n要比valido_n提前拉高一个时钟周期表示最后一位数据;这里注意我们是按照协议写的TB,因此DUT并不一定是frameo_n拉高最后一位数就来了,因此我们也要验证这个点!
代码及讲解如下所示 :
task get_pay1oad();pkt2cmp_payload.delete();forkbeginfork@(negedge rtr_io.cb.frameo_n[da]);beginrepeat(1000) @(rtr_io.cb);$display ("\n%m\n [ERROR] %t Frame signal timed out!\n", $realtime);$finishendjoin_any disable fork;endjoinforever begin//一次数据可能包含好多8bits数据,因此要反复执行采集数据,并在代码中判断这次数据的结束并终止此tasklogic[7:0]datum;//定义一个位宽为8bits的变量储存数据for(int i=0;i<8; )begin//注意这里并没有i++,而是放到了下面的datum中,非常妙!!!这意味着frameo_n拉低后,如果valido_n没有拉低,i就不自增也就不采集数据,直到valido_n拉低,i++并采集数据。如果这里把i++放到for循环里,那无论valido_n拉低没有,i都自增了,那就会对后面采集8位数据造成误判!if(!rtr_io.cb.valido_n[da])//按照输出时序协议,valido_n为低时是有效数据,因此这里判断valido_n是否为低,是的话就把数据存到datum中datum[i++]=rtr_io.cb.dout[da]//这里注意i++首先取的是i的值,再自增if(rtr_io.cb.frameo_n[da])//按照输出时序协议,frameo_n拉高表示下一位数是这次数据(一次数据可能包含好几个8位数据)的最后一个8位数据的最后一位,也就是说frameo_n拉高,表示下一位是最后一个8位数据的第8位if(i==8)begin//判断是不是第8位pkt2cmp_payload.push_back(datum);//是,就把最后一个8位数据放到pkt2cmp_payload队列中return;//同时结束task任务,表示这次的数据采集完成了endelse begin//frameo_n拉高却不是第8位,按照协议这是有问题的$display ("\n%m\n [ERROR] %t Packet payload not byte aligned!\n",
$realtime);//报错并停止仿真$finish;end@(rtr_io.cb)//上面都是在clk上升沿瞬间完成的,这里要等下一个上升沿的数据,因此要等一个cbendpkt2cmp_payload.push_back(datum);//一次数据中可能包含好几个8位数据,所以就要在结束一次for循环后,把一个8位数据存到队列中一次endendtask
4.检查函数
该函数就是为了检查DUT输出的数据是不是对应的输入数据,也就是比较payload队列和 pkt2cmp_payload是不是一样的/
因此我们可以定义一个比较函数来比较2个队列的数据的个数和数据是否一一对应,如果都对应则返回1表示没问题,如果有问题则返回0表示有问题,这样函数话返回数值的好处就是方便其在任何地方调用。
task check();string message;//定义一个字符串变量用来打印提示信息static int pkts_checked = 0;//用来计数,检查了多少次数据if (!compare(message)) begin//如果数据有问题,compare返回0$display ("\n%m\n [ERROR] %t Packet #%0d %s\n", $realtime, pkts_checked, message);$finish ; //打印错误提示,告诉验证人员第几组数据出了问题并终止仿真end$display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);//一组数据没问题就计数+1,方便前面的有问题数据是第几组的提示endtaskfunction compare();//既要比较一组数据中8bits数据的个数,也要比较数据内容if(payload.size()!=pkt2cmp_payload.size())begin//如果个数不一样message = "Payload Size Mismatch:\n";//打印提示信息message = { message, $sformatf("payload.size() = %0d, pkt2cmp payload.size () = %0d\n", payload.size (), pkt2cmp_payload.size() ) };//并打印两个队列各自的尺寸return(0);endif(payload==pkt2cmp_payload)//==表示尺寸内容都一样,由于是顺序执行,因此上面先比较尺寸,这里如果有问题而上面没问题那一定是内容不对;//没问题,此处先不执行操作,放到后面执行else begin//有问题message = "Payload Content Mismatch:\n";//打印提示信息message = {message, $sformatf("Packet Sent: %p\n Pkt Received: %p",payload, pkt2cmp_payload) }; //并打印两个队列各自的数据return(0);end//打印成功提示message = "Successfully Compared";return (1);endfunction
5.仿真结果
仿真打印结果如下,由于我们在TB中的设置,如果仿真中遇到任何问题,就终止仿真;因此如果执行到了最后一次,意味着所有的仿真都正确。
6.完整test代码
注意这里把gen()函数中sa和da的值改成了随机值,从而实现输入端口和输出端口的随机化。
program automatic test (router__io.TB rtr__io);bit [3:0] sa; bit[3:0] da;logic[7:0] payload[$];int run_for_n_packets; logic[7:0] pkt2cmp_payload[$];initial begin$display("Hello World!"); $vcdpluson; run_for_n_packets = 2000;//随机2000次reset ();repeat (run_for_n_packets) begingen ();forksend();recv();joincheck();endend/*>=====================================task==========================================<*/task reset();router.reset_n=1'b0;router.cb.frame_n.<='b1; router.cb.valid_n<='b1;##2 router.cb.reset_n<=1'b1;repeat(15) @(router.cb); endtasktask gen();sa=$urandom;//端口随机化da=$urandom;payload.delete();repeat($urandom_range(2,4)) payload.push_back($urandom);endtasktask send();send_addrs();send_pad();send_payload();endtasktask send_addrs();rtr_io.cb.frame_n[sa]<=1'b0;for(int i=0;i<4;i++)beginrtr_io.cb.din[sa]<=da[i];@(rtr_io.cb);endendtasktask send_pad();rtr_io.cb.frame_n[sa]<=1'b0;rtr_io.cb.valid_n[sa]<=1'b1;rtr_io.cb.din[sa]<=1'b1;repeat(5) @(rtr_io.cb);endtasktask send_payload();foreach(payload[index])for(int i=0;i<8;i++)beginrtr_io.cb.din[sa]<=payload[index][i];rtr_io.cb.valid_n[sa]<=1'b0;rtr_io.cb.frame_n[sa]<=(index==(payload.size()-1))&&(i==7);@(rtr_io.cb)endendtasktask recv();get_pay1oad();endtasktask get_pay1oad();pkt2cmp_payload.delete();forkbeginfork@(negedge rtr_io.cb.frameo_n[da]);beginrepeat(1000) @(rtr_io.cb);$display ("\n%m\n [ERROR] %t Frame signal timed out!\n", $realtime);$finishendjoin_any disable fork;endjoinforever beginlogic[7:0]datum;for(int i=0;i<8; )beginif(!rtr_io.cb.valido_n[da])datum[i++]=rtr_io.cb.dout[da];if(rtr_io.cb.frameo_n[da])if(i==8)beginpkt2cmp_payload.push_back(datum);return;endelse begin$display ("\n%m\n [ERROR] %t Packet payload not byte aligned!\n",
$realtime);$finish;end@(rtr_io.cb)endpkt2cmp_payload.push_back(datum);endendtasktask check();string message;static int pkts_checked = 0;if (!compare(message)) begin$display ("\n%m\n [ERROR] %t Packet #%0d %s\n", $realtime, pkts_checked, message);$finish ; end$display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);endtaskfunction compare();if(payload.size()!=pkt2cmp_payload.size())beginmessage = "Payload Size Mismatch:\n";message = { message, $sformatf("payload.size() = %0d, pkt2cmp payload.size () = %0d\n", payload.size (), pkt2cmp_payload.size() ) };return(0);endif(payload==pkt2cmp_payload);else beginmessage = "Payload Content Mismatch:\n";message = {message, $sformatf("Packet Sent: %p\n Pkt Received: %p",payload, pkt2cmp_payload) };return(0);endmessage = "Successfully Compared";return (1);endfunction
/*>====================================endtask========================================<*/endprogram
Synopsys SV Lab Guide—lab3相关推荐
- Synopsys SV Lab Guide—lab2
目录 0.前言 1.全局变量声明 2.定义generator产生随机激励 3.将随机激励驱动到DUT上 4.仿真波形 5.值得注意的细节 0.前言 该lab的目标有以下2点: 1.写一个generat ...
- Synopsys SV lab guide—lab1
目录 0.前言 1.Interface代码 1.1声明接口 1.2声明clocking block 1.3声明modport 2.test代码 3.Test Harness 文件 4.波形文件 0.前 ...
- Synopsys SV Lab Guide—router简介
目录 1.管脚图 2.设计说明 3.复位协议 4.输入信号协议 5.输出信号协议 1.管脚图 该router有5个输入,4个输出,除了时钟和复位端口外其它信号端口均为16bits,如上左图:需要注意的 ...
- ICC使用----ICC 1 Lab Guide学习笔记
文章目录 Preface ICC 1 Lab Guide Note: 1.Data Setup & Basic Flow(P27) Learning Objectives Create a M ...
- SV验证-3Scoreboard
SV验证-3Scoreboad验证结果 本文采用system verilog语言对一个router.v模块进行验证.参考文档为Synopsys公司2012年出版的<SystemVerilog ...
- 【IC设计】Synopsys数字IC设计流程
文章目录 数字IC设计流程 前端设计 RTL编写和HDL仿真 逻辑综合 门级仿真 形式化验证 后端设计 数据准备 set mw_phys_refs * set link_library * 数据准备 ...
- [CS144] Lab 1: stitching substrings into a byte
Lab 1: stitching substrings into a byte stream Lab Guide: Checkpoint 1: stitching substrings into a ...
- 数字电路设计资料目录内容
┃ ┣━数字集成电路350G教程和EDA工具 ┃ ┃ ┣━数字集成电路视频教程和资料_设计和验证 ┃ ┃ ┃ ┣━数字后端视频教程和配套资料 ┃ ┃ ┃ ┃ ┣━oc8051项目脚 ...
- IC前端数字验证导学
前言: 20年,真的很特殊.开学到校,需要等待:毕业答辩,需要等待:研究生复试,也是等待.漫长的等待,使得自己思考了很多,其中之一就是对"中国芯"的考量.在与师兄师姐交流后,意识到 ...
最新文章
- unity test相关
- 【转】Android兼容性测试CTS --环境搭建、测试执行、结果分析
- 架构师速成8.3-架构师必须要了解的规则(转)
- [云炬创业基础笔记]第六章商业模式测试6
- 趣学python3(30)-字典
- 博后招募 | 新加坡国立大学WING实验室招募自然语言处理方向博士后
- Luogu P2577 [ZJOI2005]午餐
- 微软Build2021今日召开,共同期待VS2022+.NET6!
- python蒙特卡洛模拟_基于Python的21点游戏蒙特卡洛模拟
- [leetcode]Next Greater Element
- python可以做系统吗_哪个操作系统更适合用来做Python开发
- Delphi中用Sender参数实现代码重用
- 示波器同步的调节方法
- 鹰式价差matlab,蝶式及鹰式价差组合策略
- hdu2586How far away ?
- PS抠印章|证件照换背景
- 【震驚】中国电信接管CDMA业务,內部FAQ (注意所有括弧的內容)
- c#窗体程序生成错误_创建一个没有窗口的程序 (C#) | 学步园
- sudo: /etc/sudoers.d 可被任何人写
- 为网页中的图片添加水印的效果
热门文章
- print driver host for applications 已停止工作
- C#整数(包括正数和负数)与十六进制byte[]的互相转换(两字节)
- vue nuxt 服务器渲染和缓存
- 应用支持向量机对婴儿EEG数据进行多元模式分析
- 基于数据融合和串级PID的小型四旋翼无人机高度测量与控制系统
- 计算机应用基础实训报告,计算机应用基础教学小结
- excel 按数据拆分 xlam_Excel表格把数据按类别快速拆分到不同工作表或工作簿
- 高通AR Unity播放器特性
- multisim收敛助手有啥用_登记注册小助手“减肥”了……
- python变量快速学习_如何快速的复习学习过的Python