本文延续前一篇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)相关推荐

  1. sv_labs学习笔记——sv_lab5_上(System Verilog)

    本节将介绍lab5的第一部分,主要总结一般设计学习与思考的方式与需要着重学习的点,同时以lab5作为参考,分析数据流流向,验证组件的通信与抽象化,实现的整体思路. sv_labs学习笔记--sv_la ...

  2. sv_labs学习笔记 专栏说明博文目录

    栏目说明 专栏主要提供sv_labs学习过程中笔者认为比较重要的点以及相关延申.本文假设读者已经具有相关语言的背景.不会过分纠结语言本身,但会重点对于一些语言进行理解.语言的理解见笔者的另外一个专栏S ...

  3. sv_labs学习笔记——sv_lab4(System Verilog)

    sv_labs学习笔记--sv_lab4(System Verilog) lab4 OOP encapsulation 实验概述 任务代码解析 Packat实现与理解 语法点解析 randomize( ...

  4. sv_labs学习笔记——sv_lab3(System Verilog)

    这里我们在前两个lab的基础上继续完善,搭建一个数据接受的功能.在lab2 中我们实现了相关发送信息的打印,选择发送接受的端口,完善发送时序,在这一小节中将实现对端口发送数据的回收,然后进行比较发送的 ...

  5. sv_labs学习笔记——sv_lab2(System Verilog)

    该博文在lab1的基础上,根据说明以及solution里的文件,实现了接口发送时序.简单对代码进行分析.分析的内容在文章的注释区中.对于不是很清楚的语法进行解释.最后在原文件的基础上给出增加了相关打印 ...

  6. sv_labs学习笔记——sv_lab1(System Verilog)

    sv_labs学习笔记--sv_lab1(System Verilog) 概述 lab1 功能简述 代码分析 仿真精度 理解repeat(15) @(rtr_io.cb); 理解$timeformat ...

  7. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  8. 2021-11-16派森编程学习笔记“上帝视角下的游戏操盘手” 通过类的继承学会了复用代码,减少代码冗余,提高编程效率。

    派森编程学习笔记"上帝视角下的游戏操盘手" [自学笔记] 继承 在Python中继承是指:在类的基础上,它可以实现现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩 ...

  9. 【Python学习笔记】下划线的含义

    [Python学习笔记]下划线的含义 1.单前导下划线_var 2. 单末尾下划线var_ 3. 双前导下划线__var 4. 双前导和末尾下划线__var__ 5. 单下划线_ 在Python中单下 ...

最新文章

  1. 告别无止境的增删改查:Java代码生成器
  2. java B2B2C Springboot电子商务平台源码-SSO单点登录之OAuth2.0登录认证
  3. python处理mysql数据结构_python环境下使用mysql数据及数据结构和二叉树算法(图)...
  4. python comprehensions_Python_基础
  5. 数据科学 IPython 笔记本 7.3 Pandas 数据操作
  6. 从淘宝第1位程序员, 到阿里合伙人,20多年了,非科班出身的他还在编程,程序员的榜样
  7. PHP计划任务:如何使用Linux的Crontab执行PHP脚本(转载)
  8. 我的Android进阶之旅------Android检测wifi连接状态
  9. 简单易用的安装文件制作工具NSIS的使用demo示例
  10. 最新消息!Cloudera 全球发行版正式集成 Apache Flink
  11. android桌面快捷网页,Android向桌面添加快捷方式,使其指向特定的网页
  12. Windows驱动签名,还需要使用EV代码签名证书吗?
  13. HTML5基础网页设计(加代码CSS)
  14. MATLAB中minDiff,findpeaks,diff, intersect等函数详解
  15. 比知识更重要的,是元认知和深度思考
  16. [转]那些著名或非著名的iOS面试题(上)
  17. Altium desiger10安装破解过程
  18. ssh连接失败报错:Socket error Event: 32 Error: 10053.
  19. golang 读取Response Body 超时问题
  20. 以太坊开发框架——Truffle的基础使用

热门文章

  1. Consul 服务注册与发现一站式解决方案
  2. JS 字符串编码函数(解决URL特殊字符传递问题):escape()、encodeURI()、encodeURIComponent()区别详解
  3. JMETER java.net.SocketException: Connection reset 报错解决方案
  4. 解决Vue循环中子组件不实时更新的问题
  5. 对服务与工厂感到困惑
  6. 表单防重复提交拦截器
  7. dwa轨迹规划,局部路径规划
  8. Spring IOC p名称空间的使用-了解
  9. SimpleDateFormat时间日期格式化,时间日期类使用示例
  10. python36.dll下载_python36.dll