如何迭代地创建参数化大小的总线以连接模块也迭代创建?

时间:2013-12-12 23:53:06

标签: verilog

我正在尝试使用组合逻辑方法在verilog中创建一个乘法器模块,这样就不会涉及时钟。我希望模块具有通用定义,也就是说,我希望乘法器分别接收大小为M和N位的两个因子,并返回大小为M + N位的乘积。

基本思想是计算部分乘积的总和,每个乘积根据其等级向左移动一定量的比特。要理解这个想法,请看下面的例子:

A = A3 A2 A1 A0和B = B2 B1 B0

然后, A X B 将按如下方式计算:

                  A3*B0  A2*B0  A1*B0 A0*B0
           A3*B1  A2*B1  A1*B1 A0*B1
+   A3*B2  A2*B2  A1*B2 A0*B2
____________________________________________

为了得到部分乘积的总和,我需要得出前两个乘积(A乘以B0)+([A乘以B1] <&lt; 1)的总和,这可以通过以下方式轻松制作:一个RippleCarryAdder [许多连接的FullAdders],然后使用这个和的输出以及随后的移位的部分乘积([A次B2]&lt;&lt; 2)作为第二个RippleCarryAdder的两个输入。

更一般地说,要计算乘积A [M-1:0]乘以B [N-1:0],我们需要使用N-1 RippleCarryAdder(每个定义比前一个多一位)并以某种方式使用每一个的输出作为下一个的两个输入之一。

到目前为止,这是我不完整的verilog代码:

首先, RippleCarryAdder参数化,这可以正常工作

module RippleCarryAdder#(parameter N = 4)(A,B,Cin,S,Cout);

input [N-1:0] A;
input [N-1:0] B;
input Cin;
output [N-1:0] S;
output Cout;
wire [N:0] CC;

assign CC[0] = Cin;
assign Cout = CC[N];
genvar i;
generate
for (i=0; i < N; i=i+1)
begin: addbit
    FullAdder unit(A[i],B[i],CC[i],S[i],CC[i+1]);
end
endgenerate

endmodule

乘数的不完整代码

module Multiplier #(parameter M = 4, N = 4)(A,B,P);

input [M-1:0] A; //Input A, size M
input [N-1:0] B; //Input B, size N
output [M+N-1:0] P;  //Output P (product), size M+N

wire [N-1:0] CC; //Bus for the carries of the RippleCarryAdders

assign CC[0] = 1'b0;

RippleCarryAdder#(M+1) adder0({1'b0,A&{M{B[0]}}},{A&{M{B[1]}},1'b0},CC[0], /*insert bus P0 here*/);

/*I want bus P0 =  (0 A[N-1]&B[0] ... A[0]&B[0]) + (A[N-1]&B[1] ... A[0]&B[1] 0) + CC[0], with CC[0] = 0 because it is the first sum */

genvar i;
generate
for (i=2; i < N; i=i+1)
begin: addPartialProduct
    RippleCarryAdder#(M+i) adder({A&{M{B[i]}},{(i{1'b0}}},/*{CC[i-1],P[i-2]}*/,CC[i-2],/*P[i-1]*/,CC[i-1]);

//When I do {CC[i-1],P[i-1]}, I mean the concatenation of the carry CC[i] (1 bit) with the product P[i-1] (several bits)


end
endgenerate

//Finally, I want P = P[N-1], the output of the last RippleCarryAdder

endmodule

所以我的问题是:如何定义这些参数化大小的P [i]总线,以便它们可以用来连接每对连续RippleCarryAdder的输入和输出?请注意,每个总线P [i]的大小(M + i + 1),i = 0,...,N-1

如果不可能,那么只有使用Combitional Logic(没有涉及时钟)的参数化乘法器存在哪些其他解?

提前致谢。

PS:我知道有使用时钟的有效解决方案,但挑战不是使用它们。

1 个答案:

答案 0 :(得分:0)

创建求和/部分乘积的菊花链数组,类似于纹波加法器中使用的进位链。这个链需要是一个二维数组。链阵列的打包部分将是sum / partial-product,unpacked将是级别。使用2D数组意味着永远不会使用某些位,例如S[0][M+N-1:M+1]。在合成期间,未使用的位将被优化。以下代码剪辑 - 它演示了使用纹波加法器实现的无符号乘法器的所需行为。

wire [M+N-1:0] S [N-1:0]; // chain of sums / partial-products

assign S[0][M:0] = { 1'b0 , { A & {M{B[0]}} } };
// assign S[0][M+N-1:M+1] = {(N-1){1'b0}}; // uncomment to make probing readable
assign P = S[N-1]; // Product

genvar i;
generate
for (i=1; i < N; i=i+1)
begin: addPartialProduct
    //if (i+1<N) assign S[i][M+N-1:M+i+1] = {(N-i){1'b0}}; // uncomment to make probing readable
    RippleCarryAdder#(M+i) adder(
        .A   ( S[i-1][M+i-1:0] ),
        .B   ( { A & {M{B[i]}} , {i{1'b0}} } ),
        .Cin ( 1'b0 ),
        .S   ( S[i][M+i-1:0] ),
        .Cout( S[i][M+i] ) );
end
endgenerate