1.竞争问题
如何避免采样的竞争问题:1)在驱动时,添加相应的人为延迟
2)在采样事件前某段时刻中进行采样
例题1:
已知在45ns处,clk1在上升沿处采样得到d1的数值为1,那么clk2在45ns处,采样得到的d1数值应为多少呢?
A 2 B 1 C 0
例题代码如下:
`timescale 1ns/1ps
module race1;
bit clk1,clk2;
bit rstn;
logic [7:0] d1;
initial begin
forever #5 clk <= !clk;
end
always @ (clk1) clk2 <= clk1;
initial begin
#10 rstn <= 0;
#20 rstn <= 1;
end
always @ (posedge clk1,negedge rstn) begin
if (!rstn )
d1 <= 0;
else
d1 <= d1 + 1;
end
always @ (posedge clk1)
$display("%0t ns d1 value is 0x%0x",time,d1);
always @ (posedge clk2)
$display("%0t ns d1 value is 0x%0x",time,d1);
endmodule
解析:由代码 always @ (clk1) clk2 <= clk1;可知,clk2比clk1慢一拍,所以当clk1采到为1时,clk2采到的应该是0.
可以看到45ns时,clk1 = 1,clk2 = 0,所以clk2还没进行下一次采样。
一个time-slot中包含无穷多个delta-cycle
2.接口中的clocking
在interface中可以定义多个clocking,同一个变量在不同clocking中可以声明不同方向。
3.分析代码
module clocking1;
bit vld;
bit grt;
bit clk;
clocking ck @ (posedge clk);
default input #3ns output #3ns;
input vld;
output grt;
endclocking
initial forever #5ns clk <= !clk;
initial begin : drv_vld
$display("$%0t vld initial value id %d",$time,vld);
#3ns vld = 1; $display("$%0t vld is assigned %d",$time,vld);
#10ns vld = 0; $display("$%0t vld is assigned %d",$time,vld);
#8ns vld = 1; $display("$%0t vld is assigned %d",$time,vld);
end
initial forever // @ck == @(posedge clk)
@ck $display ("$%0t vld is sampled as %d at sampling time $%0t",$time,vld,$time);
initial forever
@ck $display ("$%0t ck.vld is sampled as %d at sampling time $%0t",$time,ck.vld,$time-3);
initial begin : drv_grt
$display("$%0t grt initial value is %d",$time,grt);
@ck ck.grt <= 1;$display ("$%0t grt is assigned 1",$time);
@ck ck.grt <= 0;$display ("$%0t grt is assigned 0",$time);
@ck ck.grt <= 1;$display ("$%0t grt is assigned 1",$time);
end
initial forever
@grt $display ("$%0t grt is dviven sa %d",$time,grt);
endmodule
a.代码中采用时钟块的采样时序图(ck.vld)
采样时序中,第一个上升沿采到的应该是1,但因为添加了时钟块,提前3ns采样,所以采到的为0,所以采样ck.vld在第一个上升沿显示为0。
b.代码中采用时钟块的驱动时序图
同理,第一个上升沿的驱动为1,但因为添加了时钟块,所以要延时3ns显示,所以grant的1比上升沿晚了3ns
4.结论