[SystemVerilog] clocking block

clocking block

  • cb input sample 采样受 #(input skew)控制,如果#n step(n>0),采样的是前n个step的postpone区;如果#0,则是在本timestep的observed region进行采样。
  • active区会判断@(event),如果有**@(edge)这样的事件,就会准备规划后面的cb内变量采样和驱动事件,这里只是一个触发**,并不真正采样或者驱动。如果是#0采样,那么规划在observed区结束时采样,如果#nstep则不会规划在observed区结束时采样。 active区可能有不只一次规划这个事件,如果是其他区域规划了active区有时钟事件,active区就会再次规划observed区的cb.in采样
  • observed区如果有时钟事件且#0就先采样此时的值,如果没有时钟事件或者#nstep就不用采样。然后触发cb事件。让后边的区域继续处理。observed区可以被执行多次,如果active区有新的时钟事件,那么observed区就该被规划和执行与该新时钟事件相应的采样和 cb.trigger。
  • 同步驱动规划在RE-NBA区,前提是本timestep有触发事件在active区被纪录,在observed区域被触发。
  • 至此,如果输出的#(output_skew)为0,又可导致执行回到active区,并在active区触发新的时钟事件,然后按照前边的流程循环执行。如果active区没有了新的时钟事件了,那么在observed就不在执行新的采样。

在非時鐘沿去做cb賦值的時候,cb只會等到里程沿才會將值給到真正的signal。
在這種植情況下,如出現下面這種情況:
cb.a<=1;
@(cb);
cb.a<=2;
如果cb.a<=1 在沿1與沿2的中間,那么在沿2的時候,a的值將直接變為2

SOLUTION:
cb.a<=1;
@(cb);
if(cb.a!=1)
@(cb);
cb.a<=2


example1:

clocking cb @(negedge clk);
  input v;
endclocking

always @(cb) $display(cb.v);
always @(negedge clk) $display(cb.v);
  1. cb在observed区被触发,然后循环执行@cb,看到的是经过#nstep升级的,或者是#0在本timestep升级的cb.v
  2. 该事件如果在#0情况下在active区执行,看到的是旧值;如果#nstep在active区执行,看到的是nstep前的postpone区值,也可叫新值。如果#0在REACTIVE区执行,看到的本timesep升级后的值。等等情况不太确定

example2:

clocking cb @(posedge clk);
  input v;
endclocking

task tclk();
  $display($time,"  pre-clk");
  @(posedge clk);
  $display($time,"  post-clk");
endtask

task tcb();
  $display($time,"  pre-cb");
  @(cb);
  $display($time,"  post-cb");
endtask

initial begin
  fork
    begin:clk
      @(posedge clk);//active
      tclk();//next active
    end
    begin:cb
      @(posedge clk);//current active
      tcb();//current observed
    end
  join
end

result :

30     pre-clk
30     pre-cb
30     post-cb
40     post-clk

假设当前时刻是30,clock 周期是10,则其中clk 进程的两条语句执行的时间分别在30,40 ;
cb 进程的两条语句执行的时间都为30


clocking block 写法实例:

clocking bus @(posedge clock1);
  default input #10ns output #2ns;
  input data, ready, enable = top.mem1.enable;
  output negedge ack;
  input #1step addr;
endclocking

对于同一信号,经过cb比没经过cb的晚1T(与input,output无关)。比如说vif.cb.a会比vif.a delay 1T。

在验证环境中,我们通常的做法:
driver中利用cb来drive signals; 比如: vif.cb.a <= 1’b1
连接DUT时却用的是不加cb的信号;比如: .frame_in(vif.a)
monitor中用加cb的信号sample; 比如: txn.a = vif.cb.a
waveform:

                          ___
     vif.a        _______|   |_________(DUT的输入信号)
                              ___
     vif.cb.a   _____________|   |_________(monitor sample的信号)
                         1   2   3

在时钟沿采到的是沿前的值,所以monitor采到的值比DUT的值delay 1T。

上述情况是针对drive DUT input和sample DUT output;当在环境描述signal level behavior时,cb使用状况有差别。

fork 
   forever begin//进程1
    @(posedge line_ck or negedge rst_b);
     cur_vld = (rate_cnt == 0);
   end
 
   forever begin//进程2
      @(posedge line_ck or negedge rst_b);
      if(cur_vld == 1'b1)
        ......
   end
join

上面描述了两个并行进程,进程1 drive cur_vld ,进程2 sample cur_vld.
上面这种写法会产生竞争冒险,因为在同一时间既drive又sample.
此时我们想到了clocking block,它可以规避这件事。

interface vif;
      parameter setup_time = 0.05;
      parameter hold_time = 0.05;
     logic cur_vld;
     clocking line_cb @(posedge line_ck );
           default input #setup_time output #hold_time;
           inout cur_vld;
     endclocking   
endinterface


fork 
   forever begin//进程1
    @(line_cb or negedge rst_b);
     vif.line_cb.cur_vld <= (rate_cnt == 0);//驱动时加cb
   end
 
   forever begin//进程2
      @(line_cb or negedge rst_b);
      if(vif.line_cb.cur_vld === 1'b1) //采样时加cb
        ......
   end
join

上面的写法可看出: 当自己驱动自己采样时 drive signals 时用cb, sample时也用cb.

                            __
 vif.cur_vld        _______|  |_________(DUT的输入信号)
                               __
 vif.cb.cur_vld  _____________|  |_________(monitor sample的信号)
                           1  2  3

采样时加不加cb都会在位置2处采到,debug看waveform时看不加cb的信号即可。前提是格式要统一,不要混用 ,即

forever begin//进程2
      @(line_cb or negedge rst_b);//等cb
      if(vif.line_cb.cur_vld === 1'b1) //采样时加cb
        ......
   end

forever begin//进程2
      @(posedge line_ck or negedge rst_b);//等posedge clk
      if(vif.cur_vld === 1'b1) //采样时不加cb
        ......
   end
Created with Raphaël 2.2.0 开始 preponed active inactive NBA observed reactive postponed next timeslot? 结束 yes no
SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据类型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举类型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口中的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装:类 209 5.1 概述 209 5.2 类的成员 233 5.3 类的继承 245 三种类型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第九章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率类型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 类型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的类 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值