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_lsu_cappuccino.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:  Data bus interface
8
 
9
  All combinatorial outputs to pipeline
10
  Dbus interface request signal out synchronous
11
 
12
  32-bit specific
13
 
14
  Copyright (C) 2012 Julius Baxter <juliusbaxter@gmail.com>
15
  Copyright (C) 2013 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
16
 
17
***************************************************************************** */
18
 
19
`include "mor1kx-defines.v"
20
 
21
module mor1kx_lsu_cappuccino
22
  #(
23
    parameter FEATURE_DATACACHE = "NONE",
24
    parameter OPTION_OPERAND_WIDTH = 32,
25
    parameter OPTION_DCACHE_BLOCK_WIDTH = 5,
26
    parameter OPTION_DCACHE_SET_WIDTH = 9,
27
    parameter OPTION_DCACHE_WAYS = 2,
28
    parameter OPTION_DCACHE_LIMIT_WIDTH = 32,
29
    parameter OPTION_DCACHE_SNOOP = "NONE",
30
    parameter FEATURE_DMMU = "NONE",
31
    parameter FEATURE_DMMU_HW_TLB_RELOAD = "NONE",
32
    parameter OPTION_DMMU_SET_WIDTH = 6,
33
    parameter OPTION_DMMU_WAYS = 1,
34
    parameter FEATURE_STORE_BUFFER = "ENABLED",
35
    parameter OPTION_STORE_BUFFER_DEPTH_WIDTH = 8,
36
    parameter FEATURE_ATOMIC = "ENABLED"
37
    )
38
   (
39
    input                             clk,
40
    input                             rst,
41
 
42
    input                             padv_execute_i,
43
    input                             padv_ctrl_i, // needed for dmmu spr
44
    input                             decode_valid_i,
45
    // calculated address from ALU
46
    input [OPTION_OPERAND_WIDTH-1:0]  exec_lsu_adr_i,
47
    input [OPTION_OPERAND_WIDTH-1:0]  ctrl_lsu_adr_i,
48
 
49
    // register file B in (store operand)
50
    input [OPTION_OPERAND_WIDTH-1:0]  ctrl_rfb_i,
51
 
52
    // from decode stage regs, indicate if load or store
53
    input                             exec_op_lsu_load_i,
54
    input                             exec_op_lsu_store_i,
55
    input                             exec_op_lsu_atomic_i,
56
    input                             ctrl_op_lsu_load_i,
57
    input                             ctrl_op_lsu_store_i,
58
    input                             ctrl_op_lsu_atomic_i,
59
    input [1:0]                ctrl_lsu_length_i,
60
    input                             ctrl_lsu_zext_i,
61
 
62
    // From control stage, exception PC for the store buffer input
63
    input [OPTION_OPERAND_WIDTH-1:0]  ctrl_epcr_i,
64
    // The exception PC as it has went through the store buffer
65
    output [OPTION_OPERAND_WIDTH-1:0] store_buffer_epcr_o,
66
 
67
    output [OPTION_OPERAND_WIDTH-1:0] lsu_result_o,
68
    output                            lsu_valid_o,
69
    // exception output
70
    output                            lsu_except_dbus_o,
71
    output                            lsu_except_align_o,
72
    output                            lsu_except_dtlb_miss_o,
73
    output                            lsu_except_dpagefault_o,
74
 
75
    // Indicator that the dbus exception came via the store buffer
76
    output reg                        store_buffer_err_o,
77
 
78
    // Atomic operation flag set/clear logic
79
    output                            atomic_flag_set_o,
80
    output                            atomic_flag_clear_o,
81
 
82
    // SPR interface
83
    input [15:0]                       spr_bus_addr_i,
84
    input                             spr_bus_we_i,
85
    input                             spr_bus_stb_i,
86
    input [OPTION_OPERAND_WIDTH-1:0]  spr_bus_dat_i,
87
    output [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dc_o,
88
    output                            spr_bus_ack_dc_o,
89
    output [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_dmmu_o,
90
    output                            spr_bus_ack_dmmu_o,
91
 
92
    input                             dc_enable_i,
93
    input                             dmmu_enable_i,
94
    input                             supervisor_mode_i,
95
 
96
    // interface to data bus
97
    output [OPTION_OPERAND_WIDTH-1:0] dbus_adr_o,
98
    output reg                        dbus_req_o,
99
    output [OPTION_OPERAND_WIDTH-1:0] dbus_dat_o,
100
    output reg [3:0]                   dbus_bsel_o,
101
    output                            dbus_we_o,
102
    output                            dbus_burst_o,
103
    input                             dbus_err_i,
104
    input                             dbus_ack_i,
105
    input [OPTION_OPERAND_WIDTH-1:0]  dbus_dat_i,
106
    input                             pipeline_flush_i,
107
 
108
    input [31:0]                       snoop_adr_i,
109
    input                             snoop_en_i
110
    );
111
 
112
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_dat_aligned;  // comb.
113
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_dat_extended; // comb.
114
 
115
   reg                               access_done;
116
 
117
   wire                              align_err_word;
118
   wire                              align_err_short;
119
 
120
   wire                              align_err;
121
 
122
   wire                              except_align;
123
 
124
   reg                               except_dbus;
125
 
126
   reg                               dbus_ack;
127
   reg                               dbus_err;
128
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_dat;
129
   reg [OPTION_OPERAND_WIDTH-1:0]    dbus_adr;
130
   wire [OPTION_OPERAND_WIDTH-1:0]   next_dbus_adr;
131
   reg                               dbus_we;
132
   reg [3:0]                          dbus_bsel;
133
   wire                              dbus_access;
134
   wire                              dbus_stall;
135
 
136
   wire [OPTION_OPERAND_WIDTH-1:0]   lsu_ldat;
137
   wire [OPTION_OPERAND_WIDTH-1:0]   lsu_sdat;
138
   wire                              lsu_ack;
139
 
140
   wire                              dc_err;
141
   wire                              dc_ack;
142
   wire [31:0]                        dc_ldat;
143
   wire [31:0]                        dc_sdat;
144
   wire [31:0]                        dc_adr;
145
   wire [31:0]                        dc_adr_match;
146
   wire                              dc_req;
147
   wire                              dc_we;
148
   wire [3:0]                         dc_bsel;
149
 
150
   wire                              dc_access;
151
   wire                              dc_refill_allowed;
152
   wire                              dc_refill;
153
   wire                              dc_refill_req;
154
   wire                              dc_refill_done;
155
 
156
   reg                               dc_enable_r;
157
   wire                              dc_enabled;
158
 
159
   wire                              ctrl_op_lsu;
160
 
161
   // DMMU
162
   wire                              tlb_miss;
163
   wire                              pagefault;
164
   wire [OPTION_OPERAND_WIDTH-1:0]   dmmu_phys_addr;
165
   wire                              except_dtlb_miss;
166
   reg                               except_dtlb_miss_r;
167
   wire                              except_dpagefault;
168
   reg                               except_dpagefault_r;
169
   wire                              dmmu_cache_inhibit;
170
 
171
   wire                              tlb_reload_req;
172
   wire                              tlb_reload_busy;
173
   wire [OPTION_OPERAND_WIDTH-1:0]   tlb_reload_addr;
174
   wire                              tlb_reload_pagefault;
175
   reg                               tlb_reload_ack;
176
   reg [OPTION_OPERAND_WIDTH-1:0]    tlb_reload_data;
177
   wire                              tlb_reload_pagefault_clear;
178
   reg                               tlb_reload_done;
179
 
180
   // Store buffer
181
   wire                              store_buffer_write;
182
   wire                              store_buffer_read;
183
   wire                              store_buffer_full;
184
   wire                              store_buffer_empty;
185
   wire [OPTION_OPERAND_WIDTH-1:0]   store_buffer_radr;
186
   wire [OPTION_OPERAND_WIDTH-1:0]   store_buffer_wadr;
187
   wire [OPTION_OPERAND_WIDTH-1:0]   store_buffer_dat;
188
   wire [OPTION_OPERAND_WIDTH/8-1:0] store_buffer_bsel;
189
   wire                              store_buffer_atomic;
190
   reg                               store_buffer_write_pending;
191
 
192
   reg                               dbus_atomic;
193
 
194
   reg                               last_write;
195
   reg                               write_done;
196
 
197
   // Atomic operations
198
   reg [OPTION_OPERAND_WIDTH-1:0]    atomic_addr;
199
   reg                               atomic_reserve;
200
   wire                              swa_success;
201
 
202
   wire                              snoop_valid;
203
   wire                              dc_snoop_hit;
204
 
205
   // We have to mask out our snooped bus accesses
206
   assign snoop_valid = snoop_en_i &
207
                        !((snoop_adr_i == dbus_adr_o) & dbus_ack_i);
208
 
209
   assign ctrl_op_lsu = ctrl_op_lsu_load_i | ctrl_op_lsu_store_i;
210
 
211
   assign lsu_sdat = (ctrl_lsu_length_i == 2'b00) ? // byte access
212
                     {ctrl_rfb_i[7:0],ctrl_rfb_i[7:0],
213
                      ctrl_rfb_i[7:0],ctrl_rfb_i[7:0]} :
214
                     (ctrl_lsu_length_i == 2'b01) ? // halfword access
215
                     {ctrl_rfb_i[15:0],ctrl_rfb_i[15:0]} :
216
                     ctrl_rfb_i;                    // word access
217
 
218
   assign align_err_word = |ctrl_lsu_adr_i[1:0];
219
   assign align_err_short = ctrl_lsu_adr_i[0];
220
 
221
 
222
   assign lsu_valid_o = (lsu_ack | access_done) & !tlb_reload_busy & !dc_snoop_hit;
223
 
224
   assign lsu_except_dbus_o = except_dbus | store_buffer_err_o;
225
 
226
   assign align_err = (ctrl_lsu_length_i == 2'b10) & align_err_word |
227
                      (ctrl_lsu_length_i == 2'b01) & align_err_short;
228
 
229
   assign except_align = ctrl_op_lsu & align_err;
230
 
231
   assign lsu_except_align_o = except_align & !pipeline_flush_i;
232
 
233
   assign except_dtlb_miss = ctrl_op_lsu & tlb_miss & dmmu_enable_i &
234
                             !tlb_reload_busy;
235
 
236
   assign lsu_except_dtlb_miss_o = except_dtlb_miss & !pipeline_flush_i;
237
 
238
   assign except_dpagefault = ctrl_op_lsu & pagefault & dmmu_enable_i &
239
                              !tlb_reload_busy | tlb_reload_pagefault;
240
 
241
   assign lsu_except_dpagefault_o = except_dpagefault & !pipeline_flush_i;
242
 
243
 
244
   always @(posedge clk `OR_ASYNC_RST)
245
     if (rst)
246
       access_done <= 0;
247
     else if (padv_execute_i)
248
       access_done <= 0;
249
     else if (lsu_ack)
250
       access_done <= 1;
251
 
252
   always @(posedge clk `OR_ASYNC_RST)
253
     if (rst)
254
       except_dbus <= 0;
255
     else if (padv_execute_i | pipeline_flush_i)
256
       except_dbus <= 0;
257
     else if (dbus_err_i)
258
       except_dbus <= 1;
259
 
260
   always @(posedge clk `OR_ASYNC_RST)
261
     if (rst)
262
       except_dtlb_miss_r <= 0;
263
     else if (padv_execute_i)
264
       except_dtlb_miss_r <= 0;
265
     else if (except_dtlb_miss)
266
       except_dtlb_miss_r <= 1;
267
 
268
   always @(posedge clk `OR_ASYNC_RST)
269
     if (rst)
270
       except_dpagefault_r <= 0;
271
     else if (padv_execute_i)
272
       except_dpagefault_r <= 0;
273
     else if (except_dpagefault)
274
       except_dpagefault_r <= 1;
275
 
276
   always @(posedge clk `OR_ASYNC_RST)
277
     if (rst)
278
       store_buffer_err_o <= 0;
279
     else if (pipeline_flush_i)
280
       store_buffer_err_o <= 0;
281
     else if (dbus_err_i & dbus_we_o)
282
       store_buffer_err_o <= 1;
283
 
284
   // Big endian bus mapping
285
   always @(*)
286
     case (ctrl_lsu_length_i)
287
       2'b00: // byte access
288
         case(ctrl_lsu_adr_i[1:0])
289
           2'b00:
290
             dbus_bsel = 4'b1000;
291
           2'b01:
292
             dbus_bsel = 4'b0100;
293
           2'b10:
294
             dbus_bsel = 4'b0010;
295
           2'b11:
296
             dbus_bsel = 4'b0001;
297
         endcase
298
       2'b01: // halfword access
299
            case(ctrl_lsu_adr_i[1])
300
              1'b0:
301
                dbus_bsel = 4'b1100;
302
              1'b1:
303
                dbus_bsel = 4'b0011;
304
            endcase
305
       2'b10,
306
       2'b11:
307
         dbus_bsel = 4'b1111;
308
     endcase
309
 
310
   // Select part of read word
311
   always @*
312
     case(ctrl_lsu_adr_i[1:0])
313
       2'b00:
314
         dbus_dat_aligned = lsu_ldat;
315
       2'b01:
316
         dbus_dat_aligned = {lsu_ldat[23:0],8'd0};
317
       2'b10:
318
         dbus_dat_aligned = {lsu_ldat[15:0],16'd0};
319
       2'b11:
320
         dbus_dat_aligned = {lsu_ldat[7:0],24'd0};
321
     endcase // case (ctrl_lsu_adr_i[1:0])
322
 
323
   // Do appropriate extension
324
   always @(*)
325
     case({ctrl_lsu_zext_i, ctrl_lsu_length_i})
326
       3'b100: // lbz
327
         dbus_dat_extended = {24'd0,dbus_dat_aligned[31:24]};
328
       3'b101: // lhz
329
         dbus_dat_extended = {16'd0,dbus_dat_aligned[31:16]};
330
       3'b000: // lbs
331
         dbus_dat_extended = {{24{dbus_dat_aligned[31]}},
332
                              dbus_dat_aligned[31:24]};
333
       3'b001: // lhs
334
         dbus_dat_extended = {{16{dbus_dat_aligned[31]}},
335
                              dbus_dat_aligned[31:16]};
336
       default:
337
         dbus_dat_extended = dbus_dat_aligned;
338
     endcase
339
 
340
   assign lsu_result_o = dbus_dat_extended;
341
 
342
   // Bus access logic
343
   localparam [2:0]
344
     IDLE               = 3'd0,
345
     READ               = 3'd1,
346
     WRITE              = 3'd2,
347
     TLB_RELOAD         = 3'd3,
348
     DC_REFILL          = 3'd4;
349
 
350
   reg [2:0] state;
351
 
352
   assign dbus_access = (!dc_access | tlb_reload_busy | ctrl_op_lsu_store_i) &
353
                        (state != DC_REFILL) | (state == WRITE);
354
   reg      dc_refill_r;
355
 
356
   always @(posedge clk)
357
     dc_refill_r <= dc_refill;
358
 
359
   wire     store_buffer_ack;
360
   assign store_buffer_ack = (FEATURE_STORE_BUFFER!="NONE") ?
361
                             store_buffer_write :
362
                             write_done;
363
 
364
   assign lsu_ack = (ctrl_op_lsu_store_i | state == WRITE) ?
365
                    (store_buffer_ack & !ctrl_op_lsu_atomic_i |
366
                     write_done & ctrl_op_lsu_atomic_i) :
367
                    (dbus_access ? dbus_ack : dc_ack);
368
 
369
   assign lsu_ldat = dbus_access ? dbus_dat : dc_ldat;
370
   assign dbus_adr_o = dbus_adr;
371
 
372
   assign dbus_dat_o = dbus_dat;
373
 
374
   assign dbus_burst_o = (state == DC_REFILL) & !dc_refill_done;
375
 
376
   //
377
   // Slightly subtle, but if there is an atomic store coming out from the
378
   // store buffer, and the link has been broken while it was waiting there,
379
   // the bus access is still performed as a (discarded) read.
380
   //
381
   assign dbus_we_o = dbus_we & (!dbus_atomic | atomic_reserve);
382
 
383
   assign next_dbus_adr = (OPTION_DCACHE_BLOCK_WIDTH == 5) ?
384
                          {dbus_adr[31:5], dbus_adr[4:0] + 5'd4} : // 32 byte
385
                          {dbus_adr[31:4], dbus_adr[3:0] + 4'd4};  // 16 byte
386
 
387
   always @(posedge clk `OR_ASYNC_RST)
388
     if (rst)
389
       dbus_err <= 0;
390
     else
391
       dbus_err <= dbus_err_i;
392
 
393
   always @(posedge clk) begin
394
      dbus_ack <= 0;
395
      write_done <= 0;
396
      tlb_reload_ack <= 0;
397
      tlb_reload_done <= 0;
398
      case (state)
399
        IDLE: begin
400
           dbus_req_o <= 0;
401
           dbus_we <= 0;
402
           dbus_adr <= 0;
403
           dbus_bsel_o <= 4'hf;
404
           dbus_atomic <= 0;
405
           last_write <= 0;
406
           if (store_buffer_write | !store_buffer_empty) begin
407
              state <= WRITE;
408
           end else if (ctrl_op_lsu & dbus_access & !dc_refill & !dbus_ack &
409
                        !dbus_err & !except_dbus & !access_done &
410
                        !pipeline_flush_i) begin
411
              if (tlb_reload_req) begin
412
                 dbus_adr <= tlb_reload_addr;
413
                 dbus_req_o <= 1;
414
                 state <= TLB_RELOAD;
415
              end else if (dmmu_enable_i) begin
416
                 dbus_adr <= dmmu_phys_addr;
417
                 if (!tlb_miss & !pagefault & !except_align) begin
418
                    if (ctrl_op_lsu_load_i) begin
419
                       dbus_req_o <= 1;
420
                       dbus_bsel_o <= dbus_bsel;
421
                       state <= READ;
422
                    end
423
                 end
424
              end else if (!except_align) begin
425
                 dbus_adr <= ctrl_lsu_adr_i;
426
                 if (ctrl_op_lsu_load_i) begin
427
                    dbus_req_o <= 1;
428
                    dbus_bsel_o <= dbus_bsel;
429
                    state <= READ;
430
                 end
431
              end
432
           end else if (dc_refill_req) begin
433
              dbus_req_o <= 1;
434
              dbus_adr <= dc_adr_match;
435
              state <= DC_REFILL;
436
           end
437
        end
438
 
439
        DC_REFILL: begin
440
           dbus_req_o <= 1;
441
           if (dbus_ack_i) begin
442
              dbus_adr <= next_dbus_adr;
443
              if (dc_refill_done) begin
444
                 dbus_req_o <= 0;
445
                 state <= IDLE;
446
              end
447
           end
448
 
449
           // TODO: only abort on snoop-hits to refill address
450
           if (dbus_err_i | dc_snoop_hit) begin
451
              dbus_req_o <= 0;
452
              state <= IDLE;
453
           end
454
        end
455
 
456
        READ: begin
457
           dbus_ack <= dbus_ack_i;
458
           dbus_dat <= dbus_dat_i;
459
           if (dbus_ack_i | dbus_err_i) begin
460
              dbus_req_o <= 0;
461
              state <= IDLE;
462
           end
463
        end
464
 
465
        WRITE: begin
466
           dbus_req_o <= 1;
467
           dbus_we <= 1;
468
 
469
           if (!dbus_req_o | dbus_ack_i & !last_write) begin
470
              dbus_bsel_o <= store_buffer_bsel;
471
              dbus_adr <= store_buffer_radr;
472
              dbus_dat <= store_buffer_dat;
473
              dbus_atomic <= store_buffer_atomic;
474
              last_write <= store_buffer_empty;
475
           end
476
 
477
           if (store_buffer_write)
478
             last_write <= 0;
479
 
480
           if (last_write & dbus_ack_i | dbus_err_i) begin
481
              dbus_req_o <= 0;
482
              dbus_we <= 0;
483
              if (!store_buffer_write) begin
484
                 state <= IDLE;
485
                 write_done <= 1;
486
              end
487
           end
488
        end
489
 
490
        TLB_RELOAD: begin
491
           dbus_adr <= tlb_reload_addr;
492
           tlb_reload_data <= dbus_dat_i;
493
           tlb_reload_ack <= dbus_ack_i & tlb_reload_req;
494
 
495
           if (!tlb_reload_req | dbus_err_i) begin
496
              state <= IDLE;
497
              tlb_reload_done <= 1;
498
           end
499
 
500
           dbus_req_o <= tlb_reload_req;
501
           if (dbus_ack_i | tlb_reload_ack)
502
             dbus_req_o <= 0;
503
        end
504
 
505
        default:
506
          state <= IDLE;
507
      endcase
508
 
509
      if (rst)
510
        state <= IDLE;
511
   end
512
 
513
   assign dbus_stall = tlb_reload_busy | except_align | except_dbus |
514
                       except_dtlb_miss | except_dpagefault |
515
                       pipeline_flush_i;
516
 
517
generate
518
if (FEATURE_ATOMIC!="NONE") begin : atomic_gen
519
   // Atomic operations logic
520
   reg atomic_flag_set;
521
   reg atomic_flag_clear;
522
 
523
   always @(posedge clk `OR_ASYNC_RST)
524
     if (rst)
525
       atomic_reserve <= 0;
526
     else if (pipeline_flush_i)
527
       atomic_reserve <= 0;
528
     else if (ctrl_op_lsu_store_i & ctrl_op_lsu_atomic_i & write_done ||
529
              !ctrl_op_lsu_atomic_i & store_buffer_write &
530
              (store_buffer_wadr == atomic_addr) ||
531
              (snoop_valid & (snoop_adr_i == atomic_addr)))
532
       atomic_reserve <= 0;
533
     else if (ctrl_op_lsu_load_i & ctrl_op_lsu_atomic_i & padv_ctrl_i)
534
       atomic_reserve <= !(snoop_valid & (snoop_adr_i == dc_adr_match));
535
 
536
   always @(posedge clk)
537
     if (ctrl_op_lsu_load_i & ctrl_op_lsu_atomic_i & padv_ctrl_i)
538
       atomic_addr <= dc_adr_match;
539
 
540
   assign swa_success = ctrl_op_lsu_store_i & ctrl_op_lsu_atomic_i &
541
                        atomic_reserve & (dbus_adr == atomic_addr);
542
 
543
   always @(posedge clk)
544
     if (padv_ctrl_i)
545
       atomic_flag_set <= 0;
546
     else if (write_done)
547
       atomic_flag_set <= swa_success & lsu_valid_o;
548
 
549
   always @(posedge clk)
550
     if (padv_ctrl_i)
551
       atomic_flag_clear <= 0;
552
     else if (write_done)
553
       atomic_flag_clear <= !swa_success & lsu_valid_o &
554
                            ctrl_op_lsu_atomic_i & ctrl_op_lsu_store_i;
555
 
556
   assign atomic_flag_set_o = atomic_flag_set;
557
   assign atomic_flag_clear_o = atomic_flag_clear;
558
 
559
end else begin
560
   assign atomic_flag_set_o = 0;
561
   assign atomic_flag_clear_o = 0;
562
   assign swa_success = 0;
563
   always @(posedge clk) begin
564
      atomic_addr <= 0;
565
      atomic_reserve <= 0;
566
   end
567
end
568
endgenerate
569
 
570
   // Store buffer logic
571
   always @(posedge clk)
572
     if (rst)
573
       store_buffer_write_pending <= 0;
574
     else if (store_buffer_write | pipeline_flush_i)
575
       store_buffer_write_pending <= 0;
576
     else if (ctrl_op_lsu_store_i & padv_ctrl_i & !dbus_stall &
577
              (store_buffer_full | dc_refill | dc_refill_r | dc_snoop_hit))
578
       store_buffer_write_pending <= 1;
579
 
580
   assign store_buffer_write = (ctrl_op_lsu_store_i &
581
                                (padv_ctrl_i | tlb_reload_done) |
582
                                store_buffer_write_pending) &
583
                               !store_buffer_full & !dc_refill & !dc_refill_r &
584
                               !dbus_stall & !dc_snoop_hit;
585
 
586
generate
587
if (FEATURE_STORE_BUFFER!="NONE") begin : store_buffer_gen
588
   assign store_buffer_read = (state == IDLE) & store_buffer_write |
589
                              (state == IDLE) & !store_buffer_empty |
590
                              (state == WRITE) & (dbus_ack_i | !dbus_req_o) &
591
                              (!store_buffer_empty | store_buffer_write) &
592
                              !last_write |
593
                              (state == WRITE) & last_write &
594
                              store_buffer_write;
595
 
596
   mor1kx_store_buffer
597
     #(
598
       .DEPTH_WIDTH(OPTION_STORE_BUFFER_DEPTH_WIDTH),
599
       .OPTION_OPERAND_WIDTH(OPTION_OPERAND_WIDTH)
600
       )
601
   mor1kx_store_buffer
602
     (
603
      .clk      (clk),
604
      .rst      (rst),
605
 
606
      .pc_i     (ctrl_epcr_i),
607
      .adr_i    (store_buffer_wadr),
608
      .dat_i    (lsu_sdat),
609
      .bsel_i   (dbus_bsel),
610
      .atomic_i (ctrl_op_lsu_atomic_i),
611
      .write_i  (store_buffer_write),
612
 
613
      .pc_o     (store_buffer_epcr_o),
614
      .adr_o    (store_buffer_radr),
615
      .dat_o    (store_buffer_dat),
616
      .bsel_o   (store_buffer_bsel),
617
      .atomic_o (store_buffer_atomic),
618
      .read_i   (store_buffer_read),
619
 
620
      .full_o   (store_buffer_full),
621
      .empty_o  (store_buffer_empty)
622
      );
623
end else begin
624
   assign store_buffer_epcr_o = ctrl_epcr_i;
625
   assign store_buffer_radr = store_buffer_wadr;
626
   assign store_buffer_dat = lsu_sdat;
627
   assign store_buffer_bsel = dbus_bsel;
628
   assign store_buffer_empty = 1'b1;
629
 
630
   reg store_buffer_full_r;
631
   always @(posedge clk)
632
     if (store_buffer_write)
633
       store_buffer_full_r <= 1;
634
     else if (write_done)
635
       store_buffer_full_r <= 0;
636
 
637
   assign store_buffer_full = store_buffer_full_r & !write_done;
638
end
639
endgenerate
640
   assign store_buffer_wadr = dc_adr_match;
641
 
642
   always @(posedge clk `OR_ASYNC_RST)
643
     if (rst)
644
       dc_enable_r <= 0;
645
     else if (dc_enable_i & !dbus_req_o)
646
       dc_enable_r <= 1;
647
     else if (!dc_enable_i & !dc_refill)
648
       dc_enable_r <= 0;
649
 
650
   assign dc_enabled = dc_enable_i & dc_enable_r;
651
   assign dc_adr = padv_execute_i &
652
                   (exec_op_lsu_load_i | exec_op_lsu_store_i) ?
653
                   exec_lsu_adr_i : ctrl_lsu_adr_i;
654
   assign dc_adr_match = dmmu_enable_i ?
655
                         {dmmu_phys_addr[OPTION_OPERAND_WIDTH-1:2],2'b0} :
656
                         {ctrl_lsu_adr_i[OPTION_OPERAND_WIDTH-1:2],2'b0};
657
 
658
   assign dc_req = ctrl_op_lsu & dc_access & !access_done & !dbus_stall &
659
                   !(dbus_atomic & dbus_we & !atomic_reserve);
660
   assign dc_refill_allowed = !(ctrl_op_lsu_store_i | state == WRITE) &
661
                              !dc_snoop_hit & !snoop_valid;
662
 
663
generate
664
if (FEATURE_DATACACHE!="NONE") begin : dcache_gen
665
   if (OPTION_DCACHE_LIMIT_WIDTH == OPTION_OPERAND_WIDTH) begin
666
      assign dc_access =  ctrl_op_lsu_store_i | dc_enabled &
667
                         !(dmmu_cache_inhibit & dmmu_enable_i);
668
   end else if (OPTION_DCACHE_LIMIT_WIDTH < OPTION_OPERAND_WIDTH) begin
669
      assign dc_access = ctrl_op_lsu_store_i | dc_enabled &
670
                         dc_adr_match[OPTION_OPERAND_WIDTH-1:
671
                                      OPTION_DCACHE_LIMIT_WIDTH] == 0 &
672
                         !(dmmu_cache_inhibit & dmmu_enable_i);
673
   end else begin
674
      initial begin
675
         $display("ERROR: OPTION_DCACHE_LIMIT_WIDTH > OPTION_OPERAND_WIDTH");
676
         $finish();
677
      end
678
   end
679
 
680
   wire dc_rst = rst | dbus_err;
681
 
682
   assign dc_bsel = dbus_bsel;
683
   assign dc_we = exec_op_lsu_store_i & !exec_op_lsu_atomic_i & padv_execute_i |
684
                  dbus_atomic & dbus_we_o & !write_done |
685
                  ctrl_op_lsu_store_i & tlb_reload_busy & !tlb_reload_req;
686
 
687
   /* mor1kx_dcache AUTO_TEMPLATE (
688
            .refill_o                   (dc_refill),
689
            .refill_req_o               (dc_refill_req),
690
            .refill_done_o              (dc_refill_done),
691
            .cpu_err_o                  (dc_err),
692
            .cpu_ack_o                  (dc_ack),
693
            .cpu_dat_o                  (dc_ldat),
694
            .spr_bus_dat_o              (spr_bus_dat_dc_o),
695
            .spr_bus_ack_o              (spr_bus_ack_dc_o),
696
            .snoop_hit_o                (dc_snoop_hit),
697
            // Inputs
698
            .clk                        (clk),
699
            .rst                        (dc_rst),
700
            .dc_enable_i                (dc_enabled),
701
            .dc_access_i                (dc_access),
702
            .cpu_dat_i                  (lsu_sdat),
703
            .cpu_adr_i                  (dc_adr),
704
            .cpu_adr_match_i            (dc_adr_match),
705
            .cpu_req_i                  (dc_req),
706
            .cpu_we_i                   (dc_we),
707
            .cpu_bsel_i                 (dc_bsel),
708
            .refill_allowed             (dc_refill_allowed),
709
            .wradr_i                    (dbus_adr),
710
            .wrdat_i                    (dbus_dat_i),
711
            .we_i                       (dbus_ack_i),
712
            .snoop_valid_i              (snoop_valid),
713
    );*/
714
 
715
   mor1kx_dcache
716
     #(
717
       .OPTION_OPERAND_WIDTH(OPTION_OPERAND_WIDTH),
718
       .OPTION_DCACHE_BLOCK_WIDTH(OPTION_DCACHE_BLOCK_WIDTH),
719
       .OPTION_DCACHE_SET_WIDTH(OPTION_DCACHE_SET_WIDTH),
720
       .OPTION_DCACHE_WAYS(OPTION_DCACHE_WAYS),
721
       .OPTION_DCACHE_LIMIT_WIDTH(OPTION_DCACHE_LIMIT_WIDTH),
722
       .OPTION_DCACHE_SNOOP(OPTION_DCACHE_SNOOP)
723
       )
724
   mor1kx_dcache
725
           (/*AUTOINST*/
726
            // Outputs
727
            .refill_o                   (dc_refill),             // Templated
728
            .refill_req_o               (dc_refill_req),         // Templated
729
            .refill_done_o              (dc_refill_done),        // Templated
730
            .cpu_err_o                  (dc_err),                // Templated
731
            .cpu_ack_o                  (dc_ack),                // Templated
732
            .cpu_dat_o                  (dc_ldat),               // Templated
733
            .snoop_hit_o                (dc_snoop_hit),          // Templated
734
            .spr_bus_dat_o              (spr_bus_dat_dc_o),      // Templated
735
            .spr_bus_ack_o              (spr_bus_ack_dc_o),      // Templated
736
            // Inputs
737
            .clk                        (clk),                   // Templated
738
            .rst                        (dc_rst),                // Templated
739
            .dc_enable_i                (dc_enabled),            // Templated
740
            .dc_access_i                (dc_access),             // Templated
741
            .cpu_dat_i                  (lsu_sdat),              // Templated
742
            .cpu_adr_i                  (dc_adr),                // Templated
743
            .cpu_adr_match_i            (dc_adr_match),          // Templated
744
            .cpu_req_i                  (dc_req),                // Templated
745
            .cpu_we_i                   (dc_we),                 // Templated
746
            .cpu_bsel_i                 (dc_bsel),               // Templated
747
            .refill_allowed             (dc_refill_allowed),     // Templated
748
            .wradr_i                    (dbus_adr),              // Templated
749
            .wrdat_i                    (dbus_dat_i),            // Templated
750
            .we_i                       (dbus_ack_i),            // Templated
751
            .snoop_adr_i                (snoop_adr_i[31:0]),
752
            .snoop_valid_i              (snoop_valid),           // Templated
753
            .spr_bus_addr_i             (spr_bus_addr_i[15:0]),
754
            .spr_bus_we_i               (spr_bus_we_i),
755
            .spr_bus_stb_i              (spr_bus_stb_i),
756
            .spr_bus_dat_i              (spr_bus_dat_i[OPTION_OPERAND_WIDTH-1:0]));
757
end else begin
758
   assign dc_access = 0;
759
   assign dc_refill = 0;
760
   assign dc_refill_done = 0;
761
   assign dc_refill_req = 0;
762
   assign dc_err = 0;
763
   assign dc_ack = 0;
764
   assign dc_bsel = 0;
765
   assign dc_we = 0;
766
   assign dc_snoop_hit = 0;
767
end
768
 
769
endgenerate
770
 
771
generate
772
if (FEATURE_DMMU!="NONE") begin : dmmu_gen
773
   wire  [OPTION_OPERAND_WIDTH-1:0] virt_addr;
774
   wire                             dmmu_spr_bus_stb;
775
   wire                             dmmu_enable;
776
 
777
   assign virt_addr = dc_adr;
778
 
779
   // small hack to delay dmmu spr reads by one cycle
780
   // ideally the spr accesses should work so that the address is presented
781
   // in execute stage and the delayed data should be available in control
782
   // stage, but this is not how things currently work.
783
   assign dmmu_spr_bus_stb = spr_bus_stb_i & (!padv_ctrl_i | spr_bus_we_i);
784
 
785
   assign tlb_reload_pagefault_clear = !ctrl_op_lsu; // use pipeline_flush_i?
786
 
787
   assign dmmu_enable = dmmu_enable_i & !pipeline_flush_i;
788
 
789
   /* mor1kx_dmmu AUTO_TEMPLATE (
790
    .enable_i                           (dmmu_enable),
791
    .phys_addr_o                        (dmmu_phys_addr),
792
    .cache_inhibit_o                    (dmmu_cache_inhibit),
793
    .op_store_i                         (ctrl_op_lsu_store_i),
794
    .op_load_i                          (ctrl_op_lsu_load_i),
795
    .tlb_miss_o                         (tlb_miss),
796
    .pagefault_o                        (pagefault),
797
    .tlb_reload_req_o                   (tlb_reload_req),
798
    .tlb_reload_busy_o                  (tlb_reload_busy),
799
    .tlb_reload_addr_o                  (tlb_reload_addr),
800
    .tlb_reload_pagefault_o             (tlb_reload_pagefault),
801
    .tlb_reload_ack_i                   (tlb_reload_ack),
802
    .tlb_reload_data_i                  (tlb_reload_data),
803
    .tlb_reload_pagefault_clear_i       (tlb_reload_pagefault_clear),
804
    .spr_bus_dat_o                      (spr_bus_dat_dmmu_o),
805
    .spr_bus_ack_o                      (spr_bus_ack_dmmu_o),
806
    .spr_bus_stb_i                      (dmmu_spr_bus_stb),
807
    .virt_addr_i                        (virt_addr),
808
    .virt_addr_match_i                  (ctrl_lsu_adr_i),
809
    ); */
810
   mor1kx_dmmu
811
     #(
812
       .FEATURE_DMMU_HW_TLB_RELOAD(FEATURE_DMMU_HW_TLB_RELOAD),
813
       .OPTION_OPERAND_WIDTH(OPTION_OPERAND_WIDTH),
814
       .OPTION_DMMU_SET_WIDTH(OPTION_DMMU_SET_WIDTH),
815
       .OPTION_DMMU_WAYS(OPTION_DMMU_WAYS)
816
       )
817
   mor1kx_dmmu
818
     (/*AUTOINST*/
819
      // Outputs
820
      .phys_addr_o                      (dmmu_phys_addr),        // Templated
821
      .cache_inhibit_o                  (dmmu_cache_inhibit),    // Templated
822
      .tlb_miss_o                       (tlb_miss),              // Templated
823
      .pagefault_o                      (pagefault),             // Templated
824
      .tlb_reload_req_o                 (tlb_reload_req),        // Templated
825
      .tlb_reload_busy_o                (tlb_reload_busy),       // Templated
826
      .tlb_reload_addr_o                (tlb_reload_addr),       // Templated
827
      .tlb_reload_pagefault_o           (tlb_reload_pagefault),  // Templated
828
      .spr_bus_dat_o                    (spr_bus_dat_dmmu_o),    // Templated
829
      .spr_bus_ack_o                    (spr_bus_ack_dmmu_o),    // Templated
830
      // Inputs
831
      .clk                              (clk),
832
      .rst                              (rst),
833
      .enable_i                         (dmmu_enable),           // Templated
834
      .virt_addr_i                      (virt_addr),             // Templated
835
      .virt_addr_match_i                (ctrl_lsu_adr_i),        // Templated
836
      .op_store_i                       (ctrl_op_lsu_store_i),   // Templated
837
      .op_load_i                        (ctrl_op_lsu_load_i),    // Templated
838
      .supervisor_mode_i                (supervisor_mode_i),
839
      .tlb_reload_ack_i                 (tlb_reload_ack),        // Templated
840
      .tlb_reload_data_i                (tlb_reload_data),       // Templated
841
      .tlb_reload_pagefault_clear_i     (tlb_reload_pagefault_clear), // Templated
842
      .spr_bus_addr_i                   (spr_bus_addr_i[15:0]),
843
      .spr_bus_we_i                     (spr_bus_we_i),
844
      .spr_bus_stb_i                    (dmmu_spr_bus_stb),      // Templated
845
      .spr_bus_dat_i                    (spr_bus_dat_i[OPTION_OPERAND_WIDTH-1:0]));
846
end else begin
847
   assign dmmu_cache_inhibit = 0;
848
   assign tlb_miss = 0;
849
   assign pagefault = 0;
850
   assign tlb_reload_busy = 0;
851
   assign tlb_reload_req = 0;
852
   assign tlb_reload_pagefault = 0;
853
end
854
endgenerate
855
 
856
endmodule // mor1kx_lsu_cappuccino

powered by: WebSVN 2.1.0

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