sv_labs学习笔记——sv_lab5_下(System Verilog)
本文延续前一篇sv_labs学习笔记——sv_lab5_上(System Verilog),进一步学习完善lab5的内容
sv_labs学习笔记——sv_lab5_下(System Verilog)
- lab5 Braod Spectrum Verfication(下)
- 思路梳理
- 代码分析
- Packet.sv
- ReceiverBase.sv
- Receiver.sv
- Scoreboard.sv
lab5 Braod Spectrum Verfication(下)
思路梳理
计划本博文实现Packet的介绍,Reciver的介绍以及scoreboard。我们在前一节完成了数据的发送,然后执行接收,最后进行数据的比对。
代码分析
Packet.sv
packet与前面的基本保持一致。就是用本身的发送的Packet与接收的packet包进行比较。每次比较就是一包一包的比较。这里只是函数的定义,后续在scoreboard进行比较。
`ifndef INC_PACKET_SV
`define INC_PACKET_SV
class Packet;rand bit[3:0] sa, da; // random port selectionrand logic[7:0] payload[$]; // random payload arraystring name; // unique identifierconstraint Limit {sa inside {[0:15]};da inside {[0:15]};payload.size() inside {[2:4]};}extern function new(string name = "Packet");extern function bit compare(Packet pkt2cmp, ref string message);extern function void display(string prefix = "NOTE");
endclassfunction Packet::new(string name);this.name = name;
endfunctionfunction bit Packet::compare(Packet pkt2cmp, ref string message);if (payload.size() != pkt2cmp.payload.size()) beginmessage = "Payload Size Mismatch:\n";message = { message, $psprintf("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, $psprintf("Packet Sent: %p\nPkt Received: %p", payload, pkt2cmp.payload) };return(0);endmessage = "Successfully Compared";return(1);
endfunctionfunction void Packet::display(string prefix);$display("[%s]%t %s sa = %0d, da = %0d", prefix, $realtime, name, sa, da);foreach(payload[i])$display("[%s]%t %s payload[%0d] = %0d", prefix, $realtime, name, i, payload[i]);
endfunction
`endif
ReceiverBase.sv
ReceiverBase就是lab4前面的。基本上没有什么改变。该class会将接口的数据放到pkt2cmp中。
`ifndef INC_RECEIVERBASE_SV
`define INC_RECEIVERBASE_SV
class ReceiverBase;virtual router_io.TB rtr_io; // interface signalsstring name; // unique identifierbit[3:0] da; // output port to monitorlogic[7:0] pkt2cmp_payload[$]; // actual payload arrayPacket pkt2cmp; // actual Packet objectextern function new(string name = "ReceiverBase", virtual router_io.TB rtr_io);extern virtual task recv();extern virtual task get_payload();
endclassfunction ReceiverBase::new(string name, virtual router_io.TB rtr_io);if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, name);this.name = name;this.rtr_io = rtr_io;this.pkt2cmp = new();
endfunctiontask ReceiverBase::recv();static int pkt_cnt = 0;if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);this.get_payload();this.pkt2cmp.da = da;this.pkt2cmp.payload = this.pkt2cmp_payload;this.pkt2cmp.name = $psprintf("rcvdPkt[%0d]", pkt_cnt++);
endtasktask ReceiverBase::get_payload();if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);this.pkt2cmp_payload.delete();forkbegin: wd_timer_forkfork: frameo_wd_timer@(negedge this.rtr_io.cb.frameo_n[da]);beginrepeat(10000) @(rtr_io.cb);$display("\n%m\n[ERROR]%t Frame signal timed out!\n", $realtime);$finish;endjoin_any: frameo_wd_timerdisable fork;end: wd_timer_forkjoinforever beginlogic[7:0] datum;for (int i=0; i<8; ) beginif (!this.rtr_io.cb.valido_n[da])datum[i++] = this.rtr_io.cb.dout[da];if (this.rtr_io.cb.frameo_n[da])if (i == 8) beginthis.pkt2cmp_payload.push_back(datum);return;endelse begin$display("\n%m\n[ERROR]%t Packet payload not byte aligned!\n", $realtime);$finish;end@(this.rtr_io.cb);endthis.pkt2cmp_payload.push_back(datum);end
endtask
`endif
Receiver.sv
每一次发送结束,将发送的信息送到out_box,然后准备使用scoreboard进行比较。所有的receiver都将接收到的数据放入一个mailbox中。这里放入的顺序是依次放入的。
`ifndef INC_RECEIVER_SV
`define INC_RECEIVER_SV
`include "ReceiverBase.sv"
class Receiver extends ReceiverBase;pkt_mbox out_box; // Scoreboard mailboxextern function new(string name = "Receiver", int port_id, pkt_mbox out_box, virtual router_io.TB rtr_io);extern virtual task start();
endclass: Receiverfunction Receiver::new(string name, int port_id, pkt_mbox out_box, virtual router_io.TB rtr_io);super.new(name, rtr_io);if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);this.da = port_id;this.out_box = out_box;endfunction: newtask Receiver::start();if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);forkforever beginthis.recv();beginPacket pkt = new pkt2cmp;//使用new进行对象的复制this.out_box.put(pkt);endendjoin_noneendtask: start
`endif
Scoreboard.sv
只有一个checker,怎么能使得可以监测对比所有的数据呢?这里是一但receiver_mbox有数据,就将
`ifndef INC_SCOREBOARD_SV
`define INC_SCOREBOARD_SV
class Scoreboard;string name; // unique identifierevent DONE; // flag to indicate goal reachedPacket refPkt[$]; // reference Packet arrayPacket pkt2send; // Packet object from DriversPacket pkt2cmp; // Packet object from Receiverspkt_mbox driver_mbox; // mailbox for Packet objects from Driverspkt_mbox receiver_mbox; // mailbox for Packet objects from Receiversextern function new(string name = "Scoreboard", pkt_mbox driver_mbox = null, receiver_mbox = null);extern virtual task start();extern virtual task check();
endclass: Scoreboardfunction Scoreboard::new(string name, pkt_mbox driver_mbox, receiver_mbox);if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, name);this.name = name;if (driver_mbox == null) driver_mbox = new();this.driver_mbox = driver_mbox;if (receiver_mbox == null) receiver_mbox = new();this.receiver_mbox = receiver_mbox;
endfunction: newtask Scoreboard::start();if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);forkforever beginthis.receiver_mbox.get(this.pkt2cmp);//将recv收集到的数据拿出一个放入pkt2cmp里,准备比较while (this.driver_mbox.num()) begin //num的值是大于0的整数,其在这里表示条件语句的‘1’,为真。所以就执行语句Packet pkt;this.driver_mbox.get(pkt);this.refPkt.push_back(pkt);//向队列中放packet数据endthis.check();endjoin_none//为了不在rest.sv中阻塞下面的进程,使用join_none不同于Generator的start函数
endtask: starttask Scoreboard::check();int index[$];string message;static int pkts_checked = 0;if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);index = this.refPkt.find_first_index() with (item.da == this.pkt2cmp.da);//返回一个队列,item是队列里的那些packet。有可能refPkt里有很多包,因此需要同时if (index.size() <= 0) begin$display("\n%m\n[ERROR]%t %s not found in Reference Queue\n", $realtime, pkt2cmp.name);this.pkt2cmp.display("ERROR");$finish;endthis.pkt2send = refPkt[index[0]]; //将队列中的元素(Packet)取出,放到pkt2send this.refPkt.delete(index[0]);//将Packet从队列中删除if (!this.pkt2send.compare(this.pkt2cmp, message)) begin$display("\n%m\n[ERROR]%t Packet #%0d %s\n", $realtime, pkts_checked, message);this.pkt2send.display("ERROR");this.pkt2cmp.display("ERROR");$finish;end$display("[NOTE]%t Packet #%0d %s!!!!!!", $realtime, pkts_checked++, message);if (pkts_checked >= run_for_n_packets)->this.DONE;
endtask: check
`endif
sv_labs学习笔记——sv_lab5_下(System Verilog)相关推荐
- sv_labs学习笔记——sv_lab5_上(System Verilog)
本节将介绍lab5的第一部分,主要总结一般设计学习与思考的方式与需要着重学习的点,同时以lab5作为参考,分析数据流流向,验证组件的通信与抽象化,实现的整体思路. sv_labs学习笔记--sv_la ...
- sv_labs学习笔记 专栏说明博文目录
栏目说明 专栏主要提供sv_labs学习过程中笔者认为比较重要的点以及相关延申.本文假设读者已经具有相关语言的背景.不会过分纠结语言本身,但会重点对于一些语言进行理解.语言的理解见笔者的另外一个专栏S ...
- sv_labs学习笔记——sv_lab4(System Verilog)
sv_labs学习笔记--sv_lab4(System Verilog) lab4 OOP encapsulation 实验概述 任务代码解析 Packat实现与理解 语法点解析 randomize( ...
- sv_labs学习笔记——sv_lab3(System Verilog)
这里我们在前两个lab的基础上继续完善,搭建一个数据接受的功能.在lab2 中我们实现了相关发送信息的打印,选择发送接受的端口,完善发送时序,在这一小节中将实现对端口发送数据的回收,然后进行比较发送的 ...
- sv_labs学习笔记——sv_lab2(System Verilog)
该博文在lab1的基础上,根据说明以及solution里的文件,实现了接口发送时序.简单对代码进行分析.分析的内容在文章的注释区中.对于不是很清楚的语法进行解释.最后在原文件的基础上给出增加了相关打印 ...
- sv_labs学习笔记——sv_lab1(System Verilog)
sv_labs学习笔记--sv_lab1(System Verilog) 概述 lab1 功能简述 代码分析 仿真精度 理解repeat(15) @(rtr_io.cb); 理解$timeformat ...
- 2020年Yann Lecun深度学习笔记(下)
2020年Yann Lecun深度学习笔记(下)
- 2021-11-16派森编程学习笔记“上帝视角下的游戏操盘手” 通过类的继承学会了复用代码,减少代码冗余,提高编程效率。
派森编程学习笔记"上帝视角下的游戏操盘手" [自学笔记] 继承 在Python中继承是指:在类的基础上,它可以实现现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩 ...
- 【Python学习笔记】下划线的含义
[Python学习笔记]下划线的含义 1.单前导下划线_var 2. 单末尾下划线var_ 3. 双前导下划线__var 4. 双前导和末尾下划线__var__ 5. 单下划线_ 在Python中单下 ...
最新文章
- 告别无止境的增删改查:Java代码生成器
- java B2B2C Springboot电子商务平台源码-SSO单点登录之OAuth2.0登录认证
- python处理mysql数据结构_python环境下使用mysql数据及数据结构和二叉树算法(图)...
- python comprehensions_Python_基础
- 数据科学 IPython 笔记本 7.3 Pandas 数据操作
- 从淘宝第1位程序员, 到阿里合伙人,20多年了,非科班出身的他还在编程,程序员的榜样
- PHP计划任务:如何使用Linux的Crontab执行PHP脚本(转载)
- 我的Android进阶之旅------Android检测wifi连接状态
- 简单易用的安装文件制作工具NSIS的使用demo示例
- 最新消息!Cloudera 全球发行版正式集成 Apache Flink
- android桌面快捷网页,Android向桌面添加快捷方式,使其指向特定的网页
- Windows驱动签名,还需要使用EV代码签名证书吗?
- HTML5基础网页设计(加代码CSS)
- MATLAB中minDiff,findpeaks,diff, intersect等函数详解
- 比知识更重要的,是元认知和深度思考
- [转]那些著名或非著名的iOS面试题(上)
- Altium desiger10安装破解过程
- ssh连接失败报错:Socket error Event: 32 Error: 10053.
- golang 读取Response Body 超时问题
- 以太坊开发框架——Truffle的基础使用
热门文章
- Consul 服务注册与发现一站式解决方案
- JS 字符串编码函数(解决URL特殊字符传递问题):escape()、encodeURI()、encodeURIComponent()区别详解
- JMETER java.net.SocketException: Connection reset 报错解决方案
- 解决Vue循环中子组件不实时更新的问题
- 对服务与工厂感到困惑
- 表单防重复提交拦截器
- dwa轨迹规划,局部路径规划
- Spring IOC p名称空间的使用-了解
- SimpleDateFormat时间日期格式化,时间日期类使用示例
- python36.dll下载_python36.dll