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

Subversion Repositories next186mp3

[/] [next186mp3/] [trunk/] [HW/] [cache_controller.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 Soc PC project
4
// http://opencores.org/project,next186
5
//
6
// Filename: cache_controller.v
7
// Description: Part of the Next186 SoC PC project, cache controller
8
// Version 1.0
9
// Creation date: Jan2012
10
//
11
// Author: Nicolae Dumitrache 
12
// e-mail: ndumitrache@opencores.org
13
//
14
/////////////////////////////////////////////////////////////////////////////////
15
// 
16
// Copyright (C) 2012 Nicolae Dumitrache
17
// 
18
// This source file may be used and distributed without 
19
// restriction provided that this copyright statement is not 
20
// removed from the file and that any derivative work contains 
21
// the original copyright notice and the associated disclaimer.
22
// 
23
// This source file is free software; you can redistribute it 
24
// and/or modify it under the terms of the GNU Lesser General 
25
// Public License as published by the Free Software Foundation;
26
// either version 2.1 of the License, or (at your option) any 
27
// later version. 
28
// 
29
// This source is distributed in the hope that it will be 
30
// useful, but WITHOUT ANY WARRANTY; without even the implied 
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
32
// PURPOSE. See the GNU Lesser General Public License for more 
33
// details. 
34
// 
35
// You should have received a copy of the GNU Lesser General 
36
// Public License along with this source; if not, download it 
37
// from http://www.opencores.org/lgpl.shtml 
38
// 
39
///////////////////////////////////////////////////////////////////////////////////
40
// Additional Comments: 
41
//
42
// preloaded with bootstrap code
43
//////////////////////////////////////////////////////////////////////////////////
44
 
45
`timescale 1ns / 1ps
46
`define WAYS    2       // 2^ways
47
`define SETS    4       // 2^sets
48
 
49
module cache_controller(
50
         input [20:0] addr,
51
     output [31:0] dout,
52
         input [31:0]din,
53
         input clk,
54
         input mreq,
55
         input [3:0]wmask,
56
         output ce,     // clock enable for CPU
57
         input [15:0]ddr_din,
58
         output reg[15:0]ddr_dout,
59
         input ddr_clk,
60
         input cache_write_data, // 1 when data must be written to cache, on posedge ddr_clk
61
         input cache_read_data, // 1 when data must be read from cache, on posedge ddr_clk
62
         output reg ddr_rd = 0,
63
         output reg ddr_wr = 0,
64
         output reg [12:0] waddr,
65
         input flush
66
    );
67
 
68
        reg flushreq = 1'b0;
69
        reg [`WAYS+`SETS:0]flushcount = 0;
70
        wire r_flush = flushcount[`WAYS+`SETS];
71
        wire [`SETS-1:0]index = r_flush ? flushcount[`SETS-1:0] : addr[8+`SETS-1:8];
72
        wire [(1<<`WAYS)-1:0]fit;
73
        wire [(1<<`WAYS)-1:0]free;
74
        wire wr = |wmask;
75
 
76
        reg [(1<<`WAYS)-1:0]cache_dirty[0:(1<<`SETS)-1] =
77
                {4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h0, 4'h1, 4'h1, 4'h1, 4'h1};
78
        reg [`WAYS-1:0]cache_lru[0:(1<<`WAYS)-1][0:(1<<`SETS)-1] =
79
                {{2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0, 2'h0},
80
                 {2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1, 2'h1},
81
                 {2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2, 2'h2},
82
                 {2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3, 2'h3}};
83
        reg [12-`SETS:0]cache_addr[0:(1<<`WAYS)-1][0:(1<<`SETS)-1]=
84
                {{9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h000, 9'h0ff, 9'h0ff, 9'h0ff, 9'h0ff},
85
                 {9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h001, 9'h000, 9'h000, 9'h000, 9'h000},
86
                 {9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h002, 9'h001, 9'h001, 9'h001, 9'h001},
87
                 {9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h003, 9'h002, 9'h002, 9'h002, 9'h002}};
88
 
89
        reg [2:0]STATE = 0;
90
        reg [6:0]lowaddr = 0; //cache mem address
91
        reg s_lowaddr5 = 0;
92
        wire [31:0]cache_QA;
93
        wire [`WAYS-1:0]lru[(1<<`WAYS)-1:0];
94
 
95
        genvar i;
96
        for(i=0; i<(1<<`WAYS); i=i+1) begin
97
                assign fit[i] = ~r_flush && (cache_addr[i][index] == addr[20:8+`SETS]);
98
                assign free[i] = r_flush ? (flushcount[`WAYS+`SETS-1:`SETS] == i) : ~|cache_lru[i][index];
99
                assign lru[i] = {`WAYS{fit[i]}} & cache_lru[i][index];
100
        end
101
 
102
        wire hit = |fit;
103
        wire st0 = STATE == 3'b000;
104
        assign ce = st0 && (~mreq || hit);
105
        wire dirty = |(free & cache_dirty[index]);
106
 
107
        wire [`WAYS-1:0]blk = flushcount[`WAYS+`SETS-1:`SETS] | {|fit[3:2], fit[3] | fit[1]};
108
        wire [`WAYS-1:0]fblk = {|free[3:2], free[3] | free[1]};
109
        wire [`WAYS-1:0]csblk = lru[0] | lru[1] | lru[2] | lru[3];
110
 
111
        always @(posedge ddr_clk) begin
112
                if(cache_write_data || cache_read_data) lowaddr <= lowaddr + 1;
113
                ddr_dout <= lowaddr[0] ? cache_QA[15:0] : cache_QA[31:16];
114
        end
115
 
116
        cache cache_mem
117
        (
118
                .clka(ddr_clk), // input clka
119
                .ena(cache_write_data | cache_read_data), // input ena
120
                .wea({4{cache_write_data}} & {lowaddr[0], lowaddr[0], ~lowaddr[0], ~lowaddr[0]}), // input [3 : 0] wea
121
                .addra({blk, ~index[`SETS-1:2], index[1:0], lowaddr[6:1]}), // input [11 : 0] addra
122
                .dina({ddr_din, ddr_din}), // input [31 : 0] dina
123
                .douta(cache_QA), // output [31 : 0] douta
124
                .clkb(clk), // input clkb
125
                .enb(mreq & hit & st0), // input enb
126
                .web({4{mreq & hit & st0 & wr}} & wmask), // input [3 : 0] web
127
                .addrb({blk, ~index[`SETS-1:2], index[1:0], addr[7:2]}), // input [11 : 0] addrb
128
                .dinb(din), // input [31 : 0] dinb
129
                .doutb(dout) // output [31 : 0] doutb
130
        );
131
 
132
 
133
        for(i=0; i<(1<<`WAYS); i=i+1)
134
                always @(posedge clk)
135
                        if(st0 && mreq)
136
                                if(hit) begin
137
                                        cache_lru[i][index] <= fit[i] ? {`WAYS{1'b1}} : cache_lru[i][index] - (cache_lru[i][index] > csblk);
138
                                        if(fit[i]) cache_dirty[index][i] <= cache_dirty[index][i] | wr;
139
                                end else if(free[i]) cache_dirty[index][i] <= 1'b0;
140
 
141
 
142
        always @(posedge clk) begin
143
                s_lowaddr5 <= lowaddr[6];
144
                flushreq <= ~flushcount[`WAYS+`SETS] & (flushreq | flush);
145
 
146
                case(STATE)
147
                        3'b000: begin
148
                                if(mreq && !hit) begin  // cache miss
149
                                        waddr <= {cache_addr[fblk][index], index};
150
                                        if(!r_flush) cache_addr[fblk][index] <= addr[20:8+`SETS];
151
                                        ddr_rd <= ~dirty & ~r_flush;
152
                                        ddr_wr <= dirty;
153
                                        STATE <= dirty ? 3'b011 : 3'b100;
154
                                end else flushcount[`WAYS+`SETS] <= flushcount[`WAYS+`SETS] | flushreq;
155
                        end
156
                        3'b011: begin   // write cache to ddr
157
                                ddr_rd <= ~r_flush; //1'b1;
158
                                if(s_lowaddr5) begin
159
                                        ddr_wr <= 1'b0;
160
                                        STATE <= 3'b111;
161
                                end
162
                        end
163
                        3'b111: begin // read cache from ddr
164
                                if(~s_lowaddr5) STATE <= 3'b100;
165
                        end
166
                        3'b100: begin
167
                                if(r_flush) begin
168
                                        flushcount <= flushcount + 1;
169
                                        STATE <= 3'b000;
170
                                end else if(s_lowaddr5) STATE <= 3'b101;
171
                        end
172
                        3'b101: begin
173
                                ddr_rd <= 1'b0;
174
                                if(~s_lowaddr5) STATE <= 3'b000;
175
                        end
176
                endcase
177
        end
178
 
179
endmodule
180
 
181
 
182
module seg_map(
183
         input CLK,
184
         input [3:0]cpuaddr,
185
         output [8:0]cpurdata,
186
         input [8:0]cpuwdata,
187
         input [4:0]memaddr,
188
         output [8:0]memdata,
189
         input WE
190
    );
191
 
192
        reg [8:0]map[0:31] = {9'h000, 9'h001, 9'h002, 9'h003, 9'h004, 9'h005, 9'h006, 9'h007, 9'h008, 9'h009,
193
                                                                 9'h00a, 9'h00b,        // VGA seg 1 and 2
194
                                                                 9'h012, 9'h013, 9'h014, 9'h015,
195
                                                                 9'h016,        // HMA
196
                                                                 9'h001, 9'h002, 9'h003, 9'h004, 9'h005, 9'h006, 9'h007, 9'h008, 9'h009,
197
                                                                 9'h00a, 9'h00b, 9'h00c, 9'h00d, 9'h00e, 9'h00f}; // VGA seg 1..6                                                                
198
        assign memdata = map[memaddr];
199
        assign cpurdata = map[{1'b0, cpuaddr}];
200
//      initial $readmemh("segmap.mem", map);
201
 
202
        always @(posedge CLK)
203
                if(WE) map[{1'b0, cpuaddr}] <= cpuwdata;
204
 
205
endmodule

powered by: WebSVN 2.1.0

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