OpenCores
URL https://opencores.org/ocsvn/mips789/mips789/trunk

Subversion Repositories mips789

[/] [mips789/] [tags/] [arelease/] [verilog/] [mips_core/] [muldiv.v] - Blame information for rev 51

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mcupro
/////////////////////////////////////////////////////////////////////
2
////  Author: Liwei                                              ////
3
////                                                             ////
4
////                                                             ////
5
////  If you encountered any problem, please contact :           ////
6
////  Email: mcupro@yahoo.com.hk or mcupro@opencores.org         ////
7
////                                                             ////
8
////  Downloaded from:                                           ////
9
////     http://www.opencores.org/pdownloads.cgi/list/mips789    ////
10
/////////////////////////////////////////////////////////////////////
11
////                                                             ////
12
//// Copyright (C) 2006-2007 Liwei                               ////
13
////                         mcupro@yahoo.com.hk                 ////
14
////                                                             ////
15
////                                                             ////
16
//// This source file may be used and distributed freely without ////
17
//// restriction provided that this copyright statement is not   ////
18
//// removed from the file and any derivative work contains the  ////
19
//// original copyright notice and the associated disclaimer.    ////
20
////                                                             ////
21
//// Please let the author know if it is used                    ////
22
//// for commercial purpose.                                     ////
23
////                                                             ////
24
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
25
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
26
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
27
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
28
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
29
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
30
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
31
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
32
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
33
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
34
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
35
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
36
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
37
////                                                             ////
38
/////////////////////////////////////////////////////////////////////
39
////                                                             ////
40
////                                                             ////
41
//// Date of Creation: 2007.8.1                                  ////
42
////                                                             ////
43
//// Version: 0.0.1                                              ////
44
////                                                             ////
45
//// Description:                                                ////
46
////                                                             ////
47
////                                                             ////
48
/////////////////////////////////////////////////////////////////////
49
////                                                             ////
50
//// Change log:                                                 ////
51
////                                                             ////
52
/////////////////////////////////////////////////////////////////////
53
 
54
`define ALU_MFHI       6
55
`define ALU_MFLO       7
56
`define ALU_MULTTU     8
57
`define ALU_MULT       9
58
`define ALU_DIVU       10
59
`define ALU_DIV        11
60
`define ALU_MTHI           31
61
`define ALU_MTLO       30
62
 
63
 
64
 
65
module muldiv
66
(
67
ready,rst,op1,op2,
68
clk,dout,func
69
);
70
    input         clk,rst;
71
    wire       sign;
72
    input [4:0] func ;
73
    input [31:0] op2, op1;
74
    output [31:0] dout;
75
    output        ready;
76
    reg [31:0]    quotient, quotient_temp;
77
    reg [63:0]    dividend_copy, divider_copy, diff;
78
    reg           negative_output;
79
 
80
    reg [63:0]    product, product_temp;
81
 
82
    reg [31:0]    multiplier_copy;
83
    reg [63:0]    multiplicand_copy;
84
 
85
    reg [6:0]     mul_bit,div_bit;
86
    wire          ready = ((mul_bit==0)&&(div_bit==0));
87
 
88
    wire  [31:0]  dividend, divider;
89
 
90
    wire [31:0]  remainder;
91
    wire [31:0] multiplier,multiplicand;
92
 
93
    reg [31:0] hi,lo;
94
 
95
    assign dout = (func==`ALU_MFHI)?hi:(func==`ALU_MFLO)?lo:0;
96
 
97
    assign  remainder = (!negative_output) ?
98
            dividend_copy[31:0] :
99
            ~dividend_copy[31:0] + 1'b1;
100
 
101
    assign multiplier=op2;
102
    assign multiplicand=op1;
103
    assign dividend=op1;
104
    assign  divider = op2;
105
    assign sign = ((func==`ALU_MULT)||(func==`ALU_DIV));
106
 
107
    always @( posedge clk or negedge rst)
108
        if (~rst)
109
        begin
110
            mul_bit=0;
111
            div_bit=0;
112
            hi = 0;
113
            lo = 0;
114
            negative_output = 0;
115
        end
116
        else
117
        begin
118
            if((ready)&&((func==`ALU_MULT)||(func==`ALU_MULTTU)))
119
            begin
120
                mul_bit               = 33;
121
                product           = 0;
122
                product_temp      = 0;
123
                multiplicand_copy = (!sign || !multiplicand[31]) ?
124
                                  { 32'd0, multiplicand } :
125
                                  { 32'd0, ~multiplicand + 1'b1};
126
                multiplier_copy   = (!sign || !multiplier[31]) ?multiplier :~multiplier + 1'b1;
127
 
128
                negative_output = sign &&
129
                                ((multiplier[31] && !multiplicand[31])
130
                                 ||(!multiplier[31] && multiplicand[31]));
131
            end
132
            if ( mul_bit > 1 )
133
            begin
134
 
135
                if( multiplier_copy[0] == 1'b1 )
136
                    product_temp = product_temp +multiplicand_copy;
137
 
138
 
139
                product = (!negative_output) ?
140
                        product_temp :
141
                        ~product_temp + 1'b1;
142
 
143
                multiplier_copy = multiplier_copy >> 1;
144
                multiplicand_copy = multiplicand_copy << 1;
145
                mul_bit = mul_bit - 1'b1;
146
            end
147
            else if (mul_bit == 1)
148
            begin
149
                hi =  product[63:32];
150
                lo =  product[31:0];
151
                mul_bit=0;
152
            end
153
 
154
            if((ready)&&((func==`ALU_DIV)||(func==`ALU_DIVU)))
155
            begin
156
                div_bit = 33;
157
                quotient = 0;
158
                quotient_temp = 0;
159
                dividend_copy = (!sign || !dividend[31]) ?
160
                              {32'd0,dividend} :
161
                              {32'd0,~dividend + 1'b1};
162
 
163
                divider_copy = (!sign || !divider[31]) ?
164
                             {1'b0,divider,31'd0} :
165
                             {1'b0,~divider + 1'b1,31'd0};
166
 
167
                negative_output = sign &&
168
                                ((divider[31] && !dividend[31])
169
                                 ||(!divider[31] && dividend[31]));
170
            end
171
            else if (div_bit > 1)
172
            begin
173
                diff = dividend_copy - divider_copy;
174
                quotient_temp = quotient_temp << 1;
175
                if( !diff[63] )
176
                begin
177
                    dividend_copy = diff;
178
                    quotient_temp[0] = 1'd1;
179
                end
180
                quotient = (!negative_output) ?quotient_temp :~quotient_temp + 1'b1;
181
                divider_copy = divider_copy >> 1;
182
                div_bit = div_bit - 1'b1;
183
            end
184
            else if (div_bit == 1)
185
            begin
186
                lo =  quotient;
187
                hi =  remainder;
188
                div_bit=0;
189
            end
190
 
191
            if (func==`ALU_MTHI)
192
                hi=op1 ;
193
 
194
            if (func==`ALU_MTLO)
195
                lo=op1 ;
196
 
197
        end
198
 
199
endmodule
200
 
201
 
202
 
203
/* I search the multiply and divide module in
204
http://www.answers.google.com/answers
205
and find the two below modules ,
206
what I have done is combining the two modules and making it work in the mips_core.
207
original link is (I've no idear whether the link now works or not)
208
http://www.answers.google.com/answers/threadview?id=109219
209
and the original modules is list as below.
210
 
211
module multiply(ready,product,multiplier,multiplicand,sign,clk);
212
 
213
   input         clk;
214
   input         sign;
215
   input [31:0]  multiplier, multiplicand;
216
   output [63:0] product;
217
   output        ready;
218
 
219
   reg [63:0]    product, product_temp;
220
 
221
   reg [31:0]    multiplier_copy;
222
   reg [63:0]    multiplicand_copy;
223
   reg           negative_output;
224
 
225
   reg [5:0]     bit;
226
   wire          ready = !bit;
227
 
228
   initial bit = 0;
229
   initial negative_output = 0;
230
 
231
   always @( posedge clk )
232
 
233
     if( ready ) begin
234
 
235
        bit               = 6'd32;
236
        product           = 0;
237
        product_temp      = 0;
238
        multiplicand_copy = (!sign || !multiplicand[31]) ?
239
                            { 32'd0, multiplicand } :
240
                            { 32'd0, ~multiplicand + 1'b1};
241
        multiplier_copy   = (!sign || !multiplier[31]) ?
242
                            multiplier :
243
                            ~multiplier + 1'b1;
244
 
245
        negative_output = sign &&
246
                          ((multiplier[31] && !multiplicand[31])
247
                        ||(!multiplier[31] && multiplicand[31]));
248
 
249
     end
250
     else if ( bit > 0 ) begin
251
 
252
        if( multiplier_copy[0] == 1'b1 ) product_temp = product_temp +
253
multiplicand_copy;
254
 
255
        product = (!negative_output) ?
256
                  product_temp :
257
                  ~product_temp + 1'b1;
258
 
259
        multiplier_copy = multiplier_copy >> 1;
260
        multiplicand_copy = multiplicand_copy << 1;
261
        bit = bit - 1'b1;
262
 
263
     end
264
endmodule
265
 
266
 
267
module divide(ready,quotient,remainder,dividend,divider,sign,clk);
268
 
269
   input         clk;
270
   input         sign;
271
   input [31:0]  dividend, divider;
272
   output [31:0] quotient, remainder;
273
   output        ready;
274
 
275
   reg [31:0]    quotient, quotient_temp;
276
   reg [63:0]    dividend_copy, divider_copy, diff;
277
   reg           negative_output;
278
 
279
   wire [31:0]   remainder = (!negative_output) ?
280
                             dividend_copy[31:0] :
281
                             ~dividend_copy[31:0] + 1'b1;
282
 
283
   reg [5:0]     bit;
284
   wire          ready = !bit;
285
 
286
   initial bit = 0;
287
   initial negative_output = 0;
288
 
289
   always @( posedge clk )
290
 
291
     if( ready ) begin
292
 
293
        bit = 6'd32;
294
        quotient = 0;
295
        quotient_temp = 0;
296
        dividend_copy = (!sign || !dividend[31]) ?
297
                        {32'd0,dividend} :
298
                        {32'd0,~dividend + 1'b1};
299
        divider_copy = (!sign || !divider[31]) ?
300
                       {1'b0,divider,31'd0} :
301
                       {1'b0,~divider + 1'b1,31'd0};
302
 
303
        negative_output = sign &&
304
                          ((divider[31] && !dividend[31])
305
                        ||(!divider[31] && dividend[31]));
306
 
307
     end
308
     else if ( bit > 0 ) begin
309
 
310
        diff = dividend_copy - divider_copy;
311
 
312
        quotient_temp = quotient_temp << 1;
313
 
314
        if( !diff[63] ) begin
315
 
316
           dividend_copy = diff;
317
           quotient_temp[0] = 1'd1;
318
 
319
        end
320
 
321
        quotient = (!negative_output) ?
322
                   quotient_temp :
323
                   ~quotient_temp + 1'b1;
324
 
325
        divider_copy = divider_copy >> 1;
326
        bit = bit - 1'b1;
327
 
328
     end
329
endmodule
330
*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.