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

Subversion Repositories thor

[/] [thor/] [trunk/] [rtl/] [verilog/] [Thor_alu.v] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2013,2015  Robert Finch, Stratford
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
// This source file is free software: you can redistribute it and/or modify 
9
// it under the terms of the GNU Lesser General Public License as published 
10
// by the Free Software Foundation, either version 3 of the License, or     
11
// (at your option) any later version.                                      
12
//                                                                          
13
// This source file is distributed in the hope that it will be useful,      
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
16
// GNU General Public License for more details.                             
17
//                                                                          
18
// You should have received a copy of the GNU General Public License        
19
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
20
//
21
//
22
// Thor SuperScaler
23
// ALU
24
//
25
// ============================================================================
26
//
27
`include "Thor_defines.v"
28
 
29
module Thor_alu(corenum, rst, clk, alu_ld, alu_op, alu_fn, alu_argA, alu_argB, alu_argC, alu_argI, alu_pc, insnsz, o, alu_done, alu_divByZero);
30
parameter DBW=64;
31
parameter BIG=1;
32
parameter FEATURES = 0;
33
input [63:0] corenum;
34
input rst;
35
input clk;
36
input alu_ld;
37
input [7:0] alu_op;
38
input [5:0] alu_fn;
39
input [DBW-1:0] alu_argA;
40
input [DBW-1:0] alu_argB;
41
input [DBW-1:0] alu_argC;
42
input [DBW-1:0] alu_argI;
43
input [DBW-1:0] alu_pc;
44
input [3:0] insnsz;
45
output reg [DBW-1:0] o;
46
output reg alu_done;
47
output alu_divByZero;
48
 
49
wire signed [DBW-1:0] alu_argAs = alu_argA;
50
wire signed [DBW-1:0] alu_argBs = alu_argB;
51
wire signed [DBW-1:0] alu_argIs = alu_argI;
52
wire [DBW-1:0] andi_res = alu_argA & alu_argI;
53
wire [127:0] alu_prod;
54
wire [63:0] alu_divq;
55
wire [63:0] alu_rem;
56
wire [7:0] bcdao,bcdso;
57
wire [15:0] bcdmo;
58
wire [DBW-1:0] bf_out;
59
wire [DBW-1:0] shfto;
60
wire alu_mult_done,alu_div_done;
61
wire [DBW-1:0] p_out;
62
 
63
integer n;
64
 
65
Thor_multiplier #(DBW) umult1
66
(
67
        .rst(rst),
68
        .clk(clk),
69
        .ld(alu_ld && ((alu_op==`RR && (alu_fn==`MUL || alu_fn==`MULU)) || alu_op==`MULI || alu_op==`MULUI)),
70
        .sgn((alu_op==`RR && alu_op==`MUL) || alu_op==`MULI),
71
        .isMuli(alu_op==`MULI || alu_op==`MULUI),
72
        .a(alu_argA),
73
        .b(alu_argB),
74
        .imm(alu_argI),
75
        .o(alu_prod),
76
        .done(alu_mult_done)
77
);
78
 
79
Thor_divider #(DBW) udiv1
80
(
81
        .rst(rst),
82
        .clk(clk),
83
        .ld(alu_ld && ((alu_op==`RR && (alu_fn==`DIV || alu_fn==`DIVU)) || alu_op==`DIVI || alu_op==`DIVUI)),
84
        .sgn((alu_op==`RR && alu_fn==`DIV) || alu_op==`DIVI),
85
        .isDivi(alu_op==`DIVI || alu_op==`DIVUI),
86
        .a(alu_argA),
87
        .b(alu_argB),
88
        .imm(alu_argI),
89
        .qo(alu_divq),
90
        .ro(alu_rem),
91
        .dvByZr(alu_divByZero),
92
        .done(alu_div_done)
93
);
94
 
95
Thor_shifter #(DBW) ushft0
96
(
97
        .func(alu_fn),
98
        .a(alu_argA),
99
        .b(alu_argB),
100
        .o(shfto)
101
);
102
 
103
BCDAdd ubcda
104
(
105
        .ci(1'b0),
106
        .a(alu_argA[7:0]),
107
        .b(alu_argB[7:0]),
108
        .o(bcdao),
109
        .c()
110
);
111
 
112
BCDSub ubcds
113
(
114
        .ci(1'b0),
115
        .a(alu_argA[7:0]),
116
        .b(alu_argB[7:0]),
117
        .o(bcdso),
118
        .c()
119
);
120
 
121
BCDMul2 ubcdm
122
(
123
        .a(alu_argA),
124
        .b(alu_argB),
125
        .o(bcdmo)
126
);
127
 
128
Thor_bitfield #(DBW) ubf1
129
(
130
        .op(alu_fn),
131
        .a(alu_argA),
132
        .b(alu_argB),
133
        .m(alu_argI[11:0]),
134
        .o(bf_out),
135
        .masko()
136
);
137
 
138
Thor_P #(DBW) upr1
139
(
140
    .fn(alu_fn),
141
    .ra(alu_argI[5:0]),
142
    .rb(alu_argI[11:6]),
143
    .rt(alu_argI[17:12]),
144
    .pregs_i(alu_argA),
145
    .pregs_o(p_out)
146
);
147
 
148
wire [DBW-1:0] cntlzo;
149
wire [DBW-1:0] cntloo;
150
wire [DBW-1:0] cntpopo;
151
 
152
generate
153
begin : clzg
154
if (DBW==64) begin
155
cntlz64 u12 ( .i(alu_argA),  .o(cntlzo) );
156
cntlo64 u13 ( .i(alu_argA),  .o(cntloo) );
157
cntpop64 u14 ( .i(alu_argA), .o(cntpopo) );
158
end
159
else begin
160
cntlz32 u12 ( .i(alu_argA),  .o(cntlzo) );
161
cntlo32 u13 ( .i(alu_argA),  .o(cntloo) );
162
cntpop32 u14 ( .i(alu_argA), .o(cntpopo) );
163
end
164
end
165
endgenerate
166
 
167
wire faz = alu_argA[DBW-2:0]==63'd0;
168
wire fbz = alu_argB[DBW-2:0]==63'd0;
169
wire feq = (faz & fbz) || (alu_argA==alu_argB); // special test for zero
170
wire fgt1 = alu_argA[DBW-2:0] > alu_argB[DBW-2:0];
171
wire flt1 = alu_argA[DBW-2:0] < alu_argB[DBW-2:0];
172
wire flt = alu_argA[DBW] ^ alu_argB[DBW] ? alu_argA[DBW] & !(faz & fbz): alu_argA[DBW] ? fgt1 : flt1;
173
wire nanA = DBW==32 ? alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0) : alu_argA[62:52]==11'h7FF && (alu_argA[51:0]!=52'd0);
174
wire nanB = DBW==32 ? alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0) : alu_argB[62:52]==11'h7FF && (alu_argB[51:0]!=52'd0);
175
 
176
wire fsaz = alu_argA[30:0]==31'd0;
177
wire fsbz = alu_argB[30:0]==31'd0;
178
wire fseq = (fsaz & fsbz) || (alu_argA[31:0]==alu_argB[31:0]);    // special test for zero
179
wire fsgt1 = alu_argA[30:0] > alu_argB[30:0];
180
wire fslt1 = alu_argA[30:0] < alu_argB[30:0];
181
wire fslt = alu_argA[31] ^ alu_argB[31] ? alu_argA[31] & !(fsaz & fsbz): alu_argA[31] ? fsgt1 : fslt1;
182
wire snanA = alu_argA[30:23]==8'hFF && (alu_argA[22:0]!=23'd0);
183
wire snanB = alu_argB[30:23]==8'hFF && (alu_argB[22:0]!=23'd0);
184
 
185
always @*
186
begin
187
casex(alu_op)
188
`LDI,`LDIS:                     o <= alu_argI;
189
`RR:
190
        case(alu_fn)
191
        `ADD,`ADDU:             o <= alu_argA + alu_argB;
192
        `SUB,`SUBU:             o <= alu_argA - alu_argB;
193
        `_2ADDU:                o <= {alu_argA[DBW-2:0],1'b0} + alu_argB;
194
        `_4ADDU:                o <= {alu_argA[DBW-3:0],2'b0} + alu_argB;
195
        `_8ADDU:                o <= {alu_argA[DBW-4:0],3'b0} + alu_argB;
196
        `_16ADDU:               o <= {alu_argA[DBW-5:0],4'b0} + alu_argB;
197
        `MIN:           o <= BIG ? (alu_argA < alu_argB ? alu_argA : alu_argB) : 64'hDEADDEADDEADDEAD;
198
        `MAX:           o <= BIG ? (alu_argA < alu_argB ? alu_argB : alu_argA) : 64'hDEADDEADDEADDEAD;
199
        `MUL,`MULU:     o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
200
        `DIV,`DIVU:     o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
201
        default:   o <= 64'hDEADDEADDEADDEAD;
202
        endcase
203
`MULI,`MULUI:   o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD;
204
`DIVI,`DIVUI:   o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD;
205
`_2ADDUI:               o <= {alu_argA[DBW-2:0],1'b0} + alu_argI;
206
`_4ADDUI:               o <= {alu_argA[DBW-3:0],2'b0} + alu_argI;
207
`_8ADDUI:               o <= {alu_argA[DBW-4:0],3'b0} + alu_argI;
208
`_16ADDUI:              o <= {alu_argA[DBW-5:0],4'b0} + alu_argI;
209
`R:
210
    case(alu_fn[3:0])
211
    `MOV:       o <= alu_argA;
212
    `NEG:               o <= -alu_argA;
213
    `NOT:       o <= |alu_argA ? 64'd0 : 64'd1;
214
    `ABS:       o <= BIG ? (alu_argA[DBW] ? -alu_argA : alu_argA) : 64'hDEADDEADDEADDEAD;
215
    `SGN:       o <= BIG ? (alu_argA[DBW] ? 64'hFFFFFFFFFFFFFFFF : alu_argA==64'd0 ? 64'd0 : 64'd1) : 64'hDEADDEADDEADDEAD;
216
    `CNTLZ:     o <= BIG ? cntlzo : 64'hDEADDEADDEADDEAD;
217
    `CNTLO:     o <= BIG ? cntloo : 64'hDEADDEADDEADDEAD;
218
    `CNTPOP:    o <= BIG ? cntpopo : 64'hDEADDEADDEADDEAD;
219
    `ZXB:       o <= BIG ? {56'd0,alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
220
    `ZXC:       o <= BIG ? {48'd0,alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
221
    `ZXH:       o <= BIG ? {32'd0,alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
222
    `COM:       o <= ~alu_argA;
223
    `SXB:       o <= BIG ? {{56{alu_argA[7]}},alu_argA[7:0]} : 64'hDEADDEADDEADDEAD;
224
    `SXC:       o <= BIG ? {{48{alu_argA[15]}},alu_argA[15:0]} : 64'hDEADDEADDEADDEAD;
225
    `SXH:       o <= BIG ? {{32{alu_argA[31]}},alu_argA[31:0]} : 64'hDEADDEADDEADDEAD;
226
    default:    o <= 64'hDEADDEADDEADDEAD;
227
    endcase
228
`R2:
229
    case(alu_fn)
230
    `CPUID:
231
        if (BIG)
232
        case(alu_argA[4:0])
233
        5'd0:       o <= corenum;
234
        5'd2:       o <= "Finitron";
235
        5'd3:       o <= "";        // vendor ID
236
        5'd4:       o <= "64BitSS"; // class
237
        5'd6:       o <= "Thor";    // Name
238
        5'd8:       o <= "M1";      // model 
239
        5'd9:       o <= "1234";    // serial num
240
        5'd10:      o <= FEATURES;
241
        5'd11:      o <= {32'd16384,32'd32768}; // Cache D,I
242
        default:    o <= 64'hDEADDEADDEADDEAD;
243
        endcase
244
        else    o <= 64'hDEADDEADDEADDEAD;
245
    `REDOR:     o <= BIG ? |alu_argA : 64'hDEADDEADDEADDEAD;
246
    `REDAND:    o <= BIG ? &alu_argA : 64'hDEADDEADDEADDEAD;
247
    `PAR:       o <= BIG ? ^alu_argA : 64'hDEADDEADDEADDEAD;
248
    default:    o <= 64'hDEADDEADDEADDEAD;
249
    endcase
250
`P: o <= p_out;
251
/*
252
`DOUBLE:
253
    if (BIG) begin
254
        if (alu_fn[5:4]==2'b00)
255
            case (alu_fn)
256
            `FMOV:      o <= alu_argA;
257
            `FNEG:              o <= {~alu_argA[DBW-1],alu_argA[DBW-2:0]};
258
            `FABS:              o <= {1'b0,alu_argA[DBW-2:0]};
259
            `FSIGN:                     if (DBW==64)
260
                                o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{10{1'b1}},{52{1'b0}}};
261
                            else
262
                                o <= alu_argA[DBW-2:0]==0 ? {DBW{1'b0}} : {alu_argA[DBW-1],1'b0,{7{1'b1}},{23{1'b0}}};
263
            `FMAN:      o <= alu_argA[(DBW==64?51:22):0];
264
            default:    o <= 64'hDEADDEADDEADDEAD;
265
            endcase
266
        else
267
            case (alu_fn)
268
            `FMOV:      o <= alu_argA;
269
            `FSNEG:     o <= {~alu_argA[31],alu_argA[30:0]};
270
            `FSABS:     o <= {1'b0,alu_argA[30:0]};
271
            `FSSIGN:    o <= alu_argA[30:0]==0 ? {DBW{1'b0}} : {alu_argA[31],1'b0,{7{1'b1}},{23{1'b0}}};
272
            `FSMAN:     o <= alu_argA[22:0];
273
            default:    o <= 64'hDEADDEADDEADDEAD;
274
            endcase
275
    end
276
    else
277
        o <= 64'hDEADDEADDEADDEAD;
278
 */
279
 
280
`ADDI,`ADDUI,`ADDUIS:
281
                o <= alu_argA + alu_argI;
282
`SUBI,`SUBUI:
283
                o <= alu_argA - alu_argI;
284
`ANDI:                  o <= alu_argA & alu_argI;
285
`ORI:                   o <= alu_argA | alu_argI;
286
`EORI:                  o <= alu_argA ^ alu_argI;
287
`LOGIC,`MLO:
288
        case(alu_fn)
289
        `AND:                   o <= alu_argA & alu_argB;
290
        `ANDC:                  o <= alu_argA & ~alu_argB;
291
        `OR:                    o <= alu_argA | alu_argB;
292
        `ORC:                   o <= alu_argA | ~alu_argB;
293
        `EOR:                   o <= alu_argA ^ alu_argB;
294
        `NAND:                  o <= ~(alu_argA & alu_argB);
295
        `NOR:                   o <= ~(alu_argA | alu_argB);
296
        `ENOR:                  o <= ~(alu_argA ^ alu_argB);
297
        default:       o <= 64'd0;
298
        endcase
299
`BITI:
300
    begin
301
        o[0] <= andi_res==64'd0;
302
        o[1] <= andi_res[DBW-1];
303
        o[2] <= andi_res[0];
304
        o[3] <= 1'b0;
305
        o[DBW-1:4] <= 60'd0;
306
    end
307
`TST:
308
        case(alu_fn)
309
        6'd0:   // TST - integer
310
                begin
311
                        o[0] <= alu_argA == 64'd0;
312
                        o[1] <= alu_argA[DBW-1];
313
                        o[2] <= 1'b0;
314
                        o[3] <= 1'b0;
315
                        o[DBW-1:4] <= 60'd0;
316
                end
317
`ifdef FLOATING_POINT
318
        6'd1:   // FSTST - float single
319
                begin
320
                        o[0] <= alu_argA[30:0]==31'd0;    // + or - zero
321
                        o[1] <= alu_argA[31];                   // signed less than
322
                        o[2] <= alu_argA[31];
323
                        // unordered
324
                        o[3] <= alu_argA[30:23]==8'hFF && alu_argA[22:0]!=23'd0; // NaN
325
                        o[DBW-1:4] <= 60'd0;
326
                end
327
        6'd2:   // FTST - float double
328
                begin
329
                        o[0] <= alu_argA[DBW-2:0]==63'd0; // + or - zero
330
                        o[1] <= alu_argA[DBW-1];                        // signed less than
331
                        o[2] <= alu_argA[DBW-1];
332
                        // unordered
333
                        if (DBW==64)
334
                                o[3] <= alu_argA[62:52]==11'h7FF && alu_argA[51:0]!=52'd0;       // NaN
335
                        else
336
                                o[3] <= 1'b0;
337
                        o[DBW-1:4] <= 60'd0;
338
                end
339
`endif
340
        default:        o <= 64'd0;
341
        endcase
342
`CMP:   begin
343
            case(alu_fn)
344
            2'd0: begin     // ICMP
345
                o[0] <= alu_argA == alu_argB;
346
                o[1] <= alu_argAs < alu_argBs;
347
                o[2] <= alu_argA < alu_argB;
348
                o[3] <= 1'b0;
349
                o[DBW-1:4] <= 60'd0;
350
                end
351
`ifdef FLOATING_POINT
352
            2'd1: begin     // FSCMP
353
                o[0] <= fseq;
354
                o[1] <= fslt;
355
                o[2] <= fslt1;
356
                o[3] <= snanA | snanB;
357
                o[DBW-1:4] <= 60'd0;
358
                end
359
            2'd2: begin     // FCMP
360
                o[0] <= feq;
361
                o[1] <= flt;
362
                o[2] <= flt1;
363
                o[3] <= nanA | nanB;
364
                o[DBW-1:4] <= 60'd0;
365
                end
366
`endif
367
            default: o <= 64'hDEADDEADDEADDEAD;
368
            endcase
369
                end
370
`CMPI:  begin
371
                        o[0] <= alu_argA == alu_argI;
372
                        o[1] <= alu_argAs < alu_argIs;
373
                        o[2] <= alu_argA < alu_argI;
374
                        o[3] <= 1'b0;
375
                        o[DBW-1:4] <= 64'd0;
376
                end
377
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVH,`STI,
378
`LWS,`SWS,`LEA,`RTS2,`STS,`STFND,`STCMP:
379
            begin
380
                                o <= alu_argA + alu_argC + alu_argI;
381
                    end
382
`LBX,`LBUX,`SBX,
383
`LCX,`LCUX,`SCX,
384
`LHX,`LHUX,`SHX,
385
`LWX,`SWX:
386
            case(alu_fn[1:0])
387
            2'd0:   o <= alu_argA + alu_argC + alu_argB;
388
            2'd1:   o <= alu_argA + alu_argC + {alu_argB,1'b0};
389
            2'd2:   o <= alu_argA + alu_argC + {alu_argB,2'b0};
390
            2'd3:   o <= alu_argA + alu_argC + {alu_argB,3'b0};
391
            endcase
392
`ifdef STACKOPS
393
`PUSH,`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8;
394
`UNLINK:    o <= alu_argA + alu_argC + 64'd8;
395
`POP:       o <= alu_argA + alu_argC;
396
`endif
397
`JSR,`JSRS,`JSRZ,`SYS:  o <= alu_pc + insnsz;
398
`INT:           o <= alu_pc;
399
`MFSPR,`MTSPR:  begin
400
                o <= alu_argA;
401
                end
402
`MUX:   begin
403
                        for (n = 0; n < DBW; n = n + 1)
404
                                o[n] <= alu_argA[n] ? alu_argB[n] : alu_argC[n];
405
                end
406
`BCD:
407
        if (BIG)
408
            case(alu_fn)
409
            `BCDADD:    o <= bcdao;
410
            `BCDSUB:    o <= bcdso;
411
            `BCDMUL:    o <= bcdmo;
412
            default:    o <= 64'hDEADDEADDEADDEAD;
413
            endcase
414
        else
415
            o <= 64'hDEADDEADDEADDEAD;
416
`SHIFT:     o <= BIG ? shfto : 64'hDEADDEADDEADDEAD;
417
`ifdef BITFIELDOPS
418
`BITFIELD:      o <= BIG ? bf_out : 64'hDEADDEADDEADDEAD;
419
`endif
420
`LOOP:      o <= alu_argB > 0 ? alu_argB - 64'd1 : alu_argB;
421
default:        o <= 64'hDEADDEADDEADDEAD;
422
endcase
423
end
424
 
425
// Generate done signal
426
always @*
427
case(alu_op)
428
`RR:
429
    case(alu_fn)
430
    `MUL,`MULU: alu_done <= alu_mult_done;
431
    `DIV,`DIVU: alu_done <= alu_div_done;
432
    default:    alu_done <= `TRUE;
433
    endcase
434
`MULI,`MULUI:   alu_done <= alu_mult_done;
435
`DIVI,`DIVUI:   alu_done <= alu_div_done;
436
default:    alu_done <= `TRUE;
437
endcase
438
 
439
endmodule

powered by: WebSVN 2.1.0

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