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 51

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

powered by: WebSVN 2.1.0

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