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-5.0/] [rtl/] [verilog/] [mor1kx_execute_alu.v] - Blame information for rev 48

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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