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

Subversion Repositories amber

[/] [amber/] [trunk/] [hw/] [vlog/] [amber25/] [a25_icache.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_icache
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_ICACHE_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
input                               i_core_stall,
86
output                              o_stall,
87
 
88
// Read / Write requests from core
89
input                               i_select,
90
input      [31:0]                   i_address,          // registered address from execute
91
input      [31:0]                   i_address_nxt,      // un-registered version of address from execute stage
92
input                               i_cache_enable,     // from co-processor 15 configuration register
93
input                               i_cache_flush,      // from co-processor 15 register
94
 
95
output      [31:0]                  o_read_data,
96
 
97
// WB Read Request                                                          
98
output                              o_wb_req,          // Read Request
99
input      [31:0]                   i_wb_read_data,
100
input                               i_wb_ready
101
);
102
 
103
`include "a25_localparams.v"
104
`include "a25_functions.v"
105
 
106
// One-hot encoded
107
localparam       C_INIT   = 0,
108
                 C_CORE   = 1,
109
                 C_FILL   = 2,
110
                 C_INVA   = 3,
111
                 C_STATES = 4;
112
 
113
localparam [3:0] CS_INIT            = 4'd0,
114
                 CS_IDLE            = 4'd1,
115
                 CS_FILL0           = 4'd2,
116
                 CS_FILL1           = 4'd3,
117
                 CS_FILL2           = 4'd4,
118
                 CS_FILL3           = 4'd5,
119
                 CS_FILL4           = 4'd6,
120
                 CS_FILL_COMPLETE   = 4'd7,
121
                 CS_TURN_AROUND     = 4'd8,
122
                 CS_WRITE_HIT1      = 4'd9,
123
                 CS_EX_DELETE       = 4'd10;
124
 
125
 
126
reg  [3:0]                  c_state    = CS_IDLE;
127
reg  [C_STATES-1:0]         source_sel = 1'd1 << C_CORE;
128
reg  [CACHE_ADDR_WIDTH:0]   init_count = 'd0;
129
 
130
wire [TAG_WIDTH-1:0]        tag_rdata_way [WAYS-1:0];
131
wire [CACHE_LINE_WIDTH-1:0] data_rdata_way[WAYS-1:0];
132
wire [WAYS-1:0]             data_wenable_way;
133
wire [WAYS-1:0]             data_hit_way;
134
wire [WAYS-1:0]             tag_wenable_way;
135
reg  [WAYS-1:0]             select_way = 'd0;
136
wire [WAYS-1:0]             next_way;
137
reg  [WAYS-1:0]             valid_bits_r = 'd0;
138
 
139
reg  [3:0]                  random_num = 4'hf;
140
 
141
wire [CACHE_ADDR_WIDTH-1:0] tag_address;
142
wire [TAG_WIDTH-1:0]        tag_wdata;
143
wire                        tag_wenable;
144
 
145
wire [CACHE_LINE_WIDTH-1:0] data_wdata;
146
wire [CACHE_ADDR_WIDTH-1:0] data_address;
147
wire [31:0]                 write_data_word;
148
 
149
wire                        idle_hit;
150
wire                        read_miss;
151
wire                        read_miss_fill;
152
wire                        invalid_read;
153
wire                        fill_state;
154
 
155
reg  [31:0]                 miss_address = 'd0;
156
wire [CACHE_LINE_WIDTH-1:0] hit_rdata;
157
 
158
wire                        cache_busy_stall;
159
wire                        read_stall;
160
 
161
wire                        enable;
162
wire [CACHE_ADDR_WIDTH-1:0] address;
163
wire [31:0]                 address_c;
164
reg  [31:0]                 address_r = 'd0;
165
 
166
reg  [CACHE_LINE_WIDTH-1:0] wb_rdata_burst_r = 'd0;
167
wire [CACHE_LINE_WIDTH-1:0] wb_rdata_burst;
168
 
169
reg  [31:0]                 wb_address = 'd0;
170
wire                        rbuf_hit = 'd0;
171
wire                        wb_hit;
172
genvar                      i;
173
 
174
// ======================================
175
// Address to use for cache access
176
// ======================================
177
// If currently stalled then the address for the next
178
// cycle will be the same as it is in the current cycle
179
//
180
assign address_c = i_core_stall ? i_address    : //[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
181
                                i_address_nxt; //[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] ;
182
 
183
assign address   = address_c[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB];
184
 
185
// ======================================
186
// Outputs
187
// ======================================
188
assign o_read_data      = wb_hit                                       ? i_wb_read_data     :
189
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? hit_rdata [31:0]   :
190
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? hit_rdata [63:32]  :
191
                          i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? hit_rdata [95:64]  :
192
                                                                         hit_rdata [127:96] ;
193
 
194
// Don't allow the cache to stall the wb i/f for an exclusive access
195
// The cache needs a couple of cycles to flush a potential copy of the exclusive
196
// address, but the wb can do the access in parallel. So there is no
197
// stall in the state CS_EX_DELETE, even though the cache is out of action. 
198
// This works fine as long as the wb is stalling the core
199
assign o_stall          = read_stall  || cache_busy_stall;
200
 
201
assign o_wb_req         = read_miss && c_state == CS_IDLE;
202
 
203
 
204
// ======================================
205
// Cache State Machine
206
// ======================================
207
 
208
// Little State Machine to Flush Tag RAMS
209
always @ ( posedge i_clk )
210
    if ( i_cache_flush )
211
        begin
212
        c_state     <= CS_INIT;
213
        source_sel  <= 1'd1 << C_INIT;
214
        init_count  <= 'd0;
215
        `ifdef A25_CACHE_DEBUG
216
        `TB_DEBUG_MESSAGE
217
        $display("Cache Flush");
218
        `endif
219
        end
220
    else
221
        case ( c_state )
222
            CS_INIT :
223
                if ( init_count < CACHE_LINES [CACHE_ADDR_WIDTH:0] )
224
                    begin
225
                    init_count  <= init_count + 1'd1;
226
                    source_sel  <= 1'd1 << C_INIT;
227
                    end
228
                else
229
                    begin
230
                    source_sel  <= 1'd1 << C_CORE;
231
                    c_state     <= CS_TURN_AROUND;
232
                    end
233
 
234
             CS_IDLE :
235
                begin
236
                source_sel  <= 1'd1 << C_CORE;
237
 
238
                if ( read_miss )
239
                    c_state <= CS_FILL0;
240
               end
241
 
242
             CS_FILL0 :
243
                begin
244
                // wb read request asserted, wait for ack
245
                if ( i_wb_ready )
246
                    c_state <= CS_FILL1;
247
                end
248
 
249
             CS_FILL1 :
250
                begin
251
                // wb read request asserted, wait for ack
252
                if ( i_wb_ready )
253
                    c_state <= CS_FILL2;
254
                end
255
 
256
 
257
             CS_FILL2 :
258
                // first read of burst of 4
259
                // wb read request asserted, wait for ack
260
                if ( i_wb_ready )
261
                    c_state <= CS_FILL3;
262
 
263
 
264
             CS_FILL3 :
265
                begin
266
                select_way  <= next_way;
267
                random_num  <= {random_num[2], random_num[1], random_num[0],
268
                                 random_num[3]^random_num[2]};
269
 
270
                // third read of burst of 4
271
                // wb read request asserted, wait for ack
272
                if ( i_wb_ready )
273
                    begin
274
                    c_state     <= CS_FILL_COMPLETE;
275
 
276
                    // Pick a way to write the cache update into
277
                    // Either pick one of the invalid caches, or if all are valid, then pick
278
                    // one randomly
279
 
280
                    end
281
                end
282
 
283
 
284
             // Write the read fetch data in this cycle
285
             CS_FILL_COMPLETE :
286
                begin
287
                // Back to normal cache operations, but
288
                // use physical address for first read as
289
                // address moved before the stall was asserted for the read_miss
290
                // However don't use it if its a non-cached address!
291
                source_sel  <= 1'd1 << C_CORE;
292
                c_state     <= CS_TURN_AROUND;
293
                end
294
 
295
 
296
             // Ignore the tag read data in this cycle   
297
             // Wait 1 cycle to pre-read the cache and return to normal operation                 
298
             CS_TURN_AROUND :
299
                begin
300
                c_state     <= CS_IDLE;
301
                end
302
 
303
        endcase
304
 
305
 
306
// ======================================
307
// Capture WB Block Read - burst of 4 words
308
// ======================================
309
assign wb_rdata_burst = {i_wb_read_data, wb_rdata_burst_r[127:32]};
310
always @ ( posedge i_clk )
311
    if ( i_wb_ready )
312
        wb_rdata_burst_r <= wb_rdata_burst;
313
 
314
 
315
// ======================================
316
// Miss Address
317
// ======================================
318
always @ ( posedge i_clk )
319
    if ( c_state == CS_IDLE )
320
        miss_address <= i_address;
321
 
322
 
323
always @ ( posedge i_clk )
324
    address_r <= address_c;
325
 
326
assign invalid_read = address_r != i_address;
327
 
328
 
329
always @(posedge i_clk)
330
    if ( o_wb_req )
331
        wb_address <= i_address;
332
    else if ( i_wb_ready && fill_state )
333
        wb_address <= {wb_address[31:4], wb_address[3:2] + 1'd1, 2'd0};
334
 
335
assign fill_state       = c_state == CS_FILL0 || c_state == CS_FILL1 || c_state == CS_FILL2 || c_state == CS_FILL3 ;
336
assign wb_hit           = i_address == wb_address && i_wb_ready && fill_state;
337
 
338
assign tag_address      = read_miss_fill     ? miss_address      [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
339
                          source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0]                      :
340
                                               address                                               ;
341
 
342
 
343
assign data_address     = read_miss_fill     ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
344
                                               address                                         ;
345
 
346
 
347
assign tag_wdata        = read_miss_fill     ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} :
348
                                               {TAG_WIDTH{1'd0}}                       ;
349
 
350
 
351
// Data comes in off the WB bus in wrap4 with the missed data word first
352
assign data_wdata       = miss_address[3:2] == 2'd0 ? { wb_rdata_burst[127:0]                        }:
353
                          miss_address[3:2] == 2'd1 ? { wb_rdata_burst[95:0], wb_rdata_burst[127:96] }:
354
                          miss_address[3:2] == 2'd2 ? { wb_rdata_burst[63:0], wb_rdata_burst[127:64] }:
355
                                                      { wb_rdata_burst[31:0], wb_rdata_burst[127:32] };
356
 
357
 
358
assign read_miss_fill   = c_state == CS_FILL3 && i_wb_ready;
359
 
360
 
361
 
362
assign tag_wenable      = read_miss_fill     ? 1'd1  :
363
                          source_sel[C_INVA] ? 1'd1  :
364
                          source_sel[C_FILL] ? 1'd1  :
365
                          source_sel[C_INIT] ? 1'd1  :
366
                          source_sel[C_CORE] ? 1'd0  :
367
                                               1'd0  ;
368
 
369
 
370
assign enable           = i_select && i_cache_enable;
371
 
372
assign idle_hit         = |data_hit_way;
373
 
374
assign read_miss        = enable && !idle_hit && !invalid_read;
375
 
376
assign read_stall       = enable && !idle_hit && !rbuf_hit && !wb_hit;
377
 
378
assign cache_busy_stall = (c_state == CS_TURN_AROUND  && enable) || c_state == CS_INIT;
379
 
380
 
381
// ======================================
382
// Instantiate RAMS
383
// ======================================
384
 
385
generate
386
    for ( i=0; i<WAYS;i=i+1 ) begin : rams
387
 
388
        // Tag RAMs 
389
        `ifdef XILINX_SPARTAN6_FPGA
390
        xs6_sram_256x21_line_en
391
        `endif
392
 
393
        `ifdef XILINX_VIRTEX6_FPGA
394
        xv6_sram_256x21_line_en
395
        `endif
396
 
397
        `ifndef XILINX_FPGA
398
        generic_sram_line_en
399
        `endif
400
 
401
            #(
402
            .DATA_WIDTH                 ( TAG_WIDTH             ),
403
            .INITIALIZE_TO_ZERO         ( 1                     ),
404
            .ADDRESS_WIDTH              ( CACHE_ADDR_WIDTH      ))
405
        u_tag (
406
            .i_clk                      ( i_clk                 ),
407
            .i_write_data               ( tag_wdata             ),
408
            .i_write_enable             ( tag_wenable_way[i]    ),
409
            .i_address                  ( tag_address           ),
410
 
411
            .o_read_data                ( tag_rdata_way[i]      )
412
            );
413
 
414
        // Data RAMs 
415
        `ifdef XILINX_SPARTAN6_FPGA
416
        xs6_sram_256x128_byte_en
417
        `endif
418
 
419
        `ifdef XILINX_VIRTEX6_FPGA
420
        xv6_sram_256x128_byte_en
421
        `endif
422
 
423
        `ifndef XILINX_FPGA
424
        generic_sram_byte_en
425
        `endif
426
 
427
            #(
428
            .DATA_WIDTH    ( CACHE_LINE_WIDTH) ,
429
            .ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )
430
        u_data (
431
            .i_clk                      ( i_clk                         ),
432
            .i_write_data               ( data_wdata                    ),
433
            .i_write_enable             ( data_wenable_way[i]           ),
434
            .i_address                  ( data_address                  ),
435
            .i_byte_enable              ( {CACHE_LINE_WIDTH/8{1'd1}}    ),
436
            .o_read_data                ( data_rdata_way[i]             )
437
            );
438
 
439
 
440
        // Per tag-ram write-enable
441
        assign tag_wenable_way[i]  = tag_wenable && ( select_way[i] || source_sel[C_INIT] );
442
 
443
        // Per data-ram write-enable
444
        assign data_wenable_way[i] = ( source_sel[C_FILL] || read_miss_fill ) && select_way[i];
445
 
446
        // Per data-ram idle_hit flag
447
        assign data_hit_way[i]     = tag_rdata_way[i][TAG_WIDTH-1] &&
448
                                     tag_rdata_way[i][TAG_ADDR_WIDTH-1:0] == i_address[31:TAG_ADDR32_LSB] &&
449
                                     c_state == CS_IDLE;
450
    end
451
endgenerate
452
 
453
 
454
// ======================================
455
// Register Valid Bits
456
// ======================================
457
generate
458
if ( WAYS == 2 ) begin : valid_bits_2ways
459
 
460
    always @ ( posedge i_clk )
461
        if ( c_state == CS_IDLE )
462
            valid_bits_r <= {tag_rdata_way[1][TAG_WIDTH-1],
463
                             tag_rdata_way[0][TAG_WIDTH-1]};
464
 
465
end
466
else if ( WAYS == 3 ) begin : valid_bits_3ways
467
 
468
    always @ ( posedge i_clk )
469
        if ( c_state == CS_IDLE )
470
            valid_bits_r <= {tag_rdata_way[2][TAG_WIDTH-1],
471
                             tag_rdata_way[1][TAG_WIDTH-1],
472
                             tag_rdata_way[0][TAG_WIDTH-1]};
473
 
474
end
475
else if ( WAYS == 4 ) begin : valid_bits_4ways
476
 
477
    always @ ( posedge i_clk )
478
        if ( c_state == CS_IDLE )
479
            valid_bits_r <= {tag_rdata_way[3][TAG_WIDTH-1],
480
                             tag_rdata_way[2][TAG_WIDTH-1],
481
                             tag_rdata_way[1][TAG_WIDTH-1],
482
                             tag_rdata_way[0][TAG_WIDTH-1]};
483
 
484
end
485
else begin : valid_bits_8ways
486
 
487
    always @ ( posedge i_clk )
488
        if ( c_state == CS_IDLE )
489
            valid_bits_r <= {tag_rdata_way[7][TAG_WIDTH-1],
490
                             tag_rdata_way[6][TAG_WIDTH-1],
491
                             tag_rdata_way[5][TAG_WIDTH-1],
492
                             tag_rdata_way[4][TAG_WIDTH-1],
493
                             tag_rdata_way[3][TAG_WIDTH-1],
494
                             tag_rdata_way[2][TAG_WIDTH-1],
495
                             tag_rdata_way[1][TAG_WIDTH-1],
496
                             tag_rdata_way[0][TAG_WIDTH-1]};
497
 
498
end
499
endgenerate
500
 
501
 
502
// ======================================
503
// Select read hit data
504
// ======================================
505
generate
506
if ( WAYS == 2 ) begin : read_data_2ways
507
 
508
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
509
                          data_hit_way[1] ? data_rdata_way[1] :
510
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
511
 
512
end
513
else if ( WAYS == 3 ) begin : read_data_3ways
514
 
515
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
516
                          data_hit_way[1] ? data_rdata_way[1] :
517
                          data_hit_way[2] ? data_rdata_way[2] :
518
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
519
 
520
end
521
else if ( WAYS == 4 ) begin : read_data_4ways
522
 
523
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
524
                          data_hit_way[1] ? data_rdata_way[1] :
525
                          data_hit_way[2] ? data_rdata_way[2] :
526
                          data_hit_way[3] ? data_rdata_way[3] :
527
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
528
 
529
end
530
else begin : read_data_8ways
531
 
532
    assign hit_rdata    = data_hit_way[0] ? data_rdata_way[0] :
533
                          data_hit_way[1] ? data_rdata_way[1] :
534
                          data_hit_way[2] ? data_rdata_way[2] :
535
                          data_hit_way[3] ? data_rdata_way[3] :
536
                          data_hit_way[4] ? data_rdata_way[4] :
537
                          data_hit_way[5] ? data_rdata_way[5] :
538
                          data_hit_way[6] ? data_rdata_way[6] :
539
                          data_hit_way[7] ? data_rdata_way[7] :
540
                                     {CACHE_LINE_WIDTH{1'd1}} ;  // all 1's for debug
541
 
542
end
543
endgenerate
544
 
545
 
546
// ======================================
547
// Function to select the way to use
548
// for fills
549
// ======================================
550
generate
551
if ( WAYS == 2 ) begin : pick_way_2ways
552
 
553
    assign next_way = pick_way ( valid_bits_r, random_num );
554
 
555
    function [WAYS-1:0] pick_way;
556
    input [WAYS-1:0] valid_bits;
557
    input [3:0]      random_num;
558
    begin
559
        if (      valid_bits[0] == 1'd0 )
560
            // way 0 not occupied so use it
561
            pick_way     = 2'b01;
562
        else if ( valid_bits[1] == 1'd0 )
563
            // way 1 not occupied so use it
564
            pick_way     = 2'b10;
565
        else
566
            begin
567
            // All ways occupied so pick one randomly
568
            case (random_num[3:1])
569
                3'd0, 3'd3,
570
                3'd5, 3'd6: pick_way = 2'b10;
571
                default:    pick_way = 2'b01;
572
            endcase
573
            end
574
    end
575
    endfunction
576
 
577
end
578
else if ( WAYS == 3 ) begin : pick_way_3ways
579
 
580
    assign next_way = pick_way ( valid_bits_r, random_num );
581
 
582
    function [WAYS-1:0] pick_way;
583
    input [WAYS-1:0] valid_bits;
584
    input [3:0]      random_num;
585
    begin
586
        if (      valid_bits[0] == 1'd0 )
587
            // way 0 not occupied so use it
588
            pick_way     = 3'b001;
589
        else if ( valid_bits[1] == 1'd0 )
590
            // way 1 not occupied so use it
591
            pick_way     = 3'b010;
592
        else if ( valid_bits[2] == 1'd0 )
593
            // way 2 not occupied so use it
594
            pick_way     = 3'b100;
595
        else
596
            begin
597
            // All ways occupied so pick one randomly
598
            case (random_num[3:1])
599
                3'd0, 3'd1, 3'd2: pick_way = 3'b010;
600
                3'd2, 3'd3, 3'd4: pick_way = 3'b100;
601
                default:          pick_way = 3'b001;
602
            endcase
603
            end
604
    end
605
    endfunction
606
 
607
end
608
else if ( WAYS == 4 ) begin : pick_way_4ways
609
 
610
    assign next_way = pick_way ( valid_bits_r, random_num );
611
 
612
    function [WAYS-1:0] pick_way;
613
    input [WAYS-1:0] valid_bits;
614
    input [3:0]      random_num;
615
    begin
616
        if (      valid_bits[0] == 1'd0 )
617
            // way 0 not occupied so use it
618
            pick_way     = 4'b0001;
619
        else if ( valid_bits[1] == 1'd0 )
620
            // way 1 not occupied so use it
621
            pick_way     = 4'b0010;
622
        else if ( valid_bits[2] == 1'd0 )
623
            // way 2 not occupied so use it
624
            pick_way     = 4'b0100;
625
        else if ( valid_bits[3] == 1'd0 )
626
            // way 3 not occupied so use it
627
            pick_way     = 4'b1000;
628
        else
629
            begin
630
            // All ways occupied so pick one randomly
631
            case (random_num[3:1])
632
                3'd0, 3'd1: pick_way = 4'b0100;
633
                3'd2, 3'd3: pick_way = 4'b1000;
634
                3'd4, 3'd5: pick_way = 4'b0001;
635
                default:    pick_way = 4'b0010;
636
            endcase
637
            end
638
    end
639
    endfunction
640
 
641
end
642
else begin : pick_way_8ways
643
 
644
    assign next_way = pick_way ( valid_bits_r, random_num );
645
 
646
    function [WAYS-1:0] pick_way;
647
    input [WAYS-1:0] valid_bits;
648
    input [3:0]      random_num;
649
    begin
650
        if (      valid_bits[0] == 1'd0 )
651
            // way 0 not occupied so use it
652
            pick_way     = 8'b00000001;
653
        else if ( valid_bits[1] == 1'd0 )
654
            // way 1 not occupied so use it
655
            pick_way     = 8'b00000010;
656
        else if ( valid_bits[2] == 1'd0 )
657
            // way 2 not occupied so use it
658
            pick_way     = 8'b00000100;
659
        else if ( valid_bits[3] == 1'd0 )
660
            // way 3 not occupied so use it
661
            pick_way     = 8'b00001000;
662
        else if ( valid_bits[4] == 1'd0 )
663
            // way 3 not occupied so use it
664
            pick_way     = 8'b00010000;
665
        else if ( valid_bits[5] == 1'd0 )
666
            // way 3 not occupied so use it
667
            pick_way     = 8'b00100000;
668
        else if ( valid_bits[6] == 1'd0 )
669
            // way 3 not occupied so use it
670
            pick_way     = 8'b01000000;
671
        else if ( valid_bits[7] == 1'd0 )
672
            // way 3 not occupied so use it
673
            pick_way     = 8'b10000000;
674
        else
675
            begin
676
            // All ways occupied so pick one randomly
677
            case (random_num[3:1])
678
                3'd0:       pick_way = 8'b00010000;
679
                3'd1:       pick_way = 8'b00100000;
680
                3'd2:       pick_way = 8'b01000000;
681
                3'd3:       pick_way = 8'b10000000;
682
                3'd4:       pick_way = 8'b00000001;
683
                3'd5:       pick_way = 8'b00000010;
684
                3'd6:       pick_way = 8'b00000100;
685
                default:    pick_way = 8'b00001000;
686
            endcase
687
            end
688
    end
689
    endfunction
690
 
691
end
692
endgenerate
693
 
694
 
695
// ========================================================
696
// Debug WB bus - not synthesizable
697
// ========================================================
698
//synopsys translate_off
699
wire    [(6*8)-1:0]     xSOURCE_SEL;
700
wire    [(20*8)-1:0]    xC_STATE;
701
 
702
assign xSOURCE_SEL = source_sel[C_CORE]            ? "C_CORE"           :
703
                     source_sel[C_INIT]            ? "C_INIT"           :
704
                     source_sel[C_FILL]            ? "C_FILL"           :
705
                     source_sel[C_INVA]            ? "C_INVA"           :
706
                                                     "UNKNON"           ;
707
 
708
assign xC_STATE    = c_state == CS_INIT            ? "CS_INIT"          :
709
                     c_state == CS_IDLE            ? "CS_IDLE"          :
710
                     c_state == CS_FILL0           ? "CS_FILL0"         :
711
                     c_state == CS_FILL1           ? "CS_FILL1"         :
712
                     c_state == CS_FILL2           ? "CS_FILL2"         :
713
                     c_state == CS_FILL3           ? "CS_FILL3"         :
714
                     c_state == CS_FILL4           ? "CS_FILL4"         :
715
                     c_state == CS_FILL_COMPLETE   ? "CS_FILL_COMPLETE" :
716
                     c_state == CS_EX_DELETE       ? "CS_EX_DELETE"     :
717
                     c_state == CS_TURN_AROUND     ? "CS_TURN_AROUND"   :
718
                     c_state == CS_WRITE_HIT1      ? "CS_WRITE_HIT1"    :
719
                                                     "UNKNOWN"          ;
720
 
721
 
722
generate
723
if ( WAYS == 2 ) begin : check_hit_2ways
724
 
725
    always @( posedge i_clk )
726
        if ( (data_hit_way[0] + data_hit_way[1] ) > 4'd1 )
727
            begin
728
            `TB_ERROR_MESSAGE
729
            $display("Hit in more than one cache ways!");
730
            end
731
 
732
end
733
else if ( WAYS == 3 ) begin : check_hit_3ways
734
 
735
    always @( posedge i_clk )
736
        if ( (data_hit_way[0] + data_hit_way[1] + data_hit_way[2] ) > 4'd1 )
737
            begin
738
            `TB_ERROR_MESSAGE
739
            $display("Hit in more than one cache ways!");
740
            end
741
 
742
end
743
else if ( WAYS == 4 ) begin : check_hit_4ways
744
 
745
    always @( posedge i_clk )
746
        if ( (data_hit_way[0] + data_hit_way[1] +
747
              data_hit_way[2] + data_hit_way[3] ) > 4'd1 )
748
            begin
749
            `TB_ERROR_MESSAGE
750
            $display("Hit in more than one cache ways!");
751
            end
752
 
753
end
754
else if ( WAYS == 8 )  begin : check_hit_8ways
755
 
756
    always @( posedge i_clk )
757
        if ( (data_hit_way[0] + data_hit_way[1] +
758
              data_hit_way[2] + data_hit_way[3] +
759
              data_hit_way[4] + data_hit_way[5] +
760
              data_hit_way[6] + data_hit_way[7] ) > 4'd1 )
761
            begin
762
            `TB_ERROR_MESSAGE
763
            $display("Hit in more than one cache ways!");
764
            end
765
 
766
end
767
else begin : check_hit_nways
768
 
769
    initial
770
        begin
771
        `TB_ERROR_MESSAGE
772
        $display("Unsupported number of ways %0d", WAYS);
773
        $display("Set A25_ICACHE_WAYS in a25_config_defines.v to either 2,3,4 or 8");
774
        end
775
 
776
end
777
endgenerate
778
 
779
//synopsys translate_on
780
 
781
endmodule
782
 

powered by: WebSVN 2.1.0

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