[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
Clocking block是一种在硬件描述语言中用于指定时钟与信号之间时序要求的机制。它可以在module、interface、checker或program中声明,并且在declaration的同时就已经实例化了,不需要再进行额外的实例化操作。\[1\] Clocking block的作用是将特定时钟下的同步信号进行集合,使得测试人员能够更加专注于事务的处理,而不需要过多关注信号与时钟的交互。一个testbench可以有多个时钟块,但是每个时钟只能有一个时钟块。\[2\] 在接口块中,可以使用不同的时钟块声明来定义不同的输入倾斜。每个时钟块声明都有不同的输入信号,并且与特定的时钟相关联。这样可以更加灵活地定义不同的时序要求。\[3\] #### 引用[.reference_title] - *1* [SystemverilogClocking blocks的记录](https://blog.csdn.net/W1Z1Q/article/details/130049057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [SV : Clocking Block](https://blog.csdn.net/jerwey/article/details/122478790)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值