Verilog流水线加法器always块中应该采用阻塞赋值(=),还是非阻塞赋值(<=)?

2019-07-15 22:24发布

二级流水线加法器非阻塞赋值.png 图一
wave3.PNG
图二
二级流水线加法器阻塞赋值.png
图三
wave4.PNG
图四

最近写了一个16位二级流水线加法器,并进行了一下仿真。发现在always块中采用阻塞赋值(=)和非阻塞赋值(<=)的结果是不一样的,书上的例程以及网上很多例程的流水线加法器都采用的是阻塞赋值。
书上对流水线加法器的描述是这样的:“采用流水线,能将一个算术操作分解为一些小规模的基本操作,将进位和中间值存储在寄存器中,并在下一个时钟周期内继续运算”。
如上图所示,图一、图二是采用非阻塞赋值的代码及仿真波形图,图三、图四是采用阻塞赋值的代码及波形图。明显可以看出,采用阻塞赋值的仿真结果是在一个时钟周期内得到结果,并没有像描述的那样在每个时钟周期内分级运算,也没有体现出流水线的特点;而非阻塞赋值好像更符合“下一个时钟周期内继续运算”的描述,也体现出了流水线的执行特点。


求大神指点!




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
17条回答
Mexican
1楼-- · 2019-07-16 15:17
同意楼上的观点 LS+1
xiaozm008
2楼-- · 2019-07-16 18:44
同意楼上的观点 LS+1
渊底一尾
3楼-- · 2019-07-16 22:34
alasga 发表于 2016-09-10 15:13
always@(posedege clk) 语句说明你要做的是同步逻辑设计,后面只能跟“非阻塞”赋值,而且你要做流水设计的话,就更应该是非阻塞赋值了;至于阻塞赋值,从语法上讲没有问题,但是最终综合成什么逻辑电路,就要完全看综合器对你这段代码的理解了,所以不同的软件版本之间,同一版本不同综合次数之间,不同的综合工具之间,最终综合结果都有可能不一样,属于不规范语法描述方式。所以不用去纠结第二代码了。
最后为什么不直接用
always@(posedge clk) begin
&nbsp;&nbsp;{cout,sum}

1、因为要采用流水线设计,所以没有直接用{cout,sum}。
2、采用图一代码,我发现仿真结果不对。上图中,我没有对高8位赋值。在我对高8位赋值后,发现:输出结果(cout)的高8位是当前输入高8位的和,而低8位则是上一个时钟输入低8位的和。请问应如何解决?不知您之前是否写过流水线加法器?求指教。
渊底一尾
4楼-- · 2019-07-16 23:24
 精彩回答 2  元偷偷看……
hqbenson
5楼-- · 2019-07-17 00:17
本帖最后由 hqbenson 于 2016-9-12 16:34 编辑

您好楼主。您再仔细分析一下您的代码就可以发现问题了。其实这和阻塞非阻塞没太大关系。(当然时序电路还是必须要用非阻塞的)
主要有
1.流水线的编写思路不太清晰。
2.always里面的加法和拼接符用的也有点问题。(写的是:{cout1,sum1}<={cina[7],cina[7:0]}+{cinb[7],cinb[7:0]}+cin;举个例子,如果低八位cina=a0;cinb=00;那么结果将是{1,a0},显示进位了。但实际并没有进位。所以有误。)

最主要的问题是流水线结构不对,根据您写的代码,我画了个RTL图,您看了图之后应该会很清楚了。
流水线的每一步都需要一个寄存器。
按图所示第一个时钟沿时,寄存器sum1寄存低八位的和值,但寄存器sum寄存的是上个时钟低八位部分的和值与当前输入值的和值。根本原因是因为高八位的加法器的输入随着cina和cinb改变而立即改变。所以才会出现您所说的高八位是当前的值,而低八位是上一个时钟的值。
正确的方法是要在画红圈处加一个寄存器锁存值。(可以锁存输入值,也可以锁存和值)
キャプチャ.PNG
94沧海一粟0
6楼-- · 2019-07-17 05:31
非阻塞,用assign语句的话,可以用阻塞!

一周热门 更多>