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

Subversion Repositories amber

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 csantifort
//////////////////////////////////////////////////////////////////
2
//                                                              //
3 17 csantifort
//  L1 Data Cache for Amber 25 Core                             //
4 16 csantifort
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9 17 csantifort
//  Synthesizable L1 Data Cache                                 //
10
//  Cache is 2, 3, 4 or 8 way, 256 line and 16 bytes per line.  //
11
//  The cache policy is write-through and                       //
12 16 csantifort
//  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 82 csantifort
`include "global_defines.vh"
46
`include "a25_config_defines.vh"
47 16 csantifort
 
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 35 csantifort
input                               i_exec_stall,
100 16 csantifort
output                              o_stall,
101
 
102
// WB Read Request                                                          
103 35 csantifort
output                              o_wb_cached_req,        // Read Request
104
input      [127:0]                  i_wb_cached_rdata,      // wb bus                              
105
input                               i_wb_cached_ready       // wb_stb && !wb_ack
106 16 csantifort
);
107
 
108 82 csantifort
`include "a25_localparams.vh"
109
`include "a25_functions.vh"
110 16 csantifort
 
111
// One-hot encoded
112
localparam       C_INIT   = 0,
113
                 C_CORE   = 1,
114
                 C_FILL   = 2,
115
                 C_INVA   = 3,
116
                 C_STATES = 4;
117
 
118
localparam [3:0] CS_INIT               = 4'd0,
119
                 CS_IDLE               = 4'd1,
120 39 csantifort
                 CS_FILL               = 4'd2,
121
                 CS_FILL_COMPLETE      = 4'd3,
122
                 CS_TURN_AROUND        = 4'd4,
123
                 CS_WRITE_HIT          = 4'd5,
124
                 CS_WRITE_HIT_WAIT_WB  = 4'd6,
125
                 CS_WRITE_MISS_WAIT_WB = 4'd7,
126
                 CS_EX_DELETE          = 4'd8;
127 16 csantifort
 
128
 
129
reg  [3:0]                  c_state    = CS_IDLE;
130
reg  [C_STATES-1:0]         source_sel = 1'd1 << C_CORE;
131
reg  [CACHE_ADDR_WIDTH:0]   init_count = 'd0;
132
 
133
wire [TAG_WIDTH-1:0]        tag_rdata_way [WAYS-1:0];
134
wire [CACHE_LINE_WIDTH-1:0] data_rdata_way[WAYS-1:0];
135
wire [WAYS-1:0]             data_wenable_way;
136
wire [WAYS-1:0]             data_hit_way;
137
reg  [WAYS-1:0]             data_hit_way_r = 'd0;
138
wire [WAYS-1:0]             tag_wenable_way;
139
reg  [WAYS-1:0]             select_way = 'd0;
140
wire [WAYS-1:0]             next_way;
141
reg  [WAYS-1:0]             valid_bits_r = 'd0;
142
 
143
reg  [3:0]                  random_num = 4'hf;
144
 
145
wire [CACHE_ADDR_WIDTH-1:0] tag_address;
146
wire [TAG_WIDTH-1:0]        tag_wdata;
147
wire                        tag_wenable;
148
 
149
wire [CACHE_LINE_WIDTH-1:0] read_miss_wdata;
150
wire [CACHE_LINE_WIDTH-1:0] write_hit_wdata;
151
reg  [CACHE_LINE_WIDTH-1:0] data_wdata_r = 'd0;
152
wire [CACHE_LINE_WIDTH-1:0] consecutive_write_wdata;
153
wire [CACHE_LINE_WIDTH-1:0] data_wdata;
154
wire [CACHE_ADDR_WIDTH-1:0] data_address;
155
wire [31:0]                 write_data_word;
156
 
157
wire                        idle_hit;
158
wire                        read_miss;
159
wire                        write_miss;
160
wire                        write_hit;
161
wire                        consecutive_write;
162
wire                        fill_state;
163
 
164
reg  [31:0]                 miss_address = 'd0;
165
wire [CACHE_LINE_WIDTH-1:0] hit_rdata;
166
 
167
wire                        read_stall;
168
wire                        write_stall;
169
wire                        cache_busy_stall;
170 35 csantifort
wire                        core_stall;
171 16 csantifort
wire                        write_state;
172
 
173
wire                        request_pulse;
174
wire                        request_hold;
175
reg                         request_r = 'd0;
176
wire [CACHE_ADDR_WIDTH-1:0] address;
177
reg  [CACHE_LINE_WIDTH-1:0] wb_rdata_burst = 'd0;
178
 
179
wire                        exclusive_access;
180
wire                        ex_read_hit;
181
reg                         ex_read_hit_r = 'd0;
182
reg  [WAYS-1:0]             ex_read_hit_way = 'd0;
183
reg  [CACHE_ADDR_WIDTH-1:0] ex_read_address;
184
wire                        ex_read_hit_clear;
185
wire                        ex_read_cache_busy;
186
 
187
reg  [31:0]                 wb_address = 'd0;
188
wire                        rbuf_hit = 'd0;
189
wire                        wb_hit;
190 35 csantifort
wire [127:0]                read_data128;
191 16 csantifort
genvar                      i;
192
 
193
// ======================================
194
// Address to use for cache access
195
// ======================================
196
// If currently stalled then the address for the next
197
// cycle will be the same as it is in the current cycle
198
//
199 35 csantifort
assign core_stall = i_fetch_stall || i_exec_stall || o_stall;
200 16 csantifort
 
201 35 csantifort
assign address = core_stall ? i_address    [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
202
                              i_address_nxt[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] ;
203 16 csantifort
 
204
// ======================================
205
// Outputs
206
// ======================================
207
 
208 35 csantifort
assign read_data128 = wb_hit ? i_wb_cached_rdata : hit_rdata;
209
 
210
assign o_read_data  = i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? read_data128 [31:0]   :
211
                      i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? read_data128 [63:32]  :
212
                      i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? read_data128 [95:64]  :
213
                                                                     read_data128 [127:96] ;
214
 
215 16 csantifort
// 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 35 csantifort
assign o_wb_cached_req = ( (read_miss || write_miss || write_hit) && c_state == CS_IDLE ) || consecutive_write;
223 16 csantifort
 
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 39 csantifort
                    c_state <= CS_FILL;
267 16 csantifort
                else if ( write_hit )
268
                    begin
269 35 csantifort
                    if ( i_wb_cached_ready )
270 39 csantifort
                        c_state <= CS_WRITE_HIT;
271 16 csantifort
                    else
272
                        c_state <= CS_WRITE_HIT_WAIT_WB;
273
                    end
274 35 csantifort
                else if ( write_miss && !i_wb_cached_ready )
275 16 csantifort
                        c_state <= CS_WRITE_MISS_WAIT_WB;
276
                end
277
 
278 35 csantifort
 
279 39 csantifort
             CS_FILL :
280 16 csantifort
                // third read of burst of 4
281
                // wb read request asserted, wait for ack
282 35 csantifort
                if ( i_wb_cached_ready )
283 16 csantifort
                    begin
284
                    c_state     <= CS_FILL_COMPLETE;
285
                    source_sel  <= 1'd1 << C_FILL;
286
 
287
                    // Pick a way to write the cache update into
288
                    // Either pick one of the invalid caches, or if all are valid, then pick
289
                    // one randomly
290
 
291
                    select_way  <= next_way;
292
                    random_num  <= {random_num[2], random_num[1], random_num[0],
293
                                     random_num[3]^random_num[2]};
294
                    end
295
 
296
 
297
             // Write the read fetch data in this cycle
298
             CS_FILL_COMPLETE :
299
                begin
300
                // Back to normal cache operations, but
301
                // use physical address for first read as
302
                // address moved before the stall was asserted for the read_miss
303
                // However don't use it if its a non-cached address!
304
                source_sel  <= 1'd1 << C_CORE;
305
                c_state     <= CS_TURN_AROUND;
306
                end
307
 
308
 
309
             // Ignore the tag read data in this cycle   
310
             // Wait 1 cycle to pre-read the cache and return to normal operation                 
311
             CS_TURN_AROUND :
312
                begin
313
                c_state     <= CS_IDLE;
314
                end
315
 
316
 
317
             // Flush the entry matching an exclusive access         
318
             CS_EX_DELETE:
319
                begin
320
                `ifdef A25_CACHE_DEBUG
321
                `TB_DEBUG_MESSAGE
322
                $display("Cache deleted Locked entry");
323
                `endif
324
                c_state    <= CS_TURN_AROUND;
325
                source_sel <= 1'd1 << C_CORE;
326
                end
327
 
328
 
329 39 csantifort
             CS_WRITE_HIT:
330 16 csantifort
                if ( !consecutive_write )
331
                    c_state     <= CS_IDLE;
332
 
333
 
334
             CS_WRITE_HIT_WAIT_WB:
335
                // wait for an ack on the wb bus to complete the write
336 35 csantifort
                if ( i_wb_cached_ready )
337 16 csantifort
                    c_state     <= CS_IDLE;
338
 
339
 
340
             CS_WRITE_MISS_WAIT_WB:
341
                // wait for an ack on the wb bus to complete the write
342 35 csantifort
                if ( i_wb_cached_ready )
343 16 csantifort
                    c_state     <= CS_IDLE;
344
 
345
        endcase
346
 
347
 
348
// ======================================
349
// Capture WB Block Read - burst of 4 words
350
// ======================================
351
always @ ( posedge i_clk )
352 35 csantifort
    if ( i_wb_cached_ready )
353
        wb_rdata_burst <= i_wb_cached_rdata;
354 16 csantifort
 
355
 
356
 
357
// ======================================
358
// Miss Address
359
// ======================================
360
always @ ( posedge i_clk )
361 35 csantifort
    if ( o_wb_cached_req || write_hit )
362 16 csantifort
        miss_address <= i_address;
363
 
364
always @ ( posedge i_clk )
365
    if ( write_hit )
366
        begin
367
        data_hit_way_r      <= data_hit_way;
368
        end
369
 
370
always @ ( posedge i_clk )
371
    if ( write_hit || consecutive_write )
372
        begin
373
        data_wdata_r   <= data_wdata;
374
        end
375
 
376
assign consecutive_write = miss_address[31:4] == i_address[31:4] &&
377
                           i_write_enable &&
378 39 csantifort
                           c_state == CS_WRITE_HIT &&
379 16 csantifort
                           request_pulse;
380
 
381
 
382
always @(posedge i_clk)
383 35 csantifort
    if ( o_wb_cached_req )
384 16 csantifort
        wb_address <= i_address;
385 35 csantifort
    else if ( i_wb_cached_ready && fill_state )
386 16 csantifort
        wb_address <= {wb_address[31:4], wb_address[3:2] + 1'd1, 2'd0};
387
 
388 39 csantifort
assign fill_state       = c_state == CS_FILL ;
389 35 csantifort
assign wb_hit           = i_address == wb_address && i_wb_cached_ready && fill_state;
390 16 csantifort
 
391
 
392
// ======================================
393
// Hold Requests
394
// ======================================
395
always @(posedge i_clk)
396
    request_r <= (request_pulse || request_r) && o_stall;
397
 
398
assign request_hold = request_pulse || request_r;
399
 
400
 
401
// ======================================
402
// Remember Read-Modify-Write Hit
403
// ======================================
404
assign ex_read_hit_clear = c_state == CS_EX_DELETE;
405
 
406
always @ ( posedge i_clk )
407
    if ( ex_read_hit_clear )
408
        begin
409
        ex_read_hit_r   <= 1'd0;
410
        ex_read_hit_way <= 'd0;
411
        end
412
    else if ( ex_read_hit )
413
        begin
414
 
415
        `ifdef A25_CACHE_DEBUG
416
            `TB_DEBUG_MESSAGE
417
            $display ("Exclusive access cache hit address 0x%08h", i_address);
418
        `endif
419
 
420
        ex_read_hit_r   <= 1'd1;
421
        ex_read_hit_way <= data_hit_way;
422
        end
423
    else if ( c_state == CS_FILL_COMPLETE && ex_read_hit_r )
424
        ex_read_hit_way <= select_way;
425
 
426
 
427
always @ (posedge i_clk)
428
    if ( ex_read_hit )
429
        ex_read_address <= i_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB];
430
 
431
 
432
assign tag_address      = source_sel[C_FILL] ? miss_address      [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
433
                          source_sel[C_INVA] ? ex_read_address                                       :
434
                          source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0]                      :
435
                          source_sel[C_CORE] ? address                                               :
436
                                               {CACHE_ADDR_WIDTH{1'd0}}                              ;
437
 
438
 
439
assign data_address     = consecutive_write  ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
440
                          write_hit          ? i_address   [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
441
                          source_sel[C_FILL] ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
442
                          source_sel[C_CORE] ? address                                         :
443
                                               {CACHE_ADDR_WIDTH{1'd0}}                        ;
444
 
445
 
446
assign tag_wdata        = source_sel[C_FILL] ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} :
447
                                               {TAG_WIDTH{1'd0}}                       ;
448
 
449
 
450
    // Data comes in off the WB bus in wrap4 with the missed data word first
451
assign data_wdata       = write_hit && c_state == CS_IDLE ? write_hit_wdata :
452
                          consecutive_write               ? consecutive_write_wdata :
453
                                                            read_miss_wdata ;
454
 
455 35 csantifort
assign read_miss_wdata  = wb_rdata_burst;
456 16 csantifort
 
457
 
458
assign write_hit_wdata  = i_address[3:2] == 2'd0 ? {hit_rdata[127:32], write_data_word                   } :
459
                          i_address[3:2] == 2'd1 ? {hit_rdata[127:64], write_data_word, hit_rdata[31:0]  } :
460
                          i_address[3:2] == 2'd2 ? {hit_rdata[127:96], write_data_word, hit_rdata[63:0]  } :
461
                                                   {                   write_data_word, hit_rdata[95:0]  } ;
462
wire [31:0] con_read_data_word;
463
wire [31:0] con_write_data_word;
464
 
465
assign consecutive_write_wdata =
466
                          i_address[3:2] == 2'd0 ? {data_wdata_r[127:32], con_write_data_word                           } :
467
                          i_address[3:2] == 2'd1 ? {data_wdata_r[127:64], con_write_data_word, data_wdata_r[31:0]  } :
468
                          i_address[3:2] == 2'd2 ? {data_wdata_r[127:96], con_write_data_word, data_wdata_r[63:0]  } :
469
                                                   {                      con_write_data_word, data_wdata_r[95:0]  } ;
470
assign con_read_data_word =
471
                          i_address[3:2] == 2'd0 ? data_wdata_r[ 31:  0] :
472
                          i_address[3:2] == 2'd1 ? data_wdata_r[ 63: 32] :
473
                          i_address[3:2] == 2'd2 ? data_wdata_r[ 95: 64] :
474
                                                   data_wdata_r[127: 96] ;
475
 
476
 
477 60 csantifort
assign con_write_data_word  =
478
                          i_byte_enable == 4'b0001 ? { con_read_data_word[31: 8], i_write_data[ 7: 0]                          } :
479
                          i_byte_enable == 4'b0010 ? { con_read_data_word[31:16], i_write_data[15: 8], con_read_data_word[ 7:0]} :
480
                          i_byte_enable == 4'b0100 ? { con_read_data_word[31:24], i_write_data[23:16], con_read_data_word[15:0]} :
481
                          i_byte_enable == 4'b1000 ? {                            i_write_data[31:24], con_read_data_word[23:0]} :
482
                          i_byte_enable == 4'b0011 ? { con_read_data_word[31:16], i_write_data[15: 0]                          } :
483
                          i_byte_enable == 4'b1100 ? {                            i_write_data[31:16], con_read_data_word[15:0]} :
484
                                                                   i_write_data                                                  ;
485 16 csantifort
 
486
 
487
 
488
 
489
// Use Byte Enables
490
assign write_data_word  = i_byte_enable == 4'b0001 ? { o_read_data[31: 8], i_write_data[ 7: 0]                   } :
491
                          i_byte_enable == 4'b0010 ? { o_read_data[31:16], i_write_data[15: 8], o_read_data[ 7:0]} :
492
                          i_byte_enable == 4'b0100 ? { o_read_data[31:24], i_write_data[23:16], o_read_data[15:0]} :
493
                          i_byte_enable == 4'b1000 ? {                     i_write_data[31:24], o_read_data[23:0]} :
494
                          i_byte_enable == 4'b0011 ? { o_read_data[31:16], i_write_data[15: 0]                   } :
495
                          i_byte_enable == 4'b1100 ? {                     i_write_data[31:16], o_read_data[15:0]} :
496
                                                     i_write_data                                                  ;
497
 
498
 
499
assign tag_wenable      = source_sel[C_INVA] ? 1'd1  :
500
                          source_sel[C_FILL] ? 1'd1  :
501
                          source_sel[C_INIT] ? 1'd1  :
502
                          source_sel[C_CORE] ? 1'd0  :
503
                                               1'd0  ;
504
 
505
 
506
assign request_pulse    = i_request && i_cache_enable;
507
 
508
assign exclusive_access = i_exclusive && i_cache_enable;
509
 
510
 
511
assign idle_hit         = |data_hit_way;
512
 
513
assign write_hit        = request_hold &&  i_write_enable && idle_hit;
514
 
515
assign write_miss       = request_hold &&  i_write_enable && !idle_hit && !consecutive_write;
516
 
517
assign read_miss        = request_hold && !idle_hit && !i_write_enable;
518
 
519
                          // Exclusive read idle_hit
520
assign ex_read_hit      = exclusive_access && !i_write_enable && idle_hit;
521
 
522
                          // Added to fix rare swap bug which occurs when the cache starts
523
                          // a fill just as the swap instruction starts to execute. The cache
524
                          // fails to check for a read idle_hit on the swap read cycle.
525
                          // This signal stalls the core in that case until after the
526
                          // fill has completed.
527
assign ex_read_cache_busy = exclusive_access && !i_write_enable && c_state != CS_IDLE;
528
 
529
                          // Need to stall for a write miss to wait for the current wb 
530
                          // read miss access to complete. Also for a write idle_hit, need 
531
                          // to stall for 1 cycle while the data cache is being written to
532 39 csantifort
assign write_state      = c_state == CS_IDLE || c_state == CS_WRITE_HIT ||
533 16 csantifort
                          c_state == CS_WRITE_HIT_WAIT_WB ||  c_state == CS_WRITE_MISS_WAIT_WB;
534
 
535 35 csantifort
assign write_stall      = (write_miss && !(i_wb_cached_ready && write_state)) || (write_hit && !i_wb_cached_ready);
536 16 csantifort
 
537
assign read_stall       = request_hold && !idle_hit && !rbuf_hit && !wb_hit && !i_write_enable;
538
 
539
assign cache_busy_stall = c_state == CS_FILL_COMPLETE || c_state == CS_TURN_AROUND || c_state == CS_INIT ||
540 35 csantifort
                          (fill_state && !rbuf_hit && !wb_hit) ||
541 39 csantifort
                          (c_state == CS_WRITE_HIT && !consecutive_write);
542 16 csantifort
 
543
 
544
// ======================================
545
// Instantiate RAMS
546
// ======================================
547
 
548
generate
549
    for ( i=0; i<WAYS;i=i+1 ) begin : rams
550
 
551
        // Tag RAMs 
552
        `ifdef XILINX_SPARTAN6_FPGA
553
        xs6_sram_256x21_line_en
554
        `endif
555
 
556
        `ifdef XILINX_VIRTEX6_FPGA
557
        xv6_sram_256x21_line_en
558
        `endif
559
 
560
        `ifndef XILINX_FPGA
561
        generic_sram_line_en
562
        `endif
563
 
564
            #(
565
            .DATA_WIDTH                 ( TAG_WIDTH             ),
566
            .INITIALIZE_TO_ZERO         ( 1                     ),
567
            .ADDRESS_WIDTH              ( CACHE_ADDR_WIDTH      ))
568
        u_tag (
569
            .i_clk                      ( i_clk                 ),
570
            .i_write_data               ( tag_wdata             ),
571
            .i_write_enable             ( tag_wenable_way[i]    ),
572
            .i_address                  ( tag_address           ),
573
 
574
            .o_read_data                ( tag_rdata_way[i]      )
575
            );
576
 
577
        // Data RAMs 
578
        `ifdef XILINX_SPARTAN6_FPGA
579
        xs6_sram_256x128_byte_en
580
        `endif
581
 
582
        `ifdef XILINX_VIRTEX6_FPGA
583
        xv6_sram_256x128_byte_en
584
        `endif
585
 
586
        `ifndef XILINX_FPGA
587
        generic_sram_byte_en
588
        `endif
589
 
590
            #(
591
            .DATA_WIDTH    ( CACHE_LINE_WIDTH) ,
592
            .ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )
593
        u_data (
594
            .i_clk                      ( i_clk                         ),
595
            .i_write_data               ( data_wdata                    ),
596
            .i_write_enable             ( data_wenable_way[i]           ),
597
            .i_address                  ( data_address                  ),
598
            .i_byte_enable              ( {CACHE_LINE_WIDTH/8{1'd1}}    ),
599
            .o_read_data                ( data_rdata_way[i]             )
600
            );
601
 
602
 
603
        // Per tag-ram write-enable
604
        assign tag_wenable_way[i]  = tag_wenable && ( select_way[i] || source_sel[C_INIT] );
605
 
606
        // Per data-ram write-enable
607
        assign data_wenable_way[i] = (source_sel[C_FILL] && select_way[i]) ||
608
                                     (write_hit && data_hit_way[i] && c_state == CS_IDLE) ||
609
                                     (consecutive_write && data_hit_way_r[i]);
610
        // Per data-ram idle_hit flag
611
        assign data_hit_way[i]     = tag_rdata_way[i][TAG_WIDTH-1] &&
612
                                     tag_rdata_way[i][TAG_ADDR_WIDTH-1:0] == i_address[31:TAG_ADDR32_LSB] &&
613
                                     c_state == CS_IDLE;
614
    end
615
endgenerate
616
 
617
 
618
// ======================================
619
// Register Valid Bits
620
// ======================================
621
generate
622
if ( WAYS == 2 ) begin : valid_bits_2ways
623
 
624
    always @ ( posedge i_clk )
625
        if ( c_state == CS_IDLE )
626
            valid_bits_r <= {tag_rdata_way[1][TAG_WIDTH-1],
627
                             tag_rdata_way[0][TAG_WIDTH-1]};
628
 
629
end
630
else if ( WAYS == 3 ) begin : valid_bits_3ways
631
 
632
    always @ ( posedge i_clk )
633
        if ( c_state == CS_IDLE )
634
            valid_bits_r <= {tag_rdata_way[2][TAG_WIDTH-1],
635
                             tag_rdata_way[1][TAG_WIDTH-1],
636
                             tag_rdata_way[0][TAG_WIDTH-1]};
637
 
638
end
639
else if ( WAYS == 4 ) begin : valid_bits_4ways
640
 
641
    always @ ( posedge i_clk )
642
        if ( c_state == CS_IDLE )
643
            valid_bits_r <= {tag_rdata_way[3][TAG_WIDTH-1],
644
                             tag_rdata_way[2][TAG_WIDTH-1],
645
                             tag_rdata_way[1][TAG_WIDTH-1],
646
                             tag_rdata_way[0][TAG_WIDTH-1]};
647
 
648
end
649
else begin : valid_bits_8ways
650
 
651
    always @ ( posedge i_clk )
652
        if ( c_state == CS_IDLE )
653
            valid_bits_r <= {tag_rdata_way[7][TAG_WIDTH-1],
654
                             tag_rdata_way[6][TAG_WIDTH-1],
655
                             tag_rdata_way[5][TAG_WIDTH-1],
656
                             tag_rdata_way[4][TAG_WIDTH-1],
657
                             tag_rdata_way[3][TAG_WIDTH-1],
658
                             tag_rdata_way[2][TAG_WIDTH-1],
659
                             tag_rdata_way[1][TAG_WIDTH-1],
660
                             tag_rdata_way[0][TAG_WIDTH-1]};
661
 
662
end
663
endgenerate
664
 
665
 
666
// ======================================
667
// Select read idle_hit data
668
// ======================================
669
 
670
generate
671
if ( WAYS == 2 ) begin : read_data_2ways
672
 
673
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
674
                          data_hit_way[1] ? data_rdata_way[1] :
675
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
676
 
677
end
678
else if ( WAYS == 3 ) begin : read_data_3ways
679
 
680
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
681
                          data_hit_way[1] ? data_rdata_way[1] :
682
                          data_hit_way[2] ? data_rdata_way[2] :
683
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
684
 
685
end
686
else if ( WAYS == 4 ) begin : read_data_4ways
687
 
688
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
689
                          data_hit_way[1] ? data_rdata_way[1] :
690
                          data_hit_way[2] ? data_rdata_way[2] :
691
                          data_hit_way[3] ? data_rdata_way[3] :
692
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
693
 
694
end
695
else begin : read_data_8ways
696
 
697
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
698
                          data_hit_way[1] ? data_rdata_way[1] :
699
                          data_hit_way[2] ? data_rdata_way[2] :
700
                          data_hit_way[3] ? data_rdata_way[3] :
701
                          data_hit_way[4] ? data_rdata_way[4] :
702
                          data_hit_way[5] ? data_rdata_way[5] :
703
                          data_hit_way[6] ? data_rdata_way[6] :
704
                          data_hit_way[7] ? data_rdata_way[7] :
705
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
706
 
707
end
708
endgenerate
709
 
710
 
711
// ======================================
712
// Function to select the way to use
713
// for fills
714
// ======================================
715
generate
716
if ( WAYS == 2 ) begin : pick_way_2ways
717
 
718
    assign next_way = pick_way ( valid_bits_r, random_num );
719
 
720
    function [WAYS-1:0] pick_way;
721
    input [WAYS-1:0] valid_bits;
722
    input [3:0]      random_num;
723
    begin
724
        if (      valid_bits[0] == 1'd0 )
725
            // way 0 not occupied so use it
726
            pick_way     = 2'b01;
727
        else if ( valid_bits[1] == 1'd0 )
728
            // way 1 not occupied so use it
729
            pick_way     = 2'b10;
730
        else
731
            begin
732
            // All ways occupied so pick one randomly
733
            case (random_num[3:1])
734
                3'd0, 3'd3,
735
                3'd5, 3'd6: pick_way = 2'b10;
736
                default:    pick_way = 2'b01;
737
            endcase
738
            end
739
    end
740
    endfunction
741
 
742
end
743
else if ( WAYS == 3 ) begin : pick_way_3ways
744
 
745
    assign next_way = pick_way ( valid_bits_r, random_num );
746
 
747
    function [WAYS-1:0] pick_way;
748
    input [WAYS-1:0] valid_bits;
749
    input [3:0]      random_num;
750
    begin
751
        if (      valid_bits[0] == 1'd0 )
752
            // way 0 not occupied so use it
753
            pick_way     = 3'b001;
754
        else if ( valid_bits[1] == 1'd0 )
755
            // way 1 not occupied so use it
756
            pick_way     = 3'b010;
757
        else if ( valid_bits[2] == 1'd0 )
758
            // way 2 not occupied so use it
759
            pick_way     = 3'b100;
760
        else
761
            begin
762
            // All ways occupied so pick one randomly
763
            case (random_num[3:1])
764
                3'd0, 3'd1, 3'd2: pick_way = 3'b010;
765
                3'd2, 3'd3, 3'd4: pick_way = 3'b100;
766
                default:          pick_way = 3'b001;
767
            endcase
768
            end
769
    end
770
    endfunction
771
 
772
end
773
else if ( WAYS == 4 ) begin : pick_way_4ways
774
 
775
    assign next_way = pick_way ( valid_bits_r, random_num );
776
 
777
    function [WAYS-1:0] pick_way;
778
    input [WAYS-1:0] valid_bits;
779
    input [3:0]      random_num;
780
    begin
781
        if (      valid_bits[0] == 1'd0 )
782
            // way 0 not occupied so use it
783
            pick_way     = 4'b0001;
784
        else if ( valid_bits[1] == 1'd0 )
785
            // way 1 not occupied so use it
786
            pick_way     = 4'b0010;
787
        else if ( valid_bits[2] == 1'd0 )
788
            // way 2 not occupied so use it
789
            pick_way     = 4'b0100;
790
        else if ( valid_bits[3] == 1'd0 )
791
            // way 3 not occupied so use it
792
            pick_way     = 4'b1000;
793
        else
794
            begin
795
            // All ways occupied so pick one randomly
796
            case (random_num[3:1])
797
                3'd0, 3'd1: pick_way = 4'b0100;
798
                3'd2, 3'd3: pick_way = 4'b1000;
799
                3'd4, 3'd5: pick_way = 4'b0001;
800
                default:    pick_way = 4'b0010;
801
            endcase
802
            end
803
    end
804
    endfunction
805
 
806
end
807
else begin : pick_way_8ways
808
 
809
    assign next_way = pick_way ( valid_bits_r, random_num );
810
 
811
    function [WAYS-1:0] pick_way;
812
    input [WAYS-1:0] valid_bits;
813
    input [3:0]      random_num;
814
    begin
815
        if (      valid_bits[0] == 1'd0 )
816
            // way 0 not occupied so use it
817
            pick_way     = 8'b00000001;
818
        else if ( valid_bits[1] == 1'd0 )
819
            // way 1 not occupied so use it
820
            pick_way     = 8'b00000010;
821
        else if ( valid_bits[2] == 1'd0 )
822
            // way 2 not occupied so use it
823
            pick_way     = 8'b00000100;
824
        else if ( valid_bits[3] == 1'd0 )
825
            // way 3 not occupied so use it
826
            pick_way     = 8'b00001000;
827
        else if ( valid_bits[4] == 1'd0 )
828
            // way 3 not occupied so use it
829
            pick_way     = 8'b00010000;
830
        else if ( valid_bits[5] == 1'd0 )
831
            // way 3 not occupied so use it
832
            pick_way     = 8'b00100000;
833
        else if ( valid_bits[6] == 1'd0 )
834
            // way 3 not occupied so use it
835
            pick_way     = 8'b01000000;
836
        else if ( valid_bits[7] == 1'd0 )
837
            // way 3 not occupied so use it
838
            pick_way     = 8'b10000000;
839
        else
840
            begin
841
            // All ways occupied so pick one randomly
842
            case (random_num[3:1])
843
                3'd0:       pick_way = 8'b00010000;
844
                3'd1:       pick_way = 8'b00100000;
845
                3'd2:       pick_way = 8'b01000000;
846
                3'd3:       pick_way = 8'b10000000;
847
                3'd4:       pick_way = 8'b00000001;
848
                3'd5:       pick_way = 8'b00000010;
849
                3'd6:       pick_way = 8'b00000100;
850
                default:    pick_way = 8'b00001000;
851
            endcase
852
            end
853
    end
854
    endfunction
855
 
856
end
857
endgenerate
858
 
859
 
860
// ========================================================
861
// Debug WB bus - not synthesizable
862
// ========================================================
863
//synopsys translate_off
864
wire    [(6*8)-1:0]     xSOURCE_SEL;
865
wire    [(22*8)-1:0]    xC_STATE;
866
 
867
assign xSOURCE_SEL = source_sel[C_CORE]               ? "C_CORE"                :
868
                     source_sel[C_INIT]               ? "C_INIT"                :
869
                     source_sel[C_FILL]               ? "C_FILL"                :
870
                     source_sel[C_INVA]               ? "C_INVA"                :
871
                                                        "UNKNON"                ;
872
 
873 39 csantifort
assign xC_STATE    = c_state == CS_INIT               ? "INIT"               :
874
                     c_state == CS_IDLE               ? "IDLE"               :
875
                     c_state == CS_FILL               ? "FILL"               :
876
                     c_state == CS_FILL_COMPLETE      ? "FILL_COMPLETE"      :
877
                     c_state == CS_EX_DELETE          ? "EX_DELETE"          :
878
                     c_state == CS_TURN_AROUND        ? "TURN_AROUND"        :
879
                     c_state == CS_WRITE_HIT          ? "WRITE_HIT"          :
880
                     c_state == CS_WRITE_HIT_WAIT_WB  ? "WRITE_HIT_WAIT_WB"  :
881
                     c_state == CS_WRITE_MISS_WAIT_WB ? "WRITE_MISS_WAIT_WB" :
882 16 csantifort
                                                        "UNKNOWN"               ;
883
 
884
 
885
generate
886
if ( WAYS == 2 ) begin : check_hit_2ways
887
 
888
    always @( posedge i_clk )
889
        if ( (data_hit_way[0] + data_hit_way[1] ) > 4'd1 )
890
            begin
891
            `TB_ERROR_MESSAGE
892
            $display("Hit in more than one cache ways!");
893
            end
894
 
895
end
896
else if ( WAYS == 3 ) begin : check_hit_3ways
897
 
898
    always @( posedge i_clk )
899
        if ( (data_hit_way[0] + data_hit_way[1] + data_hit_way[2] ) > 4'd1 )
900
            begin
901
            `TB_ERROR_MESSAGE
902
            $display("Hit in more than one cache ways!");
903
            end
904
 
905
end
906
else if ( WAYS == 4 ) begin : check_hit_4ways
907
 
908
    always @( posedge i_clk )
909
        if ( (data_hit_way[0] + data_hit_way[1] +
910
              data_hit_way[2] + data_hit_way[3] ) > 4'd1 )
911
            begin
912
            `TB_ERROR_MESSAGE
913
            $display("Hit in more than one cache ways!");
914
            end
915
 
916
end
917
else if ( WAYS == 8 )  begin : check_hit_8ways
918
 
919
    always @( posedge i_clk )
920
        if ( (data_hit_way[0] + data_hit_way[1] +
921
              data_hit_way[2] + data_hit_way[3] +
922
              data_hit_way[4] + data_hit_way[5] +
923
              data_hit_way[6] + data_hit_way[7] ) > 4'd1 )
924
            begin
925
            `TB_ERROR_MESSAGE
926
            $display("Hit in more than one cache ways!");
927
            end
928
 
929
end
930
else begin : check_hit_nways
931
 
932
    initial
933
        begin
934
        `TB_ERROR_MESSAGE
935
        $display("Unsupported number of ways %0d", WAYS);
936
        $display("Set A25_DCACHE_WAYS in a25_config_defines.v to either 2,3,4 or 8");
937
        end
938
 
939
end
940
endgenerate
941
 
942
 
943
//synopsys translate_on
944
 
945
endmodule
946
 

powered by: WebSVN 2.1.0

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