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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_mult_mac.v] - Blame information for rev 146

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 unneback
//////////////////////////////////////////////////////////////////////
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 141 marcus.erl
// $Log: or1200_mult_mac.v,v $
48
// Revision 2.0  2010/06/30 11:00:00  ORSoC
49
// Minor update: 
50
// Bugs fixed. 
51
//
52
// Revision 1.5  2006/04/09 01:32:29  lampret
53
// See OR1200_MAC_SHIFTBY in or1200_defines.v for explanation of the change. Since now no more 28 bits shift for l.macrc insns however for backward compatbility it is possible to set arbitry number of shifts.
54
//
55 10 unneback
// Revision 1.4  2004/06/08 18:17:36  lampret
56
// Non-functional changes. Coding style fixes.
57
//
58
// Revision 1.3  2003/04/24 00:16:07  lampret
59
// No functional changes. Added defines to disable implementation of multiplier/MAC
60
//
61
// Revision 1.2  2002/09/08 05:52:16  lampret
62
// Added optional l.div/l.divu insns. By default they are disabled.
63
//
64
// Revision 1.1  2002/01/03 08:16:15  lampret
65
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
66
//
67
// Revision 1.3  2001/10/21 17:57:16  lampret
68
// 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.
69
//
70
// Revision 1.2  2001/10/14 13:12:09  lampret
71
// MP3 version.
72
//
73
// Revision 1.1.1.1  2001/10/06 10:18:38  igorm
74
// no message
75
//
76
//
77
 
78
// synopsys translate_off
79
`include "timescale.v"
80
// synopsys translate_on
81
`include "or1200_defines.v"
82
 
83
module or1200_mult_mac(
84
        // Clock and reset
85
        clk, rst,
86
 
87
        // Multiplier/MAC interface
88
        ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, result, mac_stall_r,
89
 
90
        // SPR interface
91
        spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o
92
);
93
 
94
parameter width = `OR1200_OPERAND_WIDTH;
95
 
96
//
97
// I/O
98
//
99
 
100
//
101
// Clock and reset
102
//
103
input                           clk;
104
input                           rst;
105
 
106
//
107
// Multiplier/MAC interface
108
//
109
input                           ex_freeze;
110
input                           id_macrc_op;
111
input                           macrc_op;
112
input   [width-1:0]              a;
113
input   [width-1:0]              b;
114
input   [`OR1200_MACOP_WIDTH-1:0]        mac_op;
115
input   [`OR1200_ALUOP_WIDTH-1:0]        alu_op;
116
output  [width-1:0]              result;
117
output                          mac_stall_r;
118
 
119
//
120
// SPR interface
121
//
122
input                           spr_cs;
123
input                           spr_write;
124
input   [31:0]                   spr_addr;
125
input   [31:0]                   spr_dat_i;
126
output  [31:0]                   spr_dat_o;
127
 
128
//
129
// Internal wires and regs
130
//
131
`ifdef OR1200_MULT_IMPLEMENTED
132
reg     [width-1:0]              result;
133
reg     [2*width-1:0]            mul_prod_r;
134
`else
135
wire    [width-1:0]              result;
136
wire    [2*width-1:0]            mul_prod_r;
137
`endif
138
wire    [2*width-1:0]            mul_prod;
139
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op;
140
`ifdef OR1200_MAC_IMPLEMENTED
141
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
142
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
143
reg     [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
144
reg                             mac_stall_r;
145
reg     [2*width-1:0]            mac_r;
146
`else
147
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r1;
148
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r2;
149
wire    [`OR1200_MACOP_WIDTH-1:0]        mac_op_r3;
150
wire                            mac_stall_r;
151
wire    [2*width-1:0]            mac_r;
152
`endif
153
wire    [width-1:0]              x;
154
wire    [width-1:0]              y;
155
wire                            spr_maclo_we;
156
wire                            spr_machi_we;
157
wire                            alu_op_div_divu;
158
wire                            alu_op_div;
159
reg                             div_free;
160
`ifdef OR1200_IMPL_DIV
161
wire    [width-1:0]              div_tmp;
162
reg     [5:0]                    div_cntr;
163
`endif
164
 
165
//
166
// Combinatorial logic
167
//
168
`ifdef OR1200_MAC_IMPLEMENTED
169
assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR];
170
assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR];
171
assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32];
172
`else
173
assign spr_maclo_we = 1'b0;
174
assign spr_machi_we = 1'b0;
175
assign spr_dat_o = 32'h0000_0000;
176
`endif
177
`ifdef OR1200_LOWPWR_MULT
178
assign x = (alu_op_div & a[31]) ? ~a + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a : 32'h0000_0000;
179
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;
180
`else
181
assign x = alu_op_div & a[31] ? ~a + 32'b1 : a;
182
assign y = alu_op_div & b[31] ? ~b + 32'b1 : b;
183
`endif
184
`ifdef OR1200_IMPL_DIV
185
assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV);
186
assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU);
187
assign div_tmp = mul_prod_r[63:32] - y;
188
`else
189
assign alu_op_div = 1'b0;
190
assign alu_op_div_divu = 1'b0;
191
`endif
192
 
193
`ifdef OR1200_MULT_IMPLEMENTED
194
 
195
//
196
// Select result of current ALU operation to be forwarded
197
// to next instruction and to WB stage
198
//
199
always @(alu_op or mul_prod_r or mac_r or a or b)
200
        casex(alu_op)   // synopsys parallel_case
201
`ifdef OR1200_IMPL_DIV
202
                `OR1200_ALUOP_DIV:
203
                        result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0];
204
                `OR1200_ALUOP_DIVU,
205
`endif
206
                `OR1200_ALUOP_MUL: begin
207
                        result = mul_prod_r[31:0];
208
                end
209
                default:
210
`ifdef OR1200_MAC_SHIFTBY
211
                        result = mac_r[`OR1200_MAC_SHIFTBY+31:`OR1200_MAC_SHIFTBY];
212
`else
213
                        result = mac_r[31:0];
214
`endif
215
        endcase
216
 
217
//
218
// Instantiation of the multiplier
219
//
220
`ifdef OR1200_ASIC_MULTP2_32X32
221
or1200_amultp2_32x32 or1200_amultp2_32x32(
222
        .X(x),
223
        .Y(y),
224
        .RST(rst),
225
        .CLK(clk),
226
        .P(mul_prod)
227
);
228
`else // OR1200_ASIC_MULTP2_32X32
229
or1200_gmultp2_32x32 or1200_gmultp2_32x32(
230
        .X(x),
231
        .Y(y),
232
        .RST(rst),
233
        .CLK(clk),
234
        .P(mul_prod)
235
);
236
`endif // OR1200_ASIC_MULTP2_32X32
237
 
238
//
239
// Registered output from the multiplier and
240
// an optional divider
241
//
242
always @(posedge rst or posedge clk)
243
        if (rst) begin
244
                mul_prod_r <= #1 64'h0000_0000_0000_0000;
245
                div_free <= #1 1'b1;
246
`ifdef OR1200_IMPL_DIV
247
                div_cntr <= #1 6'b00_0000;
248
`endif
249
        end
250
`ifdef OR1200_IMPL_DIV
251
        else if (|div_cntr) begin
252
                if (div_tmp[31])
253
                        mul_prod_r <= #1 {mul_prod_r[62:0], 1'b0};
254
                else
255
                        mul_prod_r <= #1 {div_tmp[30:0], mul_prod_r[31:0], 1'b1};
256
                div_cntr <= #1 div_cntr - 1'b1;
257
        end
258
        else if (alu_op_div_divu && div_free) begin
259
                mul_prod_r <= #1 {31'b0, x[31:0], 1'b0};
260
                div_cntr <= #1 6'b10_0000;
261
                div_free <= #1 1'b0;
262
        end
263
`endif // OR1200_IMPL_DIV
264
        else if (div_free | !ex_freeze) begin
265
                mul_prod_r <= #1 mul_prod[63:0];
266
                div_free <= #1 1'b1;
267
        end
268
 
269
`else // OR1200_MULT_IMPLEMENTED
270
assign result = {width{1'b0}};
271
assign mul_prod = {2*width{1'b0}};
272
assign mul_prod_r = {2*width{1'b0}};
273
`endif // OR1200_MULT_IMPLEMENTED
274
 
275
`ifdef OR1200_MAC_IMPLEMENTED
276
 
277
//
278
// Propagation of l.mac opcode
279
//
280
always @(posedge clk or posedge rst)
281
        if (rst)
282
                mac_op_r1 <= #1 `OR1200_MACOP_WIDTH'b0;
283
        else
284
                mac_op_r1 <= #1 mac_op;
285
 
286
//
287
// Propagation of l.mac opcode
288
//
289
always @(posedge clk or posedge rst)
290
        if (rst)
291
                mac_op_r2 <= #1 `OR1200_MACOP_WIDTH'b0;
292
        else
293
                mac_op_r2 <= #1 mac_op_r1;
294
 
295
//
296
// Propagation of l.mac opcode
297
//
298
always @(posedge clk or posedge rst)
299
        if (rst)
300
                mac_op_r3 <= #1 `OR1200_MACOP_WIDTH'b0;
301
        else
302
                mac_op_r3 <= #1 mac_op_r2;
303
 
304
//
305
// Implementation of MAC
306
//
307
always @(posedge rst or posedge clk)
308
        if (rst)
309
                mac_r <= #1 64'h0000_0000_0000_0000;
310
`ifdef OR1200_MAC_SPR_WE
311
        else if (spr_maclo_we)
312
                mac_r[31:0] <= #1 spr_dat_i;
313
        else if (spr_machi_we)
314
                mac_r[63:32] <= #1 spr_dat_i;
315
`endif
316
        else if (mac_op_r3 == `OR1200_MACOP_MAC)
317
                mac_r <= #1 mac_r + mul_prod_r;
318
        else if (mac_op_r3 == `OR1200_MACOP_MSB)
319
                mac_r <= #1 mac_r - mul_prod_r;
320 141 marcus.erl
        else if (macrc_op && !ex_freeze)
321 10 unneback
                mac_r <= #1 64'h0000_0000_0000_0000;
322
 
323
//
324
// Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions
325
// in EX stage (e.g. inside multiplier)
326
// This stall signal is also used by the divider.
327
//
328
always @(posedge rst or posedge clk)
329
        if (rst)
330
                mac_stall_r <= #1 1'b0;
331
        else
332 141 marcus.erl
                mac_stall_r <= #1 (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & (id_macrc_op | mac_stall_r)
333 10 unneback
`ifdef OR1200_IMPL_DIV
334
                                | (|div_cntr)
335
`endif
336
                                ;
337
`else // OR1200_MAC_IMPLEMENTED
338
assign mac_stall_r = 1'b0;
339
assign mac_r = {2*width{1'b0}};
340
assign mac_op_r1 = `OR1200_MACOP_WIDTH'b0;
341
assign mac_op_r2 = `OR1200_MACOP_WIDTH'b0;
342
assign mac_op_r3 = `OR1200_MACOP_WIDTH'b0;
343
`endif // OR1200_MAC_IMPLEMENTED
344
 
345
endmodule

powered by: WebSVN 2.1.0

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