Verilog13、阻塞赋值、非阻塞赋值 傻x行为大赏

@[toc]s

阻塞赋值、非阻塞赋值傻x行为大赏

关于阻塞赋值和非阻塞赋值的问题,记录一下

1、组合逻辑对同一个变量赋值

module experiment(
    input clk,
    input rst_n,
	input	[15:0]	data_in
    );
	
	/****************************** 实验1:组合逻辑用阻塞赋值,可以对同一个变量赋值 ************************/
	reg [3:0]	mem1	[0:3];
	reg [3:0]	mem2	[0:3];
	
	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			for(i=0;i<4;i=i+1)
				mem1[i] <= 'b0;
		end
		else
		begin
			for(i=0;i<4;i=i+1)
				mem1[i] <= i+1;
		end
	end
	
	
	integer i,j;
	always@(*)
	begin
		j = 0;
		for(i=0;i<4;i=i+1)
			if(mem1[i]>1)
			begin
				mem2[j] = mem1[i];		// 如果这里是非阻塞赋值,则只会执行最后一次的赋值结果;如果是阻塞赋值,则会等待前一个赋值完成再赋值另外一个。虽然是对同一个变量j赋值,但是有先后顺序,不会出错
				j=j+1;
			end
	end
	
	/*
		// 上面的循环实际电路时循环体展开	
			if(mem1[0]>1)
			begin
				mem2[j] = mem1[0];
				j=j+1;
			end
			
			
			if(mem1[1]>1)
			begin
				mem2[j] = mem1[1];
				j=j+1;
			end
			
			……
	*/
	
	/****************************** 实验2:实验1变体 ************************/
	/*
	integer i;
	reg [3:0]	j [3:0];
	always@(*)
	begin
		for(i=0;i<4;i=i+1)
			if(mem1[i]>1)
			begin
				mem2[j[i]] = mem1[i];
				j[i+1]=j[i]+1;			// 这里虽然不是对同一个变量赋值,但当前变量的值也是要依赖于前一个值的,所以只有阻塞赋值时是正确的	
			end
			else
				j[i+1] = j[i];
	end


			// 上面的循环实际电路时循环体展开
			if(mem1[0]>1)
			begin
				mem2[j] <= mem1[0];
				j[1]=j[0]+1;
			end
			else
				j[1] = j[0];
			
			
			if(mem1[1]>1)
			begin
				mem2[j] <= mem1[1];
				j[2]=j[1]+1;
			end
			else
				j[2] = j[1];
				
			……
*/
		
endmodule

在这里插入图片描述

综上所述

  • 组合逻辑就用阻塞赋值,不要瞎用非阻塞赋值
  • 组合逻辑中可以对同一个变量赋值(前提是你知道自己的代码结果是怎样的,否则最好不要用)

2、参考实验

参考:https://www.cnblogs.com/wkl7123/p/4131671.html

2.1

module experiment():
	reg [3:0] a=0;
	reg [3:0] b=0;
	reg clk=0;

	
	always@(clk)
	begin
		a<=a+3;
		b<=b+1;
	end
	
	always@(b)
	begin
		a<=a+2;
	end
	
	always #10 clk=~clk;

endmodule

实验说明

reg [3:0] a=0;
reg [3:0] b=0;
reg clk=0; 
用非阻塞赋值

实验仿真
在这里插入图片描述
瞎猜原因
只有初始化的时候有顺序:
a=0,a,b无变化
b=0,always@(b)触发,a<=a+2=2
clk=0, always@(clk)触发,a<=a+3=5,b<=b+1=1,后面的 a=a+2不再执行是因为clk触发导致b变化,但是用的非阻塞赋值,上面和下面同时赋值,由于clk在前,所以后面的没有再执行

2.2

module experiment():
	reg [3:0] a=0;
	reg [3:0] b=0;
	reg clk=0;

	
	always@(clk)
	begin
		a=a+3;
		b=b+1;
	end
	
	always@(b)
	begin
		a=a+2;
	end
	
	always #10 clk=~clk;

endmodule

实验说明

reg [3:0] a=0;
reg [3:0] b=0;
reg clk=0; 
用阻塞赋值

仿真结果
在这里插入图片描述
瞎猜原因:
a=0,a,b无变化
b=0,a=a+2=2
clk=0, a=a+3=5,b=b+1=1,always@(b)触发,a=a+2.后面的 a=a+2会执行是因为clk触发导致b变化,always@(b)用阻塞赋值,等上面的赋值完后面再赋值,由于clk在前,所以always@(clk) 先执行,always@(b) 后执行

2.3

module experiment():
	reg clk=0;
	reg [3:0] a=0;
	reg [3:0] b=0;
	

	
	always@(clk)
	begin
		a<=a+3;
		b<=b+1;
	end
	
	always@(b)
	begin
		a<=a+2;
	end
	
	always #10 clk=~clk;

endmodule

实验说明:

reg clk=0; 
reg [3:0] a=0;
reg [3:0] b=0;
用非阻塞赋值

仿真结果
在这里插入图片描述

2.4

module experiment():
	reg clk=0;
	reg [3:0] a=0;
	reg [3:0] b=0;
	

	
	always@(clk)
	begin
		a=a+3;
		b=b+1;
	end
	
	always@(b)
	begin
		a=a+2;
	end
	
	always #10 clk=~clk;

endmodule

实验说明:

reg clk=0; 
reg [3:0] a=0;
reg [3:0] b=0;
用阻塞赋值

仿真结果
在这里插入图片描述

说明

上面的原因纯属瞎猜,实际原因可能和仿真时不同语句执行顺序有关,不同的语句在仿真的不同区中执行,导致结果差异。

欢迎各位大佬批斗发表感言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值