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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_cache_tag_ram.v] - Blame information for rev 43

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

Line No. Rev Author Line
1 26 Revanth
// -----------------------------------------------------------------------------
2
// --                                                                         --
3
// --                   (C) 2016-2018 Revanth Kamaraj.                        --
4
// --                                                                         -- 
5
// -- --------------------------------------------------------------------------
6
// --                                                                         --
7
// -- This program is free software; you can redistribute it and/or           --
8
// -- modify it under the terms of the GNU General Public License             --
9
// -- as published by the Free Software Foundation; either version 2          --
10
// -- of the License, or (at your option) any later version.                  --
11
// --                                                                         --
12
// -- This program is distributed in the hope that it will be useful,         --
13
// -- but WITHOUT ANY WARRANTY; without even the implied warranty of          --
14
// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           --
15
// -- GNU General Public License for more details.                            --
16
// --                                                                         --
17
// -- You should have received a copy of the GNU General Public License       --
18
// -- along with this program; if not, write to the Free Software             --
19
// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA           --
20
// -- 02110-1301, USA.                                                        --
21
// --                                                                         --
22
// -----------------------------------------------------------------------------
23
// --                                                                         --                   
24
// -- This is the tag RAM and data RAM unit. The tag RAM holds both the       --
25
// -- virtual tag and the physical address. The physical address is used to   --  
26
// -- avoid translation during clean operations. The cache data RAM is also   --
27
// -- present in this unit. This unit has a dedicated memory interface        -- 
28
// -- because it can perform global clean and flush by itself without         --
29
// -- depending on the cache controller.                                      --
30
// --                                                                         --
31
// -----------------------------------------------------------------------------
32
 
33
`default_nettype none
34 43 Revanth
`include "zap_defines.vh"
35 26 Revanth
 
36 43 Revanth
module zap_cache_tag_ram #(
37 26 Revanth
 
38 43 Revanth
parameter CACHE_SIZE = 1024 // Bytes.
39 26 Revanth
 
40 43 Revanth
)(
41 26 Revanth
 
42 43 Revanth
input   wire                            i_clk,
43
input   wire                            i_reset,
44
input   wire    [31:0]                  i_address_nxt,
45
input   wire    [31:0]                  i_address,
46
input   wire                            i_cache_en,
47
input   wire    [127:0]                 i_cache_line,
48
input   wire    [15:0]                  i_cache_line_ben,
49
output  reg     [127:0]                 o_cache_line,
50
input   wire                            i_cache_tag_wr_en,
51
input   wire    [`CACHE_TAG_WDT-1:0]    i_cache_tag,
52
input   wire                            i_cache_tag_dirty,
53 26 Revanth
 
54 43 Revanth
output  reg     [`CACHE_TAG_WDT-1:0]    o_cache_tag,
55
output  reg                             o_cache_tag_valid,
56
output  reg                             o_cache_tag_dirty,
57
input   wire                            i_cache_clean_req,
58
output  reg                             o_cache_clean_done,
59
input   wire                            i_cache_inv_req,
60
output  reg                             o_cache_inv_done,
61 26 Revanth
 
62 43 Revanth
/*
63
 * Cache clean operations occur through these ports.
64
 * Memory access ports, both NXT and FF. Usually you'll be connecting NXT ports
65
 */
66
output  reg                             o_wb_cyc_ff, o_wb_cyc_nxt,
67
output  reg                             o_wb_stb_ff, o_wb_stb_nxt,
68
output  reg     [31:0]                  o_wb_adr_ff, o_wb_adr_nxt,
69
output  reg     [31:0]                  o_wb_dat_ff, o_wb_dat_nxt,
70
output  reg     [3:0]                   o_wb_sel_ff, o_wb_sel_nxt,
71
output  reg                             o_wb_wen_ff, o_wb_wen_nxt,
72
output  reg     [2:0]                   o_wb_cti_ff, o_wb_cti_nxt, /* Cycle Type Indicator - 010, 111 */
73
input wire      [31:0]                  i_wb_dat,
74
input wire                              i_wb_ack
75 26 Revanth
 
76
);
77
 
78
// ----------------------------------------------------------------------------
79
 
80
`include "zap_localparams.vh"
81
 
82 43 Revanth
localparam NUMBER_OF_DIRTY_BLOCKS = ((CACHE_SIZE/16)/16); // Keep cache size > 16 bytes.
83 26 Revanth
 
84 43 Revanth
// States.
85
localparam IDLE                         = 0;
86
localparam CACHE_CLEAN_GET_ADDRESS      = 1;
87
localparam CACHE_CLEAN_WRITE            = 2;
88
localparam CACHE_INV                    = 3;
89 26 Revanth
 
90
 
91
// ----------------------------------------------------------------------------
92
 
93
reg [(CACHE_SIZE/16)-1:0]       dirty;
94
reg [(CACHE_SIZE/16)-1:0]       valid;
95
reg [`CACHE_TAG_WDT-1:0]        tag_ram [(CACHE_SIZE/16)-1:0];
96
reg [127:0]                     dat_ram [(CACHE_SIZE/16)-1:0];
97
 
98
// ----------------------------------------------------------------------------
99
 
100
reg [`CACHE_TAG_WDT-1:0]        tag_ram_wr_data;
101
reg                             tag_ram_wr_en;
102
reg [$clog2(CACHE_SIZE/16)-1:0] tag_ram_wr_addr, tag_ram_rd_addr;
103
reg                             tag_ram_clear;
104
reg                             tag_ram_clean;
105
 
106
// ----------------------------------------------------------------------------
107
 
108 43 Revanth
reg [1:0] state_ff, state_nxt;
109
 
110
// ----------------------------------------------------------------------------
111
 
112 26 Revanth
reg [$clog2(NUMBER_OF_DIRTY_BLOCKS)-1:0] blk_ctr_ff, blk_ctr_nxt;
113 43 Revanth
reg [2:0]                                adr_ctr_ff, adr_ctr_nxt;
114 26 Revanth
 
115
// ----------------------------------------------------------------------------
116
 
117
initial
118
begin: blk1
119 43 Revanth
        // FPGA anyway initializes to 0 on start.
120 26 Revanth
        integer i;
121
 
122
        for(i=0;i<CACHE_SIZE/16;i=i+1)
123
                dat_ram[i] = 0;
124
 
125
        for(i=0;i<CACHE_SIZE/16;i=i+1)
126
                tag_ram[i] = 0;
127
end
128
 
129
always @ (posedge i_clk)
130
begin
131
        o_cache_line    <=      dat_ram [ tag_ram_rd_addr ];
132
end
133
 
134
always @ (posedge i_clk)
135
begin
136
        if ( i_cache_line_ben[0]  )   dat_ram [tag_ram_wr_addr][7:0]       <=      i_cache_line[7:0];
137
        if ( i_cache_line_ben[1]  )   dat_ram [tag_ram_wr_addr][15:8]      <=      i_cache_line[15:8];
138
        if ( i_cache_line_ben[2]  )   dat_ram [tag_ram_wr_addr][23:16]     <=      i_cache_line[23:16];
139
        if ( i_cache_line_ben[3]  )   dat_ram [tag_ram_wr_addr][31:24]     <=      i_cache_line[31:24];
140
        if ( i_cache_line_ben[4]  )   dat_ram [tag_ram_wr_addr][39:32]     <=      i_cache_line[39:32];
141
        if ( i_cache_line_ben[5]  )   dat_ram [tag_ram_wr_addr][47:40]     <=      i_cache_line[47:40];
142
        if ( i_cache_line_ben[6]  )   dat_ram [tag_ram_wr_addr][55:48]     <=      i_cache_line[55:48];
143
        if ( i_cache_line_ben[7]  )   dat_ram [tag_ram_wr_addr][63:56]     <=      i_cache_line[63:56];
144
        if ( i_cache_line_ben[8]  )   dat_ram [tag_ram_wr_addr][71:64]     <=      i_cache_line[71:64];
145
        if ( i_cache_line_ben[9]  )   dat_ram [tag_ram_wr_addr][79:72]     <=      i_cache_line[79:72];
146
        if ( i_cache_line_ben[10] )   dat_ram [tag_ram_wr_addr][87:80]     <=      i_cache_line[87:80];
147
        if ( i_cache_line_ben[11] )   dat_ram [tag_ram_wr_addr][95:88]     <=      i_cache_line[95:88];
148
        if ( i_cache_line_ben[12] )   dat_ram [tag_ram_wr_addr][103:96]    <=      i_cache_line[103:96];
149
        if ( i_cache_line_ben[13] )   dat_ram [tag_ram_wr_addr][111:104]   <=      i_cache_line[111:104];
150
        if ( i_cache_line_ben[14] )   dat_ram [tag_ram_wr_addr][119:112]   <=      i_cache_line[119:112];
151
        if ( i_cache_line_ben[15] )   dat_ram [tag_ram_wr_addr][127:120]   <=      i_cache_line[127:120];
152
end
153
 
154
// ----------------------------------------------------------------------------
155
 
156
always @ (posedge i_clk)
157
begin
158
        if ( tag_ram_wr_en )
159
                tag_ram [ tag_ram_wr_addr ] <= tag_ram_wr_data;
160
end
161
 
162
always @ (posedge i_clk)
163
begin
164
                o_cache_tag                 <= tag_ram [ tag_ram_rd_addr ];
165
end
166
 
167
// ----------------------------------------------------------------------------
168
 
169
always @ (posedge i_clk)
170
begin
171
        o_cache_tag_dirty                   <= dirty [ tag_ram_rd_addr ];
172
 
173
        if ( i_reset )
174
                dirty <= 0;
175
        else if ( tag_ram_wr_en )
176
                dirty [ tag_ram_wr_addr ]   <= i_cache_tag_dirty;
177
        else if ( tag_ram_clean )
178
                dirty[tag_ram_rd_addr] <= 1'd0;// BUG FIX dirty_nxt;
179
end
180
 
181
always @ (posedge i_clk)
182
begin
183
        o_cache_tag_valid                   <= valid [ tag_ram_rd_addr ];
184
 
185
        if ( tag_ram_clear | !i_cache_en )
186
                valid <= 0;
187
        else if ( tag_ram_wr_en )
188
                valid [ tag_ram_wr_addr ]   <= 1'd1;
189
end
190
 
191
// ----------------------------------------------------------------------------
192
 
193
always @ (posedge i_clk)
194
begin
195
        if ( i_reset )
196
        begin
197 43 Revanth
                o_wb_cyc_ff             <= 0;
198
                o_wb_stb_ff             <= 0;
199
                o_wb_wen_ff             <= 0;
200
                o_wb_sel_ff             <= 0;
201
                o_wb_dat_ff             <= 0;
202
                o_wb_cti_ff             <= CTI_CLASSIC;
203
                o_wb_adr_ff             <= 0;
204
                adr_ctr_ff              <= 0;
205
                blk_ctr_ff              <= 0;
206
                state_ff                <= IDLE;
207 26 Revanth
        end
208
        else
209
        begin
210
                o_wb_cyc_ff             <= o_wb_cyc_nxt;
211
                o_wb_stb_ff             <= o_wb_stb_nxt;
212
                o_wb_wen_ff             <= o_wb_wen_nxt;
213
                o_wb_sel_ff             <= o_wb_sel_nxt;
214
                o_wb_dat_ff             <= o_wb_dat_nxt;
215
                o_wb_cti_ff             <= o_wb_cti_nxt;
216
                o_wb_adr_ff             <= o_wb_adr_nxt;
217
                adr_ctr_ff              <= adr_ctr_nxt;
218
                blk_ctr_ff              <= blk_ctr_nxt;
219 43 Revanth
                state_ff                <= state_nxt;
220 26 Revanth
        end
221
end
222
 
223
// ----------------------------------------------------------------------------
224
 
225
always @*
226
begin
227
 
228
        // Defaults.
229
        state_nxt = state_ff;
230
        tag_ram_rd_addr         = 0;//i_address_nxt [`VA__CACHE_INDEX];
231
        tag_ram_wr_addr         = i_address     [`VA__CACHE_INDEX];
232
        tag_ram_wr_en           = 0; //i_cache_tag_wr_en;
233
        tag_ram_clear           = 0;
234
        tag_ram_clean           = 0;
235
        adr_ctr_nxt             = adr_ctr_ff;
236
        blk_ctr_nxt             = blk_ctr_ff;
237
        o_cache_clean_done      = 0;
238
        o_cache_inv_done        = 0;
239
 
240
        o_wb_cyc_nxt = o_wb_cyc_ff;
241
        o_wb_stb_nxt = o_wb_stb_ff;
242
        o_wb_adr_nxt = o_wb_adr_ff;
243
        o_wb_dat_nxt = o_wb_dat_ff;
244
        o_wb_sel_nxt = o_wb_sel_ff;
245
        o_wb_wen_nxt = o_wb_wen_ff;
246
        o_wb_cti_nxt = o_wb_cti_ff;
247
 
248
        tag_ram_wr_data = 0;
249
 
250
        case ( state_ff )
251
 
252
        IDLE:
253
        begin: blp9
254
                integer i;
255
 
256
                kill_access;
257
 
258
                tag_ram_rd_addr = i_address_nxt [`VA__CACHE_INDEX];
259
                tag_ram_wr_addr = i_address     [`VA__CACHE_INDEX];
260
                tag_ram_wr_en   = i_cache_tag_wr_en;
261
                tag_ram_wr_data = i_cache_tag;
262
 
263
                if ( i_cache_clean_req )
264
                begin
265
                        tag_ram_wr_en = 0;
266
                        blk_ctr_nxt = 0;
267
 
268 43 Revanth
                // assertions_start
269 26 Revanth
 
270 43 Revanth
                        $display($time, " - %m :: Cache clean requested...");
271
 
272 26 Revanth
                        for(i=0;i<CACHE_SIZE/16;i=i+1)
273
                        begin
274 43 Revanth
                                $display($time, " - %m :: Line %d : %x %d", i, dat_ram[i], dirty[i]);
275 26 Revanth
                        end
276
 
277 43 Revanth
                // assertions_end
278 26 Revanth
 
279
 
280
                        state_nxt = CACHE_CLEAN_GET_ADDRESS;
281
                end
282
                else if ( i_cache_inv_req )
283
                begin
284
                        tag_ram_wr_en = 0;
285
                        state_nxt = CACHE_INV;
286
                end
287
        end
288
 
289
        CACHE_CLEAN_GET_ADDRESS:
290
        begin
291
                tag_ram_rd_addr = get_tag_ram_rd_addr (blk_ctr_ff , dirty);
292
 
293
                if ( baggage(dirty, blk_ctr_ff) == 5'b11111)
294
                begin
295
                        // Move to next block.
296
                        blk_ctr_nxt = blk_ctr_ff + 1;
297
 
298
                        if ( blk_ctr_ff == NUMBER_OF_DIRTY_BLOCKS - 1 )
299
                        begin
300
                                state_nxt = IDLE;
301
                                o_cache_clean_done = 1'd1;
302
                        end
303
                end
304
                else
305
                begin
306
 
307
                        // Go to state.
308
                        state_nxt = CACHE_CLEAN_WRITE;
309
                end
310
 
311
                adr_ctr_nxt     = 0; // Initialize address counter.
312
        end
313
 
314
        CACHE_CLEAN_WRITE:
315
        begin
316
                tag_ram_rd_addr = get_tag_ram_rd_addr (blk_ctr_ff , dirty);
317
                adr_ctr_nxt = adr_ctr_ff + (i_wb_ack && o_wb_stb_ff);
318
 
319
                if ( adr_ctr_nxt > 3 )
320
                begin
321
                        // Remove dirty marking. BUG FIX.
322
                        tag_ram_clean = 1;
323
 
324
                        // Kill access.
325
                        kill_access;
326
 
327
                        // Go to new state.
328
                        state_nxt = CACHE_CLEAN_GET_ADDRESS;
329
                end
330
                else
331
                begin: blk1111
332
                        reg [31:0] shamt;
333
                        reg [31:0] data;
334
                        reg [31:0] pa;
335
 
336
                        shamt = adr_ctr_nxt << 5;
337
                        data  = o_cache_line >> shamt;
338
                        pa = {o_cache_tag[`CACHE_TAG__PA], 4'd0};
339
 
340
                        // Perform a Wishbone write using Physical Address.
341
                        wb_prpr_write(  data, pa + (adr_ctr_nxt << 2), adr_ctr_nxt != 3 ? CTI_BURST : CTI_EOB, 4'b1111
342
                        );
343
                end
344
        end
345
 
346
        CACHE_INV:
347
        begin
348
                tag_ram_clear = 1'd1;
349
                state_nxt     = IDLE;
350
                o_cache_inv_done = 1'd1;
351
        end
352
 
353
        endcase
354
end
355
 
356 43 Revanth
// -----------------------------------------------------------------------------
357
 
358 26 Revanth
// Priority encoder.
359
function  [4:0] pri_enc1 ( input [15:0] in );
360
begin: priEncFn
361
                casez ( in )
362
                16'b0000_0000_0000_0001: pri_enc1 = 4'd0;
363
                16'b0000_0000_0000_001?: pri_enc1 = 4'd1;
364
                16'b0000_0000_0000_01??: pri_enc1 = 4'd2;
365
                16'b0000_0000_0000_1???: pri_enc1 = 4'd3;
366
                16'b0000_0000_0001_????: pri_enc1 = 4'd4;
367
                16'b0000_0000_001?_????: pri_enc1 = 4'd5;
368
                16'b0000_0000_01??_????: pri_enc1 = 4'd6;
369
                16'b0000_0000_1???_????: pri_enc1 = 4'd7;
370
                16'b0000_0001_????_????: pri_enc1 = 4'd8;
371
                16'b0000_001?_????_????: pri_enc1 = 4'd9;
372
                16'b0000_01??_????_????: pri_enc1 = 4'hA;
373
                16'b0000_1???_????_????: pri_enc1 = 4'hB;
374
                16'b0001_????_????_????: pri_enc1 = 4'hC;
375
                16'b001?_????_????_????: pri_enc1 = 4'hD;
376
                16'b01??_????_????_????: pri_enc1 = 4'hE;
377
                16'b1???_????_????_????: pri_enc1 = 4'hF;
378
                default:                 pri_enc1 = 5'b11111;
379
                endcase
380
end
381
endfunction
382
 
383 43 Revanth
// -----------------------------------------------------------------------------
384
 
385 26 Revanth
function [31:0] get_tag_ram_rd_addr (
386
input [31:0] blk_ctr,
387
input [CACHE_SIZE/16-1:0] dirty
388
);
389
reg [CACHE_SIZE/16-1:0] dirty_new;
390
reg [3:0] enc;
391
reg [31:0] shamt;
392
begin
393
        shamt = blk_ctr_ff << 4;
394
        dirty_new = dirty >> shamt;
395
        enc = pri_enc1(dirty_new);
396
        get_tag_ram_rd_addr = shamt + enc;
397
end
398
endfunction
399
 
400
// ----------------------------------------------------------------------------
401
 
402
/* Function to generate Wishbone read signals. */
403
task  wb_prpr_read;
404
input [31:0] i_address;
405
input [2:0]  i_cti;
406
begin
407 43 Revanth
        $display($time, " - %m :: Reading from address %x", i_address);
408 26 Revanth
 
409
        o_wb_cyc_nxt = 1'd1;
410
        o_wb_stb_nxt = 1'd1;
411
        o_wb_wen_nxt = 1'd0;
412
        o_wb_sel_nxt = 4'b1111;
413
        o_wb_adr_nxt = i_address;
414
        o_wb_cti_nxt = i_cti;
415 43 Revanth
        o_wb_dat_nxt = 0;
416 26 Revanth
end
417
endtask
418
 
419
// ----------------------------------------------------------------------------
420
 
421
/* Function to generate Wishbone write signals */
422
task  wb_prpr_write;
423
input   [31:0]  i_data;
424
input   [31:0]  i_address;
425
input   [2:0]   i_cti;
426
input   [3:0]   i_ben;
427
begin
428
        o_wb_cyc_nxt = 1'd1;
429
        o_wb_stb_nxt = 1'd1;
430
        o_wb_wen_nxt = 1'd1;
431
        o_wb_sel_nxt = i_ben;
432
        o_wb_adr_nxt = i_address;
433
        o_wb_cti_nxt = i_cti;
434
        o_wb_dat_nxt = i_data;
435
end
436
endtask
437
 
438
// ----------------------------------------------------------------------------
439
 
440
/* Disables Wishbone */
441
task  kill_access;
442
begin
443
        o_wb_cyc_nxt = 0;
444
        o_wb_stb_nxt = 0;
445
        o_wb_wen_nxt = 0;
446
        o_wb_adr_nxt = 0;
447
        o_wb_dat_nxt = 0;
448
        o_wb_sel_nxt = 0;
449
        o_wb_cti_nxt = CTI_CLASSIC;
450
end
451
endtask
452
 
453
// ----------------------------------------------------------------------------
454
 
455 43 Revanth
function [4:0] baggage ( input [CACHE_SIZE/16-1:0] dirty, input [31:0] blk_ctr_ff );
456
reg [31:0] shamt;
457
integer i;
458
begin
459
        shamt = blk_ctr_ff << 4;
460
        baggage = pri_enc1(dirty >> shamt);
461
end
462
endfunction
463
 
464 26 Revanth
endmodule // zap_cache_tag_ram.v
465
`default_nettype wire

powered by: WebSVN 2.1.0

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