OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_alu.v] - Blame information for rev 640

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

Line No. Rev Author Line
1 10 unneback
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  OR1200's ALU                                                ////
4
////                                                              ////
5
////  This file is part of the OpenRISC 1200 project              ////
6 185 julius
////  http://www.opencores.org/project,or1k                       ////
7 10 unneback
////                                                              ////
8
////  Description                                                 ////
9
////  ALU                                                         ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   - make it smaller and faster                               ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Damjan Lampret, lampret@opencores.org                 ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE.  See the GNU Lesser General Public License for more ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
//
44 141 marcus.erl
// $Log: or1200_alu.v,v $
45
// Revision 2.0  2010/06/30 11:00:00  ORSoC
46
// Minor update: 
47
// Defines added, flags are corrected. 
48 10 unneback
 
49
// synopsys translate_off
50
`include "timescale.v"
51
// synopsys translate_on
52
`include "or1200_defines.v"
53
 
54
module or1200_alu(
55
        a, b, mult_mac_result, macrc_op,
56 640 julius
        alu_op, alu_op2, comp_op,
57 10 unneback
        cust5_op, cust5_limm,
58
        result, flagforw, flag_we,
59
        cyforw, cy_we, carry, flag
60
);
61
 
62
parameter width = `OR1200_OPERAND_WIDTH;
63
 
64
//
65
// I/O
66
//
67
input   [width-1:0]              a;
68
input   [width-1:0]              b;
69
input   [width-1:0]              mult_mac_result;
70
input                           macrc_op;
71
input   [`OR1200_ALUOP_WIDTH-1:0]        alu_op;
72 401 julius
input   [`OR1200_ALUOP2_WIDTH-1:0]       alu_op2;
73 10 unneback
input   [`OR1200_COMPOP_WIDTH-1:0]       comp_op;
74
input   [4:0]                    cust5_op;
75
input   [5:0]                    cust5_limm;
76
output  [width-1:0]              result;
77
output                          flagforw;
78
output                          flag_we;
79
output                          cyforw;
80
output                          cy_we;
81
input                           carry;
82
input         flag;
83
 
84
//
85
// Internal wires and regs
86
//
87
reg     [width-1:0]              result;
88
reg     [width-1:0]              shifted_rotated;
89 640 julius
reg     [width-1:0]              extended;
90 10 unneback
reg     [width-1:0]              result_cust5;
91
reg                             flagforw;
92
reg                             flagcomp;
93
reg                             flag_we;
94
reg                             cy_we;
95
wire    [width-1:0]              comp_a;
96
wire    [width-1:0]              comp_b;
97
`ifdef OR1200_IMPL_ALU_COMP1
98
wire                            a_eq_b;
99
wire                            a_lt_b;
100
`endif
101
wire    [width-1:0]              result_sum;
102
`ifdef OR1200_IMPL_ADDC
103
wire    [width-1:0]              result_csum;
104
wire                            cy_csum;
105
`endif
106
wire    [width-1:0]              result_and;
107
wire                            cy_sum;
108 141 marcus.erl
`ifdef OR1200_IMPL_SUB
109
wire                            cy_sub;
110
`endif
111 10 unneback
reg                             cyforw;
112
 
113
//
114
// Combinatorial logic
115
//
116
assign comp_a = {a[width-1] ^ comp_op[3] , a[width-2:0]};
117
assign comp_b = {b[width-1] ^ comp_op[3] , b[width-2:0]};
118
`ifdef OR1200_IMPL_ALU_COMP1
119
assign a_eq_b = (comp_a == comp_b);
120
assign a_lt_b = (comp_a < comp_b);
121
`endif
122 141 marcus.erl
`ifdef OR1200_IMPL_SUB
123
assign cy_sub = a < b;
124
`endif
125 10 unneback
assign {cy_sum, result_sum} = a + b;
126
`ifdef OR1200_IMPL_ADDC
127 141 marcus.erl
assign {cy_csum, result_csum} = a + b + {`OR1200_OPERAND_WIDTH'd0, carry};
128 10 unneback
`endif
129
assign result_and = a & b;
130
 
131
//
132
// Simulation check for bad ALU behavior
133
//
134
`ifdef OR1200_WARNINGS
135
// synopsys translate_off
136
always @(result) begin
137
        if (result === 32'bx)
138
                $display("%t: WARNING: 32'bx detected on ALU result bus. Please check !", $time);
139
end
140
// synopsys translate_on
141
`endif
142
 
143
//
144
// Central part of the ALU
145
//
146 401 julius
always @(alu_op or alu_op2 or a or b or result_sum or result_and or macrc_op
147
         or shifted_rotated or mult_mac_result or flag or result_cust5 or carry
148 141 marcus.erl
`ifdef OR1200_IMPL_ADDC
149
         or result_csum
150
`endif
151 640 julius
`ifdef OR1200_IMPL_ALU_EXT
152
         or extended
153
`endif
154 141 marcus.erl
) begin
155 10 unneback
`ifdef OR1200_CASE_DEFAULT
156 364 julius
        casez (alu_op)          // synopsys parallel_case
157 10 unneback
`else
158 364 julius
        casez (alu_op)          // synopsys full_case parallel_case
159 10 unneback
`endif
160 401 julius
`ifdef OR1200_IMPL_ALU_FFL1
161
                `OR1200_ALUOP_FFL1: begin
162
`ifdef OR1200_CASE_DEFAULT
163
                   casez (alu_op2) // synopsys parallel_case
164
`else
165
                   casez (alu_op2) // synopsys full_case parallel_case
166
`endif
167
                     0: begin // FF1
168 141 marcus.erl
                        result = a[0] ? 1 : a[1] ? 2 : a[2] ? 3 : a[3] ? 4 : a[4] ? 5 : a[5] ? 6 : a[6] ? 7 : a[7] ? 8 : a[8] ? 9 : a[9] ? 10 : a[10] ? 11 : a[11] ? 12 : a[12] ? 13 : a[13] ? 14 : a[14] ? 15 : a[15] ? 16 : a[16] ? 17 : a[17] ? 18 : a[18] ? 19 : a[19] ? 20 : a[20] ? 21 : a[21] ? 22 : a[22] ? 23 : a[23] ? 24 : a[24] ? 25 : a[25] ? 26 : a[26] ? 27 : a[27] ? 28 : a[28] ? 29 : a[29] ? 30 : a[30] ? 31 : a[31] ? 32 : 0;
169 401 julius
                     end
170
                     default: begin // FL1
171
                        result = a[31] ? 32 : a[30] ? 31 : a[29] ? 30 : a[28] ? 29 : a[27] ? 28 : a[26] ? 27 : a[25] ? 26 : a[24] ? 25 : a[23] ? 24 : a[22] ? 23 : a[21] ? 22 : a[20] ? 21 : a[19] ? 20 : a[18] ? 19 : a[17] ? 18 : a[16] ? 17 : a[15] ? 16 : a[14] ? 15 : a[13] ? 14 : a[12] ? 13 : a[11] ? 12 : a[10] ? 11 : a[9] ? 10 : a[8] ? 9 : a[7] ? 8 : a[6] ? 7 : a[5] ? 6 : a[4] ? 5 : a[3] ? 4 : a[2] ? 3 : a[1] ? 2 : a[0] ? 1 : 0 ;
172
                     end
173
                   endcase // casez (alu_op2)
174
                end // case: `OR1200_ALUOP_FFL1
175 640 julius
`endif //  `ifdef OR1200_IMPL_ALU_FFL1
176
`ifdef OR1200_IMPL_ALU_CUST5
177
 
178 10 unneback
                `OR1200_ALUOP_CUST5 : begin
179
                                result = result_cust5;
180
                end
181 640 julius
`endif
182 10 unneback
                `OR1200_ALUOP_SHROT : begin
183
                                result = shifted_rotated;
184
                end
185
                `OR1200_ALUOP_ADD : begin
186
                                result = result_sum;
187
                end
188
`ifdef OR1200_IMPL_ADDC
189
                `OR1200_ALUOP_ADDC : begin
190
                                result = result_csum;
191
                end
192
`endif
193 141 marcus.erl
`ifdef OR1200_IMPL_SUB
194 10 unneback
                `OR1200_ALUOP_SUB : begin
195
                                result = a - b;
196
                end
197 141 marcus.erl
`endif
198 10 unneback
                `OR1200_ALUOP_XOR : begin
199
                                result = a ^ b;
200
                end
201
                `OR1200_ALUOP_OR  : begin
202
                                result = a | b;
203
                end
204 640 julius
`ifdef OR1200_IMPL_ALU_EXT
205
                `OR1200_ALUOP_EXTHB  : begin
206
                                result = extended;
207
                end
208
                `OR1200_ALUOP_EXTW  : begin
209
                                result = extended;
210
                end
211
`endif
212 10 unneback
                `OR1200_ALUOP_MOVHI : begin
213
                                if (macrc_op) begin
214
                                        result = mult_mac_result;
215
                                end
216
                                else begin
217
                                        result = b << 16;
218
                                end
219
                end
220
`ifdef OR1200_MULT_IMPLEMENTED
221 258 julius
`ifdef OR1200_DIV_IMPLEMENTED
222 10 unneback
                `OR1200_ALUOP_DIV,
223
                `OR1200_ALUOP_DIVU,
224
`endif
225 481 julius
                `OR1200_ALUOP_MUL,
226
                `OR1200_ALUOP_MULU : begin
227 10 unneback
                                result = mult_mac_result;
228
                end
229
`endif
230 141 marcus.erl
                `OR1200_ALUOP_CMOV: begin
231
                        result = flag ? a : b;
232
                end
233 10 unneback
 
234
`ifdef OR1200_CASE_DEFAULT
235 141 marcus.erl
                default: begin
236 10 unneback
`else
237 141 marcus.erl
                `OR1200_ALUOP_COMP, `OR1200_ALUOP_AND: begin
238 10 unneback
`endif
239 141 marcus.erl
                        result=result_and;
240
                end
241 10 unneback
        endcase
242
end
243
 
244
//
245
// Generate flag and flag write enable
246
//
247 141 marcus.erl
always @(alu_op or result_sum or result_and or flagcomp
248
`ifdef OR1200_IMPL_ADDC
249
         or result_csum
250
`endif
251
) begin
252 364 julius
        casez (alu_op)          // synopsys parallel_case
253 10 unneback
`ifdef OR1200_ADDITIONAL_FLAG_MODIFIERS
254
                `OR1200_ALUOP_ADD : begin
255
                        flagforw = (result_sum == 32'h0000_0000);
256
                        flag_we = 1'b1;
257
                end
258
`ifdef OR1200_IMPL_ADDC
259
                `OR1200_ALUOP_ADDC : begin
260
                        flagforw = (result_csum == 32'h0000_0000);
261
                        flag_we = 1'b1;
262
                end
263
`endif
264
                `OR1200_ALUOP_AND: begin
265
                        flagforw = (result_and == 32'h0000_0000);
266
                        flag_we = 1'b1;
267
                end
268
`endif
269
                `OR1200_ALUOP_COMP: begin
270
                        flagforw = flagcomp;
271
                        flag_we = 1'b1;
272
                end
273
                default: begin
274 141 marcus.erl
                        flagforw = flagcomp;
275 10 unneback
                        flag_we = 1'b0;
276
                end
277
        endcase
278
end
279
 
280
//
281
// Generate SR[CY] write enable
282
//
283
always @(alu_op or cy_sum
284 141 marcus.erl
`ifdef OR1200_IMPL_CY
285 10 unneback
`ifdef OR1200_IMPL_ADDC
286
        or cy_csum
287
`endif
288 141 marcus.erl
`ifdef OR1200_IMPL_SUB
289
        or cy_sub
290
`endif
291
`endif
292
) begin
293 364 julius
        casez (alu_op)          // synopsys parallel_case
294 10 unneback
`ifdef OR1200_IMPL_CY
295
                `OR1200_ALUOP_ADD : begin
296
                        cyforw = cy_sum;
297
                        cy_we = 1'b1;
298
                end
299
`ifdef OR1200_IMPL_ADDC
300
                `OR1200_ALUOP_ADDC: begin
301
                        cyforw = cy_csum;
302
                        cy_we = 1'b1;
303
                end
304
`endif
305 141 marcus.erl
`ifdef OR1200_IMPL_SUB
306
                `OR1200_ALUOP_SUB: begin
307
                        cyforw = cy_sub;
308
                        cy_we = 1'b1;
309
                end
310 10 unneback
`endif
311 141 marcus.erl
`endif
312 10 unneback
                default: begin
313
                        cyforw = 1'b0;
314
                        cy_we = 1'b0;
315
                end
316
        endcase
317
end
318
 
319
//
320
// Shifts and rotation
321
//
322 640 julius
always @(alu_op2 or a or b) begin
323
        case (alu_op2)          // synopsys parallel_case
324
          `OR1200_SHROTOP_SLL :
325 10 unneback
                                shifted_rotated = (a << b[4:0]);
326 640 julius
          `OR1200_SHROTOP_SRL :
327 10 unneback
                                shifted_rotated = (a >> b[4:0]);
328
 
329
`ifdef OR1200_IMPL_ALU_ROTATE
330 640 julius
          `OR1200_SHROTOP_ROR :
331
                                shifted_rotated = (a << (6'd32-{1'b0,b[4:0]})) |
332
                                                  (a >> b[4:0]);
333 10 unneback
`endif
334 640 julius
          default:
335
                                shifted_rotated = ({32{a[31]}} <<
336
                                                   (6'd32-{1'b0, b[4:0]})) |
337
                                                  a >> b[4:0];
338 10 unneback
        endcase
339
end
340
 
341
//
342
// First type of compare implementation
343
//
344
`ifdef OR1200_IMPL_ALU_COMP1
345
always @(comp_op or a_eq_b or a_lt_b) begin
346
        case(comp_op[2:0])       // synopsys parallel_case
347
                `OR1200_COP_SFEQ:
348
                        flagcomp = a_eq_b;
349
                `OR1200_COP_SFNE:
350
                        flagcomp = ~a_eq_b;
351
                `OR1200_COP_SFGT:
352
                        flagcomp = ~(a_eq_b | a_lt_b);
353
                `OR1200_COP_SFGE:
354
                        flagcomp = ~a_lt_b;
355
                `OR1200_COP_SFLT:
356
                        flagcomp = a_lt_b;
357
                `OR1200_COP_SFLE:
358
                        flagcomp = a_eq_b | a_lt_b;
359
                default:
360
                        flagcomp = 1'b0;
361
        endcase
362
end
363
`endif
364
 
365
//
366
// Second type of compare implementation
367
//
368
`ifdef OR1200_IMPL_ALU_COMP2
369
always @(comp_op or comp_a or comp_b) begin
370
        case(comp_op[2:0])       // synopsys parallel_case
371
                `OR1200_COP_SFEQ:
372
                        flagcomp = (comp_a == comp_b);
373
                `OR1200_COP_SFNE:
374
                        flagcomp = (comp_a != comp_b);
375
                `OR1200_COP_SFGT:
376
                        flagcomp = (comp_a > comp_b);
377
                `OR1200_COP_SFGE:
378
                        flagcomp = (comp_a >= comp_b);
379
                `OR1200_COP_SFLT:
380
                        flagcomp = (comp_a < comp_b);
381
                `OR1200_COP_SFLE:
382
                        flagcomp = (comp_a <= comp_b);
383
                default:
384
                        flagcomp = 1'b0;
385
        endcase
386
end
387
`endif
388
 
389 640 julius
`ifdef OR1200_IMPL_ALU_EXT
390
   always @(alu_op or alu_op2 or a) begin
391
      casez (alu_op2)
392
        `OR1200_EXTHBOP_HS : extended = {{16{a[15]}},a[15:0]};
393
        `OR1200_EXTHBOP_BS : extended = {{24{a[7]}},a[7:0]};
394
        `OR1200_EXTHBOP_HZ : extended = {16'd0,a[15:0]};
395
        `OR1200_EXTHBOP_BZ : extended = {24'd0,a[7:0]};
396
        default: extended = a; // Used for l.extw instructions
397
      endcase // casez (alu_op2)
398
   end
399
`endif
400
 
401
 
402
//
403
// l.cust5 custom instructions
404
//
405
`ifdef OR1200_IMPL_ALU_CUST5
406
// Examples for move byte, set bit and clear bit
407
//
408
always @(cust5_op or cust5_limm or a or b) begin
409
        casez (cust5_op)                // synopsys parallel_case
410
                5'h1 : begin
411
                        casez (cust5_limm[1:0])
412
                          2'h0: result_cust5 = {a[31:8], b[7:0]};
413
                          2'h1: result_cust5 = {a[31:16], b[7:0], a[7:0]};
414
                          2'h2: result_cust5 = {a[31:24], b[7:0], a[15:0]};
415
                          2'h3: result_cust5 = {b[7:0], a[23:0]};
416
                        endcase
417
                end
418
                5'h2 :
419
                        result_cust5 = a | (1 << cust5_limm);
420
                5'h3 :
421
                        result_cust5 = a & (32'hffffffff ^ (1 << cust5_limm));
422
//
423
// *** Put here new l.cust5 custom instructions ***
424
//
425
                default: begin
426
                        result_cust5 = a;
427
                end
428
        endcase
429
end // always @ (cust5_op or cust5_limm or a or b)
430
`endif
431
 
432 10 unneback
endmodule

powered by: WebSVN 2.1.0

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