Multiplier bugfix
[mw/milkymist.git] / cores / lm32 / rtl / lm32_multiplier_spartan6.v
1 /*
2  * Milkymist VJ SoC
3  * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 module lm32_multiplier(
19         input clk_i,
20         input rst_i,
21         input stall_x,
22         input stall_m,
23         input [31:0] operand_0,
24         input [31:0] operand_1,
25         output [31:0] result
26 );
27
28 // See UG389, esp. p. 29 "Fully Pipelined, 35 x 35 Multiplier Use Model (Large Multiplier)"
29
30 wire [17:0] au = {3'd0, operand_0[31:17]};
31 wire [17:0] al = {1'b0, operand_0[16:0]};
32 wire [17:0] bu = {3'd0, operand_1[31:17]};
33 wire [17:0] bl = {1'b0, operand_1[16:0]};
34
35 wire [17:0] bl_forward;
36 wire [35:0] al_bl;
37
38 reg [16:0] result_low;
39 always @(posedge clk_i) begin
40         if(rst_i)
41                 result_low <= 17'd0;
42         else
43                 result_low <= al_bl[16:0];
44 end
45 assign result[16:0] = result_low;
46
47 DSP48A1 #(
48         .A0REG(1),
49         .A1REG(0),
50         .B0REG(1),
51         .B1REG(0),
52         .CARRYINREG(0),
53         .CARRYINSEL("OPMODE5"),
54         .CARRYOUTREG(0),
55         .CREG(0),
56         .DREG(0),
57         .MREG(1),
58         .OPMODEREG(0),
59         .PREG(0),
60         .RSTTYPE("SYNC")
61 ) D1 (
62         .BCOUT(bl_forward),
63         .PCOUT(),
64         .CARRYOUT(),
65         .CARRYOUTF(),
66         .M(al_bl),
67         .P(),
68         .PCIN(),
69         .CLK(clk_i),
70         .OPMODE(8'd1),
71         .A(al),
72         .B(bl),
73         .C(),
74         .CARRYIN(),
75         .D(),
76         .CEA(~stall_x),
77         .CEB(~stall_x),
78         .CEC(),
79         .CECARRYIN(),
80         .CED(),
81         .CEM(~stall_m),
82         .CEOPMODE(),
83         .CEP(1'b1),
84         .RSTA(rst_i),
85         .RSTB(rst_i),
86         .RSTC(),
87         .RSTCARRYIN(),
88         .RSTD(),
89         .RSTM(rst_i),
90         .RSTOPMODE(),
91         .RSTP()
92 );
93
94 wire [47:0] au_bl_sum;
95
96 DSP48A1 #(
97         .A0REG(1),
98         .A1REG(0),
99         .B0REG(0),
100         .B1REG(0),
101         .CARRYINREG(0),
102         .CARRYINSEL("OPMODE5"),
103         .CARRYOUTREG(0),
104         .CREG(0),
105         .DREG(0),
106         .MREG(1),
107         .OPMODEREG(0),
108         .PREG(0),
109         .RSTTYPE("SYNC")
110 ) D2 (
111         .BCOUT(),
112         .PCOUT(au_bl_sum),
113         .CARRYOUT(),
114         .CARRYOUTF(),
115         .M(),
116         .P(),
117         .PCIN(),
118         .CLK(clk_i),
119         .OPMODE(8'd13),
120         .A(au),
121         .B(bl_forward),
122         .C({31'd0, al_bl[33:17]}),
123         .CARRYIN(),
124         .D(),
125         .CEA(~stall_x),
126         .CEB(),
127         .CEC(),
128         .CECARRYIN(),
129         .CED(),
130         .CEM(~stall_m),
131         .CEOPMODE(),
132         .CEP(),
133         .RSTA(rst_i),
134         .RSTB(),
135         .RSTC(),
136         .RSTCARRYIN(),
137         .RSTD(),
138         .RSTM(rst_i),
139         .RSTOPMODE(),
140         .RSTP()
141 );
142
143 wire [47:0] r_full;
144 assign result[31:17] = r_full[16:0];
145
146 DSP48A1 #(
147         .A0REG(1),
148         .A1REG(0),
149         .B0REG(1),
150         .B1REG(0),
151         .CARRYINREG(0),
152         .CARRYINSEL("OPMODE5"),
153         .CARRYOUTREG(0),
154         .CREG(0),
155         .DREG(0),
156         .MREG(1),
157         .OPMODEREG(0),
158         .PREG(1),
159         .RSTTYPE("SYNC")
160 ) D3 (
161         .BCOUT(),
162         .PCOUT(),
163         .CARRYOUT(),
164         .CARRYOUTF(),
165         .M(),
166         .P(r_full),
167         .PCIN(au_bl_sum),
168         .CLK(clk_i),
169         .OPMODE(8'd5),
170         .A(bu),
171         .B(al),
172         .C(),
173         .CARRYIN(),
174         .D(),
175         .CEA(~stall_x),
176         .CEB(~stall_x),
177         .CEC(),
178         .CECARRYIN(),
179         .CED(),
180         .CEM(~stall_m),
181         .CEOPMODE(),
182         .CEP(1'b1),
183         .RSTA(rst_i),
184         .RSTB(rst_i),
185         .RSTC(),
186         .RSTCARRYIN(),
187         .RSTD(),
188         .RSTM(rst_i),
189         .RSTOPMODE(),
190         .RSTP(rst_i)
191 );
192
193 endmodule