搜索
bottom↓
回复: 18

谈谈我对阻塞,非阻塞赋值的理解(一些新手容易混淆的问题)

[复制链接]

出0入0汤圆

发表于 2010-12-26 09:50:10 | 显示全部楼层 |阅读模式
我也是个菜鸟,如果说得不对,请大家拍砖,这些问题都是我刚开始很迷惑的。

阻塞赋值,非阻塞赋值,说实话,我刚开始也搞了好久,感觉不能深度把握,还有就是一直不明白为什么用always写组合电路时要用阻塞赋值,写时序电路的时候要用非阻塞赋值,今天就进行了一次探究。还有就是为什么总说“仿真和综合的结果不一样”

话不多说,上几段测试代码,这几段的核心都是一样的,很简单的与,或逻辑,就没写注释,相信大家很容易明白。Testbench都是一样的,没有修改,写的很粗糙,但是应该比较容易懂。


Code1

`timescale 1 ns/ 1 ns
module test(a,b,c,d,y);
input a,b,c,d;

output y;

reg y,tmp1,tmp2;
always @(a or b or c or d)

begin
tmp1 <= a&b;
tmp2 <= c&d;
y <= tmp1|tmp2;
end

endmodule

这个代码非常简单,就两个与逻辑,一个或逻辑,那么就让我们来看看,它是否按照我们所想的那样工作呢?

Testbench

`timescale 1 ns/ 1 ns
module test_vlg_tst();
// constants                                          
// general purpose registers
reg eachvec;
// test vector input registers
reg a = 0;
reg b = 1;
reg c = 1;
reg d = 0;

integer i;
// wires                                               
wire y;

// assign statements (if any)                          
test i1 (
// port map - connection between master ports and signals/registers   
        .a(a),
        .b(b),
        .c(c),
        .d(d),
        .y(y)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin                          
       for(i=0;i<10;i = i+1)
               begin
                       a = ~ a;
                       c = ~ c;

                       #20;
               end
                                                      
// --> end                                             
$display("Running testbench");                       
end                                                   
                                                
endmodule

testbench写的也比较简单,就是一个初始化,每20ns进行一次运算,a和c翻转一次,b,d不变。那我们来看看波形吧。

Modelsim波形

code1 (原文件名:QQ截图未命名1.png)

可能波形不是太清楚,大家凑合着看吧,我们先看abcd和tmp1,tmp2的关系:符合代码所写的tmp1 为a&b,tmp2 为c&d。但是注意最下面的三个信号,也就是tmp1,tmp2,y,它们的关系出现了问题。
Y的值并不等于当前的tmp1,tmp2相或的值,而是等于上一次运算时tmp1,tmp2相或的值。就像延迟了一个周期(请允许我在这里用周期这个词,虽然不是时序电路。)。
没关系,我们接着来看第二个代码。
Code2
Code2基本与Code1一样,除了在always的敏感列表中加入了tmp1,tmp2。

`timescale 1 ns/ 1 ns
module test(a,b,c,d,y);
input a,b,c,d;

output y;

reg y,tmp1,tmp2;

always @(a or b or c or d or tmp1 or tmp2)

begin
tmp1 <= a&b;
tmp2 <= c&d;
y <= tmp1|tmp2;
end

endmodule

Modelsim波形

code2 (原文件名:未命名2.jpg)

但是我们可以看到,这时的仿真波形(注意只是仿真波形),与前面有了不同,它没有了Code1的一个周期的延时,而成了我们所想的纯粹的组合逻辑。那我们来深入探究一下,这里面究竟出了什么事情。
那我们先来猜测下,是不是因为tmp1,tmp2被添加到敏感列表后,整个代码运行的方式不一样了?


Code3

深入探究,这个为什么是这样的。
为了深入探究,我加入了一个新的变量,研究程序的进行究竟如何,它就是一个计数器,可以帮助我们判断always模块运行的次数。


`timescale 1 ns/ 1 ns
module test(a,b,c,d,y);
input a,b,c,d;

output y;

reg y,tmp1,tmp2;
reg [8:0]j=0;

always @(a or b or c or d or tmp1 or tmp2)

begin
j = j + 1;//这里用了阻塞赋值,因为j仅仅起一个指示作用,与逻辑没有关系,所以用阻塞不//       影响,而且方便分析
#5//这里加了一个延时,方便大家分析
tmp1 <= a&b;
tmp2 <= c&d;
y <= tmp1|tmp2;

end

endmodule

Modelsim波形

code3 (原文件名:QQ截图未命名3.png)

这个估计不容易看清楚,跟大家描述下,最下面那个是我新添加的起计数器作用的指示变量,每进入一次always模块,它的值就增1,可以看出,它的变化比较奇怪,大约就是一次延时15ns变化,一次延时5ns变化。
我们分析下,从计数器(就是变量j了,请允许我这样称呼)等于1开始分析:
j从0增至1,为阻塞赋值(也就是它要完全执行完),
然后延时5ns,
运行always后面的几个非阻塞赋值(这个过程在仿真中不消耗时间),
然后,tmp1,tmp2得到了新的值,而这个时候我们注意到y的值其实并没有随着tmp1,tmp2的更新而更新,也就是说没有表现出code2中的组合逻辑的特性,而是像code1中的那种延时的效果,在j变成2后再过5ns,y才得到了新的值。
而在我的这个代码中5ns只有一个地方,就是j增1后面有5ns的延时。
这说明在tmp1,tmp2更新后再次进入了always模块,然后j从1增至2,然后延时5ns,而此时abcd的值没有变,所以tmp1,tmp2不变,但是y却得到了上一次tmp1或tmp2的值,发生跳变。

所以像上面这种用非阻塞赋值写组合逻辑的方法,本质上来讲写出来的不是组合逻辑,而仅仅是因为时间太短,掩饰了其中的一个很短的延时(可能我这样说不太对,望高手指正。)。
而且这种写法,大家可以看出,为了算本来一次就可以ok的组合逻辑,仿真器不得不两次进入always模块,增加了仿真器的负担,可能这里的代码比较短,还看不出什么弊病,如果你有1000个always模块都这样写呢?我想,那样的话情况就应该大大不同了。
所以我们在写代码的时候还是要遵循那句老话:写组合逻辑的时候,always中要用阻塞赋值,写时序逻辑的时候,always模块中要用非阻塞赋值。(当然不排除为了特殊的目的不遵循这个建议)

Code4
阻塞赋值
`timescale 1 ns/ 1 ns
module test(a,b,c,d,y);
input a,b,c,d;

output y;

reg y,tmp1,tmp2;

always @(a or b or c or d)

begin
tmp1 = a&b;
tmp2 = c&d;
y = tmp1|tmp2;

end

endmodule
这次的波形就不贴了,波形同Code2


总结一下,(我觉得我说的还是老话),在赋值这个动作中有两个原子操作,1.计算右边式子的值,2.赋值。
阻塞赋值的动作是不可分割的,一次性解决。
而非阻塞赋值的动作时可以分割的,仿真器会先执行完所有的计算操作(因为它优先级高,可以去查查仿真动作的优先级),没有计算后,再赋值。
如果用电路来表示的话,阻塞赋值就是一条直线上的数据流,前面的没有执行完,后面的就无法动弹。
而非阻塞赋值就像是触发器,后面的电路无需等待前面执行完,被触发后直接可以拿输入的值运算,但是可能这个时候,真正的值前级还没有给出,所以在为组合逻辑建模时,采用非阻塞赋值容易出错,这是来源于它本身的模型特性。

还有就是初学者要弄明白,这里的波形都是仿真波形而已,这几段代码综合出的电路还是一样的,但是仿真波形不同,也就是造成了许多人所说的,仿真的波形与综合后的电路不符合。

罗嗦一下,上面四段代码的结果是不同,但是仅仅在仿真时不一样而已,他们在经过综合后的电路都是一样的,这点注意一下

综合后的电路。

综合出的电路 (原文件名:QQ截图未命名4.png)

阿莫论坛20周年了!感谢大家的支持与爱护!!

该献的血还是要献的。你不献他不献。难道让我去献? --- 出自坛友:lovejp1981

出0入0汤圆

发表于 2010-12-26 10:00:59 | 显示全部楼层
前排马克

出0入0汤圆

发表于 2010-12-26 10:03:41 | 显示全部楼层
学习ing

出0入0汤圆

发表于 2010-12-26 10:19:58 | 显示全部楼层
曾经的我也是混淆这个问题,对新手们很有帮助。

出0入0汤圆

发表于 2010-12-26 10:51:34 | 显示全部楼层
蛮好,我有博文。

http://www.cnblogs.com/yuphone/archive/2010/11/10/1874465.html

出0入0汤圆

 楼主| 发表于 2010-12-26 10:51:55 | 显示全部楼层
回复【3楼】mrcontrol
-----------------------------------------------------------------------

是的。。。

我就是把困惑我的问题写出来

出0入0汤圆

发表于 2010-12-26 11:04:38 | 显示全部楼层
组合逻辑不用clk,时序逻辑都有clk;
并且时序逻辑基本都是非阻塞

出0入0汤圆

发表于 2010-12-26 12:54:25 | 显示全部楼层
记号学习,我到现在还没完全理解。

出0入0汤圆

 楼主| 发表于 2010-12-26 14:53:27 | 显示全部楼层
回复【7楼】piaotianxia 破了戒的和尚
-----------------------------------------------------------------------

建议你用modelsim把我上面四个代码跑一下,然后看看,分析下

出0入0汤圆

发表于 2010-12-26 17:13:20 | 显示全部楼层
记号学习

出0入0汤圆

发表于 2010-12-26 17:51:22 | 显示全部楼层
以前学VHDL,我印象好像没阻塞非阻塞概念,难道记错了?只有信号与变量

出0入0汤圆

发表于 2010-12-26 18:28:44 | 显示全部楼层
回复【10楼】888888888888
-----------------------------------------------------------------------

汗!这个是Verilog

出0入0汤圆

发表于 2010-12-26 20:04:43 | 显示全部楼层
jh

出0入0汤圆

发表于 2010-12-26 20:08:25 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-12-26 20:20:04 | 显示全部楼层
回复【10楼】888888888888
-----------------------------------------------------------------------

VHDL我没有接触过,完全不知道。。。。

出0入0汤圆

发表于 2010-12-26 20:49:10 | 显示全部楼层
回复【15楼】gc56198 造化
回复【10楼】888888888888  
-----------------------------------------------------------------------
vhdl我没有接触过,完全不知道。。。。
-----------------------------------------------------------------------

回复【10楼】888888888888  
-----------------------------------------------------------------------

汗!这个是Verilog
我知道是VERILOG,我不明白的是阻塞概念与VHDL中那个概念能联系起来,因为我对VERILOG不懂

出0入0汤圆

发表于 2011-1-8 15:11:45 | 显示全部楼层
回复【3楼】mrcontrol
-----------------------------------------------------------------------

出0入0汤圆

发表于 2011-1-8 16:46:59 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 21:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表