目录

0.前言

​1.全局变量声明

2.高层次级函数的确定

3. 接收数据函数

4.检查函数

5.仿真结果

6.完整test代码


0.前言

该lab目标有以下几点:

  1. 随机化输入端口和输出端口以全面测试DUT
  2. 写一个monitor接收DUT的输出
  3. 写一个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相关推荐

  1. Synopsys SV Lab Guide—lab2

    目录 0.前言 1.全局变量声明 2.定义generator产生随机激励 3.将随机激励驱动到DUT上 4.仿真波形 5.值得注意的细节 0.前言 该lab的目标有以下2点: 1.写一个generat ...

  2. Synopsys SV lab guide—lab1

    目录 0.前言 1.Interface代码 1.1声明接口 1.2声明clocking block 1.3声明modport 2.test代码 3.Test Harness 文件 4.波形文件 0.前 ...

  3. Synopsys SV Lab Guide—router简介

    目录 1.管脚图 2.设计说明 3.复位协议 4.输入信号协议 5.输出信号协议 1.管脚图 该router有5个输入,4个输出,除了时钟和复位端口外其它信号端口均为16bits,如上左图:需要注意的 ...

  4. ICC使用----ICC 1 Lab Guide学习笔记

    文章目录 Preface ICC 1 Lab Guide Note: 1.Data Setup & Basic Flow(P27) Learning Objectives Create a M ...

  5. SV验证-3Scoreboard

    SV验证-3Scoreboad验证结果 ​ 本文采用system verilog语言对一个router.v模块进行验证.参考文档为Synopsys公司2012年出版的<SystemVerilog ...

  6. 【IC设计】Synopsys数字IC设计流程

    文章目录 数字IC设计流程 前端设计 RTL编写和HDL仿真 逻辑综合 门级仿真 形式化验证 后端设计 数据准备 set mw_phys_refs * set link_library * 数据准备 ...

  7. [CS144] Lab 1: stitching substrings into a byte

    Lab 1: stitching substrings into a byte stream Lab Guide: Checkpoint 1: stitching substrings into a ...

  8. 数字电路设计资料目录内容

    ┃  ┣━数字集成电路350G教程和EDA工具 ┃  ┃  ┣━数字集成电路视频教程和资料_设计和验证 ┃  ┃  ┃  ┣━数字后端视频教程和配套资料 ┃  ┃  ┃  ┃  ┣━oc8051项目脚 ...

  9. IC前端数字验证导学

    前言: 20年,真的很特殊.开学到校,需要等待:毕业答辩,需要等待:研究生复试,也是等待.漫长的等待,使得自己思考了很多,其中之一就是对"中国芯"的考量.在与师兄师姐交流后,意识到 ...

最新文章

  1. unity test相关
  2. 【转】Android兼容性测试CTS --环境搭建、测试执行、结果分析
  3. 架构师速成8.3-架构师必须要了解的规则(转)
  4. [云炬创业基础笔记]第六章商业模式测试6
  5. 趣学python3(30)-字典
  6. 博后招募 | 新加坡国立大学WING实验室招募自然语言处理方向博士后
  7. Luogu P2577 [ZJOI2005]午餐
  8. 微软Build2021今日召开,共同期待VS2022+.NET6!
  9. python蒙特卡洛模拟_基于Python的21点游戏蒙特卡洛模拟
  10. [leetcode]Next Greater Element
  11. python可以做系统吗_哪个操作系统更适合用来做Python开发
  12. Delphi中用Sender参数实现代码重用
  13. 示波器同步的调节方法
  14. 鹰式价差matlab,蝶式及鹰式价差组合策略
  15. hdu2586How far away ?
  16. PS抠印章|证件照换背景
  17. 【震驚】中国电信接管CDMA业务,內部FAQ (注意所有括弧的內容)
  18. c#窗体程序生成错误_创建一个没有窗口的程序 (C#) | 学步园
  19. sudo: /etc/sudoers.d 可被任何人写
  20. 为网页中的图片添加水印的效果

热门文章

  1. print driver host for applications 已停止工作
  2. C#整数(包括正数和负数)与十六进制byte[]的互相转换(两字节)
  3. vue nuxt 服务器渲染和缓存
  4. 应用支持向量机对婴儿EEG数据进行多元模式分析
  5. 基于数据融合和串级PID的小型四旋翼无人机高度测量与控制系统
  6. 计算机应用基础实训报告,计算机应用基础教学小结
  7. excel 按数据拆分 xlam_Excel表格把数据按类别快速拆分到不同工作表或工作簿
  8. 高通AR Unity播放器特性
  9. multisim收敛助手有啥用_登记注册小助手“减肥”了……
  10. python变量快速学习_如何快速的复习学习过的Python