08-阻塞赋值与非阻塞赋值

目的

主要学习verilog语法。阻塞赋值(=)和非阻塞赋值(<=)是针对时序逻辑而言,组合逻辑不存在阻塞复制或非阻塞赋值。

//组合逻辑
always@(*)
//时序逻辑 非阻塞赋值
always@(posedge Clk or Reset_n)begin
counter <= counter + 1;
end
//时序逻辑 阻塞赋值
always@(posedge Clk or Reset_n)begin
counter = counter + 1;
end

代码

通过两个案例来说明

非阻塞赋值:

module block_nonblock_1(
    Clk,
    Reset_n,
    a,
    b,
    c,
    d,
    out
    );
    input Clk;
    input Reset_n;
    input a;
    input b; 
    input c;
    output reg [1:0]d;
    output reg [1:0]out;  
       
    always@(posedge Clk or negedge Reset_n)begin
    if(!Reset_n)begin
        out <= 2'b00;
        d <= 1'b0;
        end
    else begin
        out <= d + c;
        d <= a + b;
        end
    
    end
 
endmodule

阻塞赋值:

module block_nonblock_2(
    Clk,
    Reset_n,
    a,
    b,
    c,
    d,
    out
    );
    input Clk;
    input Reset_n;
    input a;
    input b; 
    input c;
    output reg [1:0]d;
    output reg [1:0]out;  
       
    always@(posedge Clk or negedge Reset_n)begin
    if(!Reset_n)begin
        out = 2'b00;
        d = 1'b0;
        end
    else begin
        d = a + b;
        out = d + c;
        end
    
    end

endmodule

RTL图

通过RTL图来分析这两种方式的区别

非阻塞赋值

便于分析,用常用的数字电路的画法,就是下面的电路图。

阻塞赋值

从上面可以看出两种赋值方式所表达出来的电路图并不相同。

仿真

通过仿真来分析这两种方式的区别

测试文件

`timescale 1ns / 1ns

module block_nonblock_tb_1(

    );
    reg Clk;
    reg Reset_n;
    reg a;
    reg b;
    reg c;
    wire [1:0]d;
    wire [1:0]out;
    
    
    block_nonblock_1 block_nonblock_inst0(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .a(a),
    .b(b),
    .c(c),
    .d(d),
    .out(out)
    );
    
    initial Clk = 1;
    always #10 Clk =~ Clk;
    initial begin
    Reset_n = 0;
    a = 0;
    b = 0; 
    c = 0;
    #205;
    Reset_n = 1;
    #20000;
    a = 0; b = 0; c = 0;
    #20000;
    a = 0; b = 0; c = 1;
    #20000;
    a = 0; b = 1; c = 0;
    #20000;
    a = 0; b = 1; c = 1;
    #20000;
    a = 1; b = 0; c = 0;
    #20000;
    a = 1; b = 0; c = 1;
    #20000;
    a = 1; b = 1; c = 0;
    #20000;
    a = 1; b = 1; c = 1;
    #20000;
    $stop;
    end
    
    
endmodule

非阻塞赋值

阻塞赋值

通过仿真可以看到在仿真中同一个位置,out的值并不相同。

为何非阻塞赋值时,某个时刻,a = 0, b = 1, c = 0时, out = 0而不是out = 1(按道理d = 1, out = d + c = 1 + 0 = 1)?

要回答这个问题,这需要回到底层的硬件D触发器上,在非阻塞赋值中,有两个D触发器。当同一时刻,当时钟上升沿来临时,a = 0、b = 1的值被采集入D触发器,而此时此刻,第二个D触发器也在采集端口的输入,问题正是这里,因为前一级D触发器的值从D端到Q端实际是需要一定时间的,所以这时候第二个D触发器在前一级的值还未送过来时,实际上采集到的是上一次的值,也即是d = 0,所以此时out = d + c = 0 + 0 = 0。

总结

在阻塞赋值时,out = d + c;d = a + b;语句写的顺序综合出的电路和非阻塞赋值是一样的;而d = a + b;out = d + c;语句写的顺序综合出的电路与非阻塞赋值电路是不一样的。

在非阻塞赋值时,out <= d + c;d <= a + b;与d <= a + b;out <= d + c;语句写的顺序不一样,实际电路是一样的。

所以在时序逻辑中,需要使用非阻塞赋值,非阻塞赋值实现出来的逻辑电路,顺序不同,综合出的代码可能就不同。

补充

关于阻塞和非阻塞赋值再补充一点书本知识,内容来源于书籍《verilog数字系统设计教程》第二版。

 

posted @ 2022-06-17 17:52  #hua  阅读(198)  评论(0编辑  收藏  举报