01-Verilog and SystemVerilog Gotchas

gotcha 56 verifying asynchronous and synchronous reset ai time zero

initial和always块在zero time时候的执行顺序是不确定的。在zero time时,复位(复位沿发生在检测复位的逻辑之前或之后)或者时钟上升沿(上升沿发生在always语句之前或之后)可能出现不确定的执行结果。

特别时tb和dut之间信号的先后问题。

对于异步复位电路,如下所示,test模块中在0时刻有一个reset_n的下降沿(从x到0可以认作是个下降沿),所以我们期待的执行顺序是,chip module中always先执行,遇到事件控制阻塞,然后chip module中的initial开始执行,产生一个reset_n的下降沿,此时激活chip中的always块语句。但实际中always和initial的顺序是不确定的。

img

img

异步复位的解决方法:

一、在initial中reset_n信号采用非阻塞赋值,这样reset_n的非阻塞赋值过程在所有的过程块激活之后才执行。

二、SV中的program块,program有验证语义,在SV的仿真队列中,先执行design的语句,然后才执行verification语句,所以chipmodule中的always先执行,test program中的initial后执行。

对于同步复位电路:在0时刻有一个时钟上升沿,期望在时钟上升沿之前,chip module中的always和test moduloe中的initial都执行了,这样在出现时钟上升沿的时候,always才会触发,if语句才会有效。

img

img

同步复位解决:

top module中的clock信号赋值采用非阻塞赋值,等待always 和initial都执行之后才赋值。

program并不能解决这个同步复位问题。

gotcha 58 Evaluation of equality with 4-state values

全等、全不等是按位比较,也比较x和z。

img

gotcha 59 Event trigger race conditions

Verilog中的event竞争。

initial和always在0时刻执行顺序不确定导致,握手触发不能启动。

img

解决:#0 在所有的块语句激活之后再执行。但是不建议使用#0,会引起其他问题

img

SV中的解决方法:

一、非阻塞的事件触发->>,在当前仿真事件内延迟delta,等待其他的块语句都执行完了再执行,效果跟#0类似。

img

二、SV中有wait代替@,触发事件在wait语句之前后者之后发生都可以。

下面例子中,如果initial在always之前发生了,当always的wait语句执行时候,之前触发依旧可见。

用wait,事件触发在当前仿真事件的所哟阶段都是可见的。

img

gotcha 60 using semaphores

当get()请求不到所需要的keys的时候,比如请求4个keys,但此时semaphore中只有两个keys,进程会被阻塞,get()操作放到FIFO中。但是如果接下来另一个进程中的get()只请求1个keys,那么这个get()会被允许,这是不应该的。因为第二个get()操作在第一个get()操作之后,如下面的所示:

img

解决方法是:每个get()操作至请求一个key,这样只要有key available那么FIFO中第一个get()就被执行。