知识星球有一个问题,为什么在driver中使用“<=”,在monitor中使用“=”
在driver中使用非阻塞赋值(Nonblocking assignments,NBA)是为了避免竞争冒险(race conditions)问题,使得driver在“时钟边沿之后”改变驱动的数据值,这个“时钟边沿之后”指的是同一时钟边沿之后的仿真事件队列区域
对于monitor使用阻塞赋值(blocking assignments,BA),因为monitor本身就是在时钟边沿采样然后和预期值比较,不需要驱动其他变量,无需担心竞争冒险(race conditions)问题。
DUT:
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
q<= 0;
end
elsebegin
q<= d ;
end
end
在DUT中,q <= d 在仿真事件队列中的执行顺序如下:
Active region:评估d的值
NBA region:执行非阻塞赋值q <= d
阻塞driver:
repeat(10) begin
@(posedge clk) d = $random%2 ;
end
在阻塞driver中,d = $random%2在仿真事件队列中的执行顺序如下:
Active region:评估$random%2的值,并执行阻塞赋值d = $random%2
这时候我们发现对于待测设计中的q <= d评估阶段和d = $random%2的赋值阶段发生在同一个region,产生竞争冒险。如果d = $random%2的赋值阶段发生较早没有问题,但是如果q <= d评估阶段发生较早则会存在问题。
非阻塞driver:
repeat(10) begin
@(posedge clk) d <= $random%2 ;
end
如果使用非阻塞赋值d <= $random%2在仿真事件队列中的执行顺序如下:
Active region:评估$random%2的值
NBA region:执行非阻塞赋值d <= $random%2
在DUT中,q <= d 在仿真事件队列中的执行顺序依然是:
Active region:评估d的值
NBA region:执行非阻塞赋值q <= d
这样就能够避免设计的仿真的竞争冒险,#0也能达到同样的目的。
关于竞争冒险问题,一个通用的规则就是A进程写入一个变量,B进程读取这个变量,并且A进程和B进程都同步到同一个事件,必须使用非阻塞赋值来避免竞争冒险。
上述例子中的A进程就是driver,B进程就是DUT待测设计,同步事件为时钟边沿。
此外,在验证平台中program和clocking的使用也是为了同样的目的。
monitor持续对DUT进行监测,不存在竞争冒险问题,使用阻塞赋值。
本文在实验过程还存在一些问题:
1、VCS 选项-race没有检测出上述竞争冒险
2、将《UVM实战》例2.3.3中的driver中的“<=”改为“=”也没发现竞争冒险现象。
请后台大佬们指导,感激不尽~