SystemVerilog系列实验4-2

SYNOPSYS—SystemVerilog入门实验4-2


前言

在结束了实验4-1,接下来我们还需完成以下目标来结束整个实验4:

  1. 生成随机的数据包对象发送至DUT;
  2. 接收来自DUT发送出来的数据包;
  3. 对比相对于DUT输入与输出的数据包。

一、在Lab3的基础上修改

复制Lab3下的test.sv至Lab4下,并打开。

1. 修改 gen ()

将Lab3中的 task gen() 内的部分全部删除

i. 增加 `include

为了将 Packet.sv 包含进 test.sv 中,在这里需使用 `include 语句,该语句具体语法戳此链接。

`timescale 1ns/100ps
program automatic test(router_io.TB rtr_io);
  //******add 1******
  `include "Packet.sv"  
  //******add 1****** 
  int run_for_n_packets;      // number of packets to test
  bit[3:0] sa;                        // source address
  bit[3:0] da;                        // destination address
  logic[7:0] payload[$];              // expected packet data array
  
  
initial begin   
    run_for_n_packets = 2000;
      reset();
    repeat(run_for_n_packets) begin
      gen();    
      fork
        send();
        recv();
      join
      check();   
    end
    repeat(10) @(rtr_io.cb);    
end
  
  task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.cb.frame_n <= '1;
    rtr_io.cb.valid_n <= '1;
    #2 rtr_io.cb.reset_n <= 1'b1;
    repeat(15) @(rtr_io.cb);
  endtask: reset 
endprogram: test

ii. 声明静态变量 pkts_generated

其主要作用是记录DUT的输入端口共接收了多少组数据包。

`timescale 1ns/100ps
program automatic test(router_io.TB rtr_io);
  //******add 1******
  `include "Packet.sv"  
  //******add 1****** 
  int run_for_n_packets;      // number of packets to test
  bit[3:0] sa;                        // source address
  bit[3:0] da;                        // destination address
  logic[7:0] payload[$];              // expected packet data array
  
  
initial begin   
    run_for_n_packets = 2000;
      reset();
    repeat(run_for_n_packets) begin
      gen();    
      fork
        send();
        recv();
      join
      check();   
    end
    repeat(10) @(rtr_io.cb);    
end
  
  task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.cb.frame_n <= '1;
    rtr_io.cb.valid_n <= '1;
    #2 rtr_io.cb.reset_n <= 1'b1;
    repeat(15) @(rtr_io.cb);
  endtask: reset 
  task gen();
  //******add 2******
	static int pkts_generated = 0;
  //******add 2******
  endtask: gen 
endprogram: test

iii. 定义 发送至DUT(输入变量)的数据包的名称 pkt2send

在定义名称前,应首先声明一个句柄并为其开辟空间!不由想到:输入变量可以定义一个packet,那么输出变量是否也可以定义。这里的输出变量要经过数据比较器 (checker) 与输入变量进行比对,那么就不妨定义为pkt2cmp即可。

`timescale 1ns/100ps
program automatic test(router_io.TB rtr_io);
  //******add 1******
  `include "Packet.sv"  
  //******add 1****** 
  int run_for_n_packets;      // number of packets to test
  bit[3:0] sa;                        // source address
  bit[3:0] da;                        // destination address
  logic[7:0] payload[$];              // expected packet data array
  
  
  //******add 4******
  Packet pkt2send = new();
  Packet pkt2cmp  = new();
  //******add 4******  
  
initial begin   
    run_for_n_packets = 2000;
      reset();
    repeat(run_for_n_packets) begin
      gen();    
      fork
        send();
        recv();
      join
      check();   
    end
    repeat(10) @(rtr_io.cb);    
end
  
  task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.cb.frame_n <= '1;
    rtr_io.cb.valid_n <= '1;
    #2 rtr_io.cb.reset_n <= 1'b1;
    repeat(15) @(rtr_io.cb);
  endtask: reset 
  task gen();
  //******add 2******
	static int pkts_generated = 0;
  //******add 2******
 
  //******add 3******
    pkt2send.name = $sformatf("Packet[%0d]", pkts_generated++);
  //******add 3******
 
  endtask: gen 
endprogram: test

在这里需使用 $sformatf 内建函数,该函数具体语法戳此链接。

iv. 设置随机化失败即退出语句

`timescale 1ns/100ps
program automatic test(router_io.TB rtr_io);
  //******add 1******
  `include "Packet.sv"  
  //******add 1****** 
  int run_for_n_packets;      // number of packets to test
  bit[3:0] sa;                        // source address
  bit[3:0] da;                        // destination address
  logic[7:0] payload[$];              // expected packet data array
  
  
  //******add 4******
  Packet pkt2send = new();
  Packet pkt2cmp  = new();
  //******add 4******  
  
initial begin   
    run_for_n_packets = 2000;
      reset();
    repeat(run_for_n_packets) begin
      gen();    
      fork
        send();
        recv();
      join
      check();   
    end
    repeat(10) @(rtr_io.cb);    
end
  
  task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.cb.frame_n <= '1;
    rtr_io.cb.valid_n <= '1;
    #2 rtr_io.cb.reset_n <= 1'b1;
    repeat(15) @(rtr_io.cb);
  endtask: reset 
  task gen();
  //******add 2******
	static int pkts_generated = 0;
  //******add 2******
 
  //******add 3******
    pkt2send.name = $sformatf("Packet[%0d]", pkts_generated++);
  //******add 3******
 
  //******add 5******
	if(!pkt2send.randomize()) begin
	  $display("\n%m\n [ERROR] %t: Randomize Error!!", $realtime);
      $finish;
	end
  //******add 5******  
  endtask: gen 
endprogram: test

在这里需使用 $display 、 $finish 内建函数,该函数具体语法戳此链接。

v. 信号sa、da、队列payload实现同步

大家是否还记得Lab3中关于数据发送 task send() 内的语句块:根据DUT接收的时序,我们将模拟该时序把数据串行地发送进DUT,而这些数据都需要由外部的激励产生,在这里外部的激励即为 Packet.sv ,因此我们需将 Packet.sv 生成的随机数据更新至 test.sv 中。

`timescale 1ns/100ps
program automatic test(router_io.TB rtr_io);
  //******add 1******
  `include "Packet.sv"  
  //******add 1****** 
  int run_for_n_packets;      // number of packets to test
  bit[3:0] sa;                        // source address
  bit[3:0] da;                        // destination address
  logic[7:0] payload[$];              // expected packet data array
  
  
  //******add 4******
  Packet pkt2send = new();
  Packet pkt2cmp  = new();
  //******add 4******  
  
initial begin   
    run_for_n_packets = 2000;
      reset();
    repeat(run_for_n_packets) begin
      gen();    
      fork
        send();
        recv();
      join
      check();   
    end
    repeat(10) @(rtr_io.cb);    
end
  
  task reset();
    rtr_io.reset_n = 1'b0;
    rtr_io.cb.frame_n <= '1;
    rtr_io.cb.valid_n <= '1;
    #2 rtr_io.cb.reset_n <= 1'b1;
    repeat(15) @(rtr_io.cb);
  endtask: reset 
  task gen();
  //******add 2******
	static int pkts_generated = 0;
  //******add 2******
 
  //******add 3******
    pkt2send.name = $sformatf("Packet[%0d]", pkts_generated++);
  //******add 3******
 
  //******add 5******
	if(!pkt2send.randomize()) begin
	  $display("\n%m\n [ERROR] %t: Randomize Error!!", $realtime);
      $finish;
	end
  //******add 5******
  
  //******add 6******
	sa = pkt2send.sa;
	da = pkt2send.da;
	payload = pkt2send.payload;  
  //******add 6******  
  endtask: gen 
endprogram: test

至此,task gen() 已更新完毕。

2. 修改 recv ()

i. 声明静态变量 pkt_cnt

其主要作用是记录DUT的输出端口共发出了多少组数据包。

  task recv();
  //******add 1******
	static int pkt_cnt = 0;
  //******add 1******
    get_payload();  
  endtask: recv

ii. 定义 DUT发送(输出变量)的数据包名称 pkt2cmp

  task recv();
  //******add 1******
	static int pkt_cnt = 0;
  //******add 1******
    get_payload(); 
   
  //******add 2******    
	pkt2cmp.name = $sformatf("rcvdPkt[%0d]", pkt_cnt++); 
  //******add 2****** 	

  endtask: recv

iii. 信号da、队列payload实现同步

在数据比较时,若对比失败,我们希望能够明确DUT发送出来的队列payload是通过哪个通道传递的,这样对于定位问题会起到积极的作用。

  task recv();
  //******add 1******
	static int pkt_cnt = 0;
  //******add 1******
    get_payload(); 
   
  //******add 2******    
	pkt2cmp.name = $sformatf("rcvdPkt[%0d]", pkt_cnt++); 
  //******add 2****** 	

  //******add 3******    
	pkt2cmp.da = da;
	pkt2cmp.payload = pkt2cmp_payload;
  //******add 3****** 	

  endtask: recv

至此,task recv() 已更新完毕。

3. 修改 check ()

将Lab3中的 function bit compare() 内的部分全部删除。

i. 修 if (…) …begin 中的判断条件

task check() 任务中,我们把 function bit compare 放入Packet对象中,目的使验证发送和接收的数据是否正确。为了debug,我们需将错误的具体信息均进行打印。
需要说明的是,!pkt2send.compare(pkt2cmp, message) 是根据 Packet.svfunction bit Packet::compare 的返回值进行判断的,当数据错误返回0,反之返回1。

  task check();
    string message;
    static int pkts_checked = 0;  
  //******add 1******
    if (!pkt2send.compare(pkt2cmp, message)) begin
      $display("\n%m\n[ERROR]%t Packet #%0d %s\n", $realtime, pkts_checked, message);
	  pkt2send.display();
	  pkt2cmp.display();	  
  //******add 1******
      $finish;
    end
    $display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);
  endtask: check

至此,task check() 已更新完毕。
将test.sv文件保存并关闭,随即启动仿真即可。


二、总结

在这里插入图片描述

该部分实验主要将红色箭头指向的三部分进行了环境完善,至此,一个进一步优化的验证环境搭建完毕,感谢大家支持。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的隼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值