• Verilog 流水线加法器


    《数字系统设计与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后仿真,结果正确了。。。这是为啥啊?
  • 相关阅读:
    java 多线程(synchronized)
    java 多线程(daemon)
    【转】 Nginx深入详解之多进程网络模型
    Linux 网络编程(epoll)
    Linux 网络编程(多路复用)
    Linux 网络编程(UDP)
    Linux 网络编程(TCP)
    STM32F0xx_看门狗(独立+窗口)配置详细过程
    STM32F0xx_FLASH编程(片内)配置详细过程
    STM32F0xx_RTC实时时钟配置详细过程
  • 原文地址:https://www.cnblogs.com/haigege/p/2194687.html
Copyright © 2020-2023  润新知