• Verilog 流水线加法器


    转自: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后仿真,结果正确了。。。这是为啥啊?


  • 相关阅读:
    快排
    Single Number II
    简单工厂和工厂方法
    Implement strStr()
    Linked List Cycle II
    Linked List Cycle
    适配器模式
    Struts2的ActionContext
    javaScript学习随笔
    Tomcat 基本配置(转)
  • 原文地址:https://www.cnblogs.com/youngforever/p/3104702.html
Copyright © 2020-2023  润新知