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

Subversion Repositories amber

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

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

powered by: WebSVN 2.1.0

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