我正在尝试使用组合逻辑方法在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:我知道有使用时钟的有效解决方案,但挑战不是使用它们。答案 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