OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-3.1/] [rtl/] [verilog/] [mor1kx_execute_alu.v] - Blame information for rev 38

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 alirezamon
/* ****************************************************************************
2
  This Source Code Form is subject to the terms of the
3
  Open Hardware Description License, v. 1.0. If a copy
4
  of the OHDL was not distributed with this file, You
5
  can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
6
 
7
  Description: mor1kx execute stage ALU
8
 
9
  Inputs are opcodes, the immediate field, operands from RF, instruction
10
  opcode
11
 
12
  Copyright (C) 2012 Julius Baxter <juliusbaxter@gmail.com>
13
  Copyright (C) 2012-2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
14
 
15
***************************************************************************** */
16
 
17
`include "mor1kx-defines.v"
18
 
19
module mor1kx_execute_alu
20
  #(
21
    parameter OPTION_OPERAND_WIDTH = 32,
22
 
23
    parameter FEATURE_OVERFLOW = "NONE",
24
    parameter FEATURE_CARRY_FLAG = "ENABLED",
25
 
26
    parameter FEATURE_MULTIPLIER = "THREESTAGE",
27
    parameter FEATURE_DIVIDER = "NONE",
28
 
29
    parameter FEATURE_ADDC = "NONE",
30
    parameter FEATURE_SRA = "ENABLED",
31
    parameter FEATURE_ROR = "NONE",
32
    parameter FEATURE_EXT = "NONE",
33
    parameter FEATURE_CMOV = "NONE",
34
    parameter FEATURE_FFL1 = "NONE",
35
 
36
    parameter FEATURE_CUST1 = "NONE",
37
    parameter FEATURE_CUST2 = "NONE",
38
    parameter FEATURE_CUST3 = "NONE",
39
    parameter FEATURE_CUST4 = "NONE",
40
    parameter FEATURE_CUST5 = "NONE",
41
    parameter FEATURE_CUST6 = "NONE",
42
    parameter FEATURE_CUST7 = "NONE",
43
    parameter FEATURE_CUST8 = "NONE",
44
 
45
    parameter OPTION_SHIFTER = "BARREL",
46
 
47
    // Pipeline specific internal parameters
48
    parameter CALCULATE_BRANCH_DEST = "TRUE"
49
    )
50
   (
51
    input                             clk,
52
    input                             rst,
53
 
54
    // pipeline control signal in
55
    input                             padv_decode_i,
56
    input                             padv_execute_i,
57
    input                             padv_ctrl_i,
58
 
59
    // inputs to ALU
60
    input [`OR1K_ALU_OPC_WIDTH-1:0]   opc_alu_i,
61
    input [`OR1K_ALU_OPC_WIDTH-1:0]   opc_alu_secondary_i,
62
 
63
    input [`OR1K_IMM_WIDTH-1:0]       imm16_i,
64
    input [OPTION_OPERAND_WIDTH-1:0]  immediate_i,
65
    input                             immediate_sel_i,
66
 
67
    input [OPTION_OPERAND_WIDTH-1:0]  decode_immediate_i,
68
    input                             decode_immediate_sel_i,
69
 
70
    input                             decode_valid_i,
71
 
72
    input                             decode_op_mul_i,
73
 
74
    input                             op_alu_i,
75
    input                             op_add_i,
76
    input                             op_mul_i,
77
    input                             op_mul_signed_i,
78
    input                             op_mul_unsigned_i,
79
    input                             op_div_i,
80
    input                             op_div_signed_i,
81
    input                             op_div_unsigned_i,
82
    input                             op_shift_i,
83
    input                             op_ffl1_i,
84
    input                             op_setflag_i,
85
    input                             op_mtspr_i,
86
    input                             op_mfspr_i,
87
    input                             op_movhi_i,
88
    input                             op_jbr_i,
89
    input                             op_jr_i,
90
    input [9:0]                immjbr_upper_i,
91
    input [OPTION_OPERAND_WIDTH-1:0]  pc_execute_i,
92
 
93
    // Adder control logic
94
    input                             adder_do_sub_i,
95
    input                             adder_do_carry_i,
96
 
97
    input [OPTION_OPERAND_WIDTH-1:0]  decode_rfa_i,
98
    input [OPTION_OPERAND_WIDTH-1:0]  decode_rfb_i,
99
 
100
    input [OPTION_OPERAND_WIDTH-1:0]  rfa_i,
101
    input [OPTION_OPERAND_WIDTH-1:0]  rfb_i,
102
 
103
    // flag fed back from ctrl
104
    input                             flag_i,
105
 
106
    output                            flag_set_o,
107
    output                            flag_clear_o,
108
 
109
    input                             carry_i,
110
    output                            carry_set_o,
111
    output                            carry_clear_o,
112
 
113
    output                            overflow_set_o,
114
    output                            overflow_clear_o,
115
 
116
    output [OPTION_OPERAND_WIDTH-1:0] alu_result_o,
117
    output                            alu_valid_o,
118
    output [OPTION_OPERAND_WIDTH-1:0] mul_result_o,
119
    output [OPTION_OPERAND_WIDTH-1:0] adder_result_o
120
    );
121
 
122
   wire                                   alu_stall;
123
 
124
   wire [OPTION_OPERAND_WIDTH-1:0]        a;
125
   wire [OPTION_OPERAND_WIDTH-1:0]        b;
126
 
127
   // Adder & comparator wires
128
   wire [OPTION_OPERAND_WIDTH-1:0]        adder_result;
129
   wire                                   adder_carryout;
130
   wire                                   adder_signed_overflow;
131
   wire                                   adder_unsigned_overflow;
132
   wire                                   adder_result_sign;
133
 
134
   wire [OPTION_OPERAND_WIDTH-1:0]        b_neg;
135
   wire [OPTION_OPERAND_WIDTH-1:0]        b_mux;
136
   wire                                   carry_in;
137
 
138
   wire                                   a_eq_b;
139
   wire                                   a_lts_b;
140
   wire                                   a_ltu_b;
141
 
142
   // Shifter wires
143
   wire [`OR1K_ALU_OPC_SECONDARY_WIDTH-1:0] opc_alu_shr;
144
   wire [OPTION_OPERAND_WIDTH-1:0]        shift_result;
145
   wire                                   shift_valid;
146
 
147
   // Comparison wires
148
   reg                                    flag_set; // comb.
149
 
150
   // Logic wires
151
   wire                                   op_logic;
152
   reg [OPTION_OPERAND_WIDTH-1:0]          logic_result;
153
 
154
   // Multiplier wires
155
   wire [OPTION_OPERAND_WIDTH-1:0]        mul_result;
156
   wire                                   mul_valid;
157
   wire                                   mul_signed_overflow;
158
   wire                                   mul_unsigned_overflow;
159
 
160
   wire [OPTION_OPERAND_WIDTH-1:0]        div_result;
161
   wire                                   div_valid;
162
   wire                                   div_by_zero;
163
 
164
 
165
   wire [OPTION_OPERAND_WIDTH-1:0]        ffl1_result;
166
 
167
   wire                                   op_cmov;
168
   wire [OPTION_OPERAND_WIDTH-1:0]        cmov_result;
169
 
170
   wire [OPTION_OPERAND_WIDTH-1:0]        decode_a;
171
   wire [OPTION_OPERAND_WIDTH-1:0]        decode_b;
172
generate
173
if (CALCULATE_BRANCH_DEST=="TRUE") begin : calculate_branch_dest
174
   assign a = (op_jbr_i | op_jr_i) ? pc_execute_i : rfa_i;
175
   assign b = immediate_sel_i ? immediate_i :
176
              op_jbr_i ? {{4{immjbr_upper_i[9]}},immjbr_upper_i,imm16_i,2'b00} :
177
              rfb_i;
178
end else begin
179
   assign a = rfa_i;
180
   assign b = immediate_sel_i ? immediate_i : rfb_i;
181
 
182
   assign decode_a = decode_rfa_i;
183
   assign decode_b = decode_immediate_sel_i ? decode_immediate_i : decode_rfb_i;
184
 
185
end
186
endgenerate
187
 
188
   assign opc_alu_shr = opc_alu_secondary_i[`OR1K_ALU_OPC_SECONDARY_WIDTH-1:0];
189
 
190
   // Adder/subtractor inputs
191
   assign b_neg = ~b;
192
   assign carry_in = adder_do_sub_i | adder_do_carry_i & carry_i;
193
   assign b_mux = adder_do_sub_i ? b_neg : b;
194
   // Adder
195
   assign {adder_carryout, adder_result} = a + b_mux +
196
                                           {{OPTION_OPERAND_WIDTH-1{1'b0}},
197
                                            carry_in};
198
 
199
   assign adder_result_sign = adder_result[OPTION_OPERAND_WIDTH-1];
200
 
201
   assign adder_signed_overflow = // Input signs are same and ...
202
                                  (a[OPTION_OPERAND_WIDTH-1] ==
203
                                   b_mux[OPTION_OPERAND_WIDTH-1]) &
204
                                  // result sign is different to input signs
205
                                  (a[OPTION_OPERAND_WIDTH-1] ^
206
                                   adder_result[OPTION_OPERAND_WIDTH-1]);
207
 
208
   assign adder_unsigned_overflow = adder_carryout;
209
 
210
   assign adder_result_o = adder_result;
211
 
212
   generate
213
      /* verilator lint_off WIDTH */
214
      if (FEATURE_MULTIPLIER=="THREESTAGE") begin : threestagemultiply
215
         /* verilator lint_on WIDTH */
216
         // 32-bit multiplier with three registering stages to help with timing
217
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_opa;
218
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_opb;
219
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_result1;
220
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_result2;
221
         reg [2:0]                                mul_valid_shr;
222
 
223
         always @(posedge clk) begin
224
            if (op_mul_i) begin
225
               mul_opa <= a;
226
               mul_opb <= b;
227
            end
228
            mul_result1 <= mul_opa * mul_opb;
229
            mul_result2 <= mul_result1;
230
         end
231
 
232
         assign mul_result = mul_result2;
233
 
234
         always @(posedge clk)
235
           if (decode_valid_i)
236
             mul_valid_shr <= {2'b00, op_mul_i};
237
           else
238
             mul_valid_shr <= mul_valid_shr[2] ? mul_valid_shr:
239
                              {mul_valid_shr[1:0], 1'b0};
240
 
241
         assign mul_valid = mul_valid_shr[2] & !decode_valid_i;
242
 
243
         // Can't detect unsigned overflow in this implementation
244
         assign mul_unsigned_overflow = 0;
245
 
246
      end // if (FEATURE_MULTIPLIER=="THREESTAGE")
247
      /* verilator lint_off WIDTH */
248
      else if (FEATURE_MULTIPLIER=="PIPELINED") begin : pipelinedmultiply
249
         /* verilator lint_on WIDTH */
250
         // 32-bit multiplier in sync with cpu pipeline
251
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_opa;
252
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_opb;
253
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_result1;
254
         reg [OPTION_OPERAND_WIDTH-1:0]           mul_result2;
255
 
256
         always @(posedge clk) begin
257
            if (decode_op_mul_i & padv_decode_i) begin
258
               mul_opa <= decode_a;
259
               mul_opb <= decode_b;
260
            end
261
            if (padv_execute_i)
262
              mul_result1 <= mul_opa * mul_opb;
263
 
264
            mul_result2 <= mul_result1;
265
         end
266
 
267
         assign mul_result = mul_result2;
268
 
269
         assign mul_valid = 1;
270
 
271
         // Can't detect unsigned overflow in this implementation
272
         assign mul_unsigned_overflow = 0;
273
 
274
      end // if (FEATURE_MULTIPLIER=="PIPELINED")
275
      else if (FEATURE_MULTIPLIER=="SERIAL") begin : serialmultiply
276
         reg [(OPTION_OPERAND_WIDTH*2)-1:0]  mul_prod_r;
277
         reg [5:0]   serial_mul_cnt;
278
         reg         mul_done;
279
         wire [OPTION_OPERAND_WIDTH-1:0] mul_a, mul_b;
280
 
281
         // Check if it's a signed multiply and operand b is negative,
282
         // convert to positive
283
         assign mul_a = op_mul_signed_i & a[OPTION_OPERAND_WIDTH-1] ?
284
                        ~a + 1 : a;
285
         assign mul_b = op_mul_signed_i & b[OPTION_OPERAND_WIDTH-1] ?
286
                        ~b + 1 : b;
287
 
288
         always @(posedge clk)
289
           if (rst) begin
290
               mul_prod_r <=  64'h0000_0000_0000_0000;
291
               serial_mul_cnt <= 6'd0;
292
               mul_done <= 1'b0;
293
            end
294
            else if (|serial_mul_cnt) begin
295
               serial_mul_cnt <= serial_mul_cnt - 6'd1;
296
 
297
               if (mul_prod_r[0])
298
                  mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH-1]
299
                     <= mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH] + mul_a;
300
               else
301
                  mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH-1]
302
                     <= {1'b0,mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH]};
303
 
304
               mul_prod_r[OPTION_OPERAND_WIDTH-2:0] <= mul_prod_r[OPTION_OPERAND_WIDTH-1:1];
305
 
306
               if (serial_mul_cnt==6'd1)
307
                  mul_done <= 1'b1;
308
 
309
            end
310
            else if (decode_valid_i && op_mul_i) begin
311
               mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH] <= 32'd0;
312
               mul_prod_r[OPTION_OPERAND_WIDTH-1:0] <= mul_b;
313
               mul_done <= 0;
314
               serial_mul_cnt <= 6'b10_0000;
315
            end
316
            else if (decode_valid_i) begin
317
               mul_done <= 1'b0;
318
            end
319
 
320
         assign mul_valid  = mul_done & !decode_valid_i;
321
 
322
         assign mul_result = op_mul_signed_i ?
323
                             ((a[OPTION_OPERAND_WIDTH-1] ^
324
                               b[OPTION_OPERAND_WIDTH-1]) ?
325
                              ~mul_prod_r[OPTION_OPERAND_WIDTH-1:0] + 1 :
326
                              mul_prod_r[OPTION_OPERAND_WIDTH-1:0]) :
327
                             mul_prod_r[OPTION_OPERAND_WIDTH-1:0];
328
 
329
         assign mul_unsigned_overflow =  OPTION_OPERAND_WIDTH==64 ? 0 :
330
                                         |mul_prod_r[(OPTION_OPERAND_WIDTH*2)-1:
331
                                                     OPTION_OPERAND_WIDTH];
332
 
333
         // synthesis translate_off
334
         `ifndef verilator
335
         always @(posedge mul_valid)
336
           begin
337
              @(posedge clk);
338
 
339
           if (((a*b) & {OPTION_OPERAND_WIDTH{1'b1}}) != mul_result)
340
             begin
341
                $display("%t incorrect serial multiply result at pc %08h",
342
                         $time, pc_execute_i);
343
                $display("a=%08h b=%08h, mul_result=%08h, expected %08h",
344
                         a, b, mul_result, ((a*b) & {OPTION_OPERAND_WIDTH{1'b1}}));
345
             end
346
           end
347
         `endif
348
         // synthesis translate_on
349
 
350
      end // if (FEATURE_MULTIPLIER=="SERIAL")
351
      else if (FEATURE_MULTIPLIER=="SIMULATION") begin
352
         // Simple multiplier result
353
         wire [(OPTION_OPERAND_WIDTH*2)-1:0] mul_full_result;
354
         assign mul_full_result = a * b;
355
         assign mul_result = mul_full_result[OPTION_OPERAND_WIDTH-1:0];
356
 
357
         assign mul_unsigned_overflow =  OPTION_OPERAND_WIDTH==64 ? 0 :
358
               |mul_full_result[(OPTION_OPERAND_WIDTH*2)-1:OPTION_OPERAND_WIDTH];
359
 
360
         assign mul_valid = 1;
361
      end
362
      else if (FEATURE_MULTIPLIER=="NONE") begin
363
         // No multiplier
364
         assign mul_result = 0;
365
         assign mul_valid = 1'b1;
366
         assign mul_unsigned_overflow = 0;
367
      end
368
      else begin
369
         // Incorrect configuration option
370
         initial begin
371
            $display("%m: Error - chosen multiplier implementation (%s) not available",
372
                    FEATURE_MULTIPLIER);
373
            $finish;
374
         end
375
      end
376
   endgenerate
377
 
378
   // One signed overflow detection for all multiplication implmentations
379
   assign mul_signed_overflow = (FEATURE_MULTIPLIER=="NONE") ||
380
                                (FEATURE_MULTIPLIER=="PIPELINED") ? 0 :
381
                                // Same signs, check for negative result
382
                                // (should be positive)
383
                                ((a[OPTION_OPERAND_WIDTH-1] ==
384
                                  b[OPTION_OPERAND_WIDTH-1]) &&
385
                                 mul_result[OPTION_OPERAND_WIDTH-1]) ||
386
                                // Differring signs, check for positive result
387
                                // (should be negative)
388
                                ((a[OPTION_OPERAND_WIDTH-1] ^
389
                                  b[OPTION_OPERAND_WIDTH-1]) &&
390
                                 !mul_result[OPTION_OPERAND_WIDTH-1]);
391
 
392
   assign mul_result_o = mul_result;
393
 
394
   generate
395
      /* verilator lint_off WIDTH */
396
      if (FEATURE_DIVIDER=="SERIAL") begin
397
      /* verilator lint_on WIDTH */
398
         reg [5:0] div_count;
399
         reg [OPTION_OPERAND_WIDTH-1:0] div_n;
400
         reg [OPTION_OPERAND_WIDTH-1:0] div_d;
401
         reg [OPTION_OPERAND_WIDTH-1:0] div_r;
402
         wire [OPTION_OPERAND_WIDTH:0]  div_sub;
403
         reg                            div_neg;
404
         reg                            div_done;
405
         reg                            div_by_zero_r;
406
 
407
 
408
         assign div_sub = {div_r[OPTION_OPERAND_WIDTH-2:0],
409
                           div_n[OPTION_OPERAND_WIDTH-1]} - div_d;
410
 
411
         /* Cycle counter */
412
         always @(posedge clk `OR_ASYNC_RST)
413
            if (rst) begin
414
               div_done <= 0;
415
               div_count <= 0;
416
            end else if (decode_valid_i & op_div_i) begin
417
               div_done <= 0;
418
               div_count <= OPTION_OPERAND_WIDTH;
419
            end else if (div_count == 1)
420
               div_done <= 1;
421
            else if (!div_done)
422
               div_count <= div_count - 1;
423
 
424
         always @(posedge clk) begin
425
            if (decode_valid_i & op_div_i) begin
426
               div_n <= rfa_i;
427
               div_d <= rfb_i;
428
               div_r <= 0;
429
               div_neg <= 1'b0;
430
               div_by_zero_r <= !(|rfb_i);
431
 
432
               /*
433
                * Convert negative operands in the case of signed division.
434
                * If only one of the operands is negative, the result is
435
                * converted back to negative later on
436
                */
437
               if (op_div_signed_i) begin
438
                  if (rfa_i[OPTION_OPERAND_WIDTH-1] ^
439
                      rfb_i[OPTION_OPERAND_WIDTH-1])
440
                    div_neg <= 1'b1;
441
 
442
                  if (rfa_i[OPTION_OPERAND_WIDTH-1])
443
                    div_n <= ~rfa_i + 1;
444
 
445
                  if (rfb_i[OPTION_OPERAND_WIDTH-1])
446
                    div_d <= ~rfb_i + 1;
447
               end
448
            end else if (!div_done) begin
449
               if (!div_sub[OPTION_OPERAND_WIDTH]) begin // div_sub >= 0
450
                  div_r <= div_sub[OPTION_OPERAND_WIDTH-1:0];
451
                  div_n <= {div_n[OPTION_OPERAND_WIDTH-2:0], 1'b1};
452
               end else begin // div_sub < 0
453
                  div_r <= {div_r[OPTION_OPERAND_WIDTH-2:0],
454
                            div_n[OPTION_OPERAND_WIDTH-1]};
455
                  div_n <= {div_n[OPTION_OPERAND_WIDTH-2:0], 1'b0};
456
               end
457
           end
458
         end
459
 
460
         assign div_valid = div_done & !decode_valid_i;
461
         assign div_result = div_neg ? ~div_n + 1 : div_n;
462
         assign div_by_zero = div_by_zero_r;
463
      end
464
      /* verilator lint_off WIDTH */
465
      else if (FEATURE_DIVIDER=="SIMULATION") begin
466
      /* verilator lint_on WIDTH */
467
         assign div_result = a / b;
468
         assign div_valid = 1;
469
         assign div_by_zero = (opc_alu_i == `OR1K_ALU_OPC_DIV ||
470
                                 opc_alu_i == `OR1K_ALU_OPC_DIVU) && !(|b);
471
 
472
      end
473
      else if (FEATURE_DIVIDER=="NONE") begin
474
         assign div_result = 0;
475
         assign div_valid = 1'b1;
476
         assign div_by_zero = 0;
477
      end
478
      else begin
479
         // Incorrect configuration option
480
         initial begin
481
            $display("%m: Error - chosen divider implementation (%s) not available",
482
                     FEATURE_DIVIDER);
483
            $finish;
484
         end
485
      end
486
   endgenerate
487
 
488
   wire ffl1_valid;
489
   generate
490
      if (FEATURE_FFL1!="NONE") begin
491
         wire [OPTION_OPERAND_WIDTH-1:0] ffl1_result_wire;
492
         assign ffl1_result_wire = (opc_alu_secondary_i[2]) ?
493
                                   (a[31] ? 32 : a[30] ? 31 : a[29] ? 30 :
494
                                    a[28] ? 29 : a[27] ? 28 : a[26] ? 27 :
495
                                    a[25] ? 26 : a[24] ? 25 : a[23] ? 24 :
496
                                    a[22] ? 23 : a[21] ? 22 : a[20] ? 21 :
497
                                    a[19] ? 20 : a[18] ? 19 : a[17] ? 18 :
498
                                    a[16] ? 17 : a[15] ? 16 : a[14] ? 15 :
499
                                    a[13] ? 14 : a[12] ? 13 : a[11] ? 12 :
500
                                    a[10] ? 11 : a[9] ? 10 : a[8] ? 9 :
501
                                    a[7] ? 8 : a[6] ? 7 : a[5] ? 6 : a[4] ? 5 :
502
                                    a[3] ? 4 : a[2] ? 3 : a[1] ? 2 : a[0] ? 1 : 0 ) :
503
                                   (a[0] ? 1 : a[1] ? 2 : a[2] ? 3 : a[3] ? 4 :
504
                                    a[4] ? 5 : a[5] ? 6 : a[6] ? 7 : a[7] ? 8 :
505
                                    a[8] ? 9 : a[9] ? 10 : a[10] ? 11 : a[11] ? 12 :
506
                                    a[12] ? 13 : a[13] ? 14 : a[14] ? 15 :
507
                                    a[15] ? 16 : a[16] ? 17 : a[17] ? 18 :
508
                                    a[18] ? 19 : a[19] ? 20 : a[20] ? 21 :
509
                                    a[21] ? 22 : a[22] ? 23 : a[23] ? 24 :
510
                                    a[24] ? 25 : a[25] ? 26 : a[26] ? 27 :
511
                                    a[27] ? 28 : a[28] ? 29 : a[29] ? 30 :
512
                                    a[30] ? 31 : a[31] ? 32 : 0);
513
         /* verilator lint_off WIDTH */
514
         if (FEATURE_FFL1=="REGISTERED") begin
515
            /* verilator lint_on WIDTH */
516
            reg [OPTION_OPERAND_WIDTH-1:0] ffl1_result_r;
517
 
518
            assign ffl1_valid = !decode_valid_i;
519
            assign ffl1_result = ffl1_result_r;
520
 
521
            always @(posedge clk)
522
              if (decode_valid_i)
523
                ffl1_result_r = ffl1_result_wire;
524
         end else begin
525
            assign ffl1_result = ffl1_result_wire;
526
            assign ffl1_valid = 1'b1;
527
         end
528
      end
529
      else begin
530
         assign ffl1_result = 0;
531
         assign ffl1_valid = 1'b1;
532
      end
533
   endgenerate
534
 
535
   // Equal compare
536
   assign a_eq_b = (a == b);
537
   // Signed compare
538
   assign a_lts_b = !(adder_result_sign == adder_signed_overflow);
539
   // Unsigned compare
540
   assign a_ltu_b = !adder_carryout;
541
 
542
   generate
543
      /* verilator lint_off WIDTH */
544
      if (OPTION_SHIFTER=="BARREL") begin : barrel_shifter
545
         /* verilator lint_on WIDTH */
546
 
547
         function [OPTION_OPERAND_WIDTH-1:0] reverse;
548
            input [OPTION_OPERAND_WIDTH-1:0] in;
549
            integer                          i;
550
            begin
551
               for (i = 0; i < OPTION_OPERAND_WIDTH; i=i+1) begin
552
                  reverse[(OPTION_OPERAND_WIDTH-1)-i] = in[i];
553
               end
554
            end
555
         endfunction
556
 
557
         wire op_sll = (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SLL);
558
         wire op_srl = (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SRL);
559
         wire op_sra = (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SRA) &&
560
                       (FEATURE_SRA!="NONE");
561
         wire op_ror = (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_ROR) &&
562
                       (FEATURE_ROR!="NONE");
563
 
564
         wire [OPTION_OPERAND_WIDTH-1:0] shift_right;
565
         wire [OPTION_OPERAND_WIDTH-1:0] shift_lsw;
566
         wire [OPTION_OPERAND_WIDTH-1:0] shift_msw;
567
 
568
         //
569
         // Bit-reverse on left shift, perform right shift,
570
         // bit-reverse result on left shift.
571
         //
572
         assign shift_lsw = op_sll ? reverse(a) : a;
573
         assign shift_msw = op_sra ?
574
                            {OPTION_OPERAND_WIDTH{a[OPTION_OPERAND_WIDTH-1]}} :
575
                            op_ror ? a : {OPTION_OPERAND_WIDTH{1'b0}};
576
 
577
         assign shift_right = {shift_msw, shift_lsw} >> b[4:0];
578
         assign shift_result = op_sll ? reverse(shift_right) : shift_right;
579
 
580
         assign shift_valid = 1;
581
 
582
      end else if (OPTION_SHIFTER=="SERIAL") begin : serial_shifter
583
         // Serial shifter
584
         reg [4:0] shift_cnt;
585
         reg       shift_go;
586
         reg [OPTION_OPERAND_WIDTH-1:0] shift_result_r;
587
         always @(posedge clk `OR_ASYNC_RST)
588
           if (rst)
589
             shift_go <= 0;
590
           else if (decode_valid_i)
591
             shift_go <= op_shift_i;
592
 
593
         always @(posedge clk `OR_ASYNC_RST)
594
           if (rst) begin
595
              shift_cnt <= 0;
596
              shift_result_r <= 0;
597
           end
598
           else if (decode_valid_i & op_shift_i) begin
599
              shift_cnt <= 0;
600
              shift_result_r <= a;
601
           end
602
           else if (shift_go && !(shift_cnt==b[4:0])) begin
603
              shift_cnt <= shift_cnt + 1;
604
              if (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SRL)
605
                shift_result_r <= {1'b0,shift_result_r[OPTION_OPERAND_WIDTH-1:1]};
606
              else if (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SLL)
607
                shift_result_r <= {shift_result_r[OPTION_OPERAND_WIDTH-2:0],1'b0};
608
              else if (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_ROR)
609
                shift_result_r <= {shift_result_r[0]
610
                                   ,shift_result_r[OPTION_OPERAND_WIDTH-1:1]};
611
 
612
              else if (opc_alu_shr==`OR1K_ALU_OPC_SECONDARY_SHRT_SRA)
613
                shift_result_r <= {a[OPTION_OPERAND_WIDTH-1],
614
                                   shift_result_r[OPTION_OPERAND_WIDTH-1:1]};
615
           end // if (shift_go && !(shift_cnt==b[4:0]))
616
 
617
         assign shift_valid = (shift_cnt==b[4:0]) & shift_go & !decode_valid_i;
618
 
619
         assign shift_result = shift_result_r;
620
 
621
      end // if (OPTION_SHIFTER=="SERIAL")
622
      else
623
         initial begin
624
            $display("%m: Error - chosen shifter implementation (%s) not available",
625
                     OPTION_SHIFTER);
626
            $finish;
627
 
628
      end
629
   endgenerate
630
 
631
   // Conditional move
632
   generate
633
      /* verilator lint_off WIDTH */
634
      if (FEATURE_CMOV=="ENABLED") begin
635
      /* verilator lint_on WIDTH */
636
         assign cmov_result = flag_i ? a : b;
637
      end
638
   endgenerate
639
 
640
   // Comparison logic
641
   assign flag_set_o = flag_set & op_setflag_i;
642
   assign flag_clear_o = !flag_set & op_setflag_i;
643
 
644
   // Combinatorial block
645
   always @*
646
     case(opc_alu_secondary_i)
647
       `OR1K_COMP_OPC_EQ:
648
         flag_set = a_eq_b;
649
       `OR1K_COMP_OPC_NE:
650
         flag_set = !a_eq_b;
651
       `OR1K_COMP_OPC_GTU:
652
         flag_set = !(a_eq_b | a_ltu_b);
653
       `OR1K_COMP_OPC_GTS:
654
         flag_set = !(a_eq_b | a_lts_b);
655
       `OR1K_COMP_OPC_GEU:
656
         flag_set = !a_ltu_b;
657
       `OR1K_COMP_OPC_GES:
658
         flag_set = !a_lts_b;
659
       `OR1K_COMP_OPC_LTU:
660
         flag_set = a_ltu_b;
661
       `OR1K_COMP_OPC_LTS:
662
         flag_set = a_lts_b;
663
       `OR1K_COMP_OPC_LEU:
664
         flag_set = a_eq_b | a_ltu_b;
665
       `OR1K_COMP_OPC_LES:
666
         flag_set = a_eq_b | a_lts_b;
667
       default:
668
         flag_set = 0;
669
     endcase // case (opc_alu_secondary_i)
670
 
671
   //
672
   // Logic operations
673
   //
674
   // Create a look-up-table for AND/OR/XOR
675
   reg [3:0] logic_lut;
676
   always @(*) begin
677
     case(opc_alu_i)
678
       `OR1K_ALU_OPC_AND:
679
         logic_lut = 4'b1000;
680
       `OR1K_ALU_OPC_OR:
681
         logic_lut = 4'b1110;
682
       `OR1K_ALU_OPC_XOR:
683
         logic_lut = 4'b0110;
684
       default:
685
         logic_lut = 0;
686
     endcase
687
      if (!op_alu_i)
688
        logic_lut = 0;
689
      // Threat mfspr/mtspr as 'OR'
690
      if (op_mfspr_i | op_mtspr_i)
691
        logic_lut = 4'b1110;
692
   end
693
 
694
   // Extract the result, bit-for-bit, from the look-up-table
695
   integer i;
696
   always @(*)
697
     for (i = 0; i < OPTION_OPERAND_WIDTH; i=i+1) begin
698
        logic_result[i] = logic_lut[{a[i], b[i]}];
699
     end
700
 
701
   assign op_logic = |logic_lut;
702
 
703
   assign op_cmov = op_alu_i & opc_alu_i == `OR1K_ALU_OPC_CMOV;
704
 
705
   // Result muxing - result is registered in RF
706
   assign alu_result_o = op_logic ? logic_result :
707
                         op_cmov ? cmov_result :
708
                         op_movhi_i ? immediate_i :
709
                         op_mul_i ? mul_result[OPTION_OPERAND_WIDTH-1:0] :
710
                         op_shift_i ? shift_result :
711
                         op_div_i ? div_result :
712
                         op_ffl1_i ? ffl1_result :
713
                         adder_result;
714
 
715
   // Carry and overflow flag generation
716
   assign overflow_set_o = FEATURE_OVERFLOW!="NONE" &
717
                           (op_add_i & adder_signed_overflow |
718
                            op_mul_signed_i & mul_signed_overflow |
719
                            op_div_signed_i & div_by_zero);
720
 
721
   assign overflow_clear_o = FEATURE_OVERFLOW!="NONE" &
722
                             (op_add_i & !adder_signed_overflow |
723
                              op_mul_signed_i & !mul_signed_overflow |
724
                              op_div_signed_i & !div_by_zero);
725
 
726
   assign carry_set_o = FEATURE_CARRY_FLAG!="NONE" &
727
                        (op_add_i & adder_unsigned_overflow |
728
                         op_mul_unsigned_i & mul_unsigned_overflow |
729
                         op_div_unsigned_i & div_by_zero);
730
 
731
   assign carry_clear_o = FEATURE_CARRY_FLAG!="NONE" &
732
                          (op_add_i & !adder_unsigned_overflow |
733
                           op_mul_unsigned_i & !mul_unsigned_overflow |
734
                           op_div_unsigned_i & !div_by_zero);
735
 
736
   // Stall logic for multicycle ALU operations
737
   assign alu_stall = op_div_i & !div_valid |
738
                      op_mul_i & !mul_valid |
739
                      op_shift_i & !shift_valid |
740
                      op_ffl1_i & !ffl1_valid;
741
 
742
   assign alu_valid_o = !alu_stall;
743
 
744
endmodule // mor1kx_execute_alu

powered by: WebSVN 2.1.0

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