zoukankan      html  css  js  c++  java
  • Verilog -- initial块中阻塞与非阻塞赋值问题

    Verilog testbench的initial块中阻塞与非阻塞赋值问题

    问题描述

    在testbench的编写中经常要做的就是在initial块中对一些信号变化进行描述。
    比如希望信号start在仿真开始后第10个周期上升沿置为高电平。
    对于仿真时钟一般都会这么写:

     always #1 clk = ~clk;
    
    • 如果初始化clk = 0,那么实际上start应该在 #21;start=1; 也就是十个半周期后置高。
    • 如果初始化clk = 1,那么实际上start应该在 #20;start=1; 也就是准确的十个周期后置高。

    这种写法实际上不符合实际电路中的运行规则
    如果start在上层模块是通过其他FF给出的,则这样的写法往往会导致数据提前一拍,因为#20;start=1;的写法是跟时钟上升沿无关的,因此在该处时钟上升沿实际上和start的值同时改变,而我们知道,实际上FF的原理是一般都是基于正负latch,其采样和保持都需要一定的延时(clk-Q),所以用clk去驱动FF时,FF的Q端数据一般都是在上升沿之后的一段延时后才改变。
    这也是为什么verilog中要使用“<=”非阻塞赋值的一个因素,因为非阻塞赋值契合了实际电路中的这一特性,如果该FF之后又级联了一个FF,则在这个clk上升沿,如果不考虑时钟skew,那么后面级联的FF实际上采样到的数据还是前级FF赋值之前的数值,非阻塞赋值可以保证这一特性。

    • 阻塞:在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句(遇到等式时堵住值直到更新才释放);
    • 非阻塞:当前语句的执行不会阻塞下一语句的执行(遇到等式立马就把右边值给左边,不等其更新)。

    所以在tb里initial块中一般使用

    @ (posedge clk);
     start<=1;
    

    这种写法来保证非阻塞的特性,也就是在时钟上升沿之后reg值才变化。实际上没有@ posedge也可以,只要赋值语句是非阻塞的,则等式的执行实际上相对当前的时间触发会有一定的延时,而@ posedge clk可以方便的间隔一定时间知道clk的上升沿到来。
    下面是一段测试程序,以便更好的理解两者的差别:

    module test();
      reg clk;
      reg req0;
      reg req1;
      reg test_sig;
      always #1 clk = ~clk;
      initial begin
      clk = 0;
      req0 = 0;
      req1 = 0;
      test_sig = 0;
      #10;
      @ (posedge clk);
      req0 <= 1;
      req1 <= req0;
      repeat (1) @ (posedge clk)
      req0 <= 1;
      req1 <= req0;
    
      #10;
      req0 = 0;
      req1 = req0;
     end
    always@(posedge clk) begin
        if(req0==1) test_sig <= 1;
        else test_sig <= 0;
    end
    
    initial begin
        $fsdbDumpvars();
        $fsdbDumpMDA();
        $dumpvars();
        #100 $finish;
     end
    endmodule 
    
    

    其中,test_sig依赖req0的值。可以发现,当使用@ (posedge clk);配合“<="赋值时,test_sig的值在req0变化的下一周期才改变,req1也是如此,符合时序电路的规范。而下面使用"#"延时和阻塞赋值的语句则导致test_sig、req1跟着req0的值同时改变。

    再来看一个例子:

    对于用阻塞赋值并加一定延时的情况,可以发现a信号的改变是等待上一句执行结束以后才进行的。所以其中的延时是累加起来的。 而对于非阻塞赋值的情况则是下图:
    其中,信号的变化由于是非阻塞赋值,所以是三个赋值同时进行,也就是说延时是并行的。

    另外,如果把延时信息放到赋值的前面,会发生什么呢?
    首先,可以知道的是对于阻塞赋值,不管放在哪里都是一样的,都是串行执行,所以延时会累加。
    那么,对于非阻塞赋值的情况呢?下图进行了实验:

    可见,此时信号赋值的延时又变成了串行的,所以可以发现,如果延时信息放在赋值式之间, 也就是等号右边,则会当作赋值的一部分而变为非阻塞也就是并行处理,而放在其他地方则跟非阻塞赋值无关,表现为串行的延时。
  • 相关阅读:
    @PostConstruct和 @PreDestroy注解
    【JQuery】,ajax请求中,url出现[Object Object]
    筛法求素数
    母牛的故事
    将一个数拆分
    计算两个日期差
    用二分查找——查找比目标元素略大的索引
    反向输出字符串
    bootstrap table合并单元格(该版本是简单的应用)
    获取访问者IP
  • 原文地址:https://www.cnblogs.com/lyc-seu/p/12562107.html
Copyright © 2011-2022 走看看