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

Subversion Repositories or1200_hp

[/] [or1200_hp/] [trunk/] [rtl/] [rtl_cm4/] [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_cm4(
77
                clk_i_cml_1,
78
                clk_i_cml_2,
79
                clk_i_cml_3,
80
 
81
        // Clock and reset
82
        clk, rst,
83
 
84
        // Multiplier/MAC interface
85
        ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, result, mac_stall_r,
86
 
87
        // SPR interface
88
        spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
89
);
90
 
91
 
92
input clk_i_cml_1;
93
input clk_i_cml_2;
94
input clk_i_cml_3;
95
reg  ex_freeze_cml_3;
96
reg  macrc_op_cml_3;
97
reg  macrc_op_cml_2;
98
reg  macrc_op_cml_1;
99
reg [ 32 - 1 : 0 ] a_cml_3;
100
reg [ 32 - 1 : 0 ] a_cml_2;
101
reg [ 32 - 1 : 0 ] a_cml_1;
102
reg [ 32 - 1 : 0 ] b_cml_3;
103
reg [ 32 - 1 : 0 ] b_cml_2;
104
reg [ 32 - 1 : 0 ] b_cml_1;
105
reg [ 2 - 1 : 0 ] mac_op_cml_3;
106
reg [ 2 - 1 : 0 ] mac_op_cml_2;
107
reg [ 2 - 1 : 0 ] mac_op_cml_1;
108
reg  mac_stall_r_cml_3;
109
reg  mac_stall_r_cml_2;
110
reg  mac_stall_r_cml_1;
111
reg  spr_write_cml_3;
112
reg  spr_write_cml_2;
113
reg  spr_write_cml_1;
114
reg [ 31 : 0 ] spr_addr_cml_3;
115
reg [ 31 : 0 ] spr_addr_cml_2;
116
reg [ 31 : 0 ] spr_addr_cml_1;
117
reg [ 31 : 0 ] spr_dat_i_cml_3;
118
reg [ 31 : 0 ] spr_dat_i_cml_2;
119
reg [ 31 : 0 ] spr_dat_i_cml_1;
120
reg [ 2 * 32 - 1 : 0 ] mul_prod_r_cml_3;
121
reg [ 2 * 32 - 1 : 0 ] mul_prod_r_cml_2;
122
reg [ 2 * 32 - 1 : 0 ] mul_prod_r_cml_1;
123
reg [ 2 - 1 : 0 ] mac_op_r1_cml_3;
124
reg [ 2 - 1 : 0 ] mac_op_r1_cml_2;
125
reg [ 2 - 1 : 0 ] mac_op_r1_cml_1;
126
reg [ 2 - 1 : 0 ] mac_op_r2_cml_3;
127
reg [ 2 - 1 : 0 ] mac_op_r2_cml_2;
128
reg [ 2 - 1 : 0 ] mac_op_r2_cml_1;
129
reg [ 2 - 1 : 0 ] mac_op_r3_cml_3;
130
reg [ 2 - 1 : 0 ] mac_op_r3_cml_2;
131
reg [ 2 - 1 : 0 ] mac_op_r3_cml_1;
132
reg [ 2 * 32 - 1 : 0 ] mac_r_cml_3;
133
reg [ 2 * 32 - 1 : 0 ] mac_r_cml_2;
134
reg [ 2 * 32 - 1 : 0 ] mac_r_cml_1;
135
reg  div_free_cml_3;
136
reg  div_free_cml_2;
137
reg  div_free_cml_1;
138
 
139
 
140
 
141
parameter width = `OR1200_OPERAND_WIDTH;
142
 
143
//
144
// I/O
145
//
146
 
147
//
148
// Clock and reset
149
//
150
input                           clk;
151
input                           rst;
152
 
153
//
154
// Multiplier/MAC interface
155
//
156
input                           ex_freeze;
157
input                           id_macrc_op;
158
input                           macrc_op;
159
input   [width-1:0]              a;
160
input   [width-1:0]              b;
161
input   [`OR1200_MACOP_WIDTH-1:0]        mac_op;
162
input   [`OR1200_ALUOP_WIDTH-1:0]        alu_op;
163
output  [width-1:0]              result;
164
output                          mac_stall_r;
165
 
166
//
167
// SPR interface
168
//
169
input                           spr_cs;
170
input                           spr_write;
171
input   [31:0]                   spr_addr;
172
input   [31:0]                   spr_dat_i;
173
output  [31:0]                   spr_dat_o;
174
 
175
//
176
// Internal wires and regs
177
//
178
`ifdef OR1200_MULT_IMPLEMENTED
179
reg     [width-1:0]              result;
180
reg     [2*width-1:0]            mul_prod_r;
181
`else
182
wire    [width-1:0]              result;
183
wire    [2*width-1:0]            mul_prod_r;
184
`endif
185
wire    [2*width-1:0]            mul_prod;
186
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op;
187
`ifdef OR1200_MAC_IMPLEMENTED
188
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
189
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
190
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
191
reg                             mac_stall_r;
192
reg     [2*width-1:0]            mac_r;
193
`else
194
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
195
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
196
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
197
wire                            mac_stall_r;
198
wire    [2*width-1:0]            mac_r;
199
`endif
200
wire    [width-1:0]              x;
201
wire    [width-1:0]              y;
202
wire                            spr_maclo_we;
203
wire                            spr_machi_we;
204
wire                            alu_op_div_divu;
205
wire                            alu_op_div;
206
reg                             div_free;
207
`ifdef OR1200_IMPL_DIV
208
wire    [width-1:0]              div_tmp;
209
reg     [5:0]                    div_cntr;
210
`endif
211
 
212
//
213
// Combinatorial logic
214
//
215
`ifdef OR1200_MAC_IMPLEMENTED
216
 
217
// SynEDA CoreMultiplier
218
// assignment(s): spr_maclo_we
219
// replace(s): spr_write, spr_addr
220
assign spr_maclo_we = spr_cs & spr_write_cml_3 & spr_addr_cml_3[`OR1200_MAC_ADDR];
221
 
222
// SynEDA CoreMultiplier
223
// assignment(s): spr_machi_we
224
// replace(s): spr_write, spr_addr
225
assign spr_machi_we = spr_cs & spr_write_cml_3 & !spr_addr_cml_3[`OR1200_MAC_ADDR];
226
 
227
// SynEDA CoreMultiplier
228
// assignment(s): spr_dat_o
229
// replace(s): spr_addr, mac_r
230
assign spr_dat_o = spr_addr_cml_1[`OR1200_MAC_ADDR] ? mac_r_cml_1[31:0] : mac_r_cml_1[63:32];
231
`else
232
assign spr_maclo_we = 1'b0;
233
assign spr_machi_we = 1'b0;
234
assign spr_dat_o = 32'h0000_0000;
235
`endif
236
`ifdef OR1200_LOWPWR_MULT
237
assign x = (alu_op_div & a_cml_3[31]) ? ~a_cml_3 + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a_cml_3 : 32'h0000_0000;
238
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;
239
`else
240
 
241
// SynEDA CoreMultiplier
242
// assignment(s): x
243
// replace(s): a
244
assign x = alu_op_div & a_cml_3[31] ? ~a_cml_3 + 32'b1 : a_cml_3;
245
 
246
// SynEDA CoreMultiplier
247
// assignment(s): y
248
// replace(s): b
249
assign y = alu_op_div & b_cml_3[31] ? ~b_cml_3 + 32'b1 : b_cml_3;
250
`endif
251
`ifdef OR1200_IMPL_DIV
252
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
253
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
254
assign div_tmp = mul_prod_r[63:32] - y;
255
`else
256
assign alu_op_div = 1'b0;
257
assign alu_op_div_divu = 1'b0;
258
`endif
259
 
260
`ifdef OR1200_MULT_IMPLEMENTED
261
 
262
//
263
// Select result of current ALU operation to be forwarded
264
// to next instruction and to WB stage
265
//
266
always @(alu_op or mul_prod_r or mac_r or a or b)
267
        casex(alu_op)   // synopsys parallel_case
268
`ifdef OR1200_IMPL_DIV
269
                `OR1200_ALUOP_DIV:
270
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
271
                `OR1200_ALUOP_DIVU,
272
`endif
273
                `OR1200_ALUOP_MUL: begin
274
                        result = mul_prod_r[31:0];
275
                end
276
                default:
277
`ifdef OR1200_MAC_SHIFTBY
278
                        result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY];
279
`else
280
                        result = mac_r[31:0];
281
`endif
282
        endcase
283
 
284
//
285
// Instantiation of the multiplier
286
//
287
`ifdef OR1200_ASIC_MULTP2_32X32
288
or1200_amultp2_32x32 or1200_amultp2_32x32(
289
        .X(x),
290
        .Y(y),
291
        .RST(rst),
292
        .CLK(clk),
293
        .P(mul_prod)
294
);
295
`else // OR1200_ASIC_MULTP2_32X32
296
or1200_gmultp2_32x32_cm4 or1200_gmultp2_32x32(
297
                .clk_i_cml_1(clk_i_cml_1),
298
                .clk_i_cml_2(clk_i_cml_2),
299
                .clk_i_cml_3(clk_i_cml_3),
300
        .X(x),
301
        .Y(y),
302
        .RST(rst),
303
        .CLK(clk),
304
        .P(mul_prod)
305
);
306
`endif // OR1200_ASIC_MULTP2_32X32
307
 
308
//
309
// Registered output from the multiplier and
310
// an optional divider
311
//
312
 
313
// SynEDA CoreMultiplier
314
// assignment(s): mul_prod_r, div_free
315
// replace(s): ex_freeze, mul_prod_r, div_free
316
always @(posedge rst or posedge clk)
317
        if (rst) begin
318
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
319
                div_free <= #1 1'b1;
320
`ifdef OR1200_IMPL_DIV
321
                div_cntr <= #1 6'b00_0000;
322
`endif
323
        end else begin  div_free <= div_free_cml_3; mul_prod_r <= mul_prod_r_cml_3;
324
`ifdef OR1200_IMPL_DIV
325
        if (|div_cntr) begin
326
                if (div_tmp[31])
327
                        mul_prod_r <= #1 {mul_prod_r_cml_3[62:0], 1'b0};
328
                else
329
                        mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r_cml_3[31:0], 1'b1};
330
                div_cntr <= #1 div_cntr - 1'b1;
331
        end
332
        else if (alu_op_div_divu && div_free_cml_3) begin
333
                mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
334
                div_cntr <= #1 6'b10_0000;
335
                div_free <= #1 1'b0;
336
        end else
337
`endif // OR1200_IMPL_DIV
338
        if (div_free_cml_3 | !ex_freeze_cml_3) begin
339
                mul_prod_r <= #1 mul_prod[63:0];
340
                div_free <= #1 1'b1;
341
        end end
342
 
343
`else // OR1200_MULT_IMPLEMENTED
344
assign result = {width{1'b0}};
345
assign mul_prod = {2*width{1'b0}};
346
assign mul_prod_r = {2*width{1'b0}};
347
`endif // OR1200_MULT_IMPLEMENTED
348
 
349
`ifdef OR1200_MAC_IMPLEMENTED
350
 
351
//
352
// Propagation of l.mac opcode
353
//
354
 
355
// SynEDA CoreMultiplier
356
// assignment(s): mac_op_r1
357
// replace(s): mac_op, mac_op_r1
358
always @(posedge clk or posedge rst)
359
        if (rst)
360
                mac_op_r1 <= #1 `OR1200_MACOP_WIDTH'b0;
361
        else begin  mac_op_r1 <= mac_op_r1_cml_3;
362
                mac_op_r1 <= #1 mac_op_cml_3; end
363
 
364
//
365
// Propagation of l.mac opcode
366
//
367
 
368
// SynEDA CoreMultiplier
369
// assignment(s): mac_op_r2
370
// replace(s): mac_op_r1, mac_op_r2
371
always @(posedge clk or posedge rst)
372
        if (rst)
373
                mac_op_r2 <= #1 `OR1200_MACOP_WIDTH'b0;
374
        else begin  mac_op_r2 <= mac_op_r2_cml_3;
375
                mac_op_r2 <= #1 mac_op_r1_cml_3; end
376
 
377
//
378
// Propagation of l.mac opcode
379
//
380
 
381
// SynEDA CoreMultiplier
382
// assignment(s): mac_op_r3
383
// replace(s): mac_op_r2, mac_op_r3
384
always @(posedge clk or posedge rst)
385
        if (rst)
386
                mac_op_r3 <= #1 `OR1200_MACOP_WIDTH'b0;
387
        else begin  mac_op_r3 <= mac_op_r3_cml_3;
388
                mac_op_r3 <= #1 mac_op_r2_cml_3; end
389
 
390
//
391
// Implementation of MAC
392
//
393
 
394
// SynEDA CoreMultiplier
395
// assignment(s): mac_r
396
// replace(s): ex_freeze, macrc_op, spr_dat_i, mul_prod_r, mac_op_r3, mac_r
397
always @(posedge rst or posedge clk)
398
        if (rst)
399
                mac_r <= #1 64'h0000_0000_0000_0000;
400
`ifdef OR1200_MAC_SPR_WE
401
        else begin  mac_r <= mac_r_cml_3; if (spr_maclo_we)
402
                mac_r[31:0] <= #1 spr_dat_i_cml_3;
403
        else if (spr_machi_we)
404
                mac_r[63:32] <= #1 spr_dat_i_cml_3;
405
`endif
406
        else if (mac_op_r3_cml_3 == `OR1200_MACOP_MAC)
407
                mac_r <= #1 mac_r_cml_3 + mul_prod_r_cml_3;
408
        else if (mac_op_r3_cml_3 == `OR1200_MACOP_MSB)
409
                mac_r <= #1 mac_r_cml_3 - mul_prod_r_cml_3;
410
        else if (macrc_op_cml_3 & !ex_freeze_cml_3)
411
                mac_r <= #1 64'h0000_0000_0000_0000; end
412
 
413
//
414
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
415
// in EX stage (e.g. inside multiplier)
416
// This stall signal is also used by the divider.
417
//
418
 
419
// SynEDA CoreMultiplier
420
// assignment(s): mac_stall_r
421
// replace(s): mac_op, mac_stall_r, mac_op_r1, mac_op_r2
422
always @(posedge rst or posedge clk)
423
        if (rst)
424
                mac_stall_r <= #1 1'b0;
425
        else begin  mac_stall_r <= mac_stall_r_cml_3;
426
                mac_stall_r <= #1 (|mac_op_cml_3 | (|mac_op_r1_cml_3) | (|mac_op_r2_cml_3)) & id_macrc_op
427
`ifdef OR1200_IMPL_DIV
428
                                | (|div_cntr)
429
`endif
430
                                ; end
431
`else // OR1200_MAC_IMPLEMENTED
432
assign mac_stall_r = 1'b0;
433
assign mac_r = {2*width{1'b0}};
434
assign mac_op_r1 = `OR1200_MACOP_WIDTH'b0;
435
assign mac_op_r2 = `OR1200_MACOP_WIDTH'b0;
436
assign mac_op_r3 = `OR1200_MACOP_WIDTH'b0;
437
`endif // OR1200_MAC_IMPLEMENTED
438
 
439
 
440
always @ (posedge clk_i_cml_1) begin
441
macrc_op_cml_1 <= macrc_op;
442
a_cml_1 <= a;
443
b_cml_1 <= b;
444
mac_op_cml_1 <= mac_op;
445
mac_stall_r_cml_1 <= mac_stall_r;
446
spr_write_cml_1 <= spr_write;
447
spr_addr_cml_1 <= spr_addr;
448
spr_dat_i_cml_1 <= spr_dat_i;
449
mul_prod_r_cml_1 <= mul_prod_r;
450
mac_op_r1_cml_1 <= mac_op_r1;
451
mac_op_r2_cml_1 <= mac_op_r2;
452
mac_op_r3_cml_1 <= mac_op_r3;
453
mac_r_cml_1 <= mac_r;
454
div_free_cml_1 <= div_free;
455
end
456
always @ (posedge clk_i_cml_2) begin
457
macrc_op_cml_2 <= macrc_op_cml_1;
458
a_cml_2 <= a_cml_1;
459
b_cml_2 <= b_cml_1;
460
mac_op_cml_2 <= mac_op_cml_1;
461
mac_stall_r_cml_2 <= mac_stall_r_cml_1;
462
spr_write_cml_2 <= spr_write_cml_1;
463
spr_addr_cml_2 <= spr_addr_cml_1;
464
spr_dat_i_cml_2 <= spr_dat_i_cml_1;
465
mul_prod_r_cml_2 <= mul_prod_r_cml_1;
466
mac_op_r1_cml_2 <= mac_op_r1_cml_1;
467
mac_op_r2_cml_2 <= mac_op_r2_cml_1;
468
mac_op_r3_cml_2 <= mac_op_r3_cml_1;
469
mac_r_cml_2 <= mac_r_cml_1;
470
div_free_cml_2 <= div_free_cml_1;
471
end
472
always @ (posedge clk_i_cml_3) begin
473
ex_freeze_cml_3 <= ex_freeze;
474
macrc_op_cml_3 <= macrc_op_cml_2;
475
a_cml_3 <= a_cml_2;
476
b_cml_3 <= b_cml_2;
477
mac_op_cml_3 <= mac_op_cml_2;
478
mac_stall_r_cml_3 <= mac_stall_r_cml_2;
479
spr_write_cml_3 <= spr_write_cml_2;
480
spr_addr_cml_3 <= spr_addr_cml_2;
481
spr_dat_i_cml_3 <= spr_dat_i_cml_2;
482
mul_prod_r_cml_3 <= mul_prod_r_cml_2;
483
mac_op_r1_cml_3 <= mac_op_r1_cml_2;
484
mac_op_r2_cml_3 <= mac_op_r2_cml_2;
485
mac_op_r3_cml_3 <= mac_op_r3_cml_2;
486
mac_r_cml_3 <= mac_r_cml_2;
487
div_free_cml_3 <= div_free_cml_2;
488
end
489
endmodule
490
 

powered by: WebSVN 2.1.0

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