微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 请问如何verilog实现100个变量的加法

请问如何verilog实现100个变量的加法

时间:10-02 整理:3721RD 点击:
我在一个主要的always中一次性算出了a[1], a[2], a[3]......a[100],然后想把这100个数相加,用于算法的后续计算。
我目前的code如下(仿真结果正确,但是应该是无法综合的):
always @(posedge clk)
begin
a[1]=;  a[2]=, ...... a[100]= ....;   //算出了所有的a
sum=a[1]+a[2]+a[3]+a[4]+a[5]+......+a[100];   //写了好长一串,仿真结果是对的,但是肯定不可以综合;
b=function(sum);
end
于是,我的目标是再用一个always语句放在后面,单独计算sum, 如:
always @(posedge clksum) // 时钟clksum比clk快100倍;
begin
     sum=sum+a[counter];
      counter=counter+1;
end
请问这样想,思路方向对不对?

你可以把100个数拆开 流水线分开同时算那

同意楼上的,用几级流水线就可以加出来了。例如第一级是a[1]+a[100],a[2]+a[99],......
第二级再把他们的50个结果两两想加,大概5-6级流水线就出来了,也就是6个clksum周期。

楼上正解,如果timing允许,可以在一个clock之内有多级加法,这样需要的clock周期也不多。
只要pipeline输入和输出,结果就是连续的

谢谢各位大侠啊,以下是我新写的代码,仿真结果是对的,请问可以综合吗?
reg [32:1] tier1 [0:19];
  reg [32:1] tier2 [0:3];
  always @(posedge clksum)
     if(sumenable==1)
       begin
       for(j=0;j<20;j=j+1)
          tier1[j]=a[5*j+1]+a[5*j+2]+a[5*j+3]+a[5*j+4]+a[5*j+5];
       for(j=0;j<4;j=j+1)
          tier2[j]=tier1[5*j]+tier1[5*j+1]+tier1[5*j+2]+tier1[5*j+3]+tier1[5*j+4];  
       sum=tier2[0]+tier2[1]+tier2[2]+tier2[3];
       sumenable=0;
       end
感觉是一个clksum周期内完成的,不太对了。

不可能一个周期完成,和LZ的上次问题一样,你写的代码一定会对应实际的硬件电路,你想想你的代码对应什么?而且在同步电路中时钟和timming的问题很重要,一百个数一起加你考虑过路径延迟吗?逻辑云的延迟吗?建立保持时间呢?这些时间加起来和时钟周期相比,slack又是多少?verilog不是软件,你用的是描述语言,你其实是在画电路图而已

LZ要想省力气写代码的话,可以使用GENERATE语法,
第一级流水GENERATE,然后第二级,它的作用只相当于减少你CODING的工作量。
也还是要用到FOR循环之类的,
对于FOR循环,如果是组合逻辑,直接在代码里写就行了,可读性也挺高。
对于时序逻辑,最好还是GENERATE与FOR一起用在第一行里,ALWAYS@(POSEDGE CLK)里面不要含FOR语句吧。

这两天听了各位大侠的指导,开始越来越感受到自己硬件思维的模糊。但是认识到错误,也是一种进步,所以特别感谢大家。
开始回想自己这几个月的仿真(虽然仿真结果对),似乎都是不可以综合的(这个太郁闷了。)
刚看到一个帖子,他给出这样的总结:
(1)对组合逻辑建模采用阻塞式赋值。
(2)对时序逻辑建模采用非阻塞是赋值。
我这个题需要进行大量数值计算,估计要用(2)。所以我的“matlab风格的verilog描述”应该无法综合吧?
比如这个
module fixmultiply(product,a,b);
  output [32:1] product;
  input [32:1] a,b;
  reg [32:1] product;
  reg [64:1] temp;
  reg [32:1] aa,bb;
  reg a1,b1,c1; //?
  reg [64:1] cc; //?
  always @(a,b)
    begin
     a1=a[32];
     b1=b[32];
     aa=(a1==0)?a:{~a[31:1]+1'b1};
     bb=(b1==0)?b:{~b[31:1]+1'b1};
     c1=a1^b1;
     cc=aa*bb;         //31 bits times 31 bits
     if (c1==0)temp=cc;
     else temp=~{1'b0,cc}+1'b1;
     product=temp[48:17];
    end
endmodule
基本上是用阻塞赋值语句实现的matlab(真想给自己一巴掌--!), 请问有办法把这个补码乘法器,改成可综合的代码吗?
module fixmultiply(product,a,b,clk);
  output [32:1] product;
  input [32:1] a,b;
  input clk;
  wire clk;
  reg [32:1] product;
  reg [64:1] temp;
  reg [32:1] aa,bb;
  reg a1,b1,c1; //?
  reg [64:1] cc; //?
  always @(posedge clk)
    begin
     a1<=a[32];
     b1<=b[32];
     aa<=(a1==0)?a:{~a[31:1]+1'b1};
     bb<=(b1==0)?b:{~b[31:1]+1'b1};
     c1<=a1^b1;
     cc<=aa*bb;         //31 bits times 31 bits
     if (c1==0)temp<=cc;
     else temp<=~{1'b0,cc}+1'b1;
     product<=temp[48:17];
    end
endmodule
这样可以综合了吗?

一个简单的matlab算法,实现成硬件就难多了。
a=b+c;
d=a*e;
f=d+g;
前后都是依赖关系,用阻塞赋值语句很舒服(但是估计是综合不了),用非阻塞赋值语句的话变量间的前后依赖关系就脱节了,但也不敢用#1这样的延时。



    分级机加法。

如果时序要求不严的话可以串行加法

LZ的思想确实有点太软件了。不过如果你真的需要做这样的加法,可以采用二叉树的方法实现,比串行延时会少很多。

学习了

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

网站地图

Top