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

powered by: WebSVN 2.1.0

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