如何在Verilog中设计64 x 64位阵列乘法器?

如何在Verilog中设计64 x 64位阵列乘法器?,verilog,multiplication,Verilog,Multiplication,我知道如何设计4x4阵列乘法器,但如果遵循相同的逻辑,编码就会变得单调乏味 4 x 4-16部分积 64 x 64-4096部分产品 连同8个全加器和4个半加器,64 x 64位需要多少个全加器和半加器。如何减少部分产品的数量?有什么简单的方法可以解决这个问题吗?每当对重复模式进行冗长的编码时,您应该使用generate语句: module array_multiplier(a, b, y); parameter width = 8; input [width-1:0] a, b; out

我知道如何设计4x4阵列乘法器,但如果遵循相同的逻辑,编码就会变得单调乏味

  • 4 x 4-16部分积
  • 64 x 64-4096部分产品

连同8个全加器和4个半加器,64 x 64位需要多少个全加器和半加器。如何减少部分产品的数量?有什么简单的方法可以解决这个问题吗?

每当对重复模式进行冗长的编码时,您应该使用generate语句:

module array_multiplier(a, b, y);

parameter width = 8;
input [width-1:0] a, b;
output [width-1:0] y;

wire [width*width-1:0] partials;

genvar i;
assign partials[width-1 : 0] = a[0] ? b : 0;
generate for (i = 1; i < width; i = i+1) begin:gen
    assign partials[width*(i+1)-1 : width*i] = (a[i] ? b << i : 0) +
                                   partials[width*i-1 : width*(i-1)];
end endgenerate

assign y = partials[width*width-1 : width*(width-1)];

endmodule
模块阵列_乘法器(a、b、y);
参数宽度=8;
输入[width-1:0]a、b;
输出[width-1:0]y;
导线[宽度*宽度-1:0]部分;
genvar i;
分配部分[width-1:0]=a[0]?b:0;
为(i=1;i分配部分[width*(i+1)-1:width*i]=(a[i]?b
[如何]减少部分产品的数量?

一种常用的方法是修改Booth编码:
以更复杂的加数选择为代价,它至少使加数减半。

在其最简单的形式中,考虑来自其中一个操作数(例如b)的三个相邻位(重叠1)的组,并选择0, A. 2a, -2a 或 -a作为加数。

下面的代码只生成预期输出的一半

module arr_multi(a, b, y);      
parameter w = 8;       
input [w-1:0] a, b;                // w-width       
output [(2*w)-1:0] y;              // p-partials       
wire [(2*w*w)-1:0] p;        //assign width as input bits multiplied by 
 output bits
 genvar i;        
 assign p[(2*w)-1 : 0] = a[0] ? b : 0;  //first output size bits          
  generate            
      for (i = 1; i < w; i = i+1)       
         begin        
             assign p[(w*(4+(2*(i-1))))-1 : (w*2)*i] = (a[i]?b<<i :0) + p[(w*(4+(2* 
                (i-2))))-1 :(w*2)*(i-1)];       
         end     
   endgenerate          
  assign y=p[(2*w*w)-1:(2*w)*(w-1)];     //taking last output size bits            
   endmodule       
模块arr_multi(a、b、y);
参数w=8;
输入[w-1:0]a,b;//w-width
输出[(2*w)-1:0]y;//p-部分
导线[(2*w*w)-1:0]p;//将宽度指定为输入位乘以
输出位
genvar i;
分配p[(2*w)-1:0]=a[0]?b:0;//第一个输出大小位
生成
对于(i=1;i分配p[(w*(4+(2*(i-1)))-1:(w*2)*i]=(a[i]?b如果我必须通过管道传输它会怎么样?我怎么做,不是有点困难吗?我现在也在我的答案中添加了一个管道版本(见上面的编辑)。我知道这是一个很长的时间。你能重新评估你的代码吗?输出[width-1:0]y;//它不应该是[2*width-1]y;@chitranna您当然也可以创建一个具有2*宽度输出大小的乘法器。但它需要更多的更改,而不仅仅是“y”的大小:对于无符号乘法,它应该足以增加部分的大小。对于有符号乘法,它会变得有点复杂。(只要输入和输出宽度相同,我们就不需要区分有符号乘法和无符号乘法)我还想补充一点,在实践中,您将使用类似于进位保存加法器树的内容,而不是“正常”实现乘法的加法器。这不会导致精度损失吗?另外,如果我想为64位无符号数的乘法编写verilog代码,精度将非常重要,对吗?我们可以在聊天室讨论这个问题吗?在答案中放一些文本来解释你在做什么总是一个好主意,尤其是当e已经是一个被接受的答案或高评价的答案。阅读
module arr_multi(a, b, y);      
parameter w = 8;       
input [w-1:0] a, b;                // w-width       
output [(2*w)-1:0] y;              // p-partials       
wire [(2*w*w)-1:0] p;        //assign width as input bits multiplied by 
 output bits
 genvar i;        
 assign p[(2*w)-1 : 0] = a[0] ? b : 0;  //first output size bits          
  generate            
      for (i = 1; i < w; i = i+1)       
         begin        
             assign p[(w*(4+(2*(i-1))))-1 : (w*2)*i] = (a[i]?b<<i :0) + p[(w*(4+(2* 
                (i-2))))-1 :(w*2)*(i-1)];       
         end     
   endgenerate          
  assign y=p[(2*w*w)-1:(2*w)*(w-1)];     //taking last output size bits            
   endmodule