• 【FPGA/Verilog】 阻塞赋值与非阻塞赋值


    阻塞赋值与非阻塞赋值在Verilog语言的学习中是非常重要的需要区分的概念。下面对二者的区别作出说明。

    阻塞赋值:a = b;
    非阻塞赋值:a <= b;

    非阻塞赋值只能用于对寄存器类型变量的赋值,只能在initial块和always块中使用,非阻塞赋值不允许用于连续赋值。

    下文以a代表被赋值变量或表达式,b代表赋值变量或表达式。


    • 阻塞赋值,顾名思义,指的是在赋值过程中,其他赋值是被阻塞的,直到阻塞赋值完成赋值后才可执行其他赋值,且阻塞赋值是运算后立即执行的。在此之后的其他阻塞赋值语句都将使用新赋值的结果。
      因此,假如有一阻塞赋值中被赋值变量是a,同时有一阻塞赋值中赋值变量也是a,则两个阻塞赋值的执行先后次序将会直接导致最终a被赋值的值不同。这也是为什么对于时序功能的赋值,建议使用非阻塞赋值的原因。

    • 非阻塞赋值,指的是赋值语句运算后不立即执行赋值,且执行的赋值变量b的值不是当前值,而是上一次被赋值的b值。不论改非阻塞赋值与并行的其他块执行的非阻塞赋值谁先进行运算,最终都在各自块结束时才执行赋值,且执行的先后不影响最终的结果。

    上述文字表达较难理解,下面以程序为例作说明。
    程序借鉴于夏宇闻等著《Verilog数字系统设计教程》


    使用两种赋值方式执行同样的程序:

    阻塞赋值:虽然两个always块是并行的,但实际时钟沿到达两个块的时间还是可能相差几ps。若rst已从1到0,且上面always块的时钟沿早几皮秒到达,则y1和y2都取1;若下面always块的时钟沿早几皮秒到达,则y1和y2都取0。因此这个模块是不稳定的,存在冒险和竞争现象。

    module fun1(input clk, input rst, output reg y1, output reg y2);
        
        always @(posedge clk or posedge rst) begin
            if(rst) y1 = 1'b0;
            else y1 = y2;
        end
        
        always @(posedge clk or posedge rst) begin
            if(rst) y2 = 1'b1;
            else y2 = y1;
        end
        
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    非阻塞赋值:复位信号回到0后,无论哪一个always块的时钟有效沿先到达,两个非阻塞赋值都在赋值开始的时候开始计算右侧表达式,在结束时刻才更新左侧表达式。无论哪个有效沿先到,y1都为1,y2都为0。y1和y2的值是由上一个周期的时钟有效沿或rst沿确定的。

    module fun2(input clk, input rst, output reg y1, output reg y2);
        
        always @(posedge clk or posedge rst) begin
            if(rst) y1 <= 1'b0;
            else y1 <= y2;
        end
        
        always @(posedge clk or posedge rst) begin
            if(rst) y2 <= 1'b1;
            else y2 <= y1;
        end
        
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    遵守以下8个原则,即可在综合布局布线后的仿真中避免冒险竞争现象:

    • 时序电路建模时,用非阻塞赋值
    • 锁存器电路建模时,用阻塞赋值
    • 用always块建立组合逻辑模型时,用阻塞赋值
    • 在同一个always块中建立时序和组合逻辑模型时,用非阻塞赋值
    • 在同一个always块中,不要同时使用阻塞赋值和非阻塞赋值
    • 不要在一个以上的always块中为同一个变量赋值
    • 用$strobe系统任务来显示用非阻塞赋值的变量值
    • 在赋值时不要使用#0延迟

    冒险竞争现象产生的原因6.4 Verilog 竞争与冒险 | 菜鸟教程
    建立时间和保持时间3.3 Verilog 建立时间和保持时间 | 菜鸟教程

  • 相关阅读:
    计算机视觉-数学基础*变换域表示
    yolov7改进优化之蒸馏(一)
    面试题:JDK、JRE、JVM三者的区别与联系+什么是字节码+采用字节码的好处是什么+List和Set的区别+ArrayList和LinkedList区别
    【Linux】 uptime命令使用
    华为机试真题 C++ 实现【绘图机器】【计算面积】
    【微服务|Nacos】Nacos版本相关问题一览
    配置环境的坑坑洼洼
    DSP之定点数
    msfvenom制作主控与被控端
    深圳国际物流详解:深圳国际物流公司有哪些
  • 原文地址:https://blog.csdn.net/Electrical_IT/article/details/126770635