首页 > 编程知识 正文

非阻塞和阻塞赋值,非阻塞赋值和阻塞赋值

时间:2023-05-03 06:54:45 阅读:217697 作者:3222

内容简介:
IEEE Verilog标准中提供了阻塞赋值和非阻塞赋值两种赋值方式,二者的执行过程如下:
1.阻塞赋值(=):阻塞赋值操作实质上是一次性连续完成的,即计算等号右边变量(或表达式)的值(RHS)并立即赋值给等号左边的变量(LHS)。其中阻塞的含义为在同一个always块中,当前赋值语句正在执行时禁止其后的所有其他赋值语句的执行。只有当前赋值语句执行完成后,其后的赋值语句才能被执行。
2.非阻塞赋值(<=):非阻塞赋值操作实质上是分两步完成的,即第一步:在敏感事件开始时刻(如clk正跳变沿开始时刻)开始计算等号右边变量(或表达式)的值RHS;第二步:在敏感事件结束时刻(如clk正跳变沿结束时刻)将等号右边的值赋给等号左边的变量LHS。其中非阻塞的含义为在执行当前的非阻塞赋值语句的同时允许其他的语句执行。
由以上执行过程知,二者主要区别为:等号右边的变量值是否立即得到更新;赋值语句执行期间是否允许其他语句执行。

实验验证:
实验目的为验证在always块中分别采用阻塞赋值和非阻塞赋值对时序电路输出的影响。
阻塞赋值验证代码:

/*-----------------------------------------------------------Filename: barrage_assign.vFunction: 说明阻塞赋值可能带来电路的竞争冒险从而使输出不确定Author: Zhang KaizhouDate: 2019-10-12 11:58:43------------------------------------------------------------*/module barrage_assign(clk, reset, y1, y2);//输入输出端口定义output y1, y2;input clk, reset;//内部寄存器定义reg y1, y2;//功能块1always@(posedge clk or posedge reset)beginif(reset) y1 = 0;else y1 = y2;end//功能块2always@(posedge clk or posedge reset)beginif(reset) y2 = 1;else y2 = y1;endendmodule /*-----------------------------------------------------------Filename: barrage_assign_t.vFunction: barrage_assign模块的测试程序Author: Zhang KaizhouDate: 2019-10-12 21:04:06------------------------------------------------------------*/`timescale 1ns/1ns`define PERIOD 10module barrage_assign_t(y1, y2, clk, reset);output y1, y2, clk, reset;reg clk, reset;barrage_assign m0(.clk(clk), .reset(reset), .y1(y1), .y2(y2));initialbeginclk = 0; reset = 0;#100 reset = 1;#100 reset = 0;#300 reset = 1;#500 reset = 0;#500 $stop;end//产生时钟信号always #`PERIOD clk = ~clk;endmodule

阻塞赋值仿真结果:

非阻塞赋值验证代码:

/*----------------------------------Filename: non_block_assign.vFunction: 说明非阻塞赋值语句的特性Author: Zhang KaizhouDate: 2019-10-12 21:08:56-----------------------------------*/module non_block_assign(clk, reset, y1, y2);//输入输出端口定义input clk, reset;output y1, y2;//内部寄存器定义reg y1, y2;//功能块1always@(posedge clk or posedge reset)beginif(reset) y1 <= 0;else y1 <= y2;end//功能块2always@(posedge clk or posedge reset)beginif(reset) y2 <= 1;else y2 <= y1;endendmodule /*---------------------------------------Filename: non_block_assign_t.vFunction: non_block_assign模块的测试程序Author: Zhang KaizhouDate: 2019-10-12 21:09:05---------------------------------------*/`timescale 1ns/1ns`define PERIOD 10module non_block_assign_t(y1, y2, clk, reset);output y1, y2, clk, reset;reg clk, reset;non_block_assign m0(.clk(clk), .reset(reset), .y1(y1), .y2(y2));initialbeginclk = 0; reset = 0;#100 reset = 1;#100 reset = 0;#300 reset = 1;#500 reset = 0;#500 $stop;end//产生时钟信号always #`PERIOD clk = ~clk;endmodule

非阻塞赋值仿真结果:

实验总结:
对比上面两种赋值方式对应的仿真结果可知,对于阻塞赋值,因为IEEE Verilog标准规定always块的开始执行时刻的先后顺序是随机的(且always块是并行执行的),又由于在本次实验中两个always块中的变量变化相互依赖,再加上阻塞赋值是立即更新完成的,所以使得电路中存在竞争冒险现象,最终导致输出不确定。若功能块1先被执行,则输出为{y1, y2} = 2’b11;若功能块2先被执行,则输出为{y1, y2} = 2’b00。显然第一张仿真图显示的是第一种情况。
对于非阻塞赋值,虽然两个always块开始执行时刻的先后顺序是随机的,但是无论哪一个always块先提前几个ps开始执行,由于非阻塞赋值的执行过程是分两步进行的,在执行第一步(RHS计算)时,y1和y2的值仍然保持上一次更新后的值,在clk正跳变沿结束时刻,y1和y2会被同时更新为重新计算后的新值。所以在非阻塞赋值方式下,每个时钟周期y1和y2的值都会发生翻转。
附注:
用Verilog编写可综合模块时推荐遵循四条原则:
1.用always块描述时序逻辑时用非阻塞赋值(<=)。
2.用always块描述组合逻辑时用阻塞赋值(=)。
3.用always块描述时序和组合混合逻辑时用非阻塞赋值(<=)。
4.避免在多个always块中对同一变量赋值。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。