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

Subversion Repositories mips32

[/] [mips32/] [trunk/] [Classic-MIPS/] [source/] [src/] [SimpleCache.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jjf
`timescale 1ns / 1ps
2
//////////////////////////////////////////////////////////////////////////////////
3
// Company: 
4
// Engineer: 
5
// 
6
// Create Date: 2017/02/11 15:07:12
7
// Design Name: 
8
// Module Name: SimpleCache
9
// Project Name: 
10
// Target Devices: 
11
// Tool Versions: 
12
// Description: 
13
// 
14
// Dependencies: 
15
// 
16
// Revision:
17
// Revision 0.01 - File Created
18
// Additional Comments:
19
// 
20
//////////////////////////////////////////////////////////////////////////////////
21
 
22
 
23
module SimpleCache(
24
input wire              clk,
25
input wire              rst,
26
input wire              CPU_read_en,
27
output wire [31:0]      CPU_read_dout,
28
input wire              CPU_write_en,
29
input wire [31:0]       CPU_write_din,
30
input wire [31:0]       CPU_addr,
31
output wire             isCacheStall,
32
input wire              mem_b_we,
33
input wire [12:0]       mem_b_addr,
34
input wire [31:0]       mem_b_din,
35
output wire [31:0]      mem_b_dout
36
    );
37
 
38
    wire            mem_a_we;
39
    wire [12:0]     mem_a_addr;
40
    wire [31:0]     mem_a_din;
41
    wire [31:0]     mem_a_dout;
42
 
43
    wire [5:0]      cache_tag_addr;
44
    wire [22:0]      cache_tag_din;
45
    wire [22:0]     cache_tag_dout;
46
    wire             cache_tag_we;
47
    wire [20:0]     cache_tag_dout_tag;
48
    wire            cache_tag_dout_valid;
49
    wire            cache_tag_dout_overwrite;
50
 
51
    wire [8:0]      cache_data_addr;
52
    wire [31:0]     cache_data_din;
53
    wire            cache_data_we;
54
    wire [31:0]     cache_data_dout;
55
 
56
 
57
    wire [31:0]     allocate_main_mem_dout;
58
    wire [12:0]     allocate_main_mem_addr;
59
    wire [8:0]      allocate_cache_data_addr;
60
    wire [31:0]     allocate_cache_data_din;
61
    wire            allocate_cache_data_we;
62
    reg             allocate_start;
63
    wire            allocate_done;
64
 
65
    wire [8:0]      hit_cache_data_addr;
66
    wire            hit_cache_data_we;
67
    wire [31:0]     hit_cache_data_din;
68
 
69
    //instantiate of the ALLOCATE controller
70
    assign allocate_main_mem_dout = mem_a_dout;
71
    allocate allocate_i(
72
        .clk( clk ),
73
        .rst( rst ),
74
        .CPU_addr( CPU_addr ),
75
        .main_mem_dout( allocate_main_mem_dout ),
76
        .main_mem_addr( allocate_main_mem_addr ),
77
        .cache_data_addr( allocate_cache_data_addr ),
78
        .cache_data_din( allocate_cache_data_din ),
79
        .cache_data_we( allocate_cache_data_we ),
80
        .start( allocate_start ),
81
        .done( allocate_done )
82
    );
83
 
84
    wire [31:0]         wb_main_mem_din;
85
    wire                wb_main_mem_we;
86
    wire [12:0]         wb_main_mem_addr;
87
    wire [31:0]         wb_cache_data_dout;
88
    wire [8:0]          wb_cache_data_addr;
89
    reg                 wb_start;
90
    wire                wb_done;
91
    wire [31:0]         wb_CPU_addr;
92
 
93
    //instantiate of the WRITEBACK controller 
94
    assign wb_cache_data_dout = cache_data_dout;
95
    assign wb_CPU_addr = {cache_tag_dout_tag, CPU_addr_index, CPU_addr_offset, 2'b00};
96
    wback wback_i(
97
        .clk( clk ),
98
        .rst( rst ),
99
        .CPU_addr( wb_CPU_addr ),
100
        .main_mem_din( wb_main_mem_din ),
101
        .main_mem_we( wb_main_mem_we ),
102
        .main_mem_addr( wb_main_mem_addr ),
103
        .cache_data_dout( wb_cache_data_dout ),
104
        .cache_data_addr( wb_cache_data_addr ),
105
        .start( wb_start ),
106
        .done( wb_done )
107
    );
108
 
109
    //instantiate of the main memory implemented with BRAM
110
    assign mem_a_we = wb_main_mem_we;
111
    assign mem_a_din = wb_main_mem_din;
112
    assign mem_a_addr = (current_state == WBACK) ? wb_main_mem_addr : allocate_main_mem_addr;
113
    main_mem main_mem_i(
114
        .clka( clk ),
115
        .wea( mem_a_we ),
116
        .addra( mem_a_addr ),
117
        .dina( mem_a_din ),
118
        .douta( mem_a_dout ),
119
        .clkb( clk ),
120
        .web( mem_b_we ),
121
        .addrb( mem_b_addr ),
122
        .dinb( mem_b_din ),
123
        .doutb( mem_b_dout )
124
    );
125
 
126
    //instantiate of the cache_tag implemented with LUT
127
    assign cache_tag_dout_tag = cache_tag_dout[20:0];
128
    assign cache_tag_dout_valid = cache_tag_dout[21];
129
    assign cache_tag_dout_overwrite = cache_tag_dout[22];
130
 
131
    cache_tag cache_tag_i(
132
        .a( cache_tag_addr ),
133
        .d( cache_tag_din ),
134
        .clk( clk ),
135
        .we( cache_tag_we),
136
        .spo( cache_tag_dout )
137
    );
138
 
139
    //instantiate of the cache_data implemented with LUT
140
    assign cache_data_addr = CACHE_DATA_ADDR(current_state, hit_cache_data_addr, allocate_cache_data_addr, wb_cache_data_addr);
141
 
142
    /* function of the CACHE_DATA_ADDR*/
143
    function [8:0] CACHE_DATA_ADDR;
144
    input [1:0] state;
145
    input [8:0] hit_cache_data_addr;
146
    input [8:0] allocate_cache_data_addr;
147
    input [8:0] wb_cache_data_addr;
148
    case(state)
149
    IDLE:       CACHE_DATA_ADDR = hit_cache_data_addr;
150
    COMPARE:    CACHE_DATA_ADDR = hit_cache_data_addr;
151
    ALLOCATE:   CACHE_DATA_ADDR = allocate_cache_data_addr;
152
    WBACK:      CACHE_DATA_ADDR = wb_cache_data_addr;
153
    default:    CACHE_DATA_ADDR = hit_cache_data_addr;
154
    endcase
155
    endfunction
156
 
157
    assign cache_data_we = CACHE_DATA_WE(current_state, hit_cache_data_we, allocate_cache_data_we);
158
    /* function of the CACHE_DATA_WE */
159
    function CACHE_DATA_WE;
160
    input [1:0] state;
161
    input   hit_cache_data_we;
162
    input   allocate_cache_data_we;
163
    case( state )
164
    IDLE:       CACHE_DATA_WE = hit_cache_data_we;
165
    COMPARE:    CACHE_DATA_WE = hit_cache_data_we;
166
    ALLOCATE:   CACHE_DATA_WE = allocate_cache_data_we;
167
    default:    CACHE_DATA_WE = hit_cache_data_we;
168
    endcase
169
    endfunction
170
 
171
    assign cache_data_din = CACHE_DATA_DIN( current_state, hit_cache_data_din, allocate_cache_data_din);
172
    /* function of the CACHE_DATA_DIN */
173
    function [31:0] CACHE_DATA_DIN;
174
    input [1:0] state;
175
    input [31:0]    hit_cache_data_din;
176
    input [31:0]    allocate_cache_data_din;
177
    case( state )
178
    IDLE:       CACHE_DATA_DIN = hit_cache_data_din;
179
    COMPARE:    CACHE_DATA_DIN = hit_cache_data_din;
180
    ALLOCATE:   CACHE_DATA_DIN = allocate_cache_data_din;
181
    default:    CACHE_DATA_DIN = hit_cache_data_din;
182
    endcase
183
    endfunction
184
 
185
    //instantiate of the cache_data implemented with LUT
186
    cache_data cache_data_i(
187
        .a( cache_data_addr ),
188
        .d( cache_data_din ),
189
        .clk( clk ),
190
        .we( cache_data_we ),
191
        .spo( cache_data_dout )
192
    );
193
 
194
 
195
 
196
    // the extra logic
197
    wire [20:0]     CPU_addr_tag;
198
    wire [5:0]      CPU_addr_index;
199
    wire [2:0]      CPU_addr_offset;
200
    wire            isCacheHit;
201
 
202
    assign CPU_addr_tag = CPU_addr[31:11];
203
    assign CPU_addr_index = CPU_addr[10:5];
204
    assign CPU_addr_offset = CPU_addr[4:2];
205
 
206
    /* check whether cache hit */
207
    assign isCacheHit = (CPU_addr_tag == cache_tag_dout_tag) & cache_tag_dout_valid;
208
 
209
    assign CPU_read_dout = cache_data_dout;
210
 
211
    /* hit_cache_data */
212
    assign hit_cache_data_addr = (CPU_addr_index << 3) + CPU_addr_offset;
213
    assign hit_cache_data_din = CPU_write_din;
214
    assign hit_cache_data_we = (current_state == IDLE) && CPU_write_en && isCacheHit;
215
 
216
    /* cache_tag */
217
    assign cache_tag_addr = CPU_addr_index;
218
    assign cache_tag_we = CACHE_TAG_WE(current_state, CPU_write_en, isCacheHit );
219
    assign cache_tag_din = CACHE_TAG_DIN(current_state, CPU_write_en, isCacheHit, CPU_addr_tag);
220
 
221
    function CACHE_TAG_WE;
222
    input [1:0] state;
223
    input       CPU_write_en;
224
    input       isCacheHit;
225
        if( state == IDLE && CPU_write_en && isCacheHit )
226
            CACHE_TAG_WE = 1;
227
        else if( state == ALLOCATE)
228
            CACHE_TAG_WE = 1;
229
        else
230
            CACHE_TAG_WE = 0;
231
    endfunction
232
 
233
    function [22:0] CACHE_TAG_DIN;
234
    input [1:0]     state;
235
    input           CPU_write_en;
236
    input           isCacheHit;
237
    input [20:0]    CPU_addr_tag;
238
        if( state == IDLE && CPU_write_en && isCacheHit )
239
            CACHE_TAG_DIN = {1'b1, 1'b1, CPU_addr_tag};
240
        else if( state == ALLOCATE)
241
            CACHE_TAG_DIN = {1'b0, 1'b1, CPU_addr_tag};
242
        else
243
            CACHE_TAG_DIN = 0;
244
    endfunction
245
 
246
    /* the cache done */
247
//    assign cache_done = ( current_state == IDLE) && isCacheHit && (CPU_read_en | CPU_write_en);
248
//    assign cache_done = ( current_state == IDLE) && (CPU_read_en | CPU_write_en) && ((CPU_addr_tag == cache_tag_dout_tag) & cache_tag_dout_valid);
249
    assign isCacheStall = ISCACHESTALL( current_state, CPU_read_en, CPU_write_en, CPU_addr_tag, cache_tag_dout_tag, cache_tag_dout_valid);
250
 
251
    function ISCACHESTALL;
252
    input [1:0]     current_state;
253
    input           CPU_read_en;
254
    input           CPU_write_en;
255
    input [20:0]    CPU_addr_tag;
256
    input [20:0]    cache_tag_dout_tag;
257
    input           cache_tag_dout_valid;
258
        if( (CPU_write_en | CPU_read_en) == 0 )
259
            ISCACHESTALL = 0;
260
        else if( ( current_state == IDLE) && ((CPU_addr_tag == cache_tag_dout_tag) & cache_tag_dout_valid) )
261
            ISCACHESTALL = 0;
262
        else
263
            ISCACHESTALL = 1;
264
    endfunction
265
 
266
    /* the cache controller */
267
    reg [1:0]       current_state;
268
    reg [1:0]       next_state;
269
 
270
    localparam      IDLE = 2'h0, COMPARE = 2'd1, ALLOCATE = 2'd2, WBACK = 2'd3;
271
 
272
    /* the first FSM stage */
273
    always @(posedge clk)
274
    begin
275
        if( rst )
276
            current_state <= IDLE;
277
        else
278
            current_state <= next_state;
279
    end
280
 
281
    /* the second FSM stage */
282
    always @(*)
283
    begin
284
        next_state = IDLE;
285
        case( current_state )
286
        IDLE:   begin
287
                    if( (CPU_read_en | CPU_write_en) && (~isCacheHit) )
288
                        next_state = COMPARE;
289
                    else
290
                        next_state = IDLE;
291
                end
292
        COMPARE:begin
293
                    if( (~isCacheHit) && (~cache_tag_dout_overwrite))
294
                        next_state = ALLOCATE;
295
                    else if( (~isCacheHit) &&  cache_tag_dout_overwrite)
296
                        next_state = WBACK;
297
                    else
298
                        next_state = IDLE;
299
                end
300
        ALLOCATE:   begin
301
                        if( allocate_done )
302
                            next_state = IDLE;
303
                        else
304
                            next_state = ALLOCATE;
305
                    end
306
        WBACK:  begin
307
                    if( wb_done )
308
                        next_state = ALLOCATE;
309
                    else
310
                        next_state = WBACK;
311
                end
312
 
313
        endcase
314
    end
315
 
316
    /* the third FSM stage */
317
    always @(posedge clk)
318
    begin
319
        if( rst )
320
        begin
321
            allocate_start <= 0;
322
            wb_start <= 0;
323
        end
324
        else
325
        begin
326
            case( current_state )
327
            IDLE:   begin
328
                        allocate_start <= 0;
329
                        wb_start <= 0;
330
                    end
331
            COMPARE:begin
332
                        if( (~isCacheHit) && (~cache_tag_dout_overwrite))
333
                        begin
334
                            wb_start <= 0;
335
                            allocate_start <= 1;
336
                        end
337
                        else if( (~isCacheHit) && cache_tag_dout_overwrite)
338
                        begin
339
                            wb_start <= 1;
340
                            allocate_start <= 0;
341
                        end
342
                        else
343
                        begin
344
                            wb_start <= 0;
345
                            allocate_start <= 0;
346
                        end
347
                    end
348
                ALLOCATE:   begin
349
                                wb_start <= 0;
350
                                allocate_start <= 0;
351
                            end
352
                WBACK:  begin
353
                            wb_start <= 0;
354
                            /* jump to ALLOCATE state */
355
                            if( wb_done )
356
                                allocate_start <= 1;
357
                            else
358
                                allocate_start <= 0;
359
                        end
360
 
361
            endcase
362
        end
363
    end
364
 
365
endmodule

powered by: WebSVN 2.1.0

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