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_dcache.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 cache implementation
8
 
9
 Copyright (C) 2012-2013
10
    Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
11
    Stefan Wallentowitz <stefan.wallentowitz@tum.de>
12
 
13
 ******************************************************************************/
14
 
15
`include "mor1kx-defines.v"
16
 
17
module mor1kx_dcache
18
  #(
19
    parameter OPTION_OPERAND_WIDTH = 32,
20
    parameter OPTION_DCACHE_BLOCK_WIDTH = 5,
21
    parameter OPTION_DCACHE_SET_WIDTH = 9,
22
    parameter OPTION_DCACHE_WAYS = 2,
23
    parameter OPTION_DCACHE_LIMIT_WIDTH = 32,
24
    parameter OPTION_DCACHE_SNOOP = "NONE"
25
    )
26
   (
27
    input                             clk,
28
    input                             rst,
29
 
30
    input                             dc_dbus_err_i,
31
    input                             dc_enable_i,
32
    input                             dc_access_i,
33
    output                            refill_o,
34
    output                            refill_req_o,
35
    output                            refill_done_o,
36
    output                            cache_hit_o,
37
 
38
    // CPU Interface
39
    output                            cpu_err_o,
40
    output                            cpu_ack_o,
41
    output reg [OPTION_OPERAND_WIDTH-1:0] cpu_dat_o,
42
    input [OPTION_OPERAND_WIDTH-1:0]  cpu_dat_i,
43
    input [OPTION_OPERAND_WIDTH-1:0]  cpu_adr_i,
44
    input [OPTION_OPERAND_WIDTH-1:0]  cpu_adr_match_i,
45
    input                             cpu_req_i,
46
    input                             cpu_we_i,
47
    input [3:0]                cpu_bsel_i,
48
 
49
    input                             refill_allowed,
50
 
51
    input [OPTION_OPERAND_WIDTH-1:0]  wradr_i,
52
    input [OPTION_OPERAND_WIDTH-1:0]  wrdat_i,
53
    input                             we_i,
54
 
55
    // Snoop address
56
    input [31:0]                       snoop_adr_i,
57
    // Snoop event in this cycle
58
    input                             snoop_valid_i,
59
    // Whether the snoop hit. If so, there will be no tag memory write
60
    // this cycle. The LSU may need to stall the pipeline.
61
    output                            snoop_hit_o,
62
 
63
 
64
    // SPR interface
65
    input [15:0]                       spr_bus_addr_i,
66
    input                             spr_bus_we_i,
67
    input                             spr_bus_stb_i,
68
    input [OPTION_OPERAND_WIDTH-1:0]  spr_bus_dat_i,
69
 
70
    output [OPTION_OPERAND_WIDTH-1:0] spr_bus_dat_o,
71
    output                            spr_bus_ack_o
72
    );
73
 
74
   // States
75
   localparam IDLE              = 5'b00001;
76
   localparam READ              = 5'b00010;
77
   localparam WRITE             = 5'b00100;
78
   localparam REFILL            = 5'b01000;
79
   localparam INVALIDATE        = 5'b10000;
80
 
81
   // Address space in bytes for a way
82
   localparam WAY_WIDTH = OPTION_DCACHE_BLOCK_WIDTH + OPTION_DCACHE_SET_WIDTH;
83
   /*
84
    * Tag memory layout
85
    *            +---------------------------------------------------------+
86
    * (index) -> | LRU | wayN valid | wayN tag |...| way0 valid | way0 tag |
87
    *            +---------------------------------------------------------+
88
    */
89
 
90
   // The tag is the part left of the index
91
   localparam TAG_WIDTH = (OPTION_DCACHE_LIMIT_WIDTH - WAY_WIDTH);
92
 
93
   // The tag memory contains entries with OPTION_DCACHE_WAYS parts of
94
   // each TAGMEM_WAY_WIDTH. Each of those is tag and a valid flag.
95
   localparam TAGMEM_WAY_WIDTH = TAG_WIDTH + 1;
96
   localparam TAGMEM_WAY_VALID = TAGMEM_WAY_WIDTH - 1;
97
 
98
   // Additionally, the tag memory entry contains an LRU value. The
99
   // width of this is 0 for OPTION_DCACHE_LIMIT_WIDTH==1
100
   localparam TAG_LRU_WIDTH = OPTION_DCACHE_WAYS*(OPTION_DCACHE_WAYS-1) >> 1;
101
 
102
   // We have signals for the LRU which are not used for one way
103
   // caches. To avoid signal width [-1:0] this generates [0:0]
104
   // vectors for them, which are removed automatically then.
105
   localparam TAG_LRU_WIDTH_BITS = (OPTION_DCACHE_WAYS >= 2) ? TAG_LRU_WIDTH : 1;
106
 
107
   // Compute the total sum of the entry elements
108
   localparam TAGMEM_WIDTH = TAGMEM_WAY_WIDTH * OPTION_DCACHE_WAYS + TAG_LRU_WIDTH;
109
 
110
   // For convenience we define the position of the LRU in the tag
111
   // memory entries
112
   localparam TAG_LRU_MSB = TAGMEM_WIDTH - 1;
113
   localparam TAG_LRU_LSB = TAG_LRU_MSB - TAG_LRU_WIDTH + 1;
114
 
115
   // FSM state signals
116
   reg [4:0]                           state;
117
   wire                               read;
118
   wire                               write;
119
   wire                               refill;
120
 
121
   reg [WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH] invalidate_adr;
122
   wire [31:0]                         next_refill_adr;
123
   reg [31:0]                          way_wr_dat;
124
   wire                               refill_done;
125
   wire                               refill_hit;
126
   reg [(1<<(OPTION_DCACHE_BLOCK_WIDTH-2))-1:0] refill_valid;
127
   reg [(1<<(OPTION_DCACHE_BLOCK_WIDTH-2))-1:0] refill_valid_r;
128
   wire                               invalidate;
129
 
130
   // The index we read and write from tag memory
131
   wire [OPTION_DCACHE_SET_WIDTH-1:0] tag_rindex;
132
   reg [OPTION_DCACHE_SET_WIDTH-1:0]  tag_windex;
133
 
134
   // The data from the tag memory
135
   wire [TAGMEM_WIDTH-1:0]             tag_dout;
136
   wire [TAG_LRU_WIDTH_BITS-1:0]      tag_lru_out;
137
   wire [TAGMEM_WAY_WIDTH-1:0]         tag_way_out [OPTION_DCACHE_WAYS-1:0];
138
 
139
   // The data to the tag memory
140
   wire [TAGMEM_WIDTH-1:0]             tag_din;
141
   reg [TAG_LRU_WIDTH_BITS-1:0]       tag_lru_in;
142
   reg [TAGMEM_WAY_WIDTH-1:0]          tag_way_in [OPTION_DCACHE_WAYS-1:0];
143
 
144
   reg [TAGMEM_WAY_WIDTH-1:0]          tag_way_save[OPTION_DCACHE_WAYS-1:0];
145
 
146
   // Whether to write to the tag memory in this cycle
147
   reg                                tag_we;
148
 
149
   // This is the tag we need to write to the tag memory during refill
150
   wire [TAG_WIDTH-1:0]        tag_wtag;
151
 
152
   // This is the tag we check against
153
   wire [TAG_WIDTH-1:0]        tag_tag;
154
 
155
   // Access to the way memories
156
   wire [WAY_WIDTH-3:0]        way_raddr[OPTION_DCACHE_WAYS-1:0];
157
   wire [WAY_WIDTH-3:0]        way_waddr[OPTION_DCACHE_WAYS-1:0];
158
   wire [OPTION_OPERAND_WIDTH-1:0]    way_din[OPTION_DCACHE_WAYS-1:0];
159
   wire [OPTION_OPERAND_WIDTH-1:0]    way_dout[OPTION_DCACHE_WAYS-1:0];
160
   reg [OPTION_DCACHE_WAYS-1:0]       way_we;
161
 
162
   // Does any way hit?
163
   wire                               hit;
164
   wire [OPTION_DCACHE_WAYS-1:0]      way_hit;
165
 
166
   // This is the least recently used value before access the memory.
167
   // Those are one hot encoded.
168
   wire [OPTION_DCACHE_WAYS-1:0]      lru;
169
 
170
   // Register that stores the LRU value from lru
171
   reg [OPTION_DCACHE_WAYS-1:0]       tag_save_lru;
172
 
173
   // The access vector to update the LRU history is the way that has
174
   // a hit or is refilled. It is also one-hot encoded.
175
   reg [OPTION_DCACHE_WAYS-1:0]       access;
176
 
177
   // The current LRU history as read from tag memory and the update
178
   // value after we accessed it to write back to tag memory.
179
   wire [TAG_LRU_WIDTH_BITS-1:0]      current_lru_history;
180
   wire [TAG_LRU_WIDTH_BITS-1:0]      next_lru_history;
181
 
182
   // Intermediate signals to ease debugging
183
   wire [TAG_WIDTH-1:0]               check_way_tag [OPTION_DCACHE_WAYS-1:0];
184
   wire                               check_way_match [OPTION_DCACHE_WAYS-1:0];
185
   wire                               check_way_valid [OPTION_DCACHE_WAYS-1:0];
186
 
187
   reg                                write_pending;
188
 
189
   // Extract index to read from snooped address
190
   wire [OPTION_DCACHE_SET_WIDTH-1:0] snoop_index;
191
   assign snoop_index = snoop_adr_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH];
192
 
193
   // Register that is high one cycle after the actual snoop event to
194
   // drive the comparison
195
   reg                                snoop_check;
196
   // Register that stores the tag for one cycle
197
   reg [TAG_WIDTH-1:0]                 snoop_tag;
198
   // Also store the index for one cycle, for the succeeding write access
199
   reg [OPTION_DCACHE_SET_WIDTH-1:0]  snoop_windex;
200
 
201
   // Snoop tag memory interface
202
   // Data out of tag memory
203
   wire [TAGMEM_WIDTH-1:0]             snoop_dout;
204
   // Each ways information in the tag memory
205
   wire [TAGMEM_WAY_WIDTH-1:0]         snoop_way_out [OPTION_DCACHE_WAYS-1:0];
206
   // Each ways tag in the tag memory
207
   wire [TAG_WIDTH-1:0]        snoop_check_way_tag [OPTION_DCACHE_WAYS-1:0];
208
   // Whether the tag matches the snoop tag
209
   wire                               snoop_check_way_match [OPTION_DCACHE_WAYS-1:0];
210
   // Whether the tag is valid
211
   wire                               snoop_check_way_valid [OPTION_DCACHE_WAYS-1:0];
212
   // Whether the way hits
213
   wire [OPTION_DCACHE_WAYS-1:0]      snoop_way_hit;
214
   // Whether any way hits
215
   wire                               snoop_hit;
216
 
217
   assign snoop_hit_o = (OPTION_DCACHE_SNOOP != "NONE") ? snoop_hit : 0;
218
 
219
   genvar                             i;
220
 
221
   assign cpu_ack_o = ((read | refill) & hit & !write_pending |
222
                       refill_hit) & cpu_req_i & !snoop_hit;
223
 
224
   assign tag_rindex = cpu_adr_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH];
225
 
226
   assign tag_tag = cpu_adr_match_i[OPTION_DCACHE_LIMIT_WIDTH-1:WAY_WIDTH];
227
   assign tag_wtag = wradr_i[OPTION_DCACHE_LIMIT_WIDTH-1:WAY_WIDTH];
228
 
229
   generate
230
      if (OPTION_DCACHE_WAYS >= 2) begin
231
         // Multiplex the LRU history from and to tag memory
232
         assign current_lru_history = tag_dout[TAG_LRU_MSB:TAG_LRU_LSB];
233
         assign tag_din[TAG_LRU_MSB:TAG_LRU_LSB] = tag_lru_in;
234
         assign tag_lru_out = tag_dout[TAG_LRU_MSB:TAG_LRU_LSB];
235
      end
236
 
237
      for (i = 0; i < OPTION_DCACHE_WAYS; i=i+1) begin : ways
238
         assign way_raddr[i] = cpu_adr_i[WAY_WIDTH-1:2];
239
         assign way_waddr[i] = write ? cpu_adr_match_i[WAY_WIDTH-1:2] :
240
                               wradr_i[WAY_WIDTH-1:2];
241
         assign way_din[i] = way_wr_dat;
242
 
243
         // compare stored tag with incoming tag and check valid bit
244
         assign check_way_tag[i] = tag_way_out[i][TAG_WIDTH-1:0];
245
         assign check_way_match[i] = (check_way_tag[i] == tag_tag);
246
         assign check_way_valid[i] = tag_way_out[i][TAGMEM_WAY_VALID];
247
 
248
         assign way_hit[i] = check_way_valid[i] & check_way_match[i];
249
 
250
         // Multiplex the way entries in the tag memory
251
         assign tag_din[(i+1)*TAGMEM_WAY_WIDTH-1:i*TAGMEM_WAY_WIDTH] = tag_way_in[i];
252
         assign tag_way_out[i] = tag_dout[(i+1)*TAGMEM_WAY_WIDTH-1:i*TAGMEM_WAY_WIDTH];
253
 
254
         if (OPTION_DCACHE_SNOOP != "NONE") begin
255
            // The same for the snoop tag memory
256
            assign snoop_way_out[i] = snoop_dout[(i+1)*TAGMEM_WAY_WIDTH-1:i*TAGMEM_WAY_WIDTH];
257
 
258
            assign snoop_check_way_tag[i] = snoop_way_out[i][TAG_WIDTH-1:0];
259
            assign snoop_check_way_match[i] = (snoop_check_way_tag[i] == snoop_tag);
260
            assign snoop_check_way_valid[i] = snoop_way_out[i][TAGMEM_WAY_VALID];
261
 
262
            assign snoop_way_hit[i] = snoop_check_way_valid[i] & snoop_check_way_match[i];
263
         end
264
      end
265
   endgenerate
266
 
267
   assign hit = |way_hit;
268
   assign cache_hit_o = hit;
269
 
270
   assign snoop_hit = (OPTION_DCACHE_SNOOP != "NONE") &
271
                      |snoop_way_hit & snoop_check;
272
 
273
   integer w0;
274
   always @(*) begin
275
      cpu_dat_o = {OPTION_OPERAND_WIDTH{1'bx}};
276
 
277
      // Put correct way on the data port
278
      for (w0 = 0; w0 < OPTION_DCACHE_WAYS; w0 = w0 + 1) begin
279
         if (way_hit[w0] | (refill_hit & tag_save_lru[w0])) begin
280
            cpu_dat_o = way_dout[w0];
281
         end
282
      end
283
   end
284
 
285
   assign next_refill_adr = (OPTION_DCACHE_BLOCK_WIDTH == 5) ?
286
                            {wradr_i[31:5], wradr_i[4:0] + 5'd4} : // 32 byte
287
                            {wradr_i[31:4], wradr_i[3:0] + 4'd4};  // 16 byte
288
 
289
   assign refill_done_o = refill_done;
290
   assign refill_done = refill_valid[next_refill_adr[OPTION_DCACHE_BLOCK_WIDTH-1:2]];
291
   assign refill_hit = refill_valid_r[cpu_adr_match_i[OPTION_DCACHE_BLOCK_WIDTH-1:2]] &
292
                       cpu_adr_match_i[OPTION_DCACHE_LIMIT_WIDTH-1:
293
                                       OPTION_DCACHE_BLOCK_WIDTH] ==
294
                       wradr_i[OPTION_DCACHE_LIMIT_WIDTH-1:
295
                               OPTION_DCACHE_BLOCK_WIDTH] &
296
                       refill & !write_pending;
297
 
298
   assign refill = (state == REFILL);
299
   assign read = (state == READ);
300
   assign write = (state == WRITE);
301
 
302
   assign refill_o = refill;
303
 
304
   assign refill_req_o = read & cpu_req_i & !hit & !write_pending & refill_allowed | refill;
305
 
306
   /*
307
    * SPR bus interface
308
    */
309
 
310
   // The SPR interface is used to invalidate the cache blocks. When
311
   // an invalidation is started, the respective entry in the tag
312
   // memory is cleared. When another transfer is in progress, the
313
   // handling is delayed until it is possible to serve it.
314
   //
315
   // The invalidation is acknowledged to the SPR bus, but the cycle
316
   // is terminated by the core. We therefore need to hold the
317
   // invalidate acknowledgement. Meanwhile we continuously write the
318
   // tag memory which is no problem.
319
 
320
   // Net that signals an acknowledgement
321
   reg invalidate_ack;
322
 
323
   // An invalidate request is either a block flush or a block invalidate
324
   assign invalidate = spr_bus_stb_i & spr_bus_we_i &
325
                       (spr_bus_addr_i == `OR1K_SPR_DCBFR_ADDR |
326
                        spr_bus_addr_i == `OR1K_SPR_DCBIR_ADDR);
327
 
328
   // Acknowledge to the SPR bus.
329
   assign spr_bus_ack_o = invalidate_ack;
330
 
331
   /*
332
    * Cache FSM
333
    * Starts in IDLE.
334
    * State changes between READ and WRITE happens cpu_we_i is asserted or not.
335
    * cpu_we_i is in sync with cpu_adr_i, so that means that it's the
336
    * *upcoming* write that it is indicating. It only toggles for one cycle,
337
    * so if we are busy doing something else when this signal comes
338
    * (i.e. refilling) we assert the write_pending signal.
339
    * cpu_req_i is in sync with cpu_adr_match_i, so it can be used to
340
    * determined if a cache hit should cause a refill or if a write should
341
    * really be executed.
342
    */
343
   integer w1;
344
   always @(posedge clk `OR_ASYNC_RST) begin
345
      if (rst) begin
346
         state <= IDLE;
347
         write_pending <= 0;
348
      end else if(dc_dbus_err_i) begin
349
         state <= IDLE;
350
         write_pending <= 0;
351
      end else begin
352
         if (cpu_we_i)
353
           write_pending <= 1;
354
         else if (!cpu_req_i)
355
           write_pending <= 0;
356
 
357
         refill_valid_r <= refill_valid;
358
 
359
         if (snoop_valid_i) begin
360
            //
361
            // If there is a snoop event, we need to store this
362
            // information. This happens independent of whether we
363
            // have a snoop tag memory or not.
364
            //
365
            snoop_check <= 1;
366
            snoop_windex <= snoop_index;
367
            snoop_tag <= snoop_adr_i[OPTION_DCACHE_LIMIT_WIDTH-1:WAY_WIDTH];
368
         end else begin
369
            snoop_check <= 0;
370
         end
371
 
372
         case (state)
373
           IDLE: begin
374
              if (invalidate) begin
375
                 // If there is an invalidation request
376
                 //
377
                 // Store address in invalidate_adr that is muxed to the tag
378
                 // memory write address
379
                 invalidate_adr <= spr_bus_dat_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH];
380
 
381
                 // Change to invalidate state that actually accesses
382
                 // the tag memory
383
                 state <= INVALIDATE;
384
              end else if (cpu_we_i | write_pending)
385
                state <= WRITE;
386
              else if (cpu_req_i)
387
                state <= READ;
388
           end
389
 
390
           READ: begin
391
              if (dc_access_i | cpu_we_i & dc_enable_i) begin
392
                 if (!hit & cpu_req_i & !write_pending & refill_allowed) begin
393
                    refill_valid <= 0;
394
                    refill_valid_r <= 0;
395
 
396
                    // Store the LRU information for correct replacement
397
                    // on refill. Always one when only one way.
398
                    tag_save_lru <= (OPTION_DCACHE_WAYS==1) | lru;
399
 
400
                    for (w1 = 0; w1 < OPTION_DCACHE_WAYS; w1 = w1 + 1) begin
401
                       tag_way_save[w1] <= tag_way_out[w1];
402
                    end
403
 
404
                    state <= REFILL;
405
                 end else if (cpu_we_i | write_pending) begin
406
                    state <= WRITE;
407
                 end else if (invalidate) begin
408
                    state <= IDLE;
409
                 end
410
              end else if (!dc_enable_i | invalidate) begin
411
                 state <= IDLE;
412
              end
413
           end
414
 
415
           REFILL: begin
416
              if (we_i) begin
417
                 refill_valid[wradr_i[OPTION_DCACHE_BLOCK_WIDTH-1:2]] <= 1;
418
 
419
                 if (refill_done)
420
                   state <= IDLE;
421
              end
422
              // Abort refill on snoop-hit
423
              // TODO: only abort on snoop-hits to refill address
424
              if (snoop_hit) begin
425
                 refill_valid <= 0;
426
                 refill_valid_r <= 0;
427
                 state <= IDLE;
428
              end
429
           end
430
 
431
           WRITE: begin
432
              if ((!dc_access_i | !cpu_req_i | !cpu_we_i) & !snoop_hit) begin
433
                 write_pending <= 0;
434
                 state <= READ;
435
              end
436
           end
437
 
438
           INVALIDATE: begin
439
              if (invalidate) begin
440
                 // Store address in invalidate_adr that is muxed to the tag
441
                 // memory write address
442
                 invalidate_adr <= spr_bus_dat_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH];
443
 
444
                 state <= INVALIDATE;
445
              end else begin
446
                 state <= IDLE;
447
              end
448
           end
449
 
450
           default:
451
             state <= IDLE;
452
         endcase
453
      end
454
   end
455
 
456
   //
457
   // This is the combinational part of the state machine that
458
   // interfaces the tag and way memories.
459
   //
460
   integer w2;
461
   always @(*) begin
462
      // Default is to keep data, don't write and don't access
463
      tag_lru_in = tag_lru_out;
464
      for (w2 = 0; w2 < OPTION_DCACHE_WAYS; w2 = w2 + 1) begin
465
         tag_way_in[w2] = tag_way_out[w2];
466
      end
467
 
468
      tag_we = 1'b0;
469
      way_we = {(OPTION_DCACHE_WAYS){1'b0}};
470
 
471
      access = {(OPTION_DCACHE_WAYS){1'b0}};
472
 
473
      way_wr_dat = wrdat_i;
474
 
475
      // The default is (of course) not to acknowledge the invalidate
476
      invalidate_ack = 1'b0;
477
 
478
      if (snoop_hit) begin
479
         // This is the write access
480
         tag_we = 1'b1;
481
         tag_windex = snoop_windex;
482
         for (w2 = 0; w2 < OPTION_DCACHE_WAYS; w2 = w2 + 1) begin
483
            if (snoop_way_hit[w2]) begin
484
               tag_way_in[w2] = 0;
485
            end else begin
486
               tag_way_in[w2] = snoop_way_out[w2];
487
            end
488
         end
489
      end else begin
490
         //
491
         // The tag mem is written during reads and writes to write
492
         // the lru info and  during refill and invalidate.
493
         //
494
         tag_windex = read | write ?
495
                      cpu_adr_match_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH] :
496
                      (state == INVALIDATE) ? invalidate_adr :
497
                      wradr_i[WAY_WIDTH-1:OPTION_DCACHE_BLOCK_WIDTH];
498
 
499
         case (state)
500
           IDLE: begin
501
              //
502
              // When idle we can always acknowledge the invalidate as it
503
              // has the highest priority in handling. When something is
504
              // changed on the state machine handling above this needs
505
              // to be changed.
506
              //
507
              invalidate_ack = 1'b1;
508
           end
509
 
510
           READ: begin
511
              if (hit) begin
512
                 //
513
                 // We got a hit. The LRU module gets the access
514
                 // information. Depending on this we update the LRU
515
                 // history in the tag.
516
                 //
517
                 access = way_hit;
518
 
519
                 // This is the updated LRU history after hit
520
                 tag_lru_in = next_lru_history;
521
 
522
                 tag_we = 1'b1;
523
              end
524
           end
525
 
526
           WRITE: begin
527
              way_wr_dat = cpu_dat_i;
528
              if (hit & cpu_req_i) begin
529
                 /* Mux cache output with write data */
530
                 if (!cpu_bsel_i[3])
531
                   way_wr_dat[31:24] = cpu_dat_o[31:24];
532
                 if (!cpu_bsel_i[2])
533
                   way_wr_dat[23:16] = cpu_dat_o[23:16];
534
                 if (!cpu_bsel_i[1])
535
                   way_wr_dat[15:8] = cpu_dat_o[15:8];
536
                 if (!cpu_bsel_i[0])
537
                   way_wr_dat[7:0] = cpu_dat_o[7:0];
538
 
539
              way_we = way_hit;
540
 
541
              tag_lru_in = next_lru_history;
542
 
543
                 tag_we = 1'b1;
544
              end
545
           end
546
 
547
           REFILL: begin
548
              if (we_i) begin
549
                 //
550
                 // Write the data to the way that is replaced (which is
551
                 // the LRU)
552
                 //
553
                 way_we = tag_save_lru;
554
 
555
                 // Access pattern
556
                 access = tag_save_lru;
557
 
558
                 /* Invalidate the way on the first write */
559
                 if (refill_valid == 0) begin
560
                    for (w2 = 0; w2 < OPTION_DCACHE_WAYS; w2 = w2 + 1) begin
561
                       if (tag_save_lru[w2]) begin
562
                          tag_way_in[w2][TAGMEM_WAY_VALID] = 1'b0;
563
                       end
564
                    end
565
 
566
                    tag_we = 1'b1;
567
                 end
568
 
569
                 //
570
                 // After refill update the tag memory entry of the
571
                 // filled way with the LRU history, the tag and set
572
                 // valid to 1.
573
                 //
574
                 if (refill_done) begin
575
                    for (w2 = 0; w2 < OPTION_DCACHE_WAYS; w2 = w2 + 1) begin
576
                       tag_way_in[w2] = tag_way_save[w2];
577
                       if (tag_save_lru[w2]) begin
578
                          tag_way_in[w2] = { 1'b1, tag_wtag };
579
                       end
580
                    end
581
                    tag_lru_in = next_lru_history;
582
 
583
                    tag_we = 1'b1;
584
                 end
585
              end
586
           end
587
 
588
           INVALIDATE: begin
589
              invalidate_ack = 1'b1;
590
 
591
              // Lazy invalidation, invalidate everything that matches tag address
592
              tag_lru_in = 0;
593
              for (w2 = 0; w2 < OPTION_DCACHE_WAYS; w2 = w2 + 1) begin
594
                 tag_way_in[w2] = 0;
595
              end
596
 
597
              tag_we = 1'b1;
598
           end
599
 
600
           default: begin
601
           end
602
         endcase
603
      end
604
   end
605
 
606
   generate
607
      for (i = 0; i < OPTION_DCACHE_WAYS; i=i+1) begin : way_memories
608
         mor1kx_simple_dpram_sclk
609
               #(
610
                 .ADDR_WIDTH(WAY_WIDTH-2),
611
                 .DATA_WIDTH(OPTION_OPERAND_WIDTH),
612
                 .ENABLE_BYPASS(1)
613
                 )
614
         way_data_ram
615
               (
616
                // Outputs
617
                .dout                   (way_dout[i]),
618
                // Inputs
619
                .clk                    (clk),
620
                .raddr                  (way_raddr[i][WAY_WIDTH-3:0]),
621
                .re                     (1'b1),
622
                .waddr                  (way_waddr[i][WAY_WIDTH-3:0]),
623
                .we                     (way_we[i]),
624
                .din                    (way_din[i][31:0]));
625
 
626
      end
627
 
628
      if (OPTION_DCACHE_WAYS >= 2) begin : gen_u_lru
629
         /* mor1kx_cache_lru AUTO_TEMPLATE(
630
          .current  (current_lru_history),
631
          .update   (next_lru_history),
632
          .lru_pre  (lru),
633
          .lru_post (),
634
          .access   (access),
635
          ); */
636
 
637
         mor1kx_cache_lru
638
           #(.NUMWAYS(OPTION_DCACHE_WAYS))
639
         u_lru(/*AUTOINST*/
640
               // Outputs
641
               .update                  (next_lru_history),      // Templated
642
               .lru_pre                 (lru),                   // Templated
643
               .lru_post                (),                      // Templated
644
               // Inputs
645
               .current                 (current_lru_history),   // Templated
646
               .access                  (access));               // Templated
647
      end // if (OPTION_DCACHE_WAYS >= 2)
648
   endgenerate
649
 
650
   mor1kx_simple_dpram_sclk
651
     #(
652
       .ADDR_WIDTH(OPTION_DCACHE_SET_WIDTH),
653
       .DATA_WIDTH(TAGMEM_WIDTH),
654
       .ENABLE_BYPASS(OPTION_DCACHE_SNOOP != "NONE")
655
     )
656
   tag_ram
657
     (
658
      // Outputs
659
      .dout                             (tag_dout[TAGMEM_WIDTH-1:0]),
660
      // Inputs
661
      .clk                              (clk),
662
      .raddr                            (tag_rindex),
663
      .re                               (1'b1),
664
      .waddr                            (tag_windex),
665
      .we                               (tag_we),
666
      .din                              (tag_din));
667
 
668
generate
669
if (OPTION_DCACHE_SNOOP != "NONE") begin
670
   mor1kx_simple_dpram_sclk
671
     #(
672
       .ADDR_WIDTH(OPTION_DCACHE_SET_WIDTH),
673
       .DATA_WIDTH(TAGMEM_WIDTH),
674
       .ENABLE_BYPASS(1)
675
       )
676
   snoop_tag_ram
677
     (
678
      // Outputs
679
      .dout                     (snoop_dout[TAGMEM_WIDTH-1:0]),
680
      // Inputs
681
      .clk                      (clk),
682
      .raddr                    (snoop_index),
683
      .re                       (1'b1),
684
      .waddr                    (tag_windex),
685
      .we                       (tag_we),
686
      .din                      (tag_din));
687
end
688
endgenerate
689
 
690
endmodule

powered by: WebSVN 2.1.0

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