时钟采样和驱动
1. 时钟采样和驱动
采样和数据和数据驱动问题:

上图中,clk2表面上跟随clk1的变化,但是实际上clk2滞后clk1一个delta-cycle(如下图);同时,数据d1的变化也在clk上升沿后的一个delta-cycle,与clk2同时变化。所以,由于各种可能性,clk与被采样数据之间可能只存在N个delta-cycle的延迟,那么采样可能会存在问题,例如上面的例子中,clk1和clk2对d1采样,在同样的时刻中得到不同的采样结果。为了避免这种采样数据中的竞争问题,有如下两种解决办法:
1.在驱动时,添加相应的人为延迟。模拟真实的延迟行为,同时加大与变量之间的延迟,以此提高DUT使用信号的准确度和TB采样信号的可靠性。
2.对于一些采样时仍然存在delta-cycle延迟信号,我们还可以依靠在采样事件前的某段时刻进行采样,来模拟建立事件的采样要求,确保采样的可靠性。
上述两种办法的本质就是使用时钟块(clocking)
clocking块基于时钟周期对信号进行驱动或采样方式,是的testbench不再苦恼于如何准确及时对信号驱动或者采样,消除信号竞争问题。

`timescale 1ns/1ps
module tb5;
bit clk1,clk2 ;
bit rstn ;
logic [7:0] d1 ;
initial begin
forever #5 clk1 = ~clk1;
end
always @(clk1) clk2 <= clk1 ;
initial begin
#10 rstn <= 0 ;
#20 rstn <= 1 ;
end
always @(posedge clk1 or negedge rstn) begin
if(!rstn) d1 <= 0 ;
else begin
d1 <= d1 + 1 ;
end
end
always @(posedge clk1) begin
$display("@clk1 posedge %0t : d1 = %0d",$time,d1);
end
always @(posedge clk2) begin
$display("@clk2 posedge %0t : d1 = %0d",$time,d1);
end
endmodule
- 默认情况下,时钟对于组合电路的驱动会添加一个无限最小时间Δcycle的延迟,Δcycle比仿真的时间精度还小
- 在一个时间片time-slot中可以发生很多事情,run 0ns即是让仿真器运行一个Δcycle的时间
如何严格的看延迟?
可以查看delta-cycle,得到更准确的时序关系。
将光标选中波形上的clk1,再将时间轴选中到clk1在45ns处的上升变化沿,然后选中工具栏的“expanded time delta mode”,再选中“expanded time at active cursor”,这样就可以观察在特定时间点,时序逻辑或者组合逻辑中,参与硬件模拟仿真的硬件变量之间的准确时序前后关系。

clk2是用一个组合逻辑跟着clk1跳转的,所以clk2要比clk1晚一个Δcycle(45ns+0→45ns+1,"1"代表一个Δcycle),d1同理,所以clk2与d1是同步的。
clk1采对了,clk2没采对,要在d1稳定前采样,即clk1到45ns的上升沿之前采样(产生Δcycle之前)。
在“45ns+0(delta-cycle)”处,clk1=1,clk2=0,d1=1
在“45ns+1(delta-cycle)”处,clk1=1,clk2=1,d1=2
clk与被采样数据之间如果有若干个Δcycle的延迟,那么采样可能会存在竞争问题,例如上例中clk1与clk2在同一时刻(仿真器认为的同一时刻)对d1的采样不同,因此应当消除竞争问题来提高采样准确性:
采样:对于采样时存在Δcycle延迟的信号,在采样事件前的某段时刻(如1ps)进行采样,来模拟建立时间的采样要求
驱动:在驱动时添加人为延迟(如1ps),通过放大clk与变量之间的延迟来模拟真实的延迟行为
1.1 竞争问题
为了避免在RTL仿真行为中发生的信号竞争问题,建议通过非阻塞赋值或特定的信号延迟来解决同步的问题。
默认情况下,时钟对于组合电路的驱动会添加一个无限最小时间(delta-cycle)的延迟,而该延迟无法用绝对时间单位衡量,它要比最小时间单位精度还小。
在一个时间片(time-slot)中可以发生很多事情,例如在仿真器中敲命令“run 0”,即是让仿真器运行一个无限最小时间,一个时间片包含无限多个delta-cycle。 s > ms > ns > ps > fs > delta-cycle
一个time-slot中包含无穷多个delta-cycle。
查看delta-cycle可以观察在特定时间点,时序逻辑或组合逻辑中,参与硬件模拟仿真的硬件变量之间的准确时序前后关系。
由于各种可能性,clk与被采样数据之间如果只存在若干个delta-cycle的延迟,那么采样可能会存在问题,在同样的时刻中得到的是不同的采样结果,因此采样数据中的竞争问题会成为潜在困扰仿真采样准确性的问题。
1.2 如何避免采样的竞争问题
在驱动时,添加相应的人为延迟。模拟真实的延迟行为,同时加大clk与变量之间的延迟,以此提高DUT使用信号时的准确性和TB采样信号时的可靠性。
对于一些采样时依然存在的delta-cycle延迟的信号,我们还可以依靠在采样事件前的某段时刻进行采样,来模拟建立时间的采样要求,确保采样的可靠性。
1.3 接口中的clocking
clocking bus@(posedge clock1);
default input #10ns output #2ns;
input data,ready,enable;
output negedge ack;
input #1step addr;
endclocking
默认情况下,时钟clk会在clocking事件(clock1 上升沿)的前10ns来对其进行输入采样,在事件的后2ns对其进行输出驱动。
第四行声明了要驱动的ack信号,而驱动该信号的事件是时钟clock1的下降沿,即覆盖了原有的默认输出事件(clock1上升沿后的2ns)
addr也采用了自己定义的采样事件,即clock2上升沿前的1step,这里的1step会使得采样发生在clock1上升沿的上一个时间片采样区域,即可以保证采样到的数据是上一个时钟周期的数据。
在采样事件前某段时刻中进行采样;在驱动时,添加相应的人为延迟,即常说的建立时间和保持时间的概念,也刚好符合时序逻辑中时钟采样的是上一个时刻的数据,驱动的输出相对时钟上升沿延迟一定时间。


clocking可以定义在interface module program中,

将采样偏移量抽象为物理中的建立时间,要求在时钟上升沿前一段时间数据不能有变化;上图中的“采样vld"和“采样ck_cld"中,值的变化均发生在时钟上升沿,但采样点不同
硬件世界和软件世界的连接可以通过灵活的interface实现,也可以通过modport来进一步限定信号传输的方向,避免端口的连接错误。
也可以在接口中声明clocking(时序块)和采样的时钟信号,用来做信号的同步和采样。
clocking块基于时钟周期对信号进行驱动或采样的方式,使得testbench不再苦恼于如何准确及时地对信号驱动或者采样,消除了信号竞争的问题。
clocking块不但可以定义在interface中,也可以定义在module和program中。
clocking中列举的信号不是自己定义的,而是应该由interface或其它声明clocking的模块定义的。
clocking在声明完名字之后,应该伴随着定义默认的采样事件,即“default input/output event”。如果没有定义,则会默认地在clocking采样事件前的1step对输入进行采样,在采样事件后的# 0 对输出进行驱动。
为了避免可能的采样亮争问题, verifier应该在验证环境的驱动环节就添加固定延退,使得在仿真波形中更容易体现出时钟与被驱动信号之间的时序前后关系,同时这样也便于DUT的准确处理和TB的准确采样。
如果TB在采样从DUT送出的数据,在时钟与被驱动信号之间在存在delta-cycle时,应该考虑时钟采样沿的更早时间段去模拟建立时间要求采样,这种方法也可以避免由于delta-cycle问题带来的采样竞争问题。
当我们把clocking运用到interface中,用来声明各个接口与时钟的采样和驱动关系后,可以大大提高数据驱动和采样的准确性,从根本上消除采样竞争的可能性。
clocking通过类似于物理保持时间的驱动方式来实现时钟沿叠加偏移量的延迟驱动效果;时钟沿上升沿触发赋值,但是数据真正生效是在上升沿叠加偏移量的时间点

浙公网安备 33010602011771号