FPGA 32 专题 阻塞和非阻塞状态的理解

本文详细介绍了FPGA设计中阻塞赋值和非阻塞赋值的区别。阻塞赋值在代码中有先后顺序,电路结构会因顺序不同而变化,而非阻塞赋值则不考虑语句顺序,电路结构保持不变。非阻塞赋值可能导致输出延迟,适合于有中间变量的情况。通过实例展示了不同赋值方式在电路实现和仿真结果上的差异,并提出了避免延时的方法。
摘要由CSDN通过智能技术生成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t93Mpr2Y-1627401356069)(FPGA 09 阻塞和非阻塞状态的理解.assets/test.png)]

FPGA 32 专题 阻塞和非阻塞状态的理解

写的不是很细致,过两天继续完善

block_nonblock.v 文件

module block_nonblock(
	Clk ,
	Rst_n,
	a ,
	b ,
	c ,
	out 
);

	input Clk ;
	input Rst_n ;
	input a ;
	input b ;
	input c ;
	
	// out = a+b+c ;
	// d = a+b ;
	// out = d +c ;
	
	output reg [1:0]out ;
	reg [1:0]d ;
	
	always@(posedge Clk or negedge Rst_n )
	if(Rst_n == 1'b0)
		out = 2'b0 ;
	else begin 
		out <= a + b + c;  //建议使用阻塞赋值
	end


	//非阻塞赋值 : 运算符: <=  ,前后执行时【并行运算】,代码执行不分前后(结构时确定没有问题的(多条语句赋值不存在前后顺序),
	//但是如果多条语句中的数据或者说变量存在关联,那么需要考虑的是逻辑结构的延时
	//或者说是D触发器的延时问题导致的数据出现的错误)
	//阻塞赋值 :  运算符: =    ,执行语句【有先后顺寻】,存在延迟情况,存在不确定性(有的时候会出现问题)
	/********* 非阻塞赋值 **********/
	/* 方式1:
			out <= a + b + c;
	*/
	/* 方式2:
			d   <= a + b ;
			out <= a + b + c;
	*/
	/* 方式3:
			out <= d + c;
			d   <= a + b ;
	*/
	/********* 阻塞赋值 **********/
	/* 方式4: 非并行运算
			d   = a + b ;
			out = d + c;
	*/
	/* 方式5: 非并行运算
			out = d + c;
			d   = a + b ;
	*/
	//  这里可以通过仿真结果得到, 方式【4】和方式【1】得到的电路是一样的,也就是我们想要的效果
	//  这里可以通过仿真结果得到, 方式【2】和方式【3】得到的电路是一样的。
	//  这里可以通过仿真结果得到, 方式【4】和方式【5】得到的电路是【不一样】的,
	//  但是电路输出结果会因为延时得到的结果会存在延时的数据错误,我们需要在设计的时候需要去避免

endmodule



1、阻塞赋值

阻塞赋值的实际电路:

always@(posedge Clk or negedge Rst_n )
if(Rst_n == 1'b0)
	out = 2'b0 ;
else begin 
     //这里是阻塞赋值语句,有先后顺序,和C语言类似
	d  = a + b ; 
    out = d +c  ; 
end

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hWrrCIo-1627405081017)(img/blog_img/fpga/image-20210303160809968.png)]

2、阻塞赋值

always@(posedge Clk or negedge Rst_n )
if(Rst_n == 1'b0)
	out = 2'b0 ;
else begin 
    //这里是阻塞赋值语句,有先后顺序,和C语言类似
    out = d +c  ;
    d  = a + b ;  
end

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zo262CNp-1627405081018)(img/blog_img/fpga/image-20210303161517074.png)]

3、非阻塞赋值

always@(posedge Clk or negedge Rst_n )
if(Rst_n == 1'b0)
	out <= 2'b0 ;
else begin 
    //这里非阻塞赋值语句,代码无先后顺序
    out <= d +c  ;
    d  <= a + b ;  
end

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABbU6Ork-1627405081020)(img/blog_img/fpga/image-20210303161927334.png)]

4、非阻塞赋值

always@(posedge Clk or negedge Rst_n )
if(Rst_n == 1'b0)
	out <= 2'b0 ;
else begin 
    //这里非阻塞赋值语句,代码无先后顺序
    d  <= a + b ;  
    out <= d +c  ;
end

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ax0Cw28M-1627405081021)(file://E:/Blog_Template/source/_posts/img/blog_img/fpga/image-20210303161927334.png?lastModify=1614759688)]

可以发现: 非阻塞赋值( 代码3、代码 4、)中,代码前后顺序改变,内部生成的电路结构是保持一致的

阻塞赋值( 代码1、代码 2、)中,代码前后顺序改变,内部生成的电路结构是不同的**

非阻塞赋值【3、4】的仿真结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ariMCzl-1627405081022)(img/blog_img/fpga/image-20210303164445111.png)]

只有当 下一个时钟上升沿到来的时候,可以看到 out 的结果才发生了变化 。

为了避免延时需要修改成如下所示的情况:

always@(posedge Clk or negedge Rst_n )
if(Rst_n == 1'b0)
	out <= 2'b0 ;
else begin 
    //这里非阻塞赋值语句,代码无先后顺序
    d  <= a + b + c ;  
end

这样出来的结果就不会有因为D触发器所导致的寄存,而最终导致输出结果的延时问题。

本次我们的主要目的是:

知道 非阻塞赋值不考虑语句的先后顺序,内部电路结构不发生改变

阻塞赋值考虑语句的先后顺序,内部会根据先后顺序得到不同的电路结构。

个人理解:

根据自己实际的想法编写就好,如果和C 语言的用法类似,也可以考虑使用阻塞赋值,不一定非要用非阻塞赋值做运算。

非阻塞如果是有多个语句执行,而且【中间存在交互的变量 如: d=a+b out= d+c, d就是中间变量】,那么势必在结果上的输出【out】 会带来时间上的延时。

block_nonblock_tb.v 文件

`timescale 1ns/1ns

`define clock_period 20

module block_nonblock_tb;

	reg Clock;
	reg Rst_n;
	reg a,b,c;
	
	wire [1:0]out;
	
	block_nonblock block_nonblock0(Clock,Rst_n,a,b,c,out);  //新的一种模块名称加载
	
	initial Clock = 1;		//时钟信号
	always#(`clock_period/2) Clock = ~Clock;
	
	initial begin
		Rst_n = 1'b0;
		a = 0;
		b = 0;
		c = 0;
		#(`clock_period*200 + 1); //信号初始化 ,+1 避免和时钟信号对齐,仿真时更加接近实际的电路
		Rst_n = 1'b1;
		
		
		#(`clock_period*200);
		a = 0 ; b = 0 ; c = 0;
		#(`clock_period*200);
		a = 0 ; b = 0 ; c = 1;
		#(`clock_period*200);
		a = 0 ; b = 1 ; c = 0;
		#(`clock_period*200);
		a = 0 ; b = 1 ; c = 1;
		
		
		#(`clock_period*200);	
		a = 1 ; b = 0 ; c = 0;
		#(`clock_period*200);
		a = 1 ; b = 0 ; c = 1;
		#(`clock_period*200);
		a = 1 ; b = 1 ; c = 0;
		#(`clock_period*200);
		a = 1 ; b = 1 ; c = 1;
		
		
		#(`clock_period*200);
		#(`clock_period*200);
		$stop;	
	end

endmodule



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值