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

Subversion Repositories or1200_hp

[/] [or1200_hp/] [trunk/] [rtl/] [rtl_cm3/] [verilog/] [or1200_mult_mac.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 tobil
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  OR1200's Top level multiplier and MAC                       ////
4
////                                                              ////
5
////  This file is part of the OpenRISC 1200 project              ////
6
////  http://www.opencores.org/cores/or1k/                        ////
7
////                                                              ////
8
////  Description                                                 ////
9
////  Multiplier is 32x32 however multiply instructions only      ////
10
////  use lower 32 bits of the result. MAC is 32x32=64+64.        ////
11
////                                                              ////
12
////  To Do:                                                      ////
13
////   - make signed division better, w/o negating the operands   ////
14
////                                                              ////
15
////  Author(s):                                                  ////
16
////      - Damjan Lampret, lampret@opencores.org                 ////
17
////                                                              ////
18
//////////////////////////////////////////////////////////////////////
19
////                                                              ////
20
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
21
////                                                              ////
22
//// This source file may be used and distributed without         ////
23
//// restriction provided that this copyright statement is not    ////
24
//// removed from the file and that any derivative work contains  ////
25
//// the original copyright notice and the associated disclaimer. ////
26
////                                                              ////
27
//// This source file is free software; you can redistribute it   ////
28
//// and/or modify it under the terms of the GNU Lesser General   ////
29
//// Public License as published by the Free Software Foundation; ////
30
//// either version 2.1 of the License, or (at your option) any   ////
31
//// later version.                                               ////
32
////                                                              ////
33
//// This source is distributed in the hope that it will be       ////
34
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
35
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
36
//// PURPOSE.  See the GNU Lesser General Public License for more ////
37
//// details.                                                     ////
38
////                                                              ////
39
//// You should have received a copy of the GNU Lesser General    ////
40
//// Public License along with this source; if not, download it   ////
41
//// from http://www.opencores.org/lgpl.shtml                     ////
42
////                                                              ////
43
//////////////////////////////////////////////////////////////////////
44
//
45
// CVS Revision History
46
//
47
// $Log: not supported by cvs2svn $
48
// Revision 1.4  2004/06/08 18:17:36  lampret
49
// Non-functional changes. Coding style fixes.
50
//
51
// Revision 1.3  2003/04/24 00:16:07  lampret
52
// No functional changes. Added defines to disable implementation of multiplier/MAC
53
//
54
// Revision 1.2  2002/09/08 05:52:16  lampret
55
// Added optional l.div/l.divu insns. By default they are disabled.
56
//
57
// Revision 1.1  2002/01/03 08:16:15  lampret
58
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
59
//
60
// Revision 1.3  2001/10/21 17:57:16  lampret
61
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
62
//
63
// Revision 1.2  2001/10/14 13:12:09  lampret
64
// MP3 version.
65
//
66
// Revision 1.1.1.1  2001/10/06 10:18:38  igorm
67
// no message
68
//
69
//
70
 
71
// synopsys translate_off
72
`include "timescale.v"
73
// synopsys translate_on
74
`include "or1200_defines.v"
75
 
76
module or1200_mult_mac_cm3(
77
                clk_i_cml_1,
78
                clk_i_cml_2,
79
 
80
        // Clock and reset
81
        clk, rst,
82
 
83
        // Multiplier/MAC interface
84
        ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, result, mac_stall_r,
85
 
86
        // SPR interface
87
        spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
88
);
89
 
90
 
91
input clk_i_cml_1;
92
input clk_i_cml_2;
93
reg  ex_freeze_cml_2;
94
reg  macrc_op_cml_2;
95
reg  macrc_op_cml_1;
96
reg [ 32 - 1 : 0 ] a_cml_1;
97
reg [ 32 - 1 : 0 ] b_cml_2;
98
reg [ 32 - 1 : 0 ] b_cml_1;
99
reg [ 2 - 1 : 0 ] mac_op_cml_2;
100
reg [ 2 - 1 : 0 ] mac_op_cml_1;
101
reg  mac_stall_r_cml_2;
102
reg  mac_stall_r_cml_1;
103
reg  spr_write_cml_2;
104
reg [ 31 : 0 ] spr_addr_cml_2;
105
reg [ 31 : 0 ] spr_addr_cml_1;
106
reg [ 31 : 0 ] spr_dat_i_cml_2;
107
reg [ 31 : 0 ] spr_dat_i_cml_1;
108
reg [ 2 * 32 - 1 : 0 ] mul_prod_r_cml_2;
109
reg [ 2 * 32 - 1 : 0 ] mul_prod_r_cml_1;
110
reg [ 2 - 1 : 0 ] mac_op_r1_cml_2;
111
reg [ 2 - 1 : 0 ] mac_op_r1_cml_1;
112
reg [ 2 - 1 : 0 ] mac_op_r2_cml_2;
113
reg [ 2 - 1 : 0 ] mac_op_r2_cml_1;
114
reg [ 2 - 1 : 0 ] mac_op_r3_cml_2;
115
reg [ 2 - 1 : 0 ] mac_op_r3_cml_1;
116
reg [ 2 * 32 - 1 : 0 ] mac_r_cml_2;
117
reg [ 2 * 32 - 1 : 0 ] mac_r_cml_1;
118
reg  div_free_cml_2;
119
reg  div_free_cml_1;
120
 
121
 
122
 
123
parameter width = `OR1200_OPERAND_WIDTH;
124
 
125
//
126
// I/O
127
//
128
 
129
//
130
// Clock and reset
131
//
132
input                           clk;
133
input                           rst;
134
 
135
//
136
// Multiplier/MAC interface
137
//
138
input                           ex_freeze;
139
input                           id_macrc_op;
140
input                           macrc_op;
141
input   [width-1:0]              a;
142
input   [width-1:0]              b;
143
input   [`OR1200_MACOP_WIDTH-1:0]        mac_op;
144
input   [`OR1200_ALUOP_WIDTH-1:0]        alu_op;
145
output  [width-1:0]              result;
146
output                          mac_stall_r;
147
 
148
//
149
// SPR interface
150
//
151
input                           spr_cs;
152
input                           spr_write;
153
input   [31:0]                   spr_addr;
154
input   [31:0]                   spr_dat_i;
155
output  [31:0]                   spr_dat_o;
156
 
157
//
158
// Internal wires and regs
159
//
160
`ifdef OR1200_MULT_IMPLEMENTED
161
reg     [width-1:0]              result;
162
reg     [2*width-1:0]            mul_prod_r;
163
`else
164
wire    [width-1:0]              result;
165
wire    [2*width-1:0]            mul_prod_r;
166
`endif
167
wire    [2*width-1:0]            mul_prod;
168
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op;
169
`ifdef OR1200_MAC_IMPLEMENTED
170
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
171
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
172
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
173
reg                             mac_stall_r;
174
reg     [2*width-1:0]            mac_r;
175
`else
176
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
177
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
178
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
179
wire                            mac_stall_r;
180
wire    [2*width-1:0]            mac_r;
181
`endif
182
wire    [width-1:0]              x;
183
wire    [width-1:0]              y;
184
wire                            spr_maclo_we;
185
wire                            spr_machi_we;
186
wire                            alu_op_div_divu;
187
wire                            alu_op_div;
188
reg                             div_free;
189
`ifdef OR1200_IMPL_DIV
190
wire    [width-1:0]              div_tmp;
191
reg     [5:0]                    div_cntr;
192
`endif
193
 
194
//
195
// Combinatorial logic
196
//
197
`ifdef OR1200_MAC_IMPLEMENTED
198
 
199
// SynEDA CoreMultiplier
200
// assignment(s): spr_maclo_we
201
// replace(s): spr_write, spr_addr
202
assign spr_maclo_we = spr_cs & spr_write_cml_2 & spr_addr_cml_2[`OR1200_MAC_ADDR];
203
 
204
// SynEDA CoreMultiplier
205
// assignment(s): spr_machi_we
206
// replace(s): spr_write, spr_addr
207
assign spr_machi_we = spr_cs & spr_write_cml_2 & !spr_addr_cml_2[`OR1200_MAC_ADDR];
208
 
209
// SynEDA CoreMultiplier
210
// assignment(s): spr_dat_o
211
// replace(s): spr_addr, mac_r
212
assign spr_dat_o = spr_addr_cml_1[`OR1200_MAC_ADDR] ? mac_r_cml_1[31:0] : mac_r_cml_1[63:32];
213
`else
214
assign spr_maclo_we = 1'b0;
215
assign spr_machi_we = 1'b0;
216
assign spr_dat_o = 32'h0000_0000;
217
`endif
218
`ifdef OR1200_LOWPWR_MULT
219
assign x = (alu_op_div & a_cml_1[31]) ? ~a_cml_1 + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a_cml_1 : 32'h0000_0000;
220
assign y = (alu_op_div & b[31]) ? ~b + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? b : 32'h0000_0000;
221
`else
222
 
223
// SynEDA CoreMultiplier
224
// assignment(s): x
225
// replace(s): a
226
assign x = alu_op_div & a_cml_1[31] ? ~a_cml_1 + 32'b1 : a_cml_1;
227
 
228
// SynEDA CoreMultiplier
229
// assignment(s): y
230
// replace(s): b
231
assign y = alu_op_div & b_cml_2[31] ? ~b_cml_2 + 32'b1 : b_cml_2;
232
`endif
233
`ifdef OR1200_IMPL_DIV
234
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
235
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
236
assign div_tmp = mul_prod_r[63:32] - y;
237
`else
238
assign alu_op_div = 1'b0;
239
assign alu_op_div_divu = 1'b0;
240
`endif
241
 
242
`ifdef OR1200_MULT_IMPLEMENTED
243
 
244
//
245
// Select result of current ALU operation to be forwarded
246
// to next instruction and to WB stage
247
//
248
always @(alu_op or mul_prod_r or mac_r or a or b)
249
        casex(alu_op)   // synopsys parallel_case
250
`ifdef OR1200_IMPL_DIV
251
                `OR1200_ALUOP_DIV:
252
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
253
                `OR1200_ALUOP_DIVU,
254
`endif
255
                `OR1200_ALUOP_MUL: begin
256
                        result = mul_prod_r[31:0];
257
                end
258
                default:
259
`ifdef OR1200_MAC_SHIFTBY
260
                        result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY];
261
`else
262
                        result = mac_r[31:0];
263
`endif
264
        endcase
265
 
266
//
267
// Instantiation of the multiplier
268
//
269
`ifdef OR1200_ASIC_MULTP2_32X32
270
or1200_amultp2_32x32 or1200_amultp2_32x32(
271
        .X(x),
272
        .Y(y),
273
        .RST(rst),
274
        .CLK(clk),
275
        .P(mul_prod)
276
);
277
`else // OR1200_ASIC_MULTP2_32X32
278
or1200_gmultp2_32x32_cm3 or1200_gmultp2_32x32(
279
                .clk_i_cml_1(clk_i_cml_1),
280
                .clk_i_cml_2(clk_i_cml_2),
281
        .X(x),
282
        .Y(y),
283
        .RST(rst),
284
        .CLK(clk),
285
        .P(mul_prod)
286
);
287
`endif // OR1200_ASIC_MULTP2_32X32
288
 
289
//
290
// Registered output from the multiplier and
291
// an optional divider
292
//
293
 
294
// SynEDA CoreMultiplier
295
// assignment(s): mul_prod_r, div_free
296
// replace(s): ex_freeze, mul_prod_r, div_free
297
always @(posedge rst or posedge clk)
298
        if (rst) begin
299
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
300
                div_free <= #1 1'b1;
301
`ifdef OR1200_IMPL_DIV
302
                div_cntr <= #1 6'b00_0000;
303
`endif
304
        end else begin  div_free <= div_free_cml_2; mul_prod_r <= mul_prod_r_cml_2;
305
`ifdef OR1200_IMPL_DIV
306
        if (|div_cntr) begin
307
                if (div_tmp[31])
308
                        mul_prod_r <= #1 {mul_prod_r_cml_2[62:0], 1'b0};
309
                else
310
                        mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r_cml_2[31:0], 1'b1};
311
                div_cntr <= #1 div_cntr - 1'b1;
312
        end
313
        else if (alu_op_div_divu && div_free_cml_2) begin
314
                mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
315
                div_cntr <= #1 6'b10_0000;
316
                div_free <= #1 1'b0;
317
        end else
318
`endif // OR1200_IMPL_DIV
319
        if (div_free_cml_2 | !ex_freeze_cml_2) begin
320
                mul_prod_r <= #1 mul_prod[63:0];
321
                div_free <= #1 1'b1;
322
        end end
323
 
324
`else // OR1200_MULT_IMPLEMENTED
325
assign result = {width{1'b0}};
326
assign mul_prod = {2*width{1'b0}};
327
assign mul_prod_r = {2*width{1'b0}};
328
`endif // OR1200_MULT_IMPLEMENTED
329
 
330
`ifdef OR1200_MAC_IMPLEMENTED
331
 
332
//
333
// Propagation of l.mac opcode
334
//
335
 
336
// SynEDA CoreMultiplier
337
// assignment(s): mac_op_r1
338
// replace(s): mac_op, mac_op_r1
339
always @(posedge clk or posedge rst)
340
        if (rst)
341
                mac_op_r1 <= #1 `OR1200_MACOP_WIDTH'b0;
342
        else begin  mac_op_r1 <= mac_op_r1_cml_2;
343
                mac_op_r1 <= #1 mac_op_cml_2; end
344
 
345
//
346
// Propagation of l.mac opcode
347
//
348
 
349
// SynEDA CoreMultiplier
350
// assignment(s): mac_op_r2
351
// replace(s): mac_op_r1, mac_op_r2
352
always @(posedge clk or posedge rst)
353
        if (rst)
354
                mac_op_r2 <= #1 `OR1200_MACOP_WIDTH'b0;
355
        else begin  mac_op_r2 <= mac_op_r2_cml_2;
356
                mac_op_r2 <= #1 mac_op_r1_cml_2; end
357
 
358
//
359
// Propagation of l.mac opcode
360
//
361
 
362
// SynEDA CoreMultiplier
363
// assignment(s): mac_op_r3
364
// replace(s): mac_op_r2, mac_op_r3
365
always @(posedge clk or posedge rst)
366
        if (rst)
367
                mac_op_r3 <= #1 `OR1200_MACOP_WIDTH'b0;
368
        else begin  mac_op_r3 <= mac_op_r3_cml_2;
369
                mac_op_r3 <= #1 mac_op_r2_cml_2; end
370
 
371
//
372
// Implementation of MAC
373
//
374
 
375
// SynEDA CoreMultiplier
376
// assignment(s): mac_r
377
// replace(s): ex_freeze, macrc_op, spr_dat_i, mul_prod_r, mac_op_r3, mac_r
378
always @(posedge rst or posedge clk)
379
        if (rst)
380
                mac_r <= #1 64'h0000_0000_0000_0000;
381
`ifdef OR1200_MAC_SPR_WE
382
        else begin  mac_r <= mac_r_cml_2; if (spr_maclo_we)
383
                mac_r[31:0] <= #1 spr_dat_i_cml_2;
384
        else if (spr_machi_we)
385
                mac_r[63:32] <= #1 spr_dat_i_cml_2;
386
`endif
387
        else if (mac_op_r3_cml_2 == `OR1200_MACOP_MAC)
388
                mac_r <= #1 mac_r_cml_2 + mul_prod_r_cml_2;
389
        else if (mac_op_r3_cml_2 == `OR1200_MACOP_MSB)
390
                mac_r <= #1 mac_r_cml_2 - mul_prod_r_cml_2;
391
        else if (macrc_op_cml_2 & !ex_freeze_cml_2)
392
                mac_r <= #1 64'h0000_0000_0000_0000; end
393
 
394
//
395
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
396
// in EX stage (e.g. inside multiplier)
397
// This stall signal is also used by the divider.
398
//
399
 
400
// SynEDA CoreMultiplier
401
// assignment(s): mac_stall_r
402
// replace(s): mac_op, mac_stall_r, mac_op_r1, mac_op_r2
403
always @(posedge rst or posedge clk)
404
        if (rst)
405
                mac_stall_r <= #1 1'b0;
406
        else begin  mac_stall_r <= mac_stall_r_cml_2;
407
                mac_stall_r <= #1 (|mac_op_cml_2 | (|mac_op_r1_cml_2) | (|mac_op_r2_cml_2)) & id_macrc_op
408
`ifdef OR1200_IMPL_DIV
409
                                | (|div_cntr)
410
`endif
411
                                ; end
412
`else // OR1200_MAC_IMPLEMENTED
413
assign mac_stall_r = 1'b0;
414
assign mac_r = {2*width{1'b0}};
415
assign mac_op_r1 = `OR1200_MACOP_WIDTH'b0;
416
assign mac_op_r2 = `OR1200_MACOP_WIDTH'b0;
417
assign mac_op_r3 = `OR1200_MACOP_WIDTH'b0;
418
`endif // OR1200_MAC_IMPLEMENTED
419
 
420
 
421
always @ (posedge clk_i_cml_1) begin
422
macrc_op_cml_1 <= macrc_op;
423
a_cml_1 <= a;
424
b_cml_1 <= b;
425
mac_op_cml_1 <= mac_op;
426
mac_stall_r_cml_1 <= mac_stall_r;
427
spr_addr_cml_1 <= spr_addr;
428
spr_dat_i_cml_1 <= spr_dat_i;
429
mul_prod_r_cml_1 <= mul_prod_r;
430
mac_op_r1_cml_1 <= mac_op_r1;
431
mac_op_r2_cml_1 <= mac_op_r2;
432
mac_op_r3_cml_1 <= mac_op_r3;
433
mac_r_cml_1 <= mac_r;
434
div_free_cml_1 <= div_free;
435
end
436
always @ (posedge clk_i_cml_2) begin
437
ex_freeze_cml_2 <= ex_freeze;
438
macrc_op_cml_2 <= macrc_op_cml_1;
439
b_cml_2 <= b_cml_1;
440
mac_op_cml_2 <= mac_op_cml_1;
441
mac_stall_r_cml_2 <= mac_stall_r_cml_1;
442
spr_write_cml_2 <= spr_write;
443
spr_addr_cml_2 <= spr_addr_cml_1;
444
spr_dat_i_cml_2 <= spr_dat_i_cml_1;
445
mul_prod_r_cml_2 <= mul_prod_r_cml_1;
446
mac_op_r1_cml_2 <= mac_op_r1_cml_1;
447
mac_op_r2_cml_2 <= mac_op_r2_cml_1;
448
mac_op_r3_cml_2 <= mac_op_r3_cml_1;
449
mac_r_cml_2 <= mac_r_cml_1;
450
div_free_cml_2 <= div_free_cml_1;
451
end
452
endmodule
453
 

powered by: WebSVN 2.1.0

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