verilog验证平台技巧(避免竞争的办法)
1.在0时刻复位。
2.时钟沿之后复位
3.创建仿真时钟
4.在无效沿时刻输入激励
1.在0时刻复位。
在0时刻使用阻塞赋值让复位生效(Aen)可能会导致克争条件,为什么?因为所有的过程块在0时刻被激活。如果initial块在always块之前被激活,那么 always块就不会意识到复位生效。直到下一个 posedge clk或者下一次复位生效
例子: Race condition while asserting reset at time0
initial begin
ret_n = 0;
...
end
always@(posedge clk or negedge rst_n)
事实上,虽然 IEEE Verilog标准没有明确说明,但是大多数 Vendor的 Verilog仿真器在激话initial块之前,首先激活所有的 always块,这意味着在 inital块的复位信号执行之前, always块已经为复位信号准备好(等待复位的到来)。
但是设计者不应该依赖于这样的激活顺序( initial块在 always块之后激活)。避免这个竟争条件:的简单方法是:如果要让第一个复位信号在0时刻起效,那么就使用非阻塞赋值。对复位使用非阻塞赋值会强制复位信号在0时刻的最后执行,这时所有的 always块已经被激活,当复位信号在0时刻被更改时,就会触发 always块执行复位
例子: No race condition while asserting reset at time 0
initial begin
ret_n <= 0;
...
end
always@(posedge clk or negedge rst_n)
2.时钟沿之后复位
另一个避免竞争条件方法是:在仿真器开始1~2时钟周期之后,再让复位在时钟无效沿起效因为我们一般都会忽略开始前几个时钟周期不定态( Unknown),如同在真实硬件上电复位时一样
3.创建仿真时钟
很多人经常使用类似下面的代码创建时钟,这里使用了两个过程块:initial块和 always块
例子:常用的生成时钟方法
reg clk;
initial clk= I'b0;
always #50 clk =~clk;
但是生成时钟本来是一个顺序的过程:赋一个初始值,然后以一定时间间隔在0和1之间题转,所以最好写成下面的形式,在0时刻对第一个时钟赋值使用非阻塞赋值,是为了在0时刻触发那些对 negedge clk敏感的过程块。
例子:更好的生成时钟方法
reg clk;
initial begin
clk <= 0;
forever (#`cycle/2) clk =~clk;
end
4.在无效沿时刻输入激励
在激励代码中,尽可能在时钟无效沿对输入赋值,而不要使用固定的#延迟,这是一个很好的创建验证平台的策略。因为使用固定延迟有缺点,如果工程师要尝试其他的频率,所有使用固定延迟的代码都需要修改。但是如果要对使用时钟无效沿改变激励的验证平台尝试其他的频率,就很少需要修改。