OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [hw/] [vlog/] [amber25/] [a25_dcache.v] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 csantifort
//////////////////////////////////////////////////////////////////
2
//                                                              //
3
//  L1 Instruction Cache for Amber 25 Core                      //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  Synthesizable L1 Unified Data and Instruction Cache         //
10
//  Cache is 4-way, 256 line and 16 bytes per line for          //
11
//  a total of 16KB. The cache policy is write-through and      //
12
//  read allocate. For swap instructions (SWP and SWPB) the     //
13
//  location is evicted from the cache and read from main       //
14
//  memory.                                                     //
15
//                                                              //
16
//  Author(s):                                                  //
17
//      - Conor Santifort, csantifort.amber@gmail.com           //
18
//                                                              //
19
//////////////////////////////////////////////////////////////////
20
//                                                              //
21
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
22
//                                                              //
23
// This source file may be used and distributed without         //
24
// restriction provided that this copyright statement is not    //
25
// removed from the file and that any derivative work contains  //
26
// the original copyright notice and the associated disclaimer. //
27
//                                                              //
28
// This source file is free software; you can redistribute it   //
29
// and/or modify it under the terms of the GNU Lesser General   //
30
// Public License as published by the Free Software Foundation; //
31
// either version 2.1 of the License, or (at your option) any   //
32
// later version.                                               //
33
//                                                              //
34
// This source is distributed in the hope that it will be       //
35
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
36
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
37
// PURPOSE.  See the GNU Lesser General Public License for more //
38
// details.                                                     //
39
//                                                              //
40
// You should have received a copy of the GNU Lesser General    //
41
// Public License along with this source; if not, download it   //
42
// from http://www.opencores.org/lgpl.shtml                     //
43
//                                                              //
44
//////////////////////////////////////////////////////////////////
45
 
46
`include "a25_config_defines.v"
47
 
48
module a25_dcache
49
#(
50
 
51
// ---------------------------------------------------------
52
// Cache Configuration
53
 
54
// Limited to Linux 4k page sizes -> 256 lines
55
parameter CACHE_LINES          = 256,
56
 
57
// This cannot be changed without some major surgeory on
58
// this module                                       
59
parameter CACHE_WORDS_PER_LINE = 4,
60
 
61
// Changing this parameter is the recommended
62
// way to change the overall cache size; 2, 4 and 8 ways are supported.
63
//   2 ways -> 8KB  cache
64
//   4 ways -> 16KB cache
65
//   8 ways -> 32KB cache
66
parameter WAYS              = `A25_DCACHE_WAYS ,
67
 
68
// derived configuration parameters
69
parameter CACHE_ADDR_WIDTH  = log2 ( CACHE_LINES ),                        // = 8
70
parameter WORD_SEL_WIDTH    = log2 ( CACHE_WORDS_PER_LINE ),               // = 2
71
parameter TAG_ADDR_WIDTH    = 32 - CACHE_ADDR_WIDTH - WORD_SEL_WIDTH - 2,  // = 20
72
parameter TAG_WIDTH         = TAG_ADDR_WIDTH + 1,                          // = 21, including Valid flag
73
parameter CACHE_LINE_WIDTH  = CACHE_WORDS_PER_LINE * 32,                   // = 128
74
parameter TAG_ADDR32_LSB    = CACHE_ADDR_WIDTH + WORD_SEL_WIDTH + 2,       // = 12
75
parameter CACHE_ADDR32_MSB  = CACHE_ADDR_WIDTH + WORD_SEL_WIDTH + 2 - 1,   // = 11
76
parameter CACHE_ADDR32_LSB  =                    WORD_SEL_WIDTH + 2    ,   // = 4
77
parameter WORD_SEL_MSB      = WORD_SEL_WIDTH + 2 - 1,                      // = 3
78
parameter WORD_SEL_LSB      =                  2                           // = 2
79
// ---------------------------------------------------------
80
)
81
 
82
 
83
(
84
input                               i_clk,
85
 
86
// Read / Write requests from core
87
input                               i_request,
88
input                               i_exclusive,        // exclusive access, part of swap instruction
89
input      [31:0]                   i_write_data,
90
input                               i_write_enable,     // write request from execute stage
91
input      [31:0]                   i_address,          // registered address from execute
92
input      [31:0]                   i_address_nxt,      // un-registered version of address from execute stage
93
input      [3:0]                    i_byte_enable,
94
input                               i_cache_enable,     // from co-processor 15 configuration register
95
input                               i_cache_flush,      // from co-processor 15 register
96
 
97
output      [31:0]                  o_read_data,
98
input                               i_fetch_stall,
99
output                              o_stall,
100
 
101
// WB Read Request                                                          
102
output                              o_wb_req,          // Read Request
103
input      [31:0]                   i_wb_read_data,    // wb bus                              
104
input                               i_wb_ready         // wb_stb && !wb_ack
105
);
106
 
107
`include "a25_localparams.v"
108
`include "a25_functions.v"
109
 
110
// One-hot encoded
111
localparam       C_INIT   = 0,
112
                 C_CORE   = 1,
113
                 C_FILL   = 2,
114
                 C_INVA   = 3,
115
                 C_STATES = 4;
116
 
117
localparam [3:0] CS_INIT               = 4'd0,
118
                 CS_IDLE               = 4'd1,
119
                 CS_FILL0              = 4'd2,
120
                 CS_FILL1              = 4'd3,
121
                 CS_FILL2              = 4'd4,
122
                 CS_FILL3              = 4'd5,
123
                 CS_FILL_COMPLETE      = 4'd6,
124
                 CS_TURN_AROUND        = 4'd7,
125
                 CS_WRITE_HIT1         = 4'd8,
126
                 CS_WRITE_HIT_WAIT_WB  = 4'd8,
127
                 CS_WRITE_MISS_WAIT_WB = 4'd9,
128
                 CS_EX_DELETE          = 4'd10;
129
 
130
 
131
reg  [3:0]                  c_state    = CS_IDLE;
132
reg  [C_STATES-1:0]         source_sel = 1'd1 << C_CORE;
133
reg  [CACHE_ADDR_WIDTH:0]   init_count = 'd0;
134
 
135
wire [TAG_WIDTH-1:0]        tag_rdata_way [WAYS-1:0];
136
wire [CACHE_LINE_WIDTH-1:0] data_rdata_way[WAYS-1:0];
137
wire [WAYS-1:0]             data_wenable_way;
138
wire [WAYS-1:0]             data_hit_way;
139
reg  [WAYS-1:0]             data_hit_way_r = 'd0;
140
wire [WAYS-1:0]             tag_wenable_way;
141
reg  [WAYS-1:0]             select_way = 'd0;
142
wire [WAYS-1:0]             next_way;
143
reg  [WAYS-1:0]             valid_bits_r = 'd0;
144
 
145
reg  [3:0]                  random_num = 4'hf;
146
 
147
wire [CACHE_ADDR_WIDTH-1:0] tag_address;
148
wire [TAG_WIDTH-1:0]        tag_wdata;
149
wire                        tag_wenable;
150
 
151
wire [CACHE_LINE_WIDTH-1:0] read_miss_wdata;
152
wire [CACHE_LINE_WIDTH-1:0] write_hit_wdata;
153
reg  [CACHE_LINE_WIDTH-1:0] data_wdata_r = 'd0;
154
wire [CACHE_LINE_WIDTH-1:0] consecutive_write_wdata;
155
wire [CACHE_LINE_WIDTH-1:0] data_wdata;
156
wire [CACHE_ADDR_WIDTH-1:0] data_address;
157
wire [31:0]                 write_data_word;
158
 
159
wire                        idle_hit;
160
wire                        read_miss;
161
wire                        write_miss;
162
wire                        write_hit;
163
wire                        consecutive_write;
164
wire                        fill_state;
165
 
166
reg  [31:0]                 miss_address = 'd0;
167
wire [CACHE_LINE_WIDTH-1:0] hit_rdata;
168
 
169
wire                        read_stall;
170
wire                        write_stall;
171
wire                        cache_busy_stall;
172
wire                        access_stall;
173
wire                        write_state;
174
 
175
wire                        request_pulse;
176
wire                        request_hold;
177
reg                         request_r = 'd0;
178
wire [CACHE_ADDR_WIDTH-1:0] address;
179
reg  [CACHE_LINE_WIDTH-1:0] wb_rdata_burst = 'd0;
180
 
181
wire                        exclusive_access;
182
wire                        ex_read_hit;
183
reg                         ex_read_hit_r = 'd0;
184
reg  [WAYS-1:0]             ex_read_hit_way = 'd0;
185
reg  [CACHE_ADDR_WIDTH-1:0] ex_read_address;
186
wire                        ex_read_hit_clear;
187
wire                        ex_read_cache_busy;
188
 
189
reg  [31:0]                 wb_address = 'd0;
190
wire                        rbuf_hit = 'd0;
191
wire                        wb_hit;
192
 
193
genvar                      i;
194
 
195
// ======================================
196
// Address to use for cache access
197
// ======================================
198
// If currently stalled then the address for the next
199
// cycle will be the same as it is in the current cycle
200
//
201
assign access_stall = i_fetch_stall || o_stall;
202
 
203
assign address = access_stall ? i_address    [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
204
                                i_address_nxt[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] ;
205
 
206
// ======================================
207
// Outputs
208
// ======================================
209
assign o_read_data      = wb_hit                                       ? i_wb_read_data     :
210
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? hit_rdata [31:0]   :
211
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? hit_rdata [63:32]  :
212
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? hit_rdata [95:64]  :
213
                                                                         hit_rdata [127:96] ;
214
 
215
// Don't allow the cache to stall the wb i/f for an exclusive access
216
// The cache needs a couple of cycles to flush a potential copy of the exclusive
217
// address, but the wb can do the access in parallel. So there is no
218
// stall in the state CS_EX_DELETE, even though the cache is out of action. 
219
// This works fine as long as the wb is stalling the core
220
assign o_stall         = request_hold && ( read_stall || write_stall || cache_busy_stall || ex_read_cache_busy );
221
 
222
assign o_wb_req        = ( (read_miss || write_miss || write_hit) && c_state == CS_IDLE ) || consecutive_write;
223
 
224
 
225
// ======================================
226
// Cache State Machine
227
// ======================================
228
 
229
// Little State Machine to Flush Tag RAMS
230
always @ ( posedge i_clk )
231
    if ( i_cache_flush )
232
        begin
233
        c_state     <= CS_INIT;
234
        source_sel  <= 1'd1 << C_INIT;
235
        init_count  <= 'd0;
236
        `ifdef A25_CACHE_DEBUG
237
        `TB_DEBUG_MESSAGE
238
        $display("Cache Flush");
239
        `endif
240
        end
241
    else
242
        case ( c_state )
243
            CS_INIT :
244
                if ( init_count < CACHE_LINES [CACHE_ADDR_WIDTH:0] )
245
                    begin
246
                    init_count  <= init_count + 1'd1;
247
                    source_sel  <= 1'd1 << C_INIT;
248
                    end
249
                else
250
                    begin
251
                    source_sel  <= 1'd1 << C_CORE;
252
                    c_state     <= CS_TURN_AROUND;
253
                    end
254
 
255
             CS_IDLE :
256
                begin
257
                source_sel  <= 1'd1 << C_CORE;
258
 
259
                if ( ex_read_hit || ex_read_hit_r )
260
                    begin
261
                    select_way  <= data_hit_way | ex_read_hit_way;
262
                    c_state     <= CS_EX_DELETE;
263
                    source_sel  <= 1'd1 << C_INVA;
264
                    end
265
                else if ( read_miss )
266
                    c_state <= CS_FILL0;
267
                else if ( write_hit )
268
                    begin
269
                    if ( i_wb_ready )
270
                        c_state <= CS_WRITE_HIT1;
271
                    else
272
                        c_state <= CS_WRITE_HIT_WAIT_WB;
273
                    end
274
                else if ( write_miss && !i_wb_ready )
275
                        c_state <= CS_WRITE_MISS_WAIT_WB;
276
                end
277
 
278
 
279
             CS_FILL0 :
280
                // wb read request asserted, wait for ack
281
                if ( i_wb_ready )
282
                    c_state <= CS_FILL1;
283
 
284
 
285
             CS_FILL1 :
286
                // first read of burst of 4
287
                // wb read request asserted, wait for ack
288
                if ( i_wb_ready )
289
                    c_state <= CS_FILL2;
290
 
291
 
292
             CS_FILL2 :
293
                // second read of burst of 4
294
                // wb read request asserted, wait for ack
295
                if ( i_wb_ready )
296
                    c_state <= CS_FILL3;
297
 
298
 
299
             CS_FILL3 :
300
                // third read of burst of 4
301
                // wb read request asserted, wait for ack
302
                if ( i_wb_ready )
303
                    begin
304
                    c_state     <= CS_FILL_COMPLETE;
305
                    source_sel  <= 1'd1 << C_FILL;
306
 
307
                    // Pick a way to write the cache update into
308
                    // Either pick one of the invalid caches, or if all are valid, then pick
309
                    // one randomly
310
 
311
                    select_way  <= next_way;
312
                    random_num  <= {random_num[2], random_num[1], random_num[0],
313
                                     random_num[3]^random_num[2]};
314
                    end
315
 
316
 
317
             // Write the read fetch data in this cycle
318
             CS_FILL_COMPLETE :
319
                begin
320
                // Back to normal cache operations, but
321
                // use physical address for first read as
322
                // address moved before the stall was asserted for the read_miss
323
                // However don't use it if its a non-cached address!
324
                source_sel  <= 1'd1 << C_CORE;
325
                c_state     <= CS_TURN_AROUND;
326
                end
327
 
328
 
329
             // Ignore the tag read data in this cycle   
330
             // Wait 1 cycle to pre-read the cache and return to normal operation                 
331
             CS_TURN_AROUND :
332
                begin
333
                c_state     <= CS_IDLE;
334
                end
335
 
336
 
337
             // Flush the entry matching an exclusive access         
338
             CS_EX_DELETE:
339
                begin
340
                `ifdef A25_CACHE_DEBUG
341
                `TB_DEBUG_MESSAGE
342
                $display("Cache deleted Locked entry");
343
                `endif
344
                c_state    <= CS_TURN_AROUND;
345
                source_sel <= 1'd1 << C_CORE;
346
                end
347
 
348
 
349
             CS_WRITE_HIT1:
350
                if ( !consecutive_write )
351
                    c_state     <= CS_IDLE;
352
 
353
 
354
             CS_WRITE_HIT_WAIT_WB:
355
                // wait for an ack on the wb bus to complete the write
356
                if ( i_wb_ready )
357
                    c_state     <= CS_IDLE;
358
 
359
 
360
             CS_WRITE_MISS_WAIT_WB:
361
                // wait for an ack on the wb bus to complete the write
362
                if ( i_wb_ready )
363
                    c_state     <= CS_IDLE;
364
 
365
        endcase
366
 
367
 
368
// ======================================
369
// Capture WB Block Read - burst of 4 words
370
// ======================================
371
always @ ( posedge i_clk )
372
    if ( i_wb_ready )
373
        wb_rdata_burst <= {i_wb_read_data, wb_rdata_burst[127:32]};
374
 
375
 
376
 
377
// ======================================
378
// Miss Address
379
// ======================================
380
always @ ( posedge i_clk )
381
    if ( o_wb_req || write_hit )
382
        miss_address <= i_address;
383
 
384
always @ ( posedge i_clk )
385
    if ( write_hit )
386
        begin
387
        data_hit_way_r      <= data_hit_way;
388
        end
389
 
390
always @ ( posedge i_clk )
391
    if ( write_hit || consecutive_write )
392
        begin
393
        data_wdata_r   <= data_wdata;
394
        end
395
 
396
assign consecutive_write = miss_address[31:4] == i_address[31:4] &&
397
                           i_write_enable &&
398
                           c_state == CS_WRITE_HIT1 &&
399
                           request_pulse;
400
 
401
 
402
always @(posedge i_clk)
403
    if ( o_wb_req )
404
        wb_address <= i_address;
405
    else if ( i_wb_ready && fill_state )
406
        wb_address <= {wb_address[31:4], wb_address[3:2] + 1'd1, 2'd0};
407
 
408
assign fill_state       = c_state == CS_FILL0 || c_state == CS_FILL1 || c_state == CS_FILL2 || c_state == CS_FILL3 ;
409
assign wb_hit           = i_address == wb_address && i_wb_ready && fill_state;
410
 
411
 
412
// ======================================
413
// Hold Requests
414
// ======================================
415
always @(posedge i_clk)
416
    request_r <= (request_pulse || request_r) && o_stall;
417
 
418
assign request_hold = request_pulse || request_r;
419
 
420
 
421
// ======================================
422
// Remember Read-Modify-Write Hit
423
// ======================================
424
assign ex_read_hit_clear = c_state == CS_EX_DELETE;
425
 
426
always @ ( posedge i_clk )
427
    if ( ex_read_hit_clear )
428
        begin
429
        ex_read_hit_r   <= 1'd0;
430
        ex_read_hit_way <= 'd0;
431
        end
432
    else if ( ex_read_hit )
433
        begin
434
 
435
        `ifdef A25_CACHE_DEBUG
436
            `TB_DEBUG_MESSAGE
437
            $display ("Exclusive access cache hit address 0x%08h", i_address);
438
        `endif
439
 
440
        ex_read_hit_r   <= 1'd1;
441
        ex_read_hit_way <= data_hit_way;
442
        end
443
    else if ( c_state == CS_FILL_COMPLETE && ex_read_hit_r )
444
        ex_read_hit_way <= select_way;
445
 
446
 
447
always @ (posedge i_clk)
448
    if ( ex_read_hit )
449
        ex_read_address <= i_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB];
450
 
451
 
452
assign tag_address      = source_sel[C_FILL] ? miss_address      [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
453
                          source_sel[C_INVA] ? ex_read_address                                       :
454
                          source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0]                      :
455
                          source_sel[C_CORE] ? address                                               :
456
                                               {CACHE_ADDR_WIDTH{1'd0}}                              ;
457
 
458
 
459
assign data_address     = consecutive_write  ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
460
                          write_hit          ? i_address   [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
461
                          source_sel[C_FILL] ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
462
                          source_sel[C_CORE] ? address                                         :
463
                                               {CACHE_ADDR_WIDTH{1'd0}}                        ;
464
 
465
 
466
assign tag_wdata        = source_sel[C_FILL] ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} :
467
                                               {TAG_WIDTH{1'd0}}                       ;
468
 
469
 
470
    // Data comes in off the WB bus in wrap4 with the missed data word first
471
assign data_wdata       = write_hit && c_state == CS_IDLE ? write_hit_wdata :
472
                          consecutive_write               ? consecutive_write_wdata :
473
                                                            read_miss_wdata ;
474
 
475
assign read_miss_wdata  = miss_address[3:2] == 2'd0 ? wb_rdata_burst                              :
476
                          miss_address[3:2] == 2'd1 ? { wb_rdata_burst[95:0], wb_rdata_burst[127:96] }:
477
                          miss_address[3:2] == 2'd2 ? { wb_rdata_burst[63:0], wb_rdata_burst[127:64] }:
478
                                                      { wb_rdata_burst[31:0], wb_rdata_burst[127:32] };
479
 
480
 
481
assign write_hit_wdata  = i_address[3:2] == 2'd0 ? {hit_rdata[127:32], write_data_word                   } :
482
                          i_address[3:2] == 2'd1 ? {hit_rdata[127:64], write_data_word, hit_rdata[31:0]  } :
483
                          i_address[3:2] == 2'd2 ? {hit_rdata[127:96], write_data_word, hit_rdata[63:0]  } :
484
                                                   {                   write_data_word, hit_rdata[95:0]  } ;
485
wire [31:0] con_read_data_word;
486
wire [31:0] con_write_data_word;
487
 
488
assign consecutive_write_wdata =
489
                          i_address[3:2] == 2'd0 ? {data_wdata_r[127:32], con_write_data_word                           } :
490
                          i_address[3:2] == 2'd1 ? {data_wdata_r[127:64], con_write_data_word, data_wdata_r[31:0]  } :
491
                          i_address[3:2] == 2'd2 ? {data_wdata_r[127:96], con_write_data_word, data_wdata_r[63:0]  } :
492
                                                   {                      con_write_data_word, data_wdata_r[95:0]  } ;
493
assign con_read_data_word =
494
                          i_address[3:2] == 2'd0 ? data_wdata_r[ 31:  0] :
495
                          i_address[3:2] == 2'd1 ? data_wdata_r[ 63: 32] :
496
                          i_address[3:2] == 2'd2 ? data_wdata_r[ 95: 64] :
497
                                                   data_wdata_r[127: 96] ;
498
 
499
 
500
assign con_write_data_word  = i_byte_enable == 4'b0001 ? { con_read_data_word[31: 8], i_write_data[ 7: 0]                          } :
501
                              i_byte_enable == 4'b0010 ? { con_read_data_word[31:16], i_write_data[15: 8], con_read_data_word[ 7:0]} :
502
                              i_byte_enable == 4'b0100 ? { con_read_data_word[31:24], i_write_data[23:16], con_read_data_word[15:0]} :
503
                              i_byte_enable == 4'b1000 ? {                            i_write_data[31:24], con_read_data_word[23:0]} :
504
                              i_byte_enable == 4'b0011 ? { con_read_data_word[31:16], i_write_data[15: 0]                          } :
505
                              i_byte_enable == 4'b1100 ? {                            i_write_data[31:16], con_read_data_word[15:0]} :
506
                                                                       i_write_data                                                  ;
507
 
508
 
509
 
510
 
511
// Use Byte Enables
512
assign write_data_word  = i_byte_enable == 4'b0001 ? { o_read_data[31: 8], i_write_data[ 7: 0]                   } :
513
                          i_byte_enable == 4'b0010 ? { o_read_data[31:16], i_write_data[15: 8], o_read_data[ 7:0]} :
514
                          i_byte_enable == 4'b0100 ? { o_read_data[31:24], i_write_data[23:16], o_read_data[15:0]} :
515
                          i_byte_enable == 4'b1000 ? {                     i_write_data[31:24], o_read_data[23:0]} :
516
                          i_byte_enable == 4'b0011 ? { o_read_data[31:16], i_write_data[15: 0]                   } :
517
                          i_byte_enable == 4'b1100 ? {                     i_write_data[31:16], o_read_data[15:0]} :
518
                                                     i_write_data                                                  ;
519
 
520
 
521
assign tag_wenable      = source_sel[C_INVA] ? 1'd1  :
522
                          source_sel[C_FILL] ? 1'd1  :
523
                          source_sel[C_INIT] ? 1'd1  :
524
                          source_sel[C_CORE] ? 1'd0  :
525
                                               1'd0  ;
526
 
527
 
528
assign request_pulse    = i_request && i_cache_enable;
529
 
530
assign exclusive_access = i_exclusive && i_cache_enable;
531
 
532
 
533
assign idle_hit         = |data_hit_way;
534
 
535
assign write_hit        = request_hold &&  i_write_enable && idle_hit;
536
 
537
assign write_miss       = request_hold &&  i_write_enable && !idle_hit && !consecutive_write;
538
 
539
assign read_miss        = request_hold && !idle_hit && !i_write_enable;
540
 
541
                          // Exclusive read idle_hit
542
assign ex_read_hit      = exclusive_access && !i_write_enable && idle_hit;
543
 
544
                          // Added to fix rare swap bug which occurs when the cache starts
545
                          // a fill just as the swap instruction starts to execute. The cache
546
                          // fails to check for a read idle_hit on the swap read cycle.
547
                          // This signal stalls the core in that case until after the
548
                          // fill has completed.
549
assign ex_read_cache_busy = exclusive_access && !i_write_enable && c_state != CS_IDLE;
550
 
551
                          // Need to stall for a write miss to wait for the current wb 
552
                          // read miss access to complete. Also for a write idle_hit, need 
553
                          // to stall for 1 cycle while the data cache is being written to
554
assign write_state      = c_state == CS_IDLE || c_state == CS_WRITE_HIT1 ||
555
                          c_state == CS_WRITE_HIT_WAIT_WB ||  c_state == CS_WRITE_MISS_WAIT_WB;
556
 
557
assign write_stall      = (write_miss && !(i_wb_ready && write_state)) || (write_hit && !i_wb_ready);
558
 
559
assign read_stall       = request_hold && !idle_hit && !rbuf_hit && !wb_hit && !i_write_enable;
560
 
561
assign cache_busy_stall = c_state == CS_FILL_COMPLETE || c_state == CS_TURN_AROUND || c_state == CS_INIT ||
562
                          (fill_state && !rbuf_hit && !wb_hit);
563
 
564
 
565
// ======================================
566
// Instantiate RAMS
567
// ======================================
568
 
569
generate
570
    for ( i=0; i<WAYS;i=i+1 ) begin : rams
571
 
572
        // Tag RAMs 
573
        `ifdef XILINX_SPARTAN6_FPGA
574
        xs6_sram_256x21_line_en
575
        `endif
576
 
577
        `ifdef XILINX_VIRTEX6_FPGA
578
        xv6_sram_256x21_line_en
579
        `endif
580
 
581
        `ifndef XILINX_FPGA
582
        generic_sram_line_en
583
        `endif
584
 
585
            #(
586
            .DATA_WIDTH                 ( TAG_WIDTH             ),
587
            .INITIALIZE_TO_ZERO         ( 1                     ),
588
            .ADDRESS_WIDTH              ( CACHE_ADDR_WIDTH      ))
589
        u_tag (
590
            .i_clk                      ( i_clk                 ),
591
            .i_write_data               ( tag_wdata             ),
592
            .i_write_enable             ( tag_wenable_way[i]    ),
593
            .i_address                  ( tag_address           ),
594
 
595
            .o_read_data                ( tag_rdata_way[i]      )
596
            );
597
 
598
        // Data RAMs 
599
        `ifdef XILINX_SPARTAN6_FPGA
600
        xs6_sram_256x128_byte_en
601
        `endif
602
 
603
        `ifdef XILINX_VIRTEX6_FPGA
604
        xv6_sram_256x128_byte_en
605
        `endif
606
 
607
        `ifndef XILINX_FPGA
608
        generic_sram_byte_en
609
        `endif
610
 
611
            #(
612
            .DATA_WIDTH    ( CACHE_LINE_WIDTH) ,
613
            .ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )
614
        u_data (
615
            .i_clk                      ( i_clk                         ),
616
            .i_write_data               ( data_wdata                    ),
617
            .i_write_enable             ( data_wenable_way[i]           ),
618
            .i_address                  ( data_address                  ),
619
            .i_byte_enable              ( {CACHE_LINE_WIDTH/8{1'd1}}    ),
620
            .o_read_data                ( data_rdata_way[i]             )
621
            );
622
 
623
 
624
        // Per tag-ram write-enable
625
        assign tag_wenable_way[i]  = tag_wenable && ( select_way[i] || source_sel[C_INIT] );
626
 
627
        // Per data-ram write-enable
628
        assign data_wenable_way[i] = (source_sel[C_FILL] && select_way[i]) ||
629
                                     (write_hit && data_hit_way[i] && c_state == CS_IDLE) ||
630
                                     (consecutive_write && data_hit_way_r[i]);
631
        // Per data-ram idle_hit flag
632
        assign data_hit_way[i]     = tag_rdata_way[i][TAG_WIDTH-1] &&
633
                                     tag_rdata_way[i][TAG_ADDR_WIDTH-1:0] == i_address[31:TAG_ADDR32_LSB] &&
634
                                     c_state == CS_IDLE;
635
    end
636
endgenerate
637
 
638
 
639
// ======================================
640
// Register Valid Bits
641
// ======================================
642
generate
643
if ( WAYS == 2 ) begin : valid_bits_2ways
644
 
645
    always @ ( posedge i_clk )
646
        if ( c_state == CS_IDLE )
647
            valid_bits_r <= {tag_rdata_way[1][TAG_WIDTH-1],
648
                             tag_rdata_way[0][TAG_WIDTH-1]};
649
 
650
end
651
else if ( WAYS == 3 ) begin : valid_bits_3ways
652
 
653
    always @ ( posedge i_clk )
654
        if ( c_state == CS_IDLE )
655
            valid_bits_r <= {tag_rdata_way[2][TAG_WIDTH-1],
656
                             tag_rdata_way[1][TAG_WIDTH-1],
657
                             tag_rdata_way[0][TAG_WIDTH-1]};
658
 
659
end
660
else if ( WAYS == 4 ) begin : valid_bits_4ways
661
 
662
    always @ ( posedge i_clk )
663
        if ( c_state == CS_IDLE )
664
            valid_bits_r <= {tag_rdata_way[3][TAG_WIDTH-1],
665
                             tag_rdata_way[2][TAG_WIDTH-1],
666
                             tag_rdata_way[1][TAG_WIDTH-1],
667
                             tag_rdata_way[0][TAG_WIDTH-1]};
668
 
669
end
670
else begin : valid_bits_8ways
671
 
672
    always @ ( posedge i_clk )
673
        if ( c_state == CS_IDLE )
674
            valid_bits_r <= {tag_rdata_way[7][TAG_WIDTH-1],
675
                             tag_rdata_way[6][TAG_WIDTH-1],
676
                             tag_rdata_way[5][TAG_WIDTH-1],
677
                             tag_rdata_way[4][TAG_WIDTH-1],
678
                             tag_rdata_way[3][TAG_WIDTH-1],
679
                             tag_rdata_way[2][TAG_WIDTH-1],
680
                             tag_rdata_way[1][TAG_WIDTH-1],
681
                             tag_rdata_way[0][TAG_WIDTH-1]};
682
 
683
end
684
endgenerate
685
 
686
 
687
// ======================================
688
// Select read idle_hit data
689
// ======================================
690
 
691
generate
692
if ( WAYS == 2 ) begin : read_data_2ways
693
 
694
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
695
                          data_hit_way[1] ? data_rdata_way[1] :
696
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
697
 
698
end
699
else if ( WAYS == 3 ) begin : read_data_3ways
700
 
701
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
702
                          data_hit_way[1] ? data_rdata_way[1] :
703
                          data_hit_way[2] ? data_rdata_way[2] :
704
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
705
 
706
end
707
else if ( WAYS == 4 ) begin : read_data_4ways
708
 
709
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
710
                          data_hit_way[1] ? data_rdata_way[1] :
711
                          data_hit_way[2] ? data_rdata_way[2] :
712
                          data_hit_way[3] ? data_rdata_way[3] :
713
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
714
 
715
end
716
else begin : read_data_8ways
717
 
718
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
719
                          data_hit_way[1] ? data_rdata_way[1] :
720
                          data_hit_way[2] ? data_rdata_way[2] :
721
                          data_hit_way[3] ? data_rdata_way[3] :
722
                          data_hit_way[4] ? data_rdata_way[4] :
723
                          data_hit_way[5] ? data_rdata_way[5] :
724
                          data_hit_way[6] ? data_rdata_way[6] :
725
                          data_hit_way[7] ? data_rdata_way[7] :
726
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
727
 
728
end
729
endgenerate
730
 
731
 
732
// ======================================
733
// Function to select the way to use
734
// for fills
735
// ======================================
736
generate
737
if ( WAYS == 2 ) begin : pick_way_2ways
738
 
739
    assign next_way = pick_way ( valid_bits_r, random_num );
740
 
741
    function [WAYS-1:0] pick_way;
742
    input [WAYS-1:0] valid_bits;
743
    input [3:0]      random_num;
744
    begin
745
        if (      valid_bits[0] == 1'd0 )
746
            // way 0 not occupied so use it
747
            pick_way     = 2'b01;
748
        else if ( valid_bits[1] == 1'd0 )
749
            // way 1 not occupied so use it
750
            pick_way     = 2'b10;
751
        else
752
            begin
753
            // All ways occupied so pick one randomly
754
            case (random_num[3:1])
755
                3'd0, 3'd3,
756
                3'd5, 3'd6: pick_way = 2'b10;
757
                default:    pick_way = 2'b01;
758
            endcase
759
            end
760
    end
761
    endfunction
762
 
763
end
764
else if ( WAYS == 3 ) begin : pick_way_3ways
765
 
766
    assign next_way = pick_way ( valid_bits_r, random_num );
767
 
768
    function [WAYS-1:0] pick_way;
769
    input [WAYS-1:0] valid_bits;
770
    input [3:0]      random_num;
771
    begin
772
        if (      valid_bits[0] == 1'd0 )
773
            // way 0 not occupied so use it
774
            pick_way     = 3'b001;
775
        else if ( valid_bits[1] == 1'd0 )
776
            // way 1 not occupied so use it
777
            pick_way     = 3'b010;
778
        else if ( valid_bits[2] == 1'd0 )
779
            // way 2 not occupied so use it
780
            pick_way     = 3'b100;
781
        else
782
            begin
783
            // All ways occupied so pick one randomly
784
            case (random_num[3:1])
785
                3'd0, 3'd1, 3'd2: pick_way = 3'b010;
786
                3'd2, 3'd3, 3'd4: pick_way = 3'b100;
787
                default:          pick_way = 3'b001;
788
            endcase
789
            end
790
    end
791
    endfunction
792
 
793
end
794
else if ( WAYS == 4 ) begin : pick_way_4ways
795
 
796
    assign next_way = pick_way ( valid_bits_r, random_num );
797
 
798
    function [WAYS-1:0] pick_way;
799
    input [WAYS-1:0] valid_bits;
800
    input [3:0]      random_num;
801
    begin
802
        if (      valid_bits[0] == 1'd0 )
803
            // way 0 not occupied so use it
804
            pick_way     = 4'b0001;
805
        else if ( valid_bits[1] == 1'd0 )
806
            // way 1 not occupied so use it
807
            pick_way     = 4'b0010;
808
        else if ( valid_bits[2] == 1'd0 )
809
            // way 2 not occupied so use it
810
            pick_way     = 4'b0100;
811
        else if ( valid_bits[3] == 1'd0 )
812
            // way 3 not occupied so use it
813
            pick_way     = 4'b1000;
814
        else
815
            begin
816
            // All ways occupied so pick one randomly
817
            case (random_num[3:1])
818
                3'd0, 3'd1: pick_way = 4'b0100;
819
                3'd2, 3'd3: pick_way = 4'b1000;
820
                3'd4, 3'd5: pick_way = 4'b0001;
821
                default:    pick_way = 4'b0010;
822
            endcase
823
            end
824
    end
825
    endfunction
826
 
827
end
828
else begin : pick_way_8ways
829
 
830
    assign next_way = pick_way ( valid_bits_r, random_num );
831
 
832
    function [WAYS-1:0] pick_way;
833
    input [WAYS-1:0] valid_bits;
834
    input [3:0]      random_num;
835
    begin
836
        if (      valid_bits[0] == 1'd0 )
837
            // way 0 not occupied so use it
838
            pick_way     = 8'b00000001;
839
        else if ( valid_bits[1] == 1'd0 )
840
            // way 1 not occupied so use it
841
            pick_way     = 8'b00000010;
842
        else if ( valid_bits[2] == 1'd0 )
843
            // way 2 not occupied so use it
844
            pick_way     = 8'b00000100;
845
        else if ( valid_bits[3] == 1'd0 )
846
            // way 3 not occupied so use it
847
            pick_way     = 8'b00001000;
848
        else if ( valid_bits[4] == 1'd0 )
849
            // way 3 not occupied so use it
850
            pick_way     = 8'b00010000;
851
        else if ( valid_bits[5] == 1'd0 )
852
            // way 3 not occupied so use it
853
            pick_way     = 8'b00100000;
854
        else if ( valid_bits[6] == 1'd0 )
855
            // way 3 not occupied so use it
856
            pick_way     = 8'b01000000;
857
        else if ( valid_bits[7] == 1'd0 )
858
            // way 3 not occupied so use it
859
            pick_way     = 8'b10000000;
860
        else
861
            begin
862
            // All ways occupied so pick one randomly
863
            case (random_num[3:1])
864
                3'd0:       pick_way = 8'b00010000;
865
                3'd1:       pick_way = 8'b00100000;
866
                3'd2:       pick_way = 8'b01000000;
867
                3'd3:       pick_way = 8'b10000000;
868
                3'd4:       pick_way = 8'b00000001;
869
                3'd5:       pick_way = 8'b00000010;
870
                3'd6:       pick_way = 8'b00000100;
871
                default:    pick_way = 8'b00001000;
872
            endcase
873
            end
874
    end
875
    endfunction
876
 
877
end
878
endgenerate
879
 
880
 
881
// ========================================================
882
// Debug WB bus - not synthesizable
883
// ========================================================
884
//synopsys translate_off
885
wire    [(6*8)-1:0]     xSOURCE_SEL;
886
wire    [(22*8)-1:0]    xC_STATE;
887
 
888
assign xSOURCE_SEL = source_sel[C_CORE]               ? "C_CORE"                :
889
                     source_sel[C_INIT]               ? "C_INIT"                :
890
                     source_sel[C_FILL]               ? "C_FILL"                :
891
                     source_sel[C_INVA]               ? "C_INVA"                :
892
                                                        "UNKNON"                ;
893
 
894
assign xC_STATE    = c_state == CS_INIT               ? "CS_INIT"               :
895
                     c_state == CS_IDLE               ? "CS_IDLE"               :
896
                     c_state == CS_FILL0              ? "CS_FILL0"              :
897
                     c_state == CS_FILL1              ? "CS_FILL1"              :
898
                     c_state == CS_FILL2              ? "CS_FILL2"              :
899
                     c_state == CS_FILL3              ? "CS_FILL3"              :
900
                     c_state == CS_FILL_COMPLETE      ? "CS_FILL_COMPLETE"      :
901
                     c_state == CS_EX_DELETE          ? "CS_EX_DELETE"          :
902
                     c_state == CS_TURN_AROUND        ? "CS_TURN_AROUND"        :
903
                     c_state == CS_WRITE_HIT1         ? "CS_WRITE_HIT1"         :
904
                     c_state == CS_WRITE_HIT_WAIT_WB  ? "CS_WRITE_HIT_WAIT_WB"  :
905
                     c_state == CS_WRITE_MISS_WAIT_WB ? "CS_WRITE_MISS_WAIT_WB" :
906
                                                        "UNKNOWN"               ;
907
 
908
 
909
generate
910
if ( WAYS == 2 ) begin : check_hit_2ways
911
 
912
    always @( posedge i_clk )
913
        if ( (data_hit_way[0] + data_hit_way[1] ) > 4'd1 )
914
            begin
915
            `TB_ERROR_MESSAGE
916
            $display("Hit in more than one cache ways!");
917
            end
918
 
919
end
920
else if ( WAYS == 3 ) begin : check_hit_3ways
921
 
922
    always @( posedge i_clk )
923
        if ( (data_hit_way[0] + data_hit_way[1] + data_hit_way[2] ) > 4'd1 )
924
            begin
925
            `TB_ERROR_MESSAGE
926
            $display("Hit in more than one cache ways!");
927
            end
928
 
929
end
930
else if ( WAYS == 4 ) begin : check_hit_4ways
931
 
932
    always @( posedge i_clk )
933
        if ( (data_hit_way[0] + data_hit_way[1] +
934
              data_hit_way[2] + data_hit_way[3] ) > 4'd1 )
935
            begin
936
            `TB_ERROR_MESSAGE
937
            $display("Hit in more than one cache ways!");
938
            end
939
 
940
end
941
else if ( WAYS == 8 )  begin : check_hit_8ways
942
 
943
    always @( posedge i_clk )
944
        if ( (data_hit_way[0] + data_hit_way[1] +
945
              data_hit_way[2] + data_hit_way[3] +
946
              data_hit_way[4] + data_hit_way[5] +
947
              data_hit_way[6] + data_hit_way[7] ) > 4'd1 )
948
            begin
949
            `TB_ERROR_MESSAGE
950
            $display("Hit in more than one cache ways!");
951
            end
952
 
953
end
954
else begin : check_hit_nways
955
 
956
    initial
957
        begin
958
        `TB_ERROR_MESSAGE
959
        $display("Unsupported number of ways %0d", WAYS);
960
        $display("Set A25_DCACHE_WAYS in a25_config_defines.v to either 2,3,4 or 8");
961
        end
962
 
963
end
964
endgenerate
965
 
966
 
967
//synopsys translate_on
968
 
969
endmodule
970
 

powered by: WebSVN 2.1.0

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