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

Subversion Repositories or1200_hp

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

powered by: WebSVN 2.1.0

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