verilog中的阻塞和非阻塞赋值

1 阻塞赋值与非阻塞赋值

1.1 何为“阻塞”?

所谓“阻塞”,可以理解为阻止顺序语句块中其他语句的执行。例如,在一个块语句中,如果含有多条阻塞式赋值语句,当执行到其中某条语句时,若该语句未执行完,那么其后面的语句将处于等待中,不会被执行,好像都被阻塞了一样。

1.2 阻塞式赋值“=”

计算完“=”右边的值之后,立刻更新“=”左边的值。

1.3 非阻塞式赋值“<=”

所有过程语句中的非阻塞赋值语句,必须在块语句执行结束时才会整体完成赋值更新
非阻塞赋值只能用于对reg进行赋值,因此只能用在initial和always块等过程块中。

1.4 什么时候用阻塞赋值、非阻塞赋值?

①assign赋值语句中只能使用“=”,且等号左边的目标对象只能是wire型
②always语句中,两种赋值符号都可以使用,但等号左边的目标对象只能是reg型变量。

  • 组合逻辑,always块中用阻塞赋值“=”,综合生成组合逻辑的电路结构,这种电路结构只与输入电平的变化有关。
  • 时序逻辑,always块中用非阻塞赋值“<=”,综合成时序逻辑的电路结构,这种电路结构往往与触发沿有关,只在触发沿时才可能发生赋值的变化。

注意:在一个always块中,不要既用阻塞赋值又用非阻塞赋值。不允许在多个always块中对同一个变量进行赋值。

1.5 示例

  • 阻塞语句赋值示例
`timescale 1ns / 1ps

module m1(
input       sys_clk ,
input       data    ,
output  reg y
);
reg A,B,C;

always@(posedge sys_clk)begin
A=data;
B=A;
C=B;
y=C;
end

endmodule

在这里插入图片描述

由综合后的RTL电路图可以看出,阻塞表达描述电路最后只用了一个D触发器

  • 非阻塞语句赋值示例1
`timescale 1ns / 1ps

module m2(
input       sys_clk ,
input       data    ,
output  reg y
);
(* keep = "true" *) reg A,B,C;

always@(posedge sys_clk)begin
A<=data;
B<=A;
C<=B;
y<=C;
end

endmodule

在这里插入图片描述
非阻塞表达电路使用了4个D触发器。

因此,从输入端data到输出端y,如果采用阻塞赋值方式,需要一个clk时钟的时间;若采用非阻塞的表达方式,则需要4个clk时钟的时间。

  • 非阻塞赋值示例2
`timescale 1ns / 1ps

module test1(
    input  clk,
    input  rst_n,
    input  a,
    output reg [3:0] dec_reg
    );
    
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        dec_reg<=0;
    else if(a==0)begin
        dec_reg[0] <= 1'b1;
        dec_reg[3:1] <= dec_reg[2:0];
    end
    else begin
        dec_reg[0] <= 1'b0;          
        dec_reg[3:1] <= dec_reg[2:0];
    end
end    

在这里插入图片描述
仔细观察电路可以发现,对于dec_reg的赋值

//写法1
dec_reg[0] <= 1'b0;          
dec_reg[3:1] <= dec_reg[2:0];
//写法2
dec_reg[3:1] <= dec_reg[2:0];
dec_reg[0] <= 1'b0;

综合出来的电路图是完全相同的,这就是非阻塞赋值的效果。
因此,赋值语句顺序不会影响非阻塞赋值的结果,但会影响阻塞赋值语句的结果

2 电平触发与边沿触发

always块可以使用电平触发也可以使用边沿触发,电平触发往往对应组合逻辑,边沿触发往往对应时序逻辑

2.1 示例

在这个例子中,timing变量通过边沿触发来赋值,comb通过电平触发来赋值

`timescale 1ns / 1ps

module test(
    input       clk,
    input [2:0] a,
    output reg  timing,
    output reg  comb
);

                                             
always@(posedge clk )begin
    if(a>2'd2)
    timing<=1;
    else
    timing<=0;
end    
    
always@(a)begin
    if(a>2'd2)
    comb=1;
    else
    comb=0;
end    
   
endmodule

  • 原理图
    在这里插入图片描述
    在原理图中可以看到,输入a经过LUT后分别给到了comb和timing_reg。同时需要注意的是,timing和comb虽然在代码中都被声明为reg类型的变量,但它们却被综合成了不同的电路,在时序逻辑中,reg被综合成触发器。在组合逻辑中,reg被综合成硬件连线。
  • 真值表
    在这里插入图片描述
    真值表满足代码中所要求电路实现的功能,在a>0时输出1,否则输出0
  • 时序
    在这里插入图片描述
    根据时序图,comb比timing早一拍变化,这与原理图中comb的赋值是组合逻辑,timing的赋值是时序逻辑是相对应的
  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值