转自:http://www.cnblogs.com/haigege/archive/2011/09/28/2194687.html
《数字系统设计与Verilog HDL》上面有这么一段代码,用于实现8位4级流水线加法器。
module adder8pip(cout,sum,cin,ina,inb,clk
);
input cin,clk;
input [7:0] ina,inb;
output cout;
output [7:0] sum;
reg cout,tempcin;
reg [7:0] sum,tempa,tempb;
reg firstco,secondco,thirdco; //前三级加法的进位输出
reg [1:0] firstsum,thirdina,thirdinb;
reg [3:0] secondsum,secondina,secondinb;
reg [5:0] thirdsum,firstina,firstinb;
always @ (posedge clk)
begin
tempcin=cin;tempa=ina;tempb=inb;//输入数据缓存
end
always @ (posedge clk)
begin
{firstco,firstsum}=tempa[1:0]+tempb[1:0]+tempcin;//第一级低2位相加
firstina=tempa[7:2];firstinb=tempb[7:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{secondco,secondsum}={firstina[1:0]+firstinb[1:0]+firstco,firstsum};//第二级2位相加,并与前一级结果合并
secondina=firstina[5:2];secondinb=firstinb[5:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{thirdco,thirdsum}={secondina[1:0]+secondinb[1:0]+secondco,secondsum};//第三级2位相加,并与前一级结果合并
thirdina=secondina[3:2];thirdinb=secondinb[3:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{cout,sum}={thirdina[1:0]+thirdinb[1:0]+thirdco,thirdsum};//第四级最高2位相加,并与前一级结果合并
end
endmodule
综合之后发现如下警告:
FF/Latch <secondco> (without init value) has a constant value of 0 in block <adder8pip>. This FF/Latch will be trimmed during the optimization process.
再看RTL电路图,发现cout果然被接地了。
在网上找原因,原来是因为在后面三级的加法运算中,比如第二级:
{secondco,secondsum}={firstina[1:0]+firstinb[1:0]+firstco,firstsum};
”{ }”就已经限定等号右边为4位,由于等号左边为5位,这造成secondco没用,综合的时候会把secondco综合掉。
因此对于有符号数的加法,将上述代码改为:
{secondco,secondsum}={ {firstina[1],firstina[1:0]}+{firstinb[1],firstinb[1:0]}+firstco,firstsum};(未验证)
即扩展符号位,每一级的加法运算都要扩,对于第一级加法也要扩符号位。
下面是无符号数流水线加法器的完整代码:
module adder8pip(cout,sum,cin,ina,inb,clk
);
input cin,clk;
input [7:0] ina,inb;
output cout;
output [7:0] sum;
reg cout,tempcin;
reg [7:0] sum,tempa,tempb;
reg firstco,secondco,thirdco; //前三级加法的进位输出
reg [1:0] firstsum,thirdina,thirdinb;
reg [3:0] secondsum,secondina,secondinb;
reg [5:0] thirdsum,firstina,firstinb;
always @ (posedge clk)
begin
tempcin=cin;tempa=ina;tempb=inb;//输入数据缓存
end
always @ (posedge clk)
begin
{firstco,firstsum}=tempa[1:0]+tempb[1:0]+tempcin;//第一级低2位相加,由于没有{}限位,因此不需要扩展位
firstina=tempa[7:2];firstinb=tempb[7:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{secondco,secondsum}={{1'b0,firstina[1:0]}+{1'b0,firstinb[1:0]}+firstco,firstsum};//第二级2位相加,并与前一级结果合并
secondina=firstina[5:2];secondinb=firstinb[5:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{thirdco,thirdsum}={{1'b0,secondina[1:0]}+{1'b0,secondinb[1:0]}+secondco,secondsum};//第三级2位相加,并与前一级结果合并
thirdina=secondina[3:2];thirdinb=secondinb[3:2];//未参加计算的数据缓存
end
always @ (posedge clk)
begin
{cout,sum}={{1'b0,thirdina[1:0]}+{1'b0,thirdinb[1:0]}+thirdco,thirdsum};//第四级最高2位相加,并与前一级结果合并
end
endmodule
该代码用ISE综合没有报错,但是发现RTL电路仍然不符合要求,想不通,怀疑难道综合器有问题。于是装上Synplify,再综合,还真没问题了,而且界面很好看。
然后再用modelsim做前仿真,结果还是不对啊。。。为嘛,为嘛啊。。。
好吧,做map后仿真,结果正确了。。。这是为啥啊?