流水线4位(4bit)加法器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
代码如下:
`timescale 1ns / 1ps
module pipeline_add(a,b,cin,cout,sum,clk);
input[3:0] a,b;
input clk,cin;
output[3:0]sum;
output cout;
reg[3:0] tempa,tempb;
reg tempci;
reg cout;
reg firstco;
reg[1:0] firstsum;
reg[2:0] firsta,firstb; //空出fista[2]、firstn[2]放进位
reg[3:0] sum;
always@(posedge clk)
begin
tempa=a; //输入数据缓存
tempb=b;
tempci=cin;
end
always@(posedge clk)
begin
{firstco,firstsum}=tempa[1:0]+tempb[1:0]+tempci; //第一级加(低2位)
firsta=tempa[3:2]; //未参加计算的数据缓存
firstb=tempb[3:2];
end
always@(posedge clk)
begin
{cout,sum}={firsta[2:0]+firstb[2:0]+firstco,firstsum}; //第二级加(高2位)
end
endmodule
顶层测试模块代码
`timescale 1ns/1ps
module pipeline_add_test;
reg [3:0] a = 4'b0000;
reg [3:0] b = 4'b0000;
reg cin = 1'b0;
wire cout;
wire [3:0] sum;
reg clk = 1'b0;
parameter PERIOD = 200;
parameter real DUTY_CYCLE = 0.5;
parameter OFFSET = 100;
initial // Clock process for clk
begin
#OFFSET;
forever
begin
clk = 1'b0;
#(PERIOD-(PERIOD*DUTY_CYCLE)) clk = 1'b1;
#(PERIOD*DUTY_CYCLE);
end
end
pipeline_add UUT (
.a(a),
.b(b),
.cin(cin),
.cout(cout),
.sum(sum),
.clk(clk));
initial begin
// ------------- Current Time: 100ns
#100;
cin = 1'b1;
// -------------------------------------
// ------------- Current Time: 185ns
#85;
a = 4'b0010;
b = 4'b0011;
// -------------------------------------
// ------------- Current Time: 385ns
#200;
a = 4'b0100;
b = 4'b0010;
// -------------------------------------
// ------------- Current Time: 585ns
#200;
cin = 1'b0;
a = 4'b1010;
b = 4'b0011;
// -------------------------------------
// ------------- Current Time: 785ns
#200;
a = 4'b1011;
b = 4'b1010;
// -------------------------------------
// ------------- Current Time: 985ns
#200;
a = 4'b1111;
b = 4'b1110;
// -------------------------------------
// ------------- Current Time: 1185ns
#200;
a = 4'b1101;
b = 4'b0100;
// -------------------------------------
// ------------- Current Time: 1585ns
#400;
a = 4'b0011;
// -------------------------------------
// ------------- Current Time: 1785ns
#200;
b = 4'b1101;
// -------------------------------------
// ------------- Current Time: 1985ns
#200;
cin = 1'b1;
a = 4'b0101;
b = 4'b1111;
// -------------------------------------
// ------------- Current Time: 2385ns
#400;
a = 4'b0100;
b = 4'b1101;
// -------------------------------------
end
endmodule
布线-布局仿真(Post-Route Simulate)
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
流水线加法器延时3个时钟周期得到两数相加的值。
下面是综合器综合后的RTL视图。从下图也能很好解释2级流水线的工作原理和延时3个时钟周期的原因。因为经过了三个寄存器(D触发器)。
要注意的是,不能用前仿真验证,因为前仿真没有考虑器件延时,仿真出来的波形与实际不符。下面是前仿真(行为仿真Behavioral Simulation)
可以看到两个加数(a、b)没有经过延时就得到结果(sum、cout),这个可以从RTL中知道,寄存器FD在时钟上升沿,数据就从输入到输出,没仿真出来流水线的特点。
下面再认真看看程序高2位相加代码为
{cout,sum}={firsta[2:0]+firstb[2:0]+firstco,firstsum};
不能用下面代码:
{cout,sum}={firsta[1:0]+firstb[1:0]+firstco,firstsum};
这是由于”{}”就已经限定等号右边为4位,由于等号左边为5位,这造成cout没用,综合的时候会把cout综合掉
综合报告(Synthesis Report)会出现这样的信息:
WARNING:Xst:1710 - FF/Latch <cout> (without init value) has a constant value of <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />0 in block <pipeline_add>.
RTL视图可以看到cout接地了,都表明cout没用到。
之前参考了书《FPGA开发实用教程》第六节《Verilog 常用程序示例2》
(http://www.eefocus.com/article/08-03/37234s.html )写成下面的样子,结果也出错
{cout,sum}={{firsta[1],firsta[1:0]}+{firstb[1],firstb[1:0]}+firstco,firstsum};
这段代码解决了位数问题,但结果还是不正确,这是由于进位cout不单单是由firsta[1]、firstb[1]决定的:01+11=100,与firsta[1:0]和firstb[1:0]都有关系。
采用流水线设计的加法器,有效提高了系统的最高运行频率,提高了工作速度,尤其是对于FPGA器件,效果跟明显。
采用流水线设计的4位加法器时序分析:(XC3S500E)
串行加法器和超前进位加法器的时序分析可参考下面两篇博文:
参考资料:
1) Verilog数字系统设计教程,夏宇闻,北京航空航天大学出版社,P105页 ,2.6流水线
2) Verilog HDL程序设计教程,P151页,10.2流水线设计技术 (程序不能综合,具体参考上文)
下载地址:http://bbs.ednchina.com/ShowTopic.aspx?id=73098
3) 《FPGA开发实用教程》第六节《Verilog 常用程序示例2》(程序不能综合,具体参考上文)
http://www.eefocus.com/article/08-03/37234s.html
文章评论(0条评论)
登录后参与讨论