Synopsys SV Lab Guide—lab2

目录

0.前言

1.全局变量声明

2.定义generator产生随机激励

3.将随机激励驱动到DUT上

4.仿真波形

5.值得注意的细节


0.前言

该lab的目标有以下2点:

1.写一个generator产生随机激励

2.将generator产生的随机激励驱动给DUT,按照协议的时序

3.通过波形观察结果

该lab新添加的所有的操作都是在lab1中的test.sv文件中添加。

1.全局变量声明

       我们要给DUT发送激励,需要知道发给哪个端口,还要告诉DUT从哪个端口输出,所以首先我们要定义3个变量,如下:

bit [3:0] sa; //输入端口,16个端口,用4bits来声明
bit[3:0] da; // 输出端口
logic[7:0] payload[$];//声明一个队列,队列中每个元素为8bits,用来存储激励

2.定义generator产生随机激励

       在lab1中,我们首先利用reset()函数对DUT进行了初始化,现在需要产生随机激励,为了代码的简洁及可复用,我们通过在reset()后调用gen()函数来执行这个操作:

program automatic test (router__io.TB rtr__io);
  initial begin
    $display("Hello World!"); 
    $vcdpluson; 
    reset ();
    gen ();//调用gen函数产生随机激励
  end

/*>=====================================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); 
  endtask

  task gen();
    sa=3;//按照lab要求从3号接口输入
    da=7;//按照lab要求从7号接口输出
    payload.delete();//删除队列中所有的元素,用来将上一次产生的激励全部删除
    repeat($urandom_range(2,4)) payload.push_back($urandom);//在队列中插入2-4个8bits的随机数据
  endtask
endprogram

这里有几点需要注意: 

1.payload.delete()的作用是将上一次产生的激励删除,由于验证要随机产生无数次激励,如第一次产生了payload={1,2,3},将它们驱动到DUT上后;payload中的这些数据不会自己删除,因此第二次再产生激励前,我们要先把第一次产生的数据删除

2.$urandom_range(2,4)表示返回2-4之间一个无符号随机整数,$urandom表示返回一个32bits的无符号随机整数,这行代码就完成了一次激励的生成,即在队列中插入2-4个8bits的随机数据。当然插入2-4个数是lab2中要求的。

3.将随机激励驱动到DUT上

     数据产生之后,我们需要将数据drive到DUT的端口上,依然采用函数调用的方式,代码及讲解如下:

program automatic test (router__io.TB rtr__io);
  initial begin
    $display("Hello World!"); 
    $vcdpluson; 
    reset ();
    repeat (21) begin//产生21次激励,产生多少次激励可按照需要改变
      gen ();//调用gen函数产生随机激励
      send();//调用send函数按照协议把激励发送给DUT
    end
  end

/*>=====================================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); 
  endtask

  task gen();
    sa=3;
    da=7;
    payload.delete();
    repeat($urandom_range(2,4)) payload.push_back($urandom);数据
  endtask

  task send();//数据发送函数:由发送地址,隔离,数据3个函数组成
    send_addrs();//传输地址
    send_pad();//传输隔离带
    send_payload();//传输数据
  endtask

  task send_addrs();//根据协议写
    rtr_io.cb.frame_n[sa]<=1'b0;//根据协议,传输地址开始时,frame_n同时拉低
    for(int i=0;i<4;i++)begin//由于单个端口是单bit,因此要发4次构成4为地址
      rtr_io.cb.din[sa]<=da[i];
      @(rtr_io.cb); //作用后面讲解
    end
  endtask

  task send_pad();//根据协议写
    rtr_io.cb.frame_n[sa]<=1'b0;//隔离区frame_n继续拉低
    rtr_io.cb.valid_n[sa]<=1'b1;//隔离区valid_n拉高
    rtr_io.cb.din[sa]<=1'b1;//隔离区din拉高
    repeat(5) @(rtr_io.cb);//隔离5个5个周期
  endtask

  task send_payload();//根据协议写
    foreach(payload[index])//遍历队列中每个数据
      for(int i=0;i<8;i++)begin//将每个数据的bit挨个发送出去
         rtr_io.cb.din[sa]<=payload[index][i];//一个数据的单个bit
         rtr_io.cb.valid_n[sa]<=1'b0;//发数据的时候valid_n拉低
         rtr_io.cb.frame_n[sa]<=(index==(payload.size()-1))&&(i==7);//frame_n在队列中最后一个数据的最后一位发送时拉高,其余时候保持前面的0状态
         @(rtr_io.cb)
      end
  endtask
/*>====================================endtask========================================<*/

endprogram

4.仿真波形:

5.值得注意的细节

     在send_addrs和send_payload函数中,for循环里都有一个 @(rtr_io.cb),那这句话的作用是什么?有和没有对波形会有什么影响?

 task send_addrs();//根据协议写
    rtr_io.cb.frame_n[sa]<=1'b0;//根据协议,传输地址开始时,frame_n同时拉低
    for(int i=0;i<4;i++)begin//由于单个端口是单bit,因此要发4次构成4为地址
      rtr_io.cb.din[sa]<=da[i];
      @(rtr_io.cb); //作用是什么?
    end
  endtask
task send_payload();//根据协议写
    foreach(payload[index])//遍历队列中每个数据
      for(int i=0;i<8;i++)begin//将每个数据的bit挨个发送出去
         rtr_io.cb.din[sa]<=payload[index][i];//一个数据的单个bit
         rtr_io.cb.valid_n[sa]<=1'b0;//发数据的时候valid_n拉低
         rtr_io.cb.frame_n[sa]<=(index==(payload.size()-1))&&(i==7);//frame_n在队列中最后一个数据的最后一位发送时拉高,其余时候保持前面的0状态
         @(rtr_io.cb)//作用?
      end
  endtask

下面以send_addrs中的@(rtr_io.cb)为例,观察有和没有的波形:

有 @(rtr_io.cb)

可见波形按照预期的时间顺序1110产生 

无@(rtr_io.cb)

可见数据段直接没了,上来就干到隔离段,这是因为没有@(rtr_io.cb)等待一个clk,使得在din在一开始的posedge clk时,完成了send_addrs中所有数的赋值,而缺少了赋一个值等待一个clk,所以其不是没执行而是在posedge clk瞬间执行完了,因此在波形上看不出来,导致地址段的缺少。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值