微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 硬件电路设计 > 硬件电路设计讨论 > 这段verilog代码是不是有问题啊,仿真波形错误啊?

这段verilog代码是不是有问题啊,仿真波形错误啊?

时间:10-02 整理:3721RD 点击:
是一个关于流水线方式实现的8位全加器
从书上抄的一个例子:
module pipeline(cout,sum,ina,inb,cin,clk);
   
    output [7:0] sum;
    output cout;
    input [7:0] ina;
    input [7:0] 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;
    reg [3:0] secondb;
    reg [3:0] 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
自己写了一个激励文件:
`timescale 10ns / 1ns
module pipeline_tb;
   
   
    //Internal signals declarations:
    wire cout;
    wire [7:0]sum;
    reg [7:0]ina;
    reg [7:0]inb;
    reg cin;
    reg clk;
    parameter dely=10;
   
   
    // Unit Under Test port map
    pipeline UUT (
        .cout(cout),
        .sum(sum),
        .ina(ina),
        .inb(inb),
        .cin(cin),
        .clk(clk));     
   
    always #(dely/2)clk=~clk;   
   
    initial
        begin
            clk=0;
            cin=0;
            ina=8'b0;
            inb=8'b0;
            #(dely*1000)    $finish;
        end   
   
    always #(10*dely) cin=$random;
   
    always #(10*dely) ina=$random;
   
    always #(10*dely) inb=$random;
   
    initial
        $monitor($realtime,,"ps %h %h %h %h %h %h ",cout,sum,ina,inb,cin,clk);
endmodule
但是仿真出来的波形明显不对啊


就是中间那组数据有一位算错了。估计是连续进位的问题。
[ 本帖最后由 langhuamin 于 2007-11-23 08:31 编辑 ]

问题是,为何第一个进位正确,而后面的两个进位就错误了?这属于什么问题?

据猜测,程序可能有问题。
{thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds};PCB

其中,{seconda[1:0]+secondb[1:0]+secondco,seconds}是6位,{thirdco,thirds}是7位,
导致最高进位出现问题。
此属推断,待验证。
可以尝试先将second[2:0]=seconda[1:0]+secondb[1:0]+secondco;
再{thirdco,thirds}={second[2:0],seconds};

不过我这边现在没装这个工具软件。

[ 本帖最后由 langhuamin 于 2007-11-23 18:40 编辑 ]

回去试了一下,确实如此。
而且程序段可以作以下简化:

reg [8:0]ins;
always @(posedge clk)  
  begin
       tempa<=ina;
       tempb<=inb;
       tempci<=cin;
   end               
always @(posedge clk)  
begin
       ins=tempa+tempb+tempc;      
       {cout,sum}={ins};
end

虽然没错
这样的代码综合出来比流水线效率低
综合出来用的器件也多哈
呵呵

这个问题我也注意到了
但问题在于为何第一也是这样的效果为何就有进位变化
而只有后面的两个有错误?
不知道是否与verilog语言本事有关系?
我自己试了试
如何在加之前先把2位的值赋值给一个3位的值
这样就能保证赋值间的位数一样
这样进位的值就不会丢失了

也可以说是verilog本身的原因吧,
因为这里{thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds}
并不是将右边计算完后得出的数据直接放入{thirdco,thirds}中的,
这里{}={};在次序上是先将里面的算完得出运算结果(这时已经确定位数),然后再把结果作=处理。分两步进行。
本质上与second[2:0]=seconda[1:0]+secondb[1:0]+secondco;不一样。
一开始我也想到“在加之前先把2位的值赋值给一个3位的值”,这个方法和我说的那个原理类似。PCB

呵呵,这个我倒没考虑过

你可以参看一些教程里面的综合结果实例对比
代码不同效率不一样 虽然结果相同

嗯好的,有机会会多去看看的.呵呵

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top