所谓流水线的概念可能大家都不陌生,通俗的讲就是本来是一条龙服务的,现在将整个环节分割成几小段,然后让这几个分段同时开始各自的工作,最后将这些小段连接成整体,这样便提高了系统的运行速度,提高了效率。
因此,流水线加法器只是将大串的数据相加修改为小段数据相加,而这个加数和被加数的分段可以自由分配的。以下是我自己实验的42位数据相加,是带符号位的,也就是符号数,我分为3段11位相加和一段9位相加。值得注意的是前三段中相加时候要扩展一位进位,可以直接在数据前加一位0,但是在最后一段的相加中我们需要将最高的符号位扩展一次,以免加到溢出,同时可以保留符号结果。
以下是verilog代码:
module pipl_add(clk,rst,
add_a,add_b,
add_out);
input clk;
input rst;
input[41:0] add_a;
input[41:0] add_b;
output[42:0] add_out; //为保证不溢出,相加结果扩展一位;
reg[11:0] sum1;
reg[22:0] sum2;
reg[33:0] sum3;
reg[42:0] add_out;
//中间寄存的数据
reg[8:0] add_tmpa3,add_tmpb3;
reg[19:0] add_tmpa2,add_tmpb2;
reg[30:0] add_tmpa1,add_tmpb1;
always@(posedge clk or negedge rst) begin
if(!rst) sum1 <= 0;
else begin
sum1 <= {1'b0,add_a[10:0]} + {1'b0,add_b[10:0]};
add_tmpa1 <= add_a[41:11]; add_tmpb1 <= add_b[41:11]; //储存未计算的数据
end
end
always@(posedge clk or negedge rst) begin
if(!rst) sum2 <= 0;
else begin
sum2 <= {{1'b0,add_tmpa1[10:0]}+{1'b0,add_tmpb1[10:0]}+sum1[11],sum1[10:0]};//
add_tmpa2 <= add_tmpa1[30:11]; add_tmpb2 <= add_tmpb1[30:11]; //储存未计算的数据
end
end
always@(posedge clk or negedge rst) begin
if(!rst) sum3 <= 0;
else begin
sum3 <= {{1'b0,add_tmpa2[10:0]}+{1'b0,add_tmpb2[10:0]}+sum2[22],sum2[21:0]};//
add_tmpa3 <= add_tmpa2[19:11]; add_tmpb3 <= add_tmpb2[19:11]; //储存未计算的数据
end
end
always@(posedge clk or negedge rst) begin
if(!rst) add_out <= 0;
else add_out <= {{add_tmpa3[8],add_tmpa3[8:0]}+{add_tmpb3[8],add_tmpb3[8:0]}+sum3[33],sum3[32:0]};//
end
endmodule
modelsim仿真结果:
以上是综合后仿真,也就是门级仿真的结果。从数据中可以看出总体延时了3个时钟,之后数据开始显现正确结果。
cku88_223230858 2012-2-23 19:03