四级流水线方式的8位全加器

一、存在的问题

初稿参考《Verilog HDL程序设计教程》王金明编著。但是这个教材存在问题,源码如下:module pipeline
(
   cout, sum, ina, inb, cin, clk
);
output [7:0]  sum;
output        cout;
input  [7:0]  ina, inb;
input         cin, clk;
reg [7:0]     tempa, tempb, sum;
reg           tempci, firstco, secondco, thirdco, cout;
reg [1:0]     firsts, thirda, thirdb;
reg [3:0]     seconda, secondb, seconds;
reg [5:0]     firsta, firstb, thirds;


always @(posedge clk) 
begin
   tempa  <= ina;
   tempb  <= inb;
   tempci <= cin;    
end

always @(posedge clk) 
begin
   {firstco , firsts} <= tempa [1:0] + tempb [1:0] +tempci;
   firsta <= tempa [7:2];
   firstb <= tempb [7:2];    
end

always @(posedge clk) 
begin
   {secondco , seconds} <= {firsta [1:0] + firstb [1:0] + firstco , firsts};
   seconda <= firsta [5:2];
   secondb <= firstb [5:2];   
end

always @(posedge clk) 
begin
    {thirdco , thirds} <= {seconda [1:0] + secondb [1:0] + secondco , seconds};
    thirda <= seconda [3:2];
    thirdb <= secondb [3:2];
end

always @(posedge clk)  
begin
   {cout , sum} <= {thirda[1:0] + thirdb [1:0] +thirdco , thirds};    
end
endmodule

综合过后的RTL视图下,上述红色框中,cout作为进位位,实际上cout的D触发器的输入端并没有信号输入,原因是:

①{secondco , seconds} <= {firsta [1:0] + firstb [1:0] + firstco , firsts};

② {thirdco , thirds} <= {seconda [1:0] + secondb [1:0] + secondco , seconds};

③ {cout , sum} <= {thirda[1:0] + thirdb [1:0] +thirdco , thirds};    

这几行代码中,在综合过程中,①右边自动被限制为四位,在综合过程中,secondco不会得到正确的进位值,②③同理。参考:8位4级流水线加法器verilog程序 - 豆丁网 (docin.com)

如:①修改为:{secondco , seconds} <= {{1'b0,firsta [1:0]} + {1'b0,firstb [1:0]} + firstco , firsts};另外几个同理。

二、改进源码如下

方法1,加了缓存数据的寄存器,每一级都进行缓存。

module pipeline
(
    output reg             cout,
    output reg[7:0]        sum,
    input  wire[7:0]    ina,
    input  wire[7:0]    inb,
    input  wire            cin,
    input  wire            clk
);

    reg ci0_reg, ci1_reg,ci2_reg,ci3_reg;
    reg[1:0] temp1_reg;
    reg[3:0] temp2_reg;
    reg[5:0] temp3_reg;
    
    reg[5:0]    firstTemp_a,firstTemp_b;
    reg[3:0]    secondTemp_a,secondTemp_b;
    reg[1:0]    thirdTemp_a,thirdTemp_b;
    
    reg[7:0]    inputa,inputb;
    
always@(posedge clk)
    begin
        inputa     <= ina;
        inputb     <= inb;
        ci0_reg <= cin;
    end
    
always@(posedge clk)
    begin
        {ci1_reg,temp1_reg}        <=        inputa[1:0]    +    inputb[1:0]    + ci0_reg;
        firstTemp_a             <=         inputa[7:2];
        firstTemp_b             <=         inputb[7:2];
    end
    
always@(posedge clk)
    begin
        {ci2_reg,temp2_reg}        <=        {{1'b0,firstTemp_a[1:0]} + {1'b0,firstTemp_b[1:0]} + ci1_reg,temp1_reg};
        
        secondTemp_a            <=        firstTemp_a[5:2];
        secondTemp_b            <=        firstTemp_b[5:2];
    end
    
always@(posedge clk)
    begin
        {ci3_reg,temp3_reg}        <=        {{1'b0,secondTemp_a[1:0]} + {1'b0,secondTemp_b[1:0]} + ci2_reg,temp2_reg};
        
        thirdTemp_a                <=        secondTemp_a[3:2];
        thirdTemp_b                <=        secondTemp_b[3:2];
    end
    
always@(posedge clk)
    begin
        {cout,sum}                <=        {{1'b0,thirdTemp_a} + {1'b0,thirdTemp_b} + ci3_reg,temp3_reg};
    end

endmodule
RTL视图:

观察cout端口,现在端口所在的D触发器信号输入端已经有信号输入了。

简单的testbench测试 156 + 149 能不能得到正确的结果。

测试源码如下:

`timescale 1ns/1ns

module tb_pipeline;

    wire         cout;
    wire[7:0]    sum;
    
    reg[7:0]    ina;
    reg[7:0]    inb;
    reg         cin;
    reg          clk;
    
initial
    begin
        ina    <= 8'd156;
        inb    <= 8'd149;
        cin    <= 1'b0;
        clk    <= 1'b0;
    end 

always #10    clk = ~clk;

initial 
    begin
        $timeformat(-9,0,"ns",6);
        $monitor("@time %t :ina =%d, inb =%d, cout =%d,sum = %d",$time,ina,inb,cout,sum);    
    end
pipeline tb_pipeline_instan
(
    .cout(cout),
    .sum(sum),
    .ina(ina),
    .inb(inb),
    .cin(cin),
    .clk(clk)
);
endmodule
仿真结果:

 和实际设计要求相符合。

方法二,没有对每一级的没有参与计算的值都进行缓存,只保留了每次计算的结果,其实思路上和前面是一样的,放上这个代码希望能够帮助理解4级流水线的8位全加器。

module pipeline
(
    output reg             cout,
    output reg[7:0]        sum,
    input  wire[7:0]    ina,
    input  wire[7:0]    inb,
    input  wire            cin,
    input  wire            clk
);

    reg ci0_reg, ci1_reg,ci2_reg,ci3_reg;
    reg[1:0] temp1_reg;
    reg[3:0] temp2_reg;
    reg[5:0] temp3_reg;
    
    reg[5:0]    firstTemp_a,firstTemp_b;
    reg[3:0]    secondTemp_a,secondTemp_b;
    reg[1:0]    thirdTemp_a,thirdTemp_b;
    
    reg[7:0]    inputa,inputb;
    
always@(posedge clk)
    begin
        inputa     <= ina;
        inputb     <= inb;
        ci0_reg   <= cin;
    end
    
always@(posedge clk)
    begin
        {ci1_reg,temp1_reg}        <=        inputa[1:0]    +    inputb[1:0]    + ci0_reg;
    end
    
always@(posedge clk)
    begin
        {ci2_reg,temp2_reg}        <=        {{1'b0,inputa[3:2]} + {1'b0,inputb[3:2]} + ci1_reg,temp1_reg};
    end
    
always@(posedge clk)
    begin
        {ci3_reg,temp3_reg}        <=        {{1'b0,inputa[5:4]} + {1'b0,inputb[5:4]} + ci2_reg,temp2_reg};
    end
    
always@(posedge clk)
    begin
        {cout,sum}                <=        {{1'b0,inputa[7:6]} + {1'b0,inputb[7:6]} + ci3_reg,temp3_reg};
    end

endmodule

testbench和前面的是一样的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值