引用: 小白报道 发表于 2016-09-09 10:24
采用阻塞赋值在这里是很危险的行为,仿真和综合的结果可能会不同,两个always执行的顺序实际上是不固定的(虽然我们理解时认为是并行执行,但是因为时钟延时,时钟实际到达寄存器的时间是不同的),不过也可能会被综合成我们想要的威廉希尔官方网站 ,虽然比非阻塞赋值运算结果快了一个时钟周期,不过不建议使用阻塞赋值
引用: 渊底一尾 发表于 2016-9-9 10:46
你了解流水线加法器吗?书上用的是阻塞赋值,但是仿真结果却跟我想象的不一样。我感觉非阻塞赋值的仿真结果更符合流水线执行的特点。是否是我对流水线的理解有偏差?
引用: 渊底一尾 发表于 2016-9-9 11:22
讲讲你的依据吧,我也感觉这里用阻塞赋值有问题,但是没有足够理论支撑
引用: alasga 发表于 2016-09-10 15:13
always@(posedege clk) 语句说明你要做的是同步逻辑设计,后面只能跟“非阻塞”赋值,而且你要做流水设计的话,就更应该是非阻塞赋值了;至于阻塞赋值,从语法上讲没有问题,但是最终综合成什么逻辑威廉希尔官方网站 ,就要完全看综合器对你这段代码的理解了,所以不同的软件版本之间,同一版本不同综合次数之间,不同的综合工具之间,最终综合结果都有可能不一样,属于不规范语法描述方式。所以不用去纠结第二代码了。
最后为什么不直接用
always@(posedge clk) begin
{cout,sum}
引用: alasga 发表于 2016-09-10 15:13
always@(posedege clk) 语句说明你要做的是同步逻辑设计,后面只能跟“非阻塞”赋值,而且你要做流水设计的话,就更应该是非阻塞赋值了;至于阻塞赋值,从语法上讲没有问题,但是最终综合成什么逻辑威廉希尔官方网站 ,就要完全看综合器对你这段代码的理解了,所以不同的软件版本之间,同一版本不同综合次数之间,不同的综合工具之间,最终综合结果都有可能不一样,属于不规范语法描述方式。所以不用去纠结第二代码了。
最后为什么不直接用
always@(posedge clk) begin
{cout,sum}
引用: hqbenson 发表于 2016-9-12 16:23
您好楼主。您再仔细分析一下您的代码就可以发现问题了。其实这和阻塞非阻塞没太大关系。(当然时序威廉希尔官方网站 还是必须要用非阻塞的)
主要有
1.流水线的编写思路不太清晰。
引用: 渊底一尾 发表于 2016-9-14 10:19
您好!首先感谢您对我的问题作出如此详细的解答。
关于您所说的进位位以及每一级增加寄存器的问题,我后来也已经发现并改正了,但是使用阻塞赋值和非阻塞赋值的仿真结果仍然是不同的。阻塞赋值的仿真结果:输入和输出仍然是在一个时钟周期内完成,而非阻塞赋值的仿真结果:输入和输出却是阶梯状。
还望指点!谢谢! ...
引用: 渊底一尾 发表于 2016-9-12 08:34
1、因为要采用流水线设计,所以没有直接用{cout,sum}。
2、采用图一代码,我发现仿真结果不对。上图中,我没有对高8位赋值。在我对高8位赋值后,发现:输出结果(cout)的高8位是当前输入高8位的和,而低8位则是上一个时钟输入低8位的和。请问应如何解决?不知您之前是否写过流水线加法器?求指教。 ...
引用: hqbenson 发表于 2016-09-14 12:36
指点不敢..我也在学习中,只能按我理解的观点谈一下问题点...
楼主您可以试一下,源代码中,在用阻塞赋值时,如果将两个always调换位置(将第二个always写在前面,第一个always写在后面),仿真出来的结果会和原来的不一样。(sum要从第二个时钟沿才有输出,并且与当前的输入值之和不一致)
在用非阻塞赋值时,就算将两个always调换位置,仿真出来的结果是一样的。
根本原因在于,当仿真器运行到阻塞赋值语句时,先计算等号右边的值并更新,这时候赋值语句不允许任何别的verilog语句干扰,直到把该值赋值完成为止。
如果是非阻塞赋值语句,计算等号右边的值时,其他的verilog语句,非阻塞赋值语句都可以同时计算等号右边的值。非阻塞语句允许其他的语句同时操作。
按此理解,如果
1.原本代码,用阻塞:仿真器执行语句,按代码所述,第一个上升沿事件开始→计算出sum1和count1并立即赋值→计算cout和sum并立即赋值→结束上升沿事件。
2.原代码,用阻塞,将两个always对调:仿真器执行语句,第一个上升沿事件开始→计算出count和sum并立即赋值→计算出sum1和count1并立即赋值→结束上升沿事件。
3.原代码,用非阻塞:仿真器执行语句,第一个上升沿事件开始→计算出sum1和count1的值,同时计算sum,count的值(目标还未更新赋值)→更新赋值目标的值→结束上升沿事件。
情况1中,计算sum1与count1的阻塞赋值语句在前面,在sum与count执行之前,sum1与count1已经得到更新,所以第一个上升沿就有值输出。
情况2里面,由于把sum和count的语句写在了前面,仿真器先计算并更新它们俩的值,但由于此时sum1和count1仍是未知值,所以第一个时钟沿输出仍是未知值(红线),更新完sum与count后,才计算写在后面的always里面的sum1与count1的值并立即更新。
由于有这样的歧异,所以才可综合代码里,规定在含有时序逻辑的always块里面必须使用非阻塞。
由于流水线是典型的,严格的时序逻辑威廉希尔官方网站 ,所以必须使用非阻塞。
如果楼主您还不太理解,建议多写一些测试的小代码,用两种赋值修改看看仿真有什么不同然后用自己的想法去理解。当理解的差不多了,再写一些测试代码预测一下仿真结果,或者多看书上的例子。
更多回帖