Merge pull request #1814 from YosysHQ/mmicko/pyosys_makefile
[yosys.git] / tests / simple / multiplier.v
1
2 // Via http://www.edaplayground.com/s/6/591
3 // stackoverflow 20556634
4 // http://stackoverflow.com/questions/20556634/how-can-i-iteratively-create-buses-of-parameterized-size-to-connect-modules-also
5
6 // Code your design here
7 `define macro_args
8 `define indexed_part_select
9
10 module Multiplier_flat #(parameter M = 4, parameter N = 4)(
11 input [M-1:0] A, //Input A, size M
12 input [N-1:0] B, //Input B, size N
13 output [M+N-1:0] P ); //Output P (product), size M+N
14
15 /* Calculate LSB using Wolfram Alpha
16 N==3 : http://www.wolframalpha.com/input/?i=0%2C+4%2C+9%2C+15%2C+...
17 N==4 : http://www.wolframalpha.com/input/?i=0%2C+5%2C+11%2C+18%2C+26%2C+35%2C+...
18 N==5 : http://www.wolframalpha.com/input/?i=0%2C+6%2C+13%2C+21%2C+30%2C+...
19 */
20 `ifdef macro_args
21 // initial $display("Use Macro Args");
22 `define calc_pp_lsb(n) (((n)-1)*((n)+2*M)/2)
23 //`define calc_pp_msb(n) (`calc_pp_lsb(n+1)-1)
24 `define calc_pp_msb(n) ((n**2+(2*M+1)*n-2)/2)
25 //`define calc_range(n) `calc_pp_msb(n):`calc_pp_lsb(n)
26 `define calc_pp_range(n) `calc_pp_lsb(n) +: (M+n)
27
28 wire [`calc_pp_msb(N):0] PP;
29 assign PP[`calc_pp_range(1)] = { 1'b0 , { A & {M{B[0]}} } };
30 assign P = PP[`calc_pp_range(N)];
31 `elsif indexed_part_select
32 // initial $display("Use Indexed Part Select");
33 localparam MSB = (N**2+(2*M+1)*N-2)/2;
34 wire [MSB:0] PP;
35 assign PP[M:0] = { 1'b0 , { A & {M{B[0]}} } };
36 assign P = PP[MSB -: M+N];
37 `else
38 // initial $display("Use Worst Case");
39 localparam MSB = (N**2+(2*M+1)*N-2)/2;
40 wire [MSB:0] PP;
41 assign PP[M:0] = { 1'b0 , { A & {M{B[0]}} } };
42 assign P = PP[MSB : MSB+1-M-N];
43 `endif
44
45 genvar i;
46 generate
47 for (i=1; i < N; i=i+1)
48 begin: addPartialProduct
49 wire [M+i-1:0] gA,gB,gS;
50 wire Cout;
51 assign gA = { A & {M{B[i]}} , {i{1'b0}} };
52 `ifdef macro_args
53 assign gB = PP[`calc_pp_range(i)];
54 assign PP[`calc_pp_range(i+1)] = {Cout,gS};
55 `elsif indexed_part_select
56 assign gB = PP[(i-1)*(i+2*M)/2 +: M+i];
57 assign PP[i*((i+1)+2*M)/2 +: M+i+1] = {Cout,gS};
58 `else
59 localparam LSB = (i-1)*(i+2*M)/2;
60 localparam MSB = (i**2+(2*M+1)*i-2)/2;
61 localparam MSB2 = ((i+1)**2+(2*M+1)*(i+1)-2)/2;
62 assign gB = PP[MSB : LSB];
63 assign PP[ MSB2 : MSB+1] = {Cout,gS};
64 `endif
65 RippleCarryAdder#(M+i) adder( .A(gA), .B(gB), .S(gS), .Cin (1'b0), .Cout(Cout) );
66 end
67 endgenerate
68
69 `ifdef macro_args
70 // Cleanup global space
71 `undef calc_pp_range
72 `undef calc_pp_msb
73 `undef calc_pp_lsb
74 `endif
75 endmodule
76
77 module Multiplier_2D #(parameter M = 4, parameter N = 4)(
78 input [M-1:0] A, //Input A, size M
79 input [N-1:0] B, //Input B, size N
80 output [M+N-1:0] P ); //Output P (product), size M+N
81
82 wire [M+N-1:0] PP [N-1:0];
83
84 // Note: bits PP[0][M+N-1:M+1] are never used. Unused bits are optimized out during synthesis
85 //assign PP[0][M:0] = { {1'b0} , { A & {M{B[0]}} } };
86 //assign PP[0][M+N-1:M+1] = {(N-1){1'b0}}; // uncomment to make probing readable
87 assign PP[0] = { {N{1'b0}} , { A & {M{B[0]}} } };
88 assign P = PP[N-1];
89
90 genvar i;
91 generate
92 for (i=1; i < N; i=i+1)
93 begin: addPartialProduct
94 wire [M+i-1:0] gA,gB,gS; wire Cout;
95 assign gA = { A & {M{B[i]}} , {i{1'b0}} };
96 assign gB = PP[i-1][M+i-1:0];
97 //assign PP[i][M+i:0] = {Cout,gS};
98 //if (i+1<N) assign PP[i][M+N-1:M+i+1] = {(N-i){1'b0}}; // uncomment to make probing readable
99 assign PP[i] = { {(N-i){1'b0}}, Cout, gS};
100 RippleCarryAdder#(M+i) adder(
101 .A(gA), .B(gB), .S(gS), .Cin(1'b0), .Cout(Cout) );
102 end
103 endgenerate
104
105 //always@* foreach(S[i]) $display("S[%0d]:%b",i,S[i]);
106
107 endmodule
108
109 module RippleCarryAdder#(parameter N = 4)(A,B,Cin,S,Cout);
110
111 input [N-1:0] A;
112 input [N-1:0] B;
113 input Cin;
114 output [N-1:0] S;
115 output Cout;
116 wire [N:0] CC;
117
118 assign CC[0] = Cin;
119 assign Cout = CC[N];
120 genvar i;
121 generate
122 for (i=0; i < N; i=i+1)
123 begin: addbit
124 FullAdder unit(A[i],B[i],CC[i],S[i],CC[i+1]);
125 end
126 endgenerate
127
128 endmodule
129
130 module FullAdder(input A,B,Cin, output wire S,Cout);
131 assign {Cout,S} = A+B+Cin;
132 endmodule