1 |
29 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2 |
9 |
ns32kum |
//
|
3 |
|
|
// This file is part of the M32632 project
|
4 |
|
|
// http://opencores.org/project,m32632
|
5 |
|
|
//
|
6 |
23 |
ns32kum |
// Filename: CACHE_LOGIK.v
|
7 |
29 |
ns32kum |
// Version: 3.0
|
8 |
|
|
// History: 2.0 of 11 August 2016
|
9 |
|
|
// 1.1 bug fix of 7 October 2015
|
10 |
23 |
ns32kum |
// 1.0 first release of 30 Mai 2015
|
11 |
29 |
ns32kum |
// Date: 2 December 2018
|
12 |
9 |
ns32kum |
//
|
13 |
29 |
ns32kum |
// Copyright (C) 2018 Udo Moeller
|
14 |
9 |
ns32kum |
//
|
15 |
|
|
// This source file may be used and distributed without
|
16 |
|
|
// restriction provided that this copyright statement is not
|
17 |
|
|
// removed from the file and that any derivative work contains
|
18 |
|
|
// the original copyright notice and the associated disclaimer.
|
19 |
|
|
//
|
20 |
|
|
// This source file is free software; you can redistribute it
|
21 |
|
|
// and/or modify it under the terms of the GNU Lesser General
|
22 |
|
|
// Public License as published by the Free Software Foundation;
|
23 |
|
|
// either version 2.1 of the License, or (at your option) any
|
24 |
|
|
// later version.
|
25 |
|
|
//
|
26 |
|
|
// This source is distributed in the hope that it will be
|
27 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
28 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
29 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more
|
30 |
|
|
// details.
|
31 |
|
|
//
|
32 |
|
|
// You should have received a copy of the GNU Lesser General
|
33 |
|
|
// Public License along with this source; if not, download it
|
34 |
|
|
// from http://www.opencores.org/lgpl.shtml
|
35 |
|
|
//
|
36 |
29 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
37 |
9 |
ns32kum |
//
|
38 |
|
|
// Modules contained in this file:
|
39 |
29 |
ns32kum |
// 1. WRPORT Write Port
|
40 |
|
|
// 2. NEU_VALID Cache Valid RAM
|
41 |
|
|
// 3. DEBUG_AE Debug unit for address compare in data cache
|
42 |
|
|
// 4. MMU_UP MMU memory update and initalization controller
|
43 |
|
|
// 5. DCA_CONTROL Data cache valid memory update and initalization controller
|
44 |
|
|
// 6. MMU_MATCH MMU virtual address match detector
|
45 |
|
|
// 7. CA_MATCH Cache tag match detector
|
46 |
|
|
// 8. FILTCMP Address Filter and Comparator
|
47 |
|
|
// 9. DCACHE_SM Data cache state machine
|
48 |
9 |
ns32kum |
//
|
49 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
50 |
9 |
ns32kum |
|
51 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
52 |
9 |
ns32kum |
//
|
53 |
29 |
ns32kum |
// 1. WRPORT Write Port
|
54 |
9 |
ns32kum |
//
|
55 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
56 |
29 |
ns32kum |
module WRPORT ( WRITE, DRAM_Q, WRDATA, ENBYTE, VADDR, DADDR, WDAT, CAP_Q, ENB );
|
57 |
|
|
|
58 |
|
|
input WRITE;
|
59 |
|
|
input [127:0] DRAM_Q;
|
60 |
|
|
input [31:0] WRDATA;
|
61 |
|
|
input [3:0] ENBYTE;
|
62 |
|
|
input [3:2] VADDR;
|
63 |
|
|
input [3:2] DADDR;
|
64 |
|
|
|
65 |
|
|
output [127:0] WDAT;
|
66 |
|
|
|
67 |
|
|
output reg [31:0] CAP_Q;
|
68 |
|
|
output reg [15:0] ENB;
|
69 |
|
|
|
70 |
|
|
assign WDAT = WRITE ? {WRDATA,WRDATA,WRDATA,WRDATA} : DRAM_Q;
|
71 |
|
|
|
72 |
|
|
always @(DADDR or DRAM_Q)
|
73 |
|
|
case (DADDR)
|
74 |
|
|
2'b00 : CAP_Q = DRAM_Q[31:0];
|
75 |
|
|
2'b01 : CAP_Q = DRAM_Q[63:32];
|
76 |
|
|
2'b10 : CAP_Q = DRAM_Q[95:64];
|
77 |
|
|
2'b11 : CAP_Q = DRAM_Q[127:96];
|
78 |
|
|
endcase
|
79 |
|
|
|
80 |
|
|
always @(WRITE or VADDR or ENBYTE)
|
81 |
|
|
case ({WRITE,VADDR})
|
82 |
|
|
3'b100 : ENB = {4'd0 ,4'd0 ,4'd0 ,ENBYTE};
|
83 |
|
|
3'b101 : ENB = {4'd0 ,4'd0 ,ENBYTE,4'd0 };
|
84 |
|
|
3'b110 : ENB = {4'd0 ,ENBYTE,4'd0 ,4'd0 };
|
85 |
|
|
3'b111 : ENB = {ENBYTE,4'd0 ,4'd0 ,4'd0 };
|
86 |
|
|
default : ENB = 16'hFFFF;
|
87 |
|
|
endcase
|
88 |
|
|
|
89 |
|
|
endmodule
|
90 |
|
|
|
91 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
92 |
|
|
//
|
93 |
|
|
// 2. NEU_VALID Cache Valid RAM
|
94 |
|
|
//
|
95 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
96 |
23 |
ns32kum |
module NEU_VALID ( BCLK, VALIN, WADR, WREN, RADR, VALOUT );
|
97 |
|
|
|
98 |
|
|
input BCLK;
|
99 |
|
|
input [23:0] VALIN;
|
100 |
|
|
input [4:0] WADR;
|
101 |
|
|
input WREN;
|
102 |
|
|
input [4:0] RADR;
|
103 |
|
|
|
104 |
|
|
output [23:0] VALOUT;
|
105 |
|
|
|
106 |
|
|
reg [23:0] cvalid [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
|
107 |
|
|
reg [23:0] ramout;
|
108 |
|
|
reg [23:0] valhold;
|
109 |
|
|
reg gleich;
|
110 |
|
|
|
111 |
|
|
always @(posedge BCLK) ramout <= cvalid[RADR];
|
112 |
|
|
always @(posedge BCLK) if (WREN) cvalid[WADR] <= VALIN;
|
113 |
|
|
|
114 |
|
|
always @(posedge BCLK) valhold <= VALIN;
|
115 |
|
|
always @(posedge BCLK) gleich <= WREN & (RADR == WADR);
|
116 |
|
|
|
117 |
|
|
assign VALOUT = gleich ? valhold : ramout;
|
118 |
|
|
|
119 |
|
|
endmodule
|
120 |
|
|
|
121 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
122 |
|
|
//
|
123 |
29 |
ns32kum |
// 3. DEBUG_AE Debug unit for address compare in data cache
|
124 |
23 |
ns32kum |
//
|
125 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
126 |
9 |
ns32kum |
module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT );
|
127 |
|
|
|
128 |
|
|
input [40:2] DBG_IN;
|
129 |
|
|
|
130 |
|
|
input READ,WRITE;
|
131 |
|
|
input USER;
|
132 |
|
|
input VIRTUELL;
|
133 |
|
|
input ACC_OK;
|
134 |
|
|
input [31:2] VADR_R;
|
135 |
|
|
input [19:0] MMU_Q;
|
136 |
|
|
input [3:0] ENBYTE;
|
137 |
|
|
|
138 |
|
|
output DBG_HIT;
|
139 |
|
|
|
140 |
|
|
wire sd,ud,crd,cwr,vnp;
|
141 |
|
|
wire make;
|
142 |
|
|
wire virt_adr,real_adr,page_adr;
|
143 |
|
|
wire byte_en;
|
144 |
|
|
|
145 |
|
|
assign sd = DBG_IN[40];
|
146 |
|
|
assign ud = DBG_IN[39];
|
147 |
|
|
assign crd = DBG_IN[38];
|
148 |
|
|
assign cwr = DBG_IN[37];
|
149 |
|
|
assign vnp = DBG_IN[36];
|
150 |
|
|
|
151 |
|
|
assign make = ((ud & USER) | (sd & ~USER)) // compare USER or SUPERVISOR
|
152 |
|
|
& (VIRTUELL == vnp) // compare real or virtual address
|
153 |
|
|
& ((cwr & WRITE) | (crd & READ)); // compare READ or WRITE
|
154 |
|
|
|
155 |
|
|
assign virt_adr = (MMU_Q == DBG_IN[31:12]);
|
156 |
|
|
assign real_adr = (VADR_R[31:12] == DBG_IN[31:12]);
|
157 |
|
|
assign page_adr = (VADR_R[11:2] == DBG_IN[11:2]);
|
158 |
|
|
|
159 |
|
|
assign byte_en = |(ENBYTE & DBG_IN[35:32]);
|
160 |
|
|
|
161 |
|
|
assign DBG_HIT = ACC_OK // all valid
|
162 |
|
|
& make // selection is valid
|
163 |
|
|
& (VIRTUELL ? virt_adr : real_adr) & page_adr // address
|
164 |
|
|
& byte_en; // Byte Enable
|
165 |
|
|
|
166 |
|
|
endmodule
|
167 |
|
|
|
168 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
169 |
9 |
ns32kum |
//
|
170 |
29 |
ns32kum |
// 4. MMU_UP MMU memory update and initalization controller
|
171 |
9 |
ns32kum |
//
|
172 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
173 |
9 |
ns32kum |
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
|
174 |
|
|
WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN );
|
175 |
|
|
|
176 |
|
|
input BCLK;
|
177 |
|
|
input BRESET;
|
178 |
|
|
input NEW_PTB; // the MMU memory is cleared. Pulse of one BCLK cycle, Op-Dec is waiting
|
179 |
|
|
input PTB1; // which one
|
180 |
|
|
input IVAR;
|
181 |
|
|
input WR_MRAM; // BCLK : update MRAM and MMU_VAL
|
182 |
|
|
input [19:16] VADR,VADR_R; // For update
|
183 |
|
|
input [31:0] MVALID,UPDATE;
|
184 |
|
|
|
185 |
|
|
output WE_MV; // Write Enable MMU Valid
|
186 |
|
|
output [3:0] WADR_MV,RADR_MV;
|
187 |
|
|
output [31:0] DAT_MV;
|
188 |
|
|
output NEW_PTB_RUN;
|
189 |
|
|
|
190 |
|
|
reg neue_ptb,wr_flag,old_rst,run_over;
|
191 |
|
|
reg [3:0] count;
|
192 |
|
|
|
193 |
|
|
wire [15:0] new_val;
|
194 |
|
|
|
195 |
|
|
assign WE_MV = wr_flag | WR_MRAM | IVAR; // write on falling edge BCLK
|
196 |
|
|
assign RADR_MV = run_over ? count : VADR;
|
197 |
|
|
assign WADR_MV = wr_flag ? (count - 4'b0001) : VADR_R;
|
198 |
11 |
ns32kum |
assign DAT_MV = wr_flag ? {MVALID[31:16],new_val} : UPDATE; // Only the matching entries are cleared : PTB0/PTB1
|
199 |
9 |
ns32kum |
|
200 |
|
|
// [31:16] Address-Space memory, [15:0] Valid memory
|
201 |
11 |
ns32kum |
assign new_val = neue_ptb ? (PTB1 ? (MVALID[15:0] & ~MVALID[31:16]) : (MVALID[15:0] & MVALID[31:16])) : 16'h0;
|
202 |
9 |
ns32kum |
|
203 |
|
|
always @(posedge BCLK or negedge BRESET)
|
204 |
|
|
if (!BRESET) neue_ptb <= 1'b0;
|
205 |
|
|
else neue_ptb <= NEW_PTB | (neue_ptb & run_over);
|
206 |
|
|
|
207 |
|
|
always @(posedge BCLK) old_rst <= BRESET; // after Reset all will be set to 0
|
208 |
|
|
|
209 |
|
|
always @(posedge BCLK) run_over <= ((~old_rst | NEW_PTB) | (run_over & (count != 4'hF))) & BRESET;
|
210 |
|
|
|
211 |
|
|
always @(posedge BCLK) count <= run_over ? count + 4'h1 : 4'h0;
|
212 |
|
|
|
213 |
|
|
always @(posedge BCLK) wr_flag <= run_over;
|
214 |
|
|
|
215 |
|
|
assign NEW_PTB_RUN = wr_flag; // Info to Op-Dec
|
216 |
|
|
|
217 |
|
|
endmodule
|
218 |
|
|
|
219 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
220 |
9 |
ns32kum |
//
|
221 |
29 |
ns32kum |
// 5. DCA_CONTROL Data cache valid memory update and initalization controller
|
222 |
9 |
ns32kum |
//
|
223 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
224 |
29 |
ns32kum |
module DCA_CONTROL ( BCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, VADR_R, UPDATE, INVAL_A, WRITE, MDONE, USE_CA,
|
225 |
|
|
INHIBIT, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 );
|
226 |
9 |
ns32kum |
|
227 |
|
|
input BCLK;
|
228 |
|
|
input BRESET;
|
229 |
|
|
input CUPDATE; // State CUPDATE : Cache is filled from DRAM
|
230 |
|
|
input DRAM_ACC;
|
231 |
|
|
input CA_SET;
|
232 |
|
|
input HIT_ALL; // a complete cache hit !
|
233 |
|
|
input [11:7] VADR_R;
|
234 |
|
|
input [23:0] UPDATE;
|
235 |
|
|
input INVAL_A;
|
236 |
|
|
input WRITE;
|
237 |
29 |
ns32kum |
input MDONE; // Signal from DRAM : Access Done
|
238 |
|
|
input USE_CA; // Signal use cache
|
239 |
|
|
input INHIBIT; // Signal cache inhibit - no write in cache
|
240 |
9 |
ns32kum |
input KILL; // valid Ram must be updated because of collision ... or CINV
|
241 |
|
|
|
242 |
|
|
output WRCRAM0,WRCRAM1;
|
243 |
|
|
output WE_CV;
|
244 |
|
|
output [4:0] WADR_CV;
|
245 |
|
|
output [23:0] DAT_CV;
|
246 |
|
|
output INIT_CA_RUN;
|
247 |
|
|
output WRSET0,WRSET1;
|
248 |
|
|
|
249 |
|
|
reg [1:0] state;
|
250 |
|
|
reg [4:0] acount;
|
251 |
|
|
reg ca_set_d;
|
252 |
|
|
|
253 |
|
|
wire countf;
|
254 |
|
|
|
255 |
23 |
ns32kum |
always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET; // Store for whole access
|
256 |
|
|
|
257 |
9 |
ns32kum |
// physical address is stored in TAG-RAM
|
258 |
|
|
|
259 |
29 |
ns32kum |
assign WRCRAM0 = (CUPDATE & ~INHIBIT) & ~ca_set_d;
|
260 |
|
|
assign WRCRAM1 = (CUPDATE & ~INHIBIT) & ca_set_d;
|
261 |
9 |
ns32kum |
|
262 |
|
|
// Load Valid RAM :
|
263 |
|
|
|
264 |
29 |
ns32kum |
assign WE_CV = state[1] | HIT_ALL | (CUPDATE & ~INHIBIT) | KILL; // Hit All for "Last" Update
|
265 |
9 |
ns32kum |
assign WADR_CV = state[1] ? acount : VADR_R;
|
266 |
|
|
assign DAT_CV = state[1] ? 24'h0 : UPDATE;
|
267 |
|
|
|
268 |
|
|
// Clear of Cache-Valid RAMs : 32 clocks of BCLK
|
269 |
|
|
|
270 |
|
|
assign countf = (acount == 5'h1F);
|
271 |
|
|
|
272 |
|
|
always @(posedge BCLK)
|
273 |
|
|
casex ({BRESET,INVAL_A,countf,state[1:0]})
|
274 |
|
|
5'b0xx_xx : state <= 2'b01;
|
275 |
|
|
5'b1xx_01 : state <= 2'b10; // start counter
|
276 |
|
|
5'b10x_00 : state <= 2'b00; // wait ...
|
277 |
|
|
5'b11x_00 : state <= 2'b10;
|
278 |
|
|
5'b1x0_10 : state <= 2'b10;
|
279 |
|
|
5'b1x1_10 : state <= 2'b00;
|
280 |
|
|
default : state <= 2'b0;
|
281 |
|
|
endcase
|
282 |
|
|
|
283 |
|
|
always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01;
|
284 |
|
|
|
285 |
|
|
assign INIT_CA_RUN = state[1];
|
286 |
|
|
|
287 |
|
|
// WRITE Control in data RAMs
|
288 |
29 |
ns32kum |
assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA & ~ca_set_d);
|
289 |
|
|
assign WRSET1 = ( CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA & ca_set_d);
|
290 |
9 |
ns32kum |
|
291 |
|
|
endmodule
|
292 |
|
|
|
293 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
294 |
9 |
ns32kum |
//
|
295 |
29 |
ns32kum |
// 6. MMU_MATCH MMU virtual address match detector
|
296 |
9 |
ns32kum |
//
|
297 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
298 |
9 |
ns32kum |
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
|
299 |
|
|
VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 );
|
300 |
|
|
|
301 |
|
|
input USER;
|
302 |
|
|
input READ;
|
303 |
|
|
input WRITE;
|
304 |
|
|
input RMW;
|
305 |
|
|
input [2:0] MCR_FLAGS;
|
306 |
|
|
input [31:0] MVALID;
|
307 |
|
|
input [31:12] VADR_R;
|
308 |
|
|
input [31:16] MMU_VA;
|
309 |
|
|
input [1:0] IVAR; // Invalidate Entry
|
310 |
|
|
|
311 |
|
|
output VIRTUELL; // only for Adress-Mux
|
312 |
|
|
output MMU_HIT;
|
313 |
|
|
output [31:0] UPDATE;
|
314 |
|
|
output reg PROT_ERROR; // if valid must suppress write in Write Buffer and cache
|
315 |
|
|
output CI,SEL_PTB1;
|
316 |
|
|
|
317 |
|
|
reg [15:0] maske;
|
318 |
|
|
|
319 |
|
|
wire adr_space,as_sorte,match,alles_ok;
|
320 |
|
|
wire [15:0] val_bits,as_bits;
|
321 |
|
|
wire ena_prot;
|
322 |
|
|
wire zugriff;
|
323 |
|
|
|
324 |
|
|
assign zugriff = READ | WRITE;
|
325 |
|
|
|
326 |
|
|
always @(VADR_R)
|
327 |
|
|
case (VADR_R[15:12])
|
328 |
|
|
4'h0 : maske = 16'h0001;
|
329 |
|
|
4'h1 : maske = 16'h0002;
|
330 |
|
|
4'h2 : maske = 16'h0004;
|
331 |
|
|
4'h3 : maske = 16'h0008;
|
332 |
|
|
4'h4 : maske = 16'h0010;
|
333 |
|
|
4'h5 : maske = 16'h0020;
|
334 |
|
|
4'h6 : maske = 16'h0040;
|
335 |
|
|
4'h7 : maske = 16'h0080;
|
336 |
|
|
4'h8 : maske = 16'h0100;
|
337 |
|
|
4'h9 : maske = 16'h0200;
|
338 |
|
|
4'hA : maske = 16'h0400;
|
339 |
|
|
4'hB : maske = 16'h0800;
|
340 |
|
|
4'hC : maske = 16'h1000;
|
341 |
|
|
4'hD : maske = 16'h2000;
|
342 |
|
|
4'hE : maske = 16'h4000;
|
343 |
|
|
4'hF : maske = 16'h8000;
|
344 |
|
|
endcase
|
345 |
|
|
|
346 |
|
|
assign VIRTUELL = USER ? MCR_FLAGS[0] : MCR_FLAGS[1];
|
347 |
|
|
|
348 |
11 |
ns32kum |
assign adr_space = IVAR[1] ? IVAR[0] : (MCR_FLAGS[2] & USER); // adr_space = IVARx ? 1 or 0 : DualSpace & TU
|
349 |
9 |
ns32kum |
|
350 |
|
|
assign as_sorte = ((MVALID[31:16] & maske) != 16'h0);
|
351 |
|
|
|
352 |
11 |
ns32kum |
assign match = (VADR_R[31:20] == MMU_VA[31:20]) & (adr_space == as_sorte) & ((MVALID[15:0] & maske) != 16'h0000);
|
353 |
9 |
ns32kum |
|
354 |
11 |
ns32kum |
assign alles_ok = match & ( ~WRITE | MMU_VA[17] ) & ~PROT_ERROR; // Modified - Flag : reload the PTE
|
355 |
9 |
ns32kum |
|
356 |
23 |
ns32kum |
// if MMU_HIT = 0 then there is no Write-Buffer access and no update of cache !
|
357 |
9 |
ns32kum |
assign MMU_HIT = zugriff ? ( VIRTUELL ? alles_ok : 1'b1 ) : 1'b0 ; // MMU off : then always HIT
|
358 |
|
|
|
359 |
|
|
assign val_bits = IVAR[1] ? (MVALID[15:0] & (match ? ~maske : 16'hFFFF)) : (MVALID[15:0] | maske);
|
360 |
11 |
ns32kum |
assign as_bits = IVAR[1] ? MVALID[31:16] : (adr_space ? (MVALID[31:16] | maske) : (MVALID[31:16] & ~maske));
|
361 |
9 |
ns32kum |
|
362 |
|
|
assign UPDATE = {as_bits,val_bits};
|
363 |
|
|
|
364 |
|
|
assign ena_prot = zugriff & VIRTUELL & match;
|
365 |
|
|
|
366 |
|
|
// A Protection error must suppress write in WB and cache
|
367 |
|
|
always @(ena_prot or MMU_VA or USER or WRITE or RMW)
|
368 |
|
|
case ({ena_prot,MMU_VA[19:18]})
|
369 |
|
|
3'b100 : PROT_ERROR = USER | WRITE | RMW; // Only Supervisor READ
|
370 |
|
|
3'b101 : PROT_ERROR = USER; // no USER access
|
371 |
|
|
3'b110 : PROT_ERROR = USER & (WRITE | RMW); // USER only READ
|
372 |
|
|
default : PROT_ERROR = 1'b0;
|
373 |
|
|
endcase
|
374 |
|
|
|
375 |
|
|
assign CI = VIRTUELL & MMU_VA[16];
|
376 |
|
|
assign SEL_PTB1 = adr_space; // For PTE update
|
377 |
|
|
|
378 |
|
|
endmodule
|
379 |
|
|
|
380 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
381 |
9 |
ns32kum |
//
|
382 |
29 |
ns32kum |
// 7. CA_MATCH Cache tag match detector
|
383 |
9 |
ns32kum |
//
|
384 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
385 |
23 |
ns32kum |
module CA_MATCH ( CVALID, DRAMSZ, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
|
386 |
9 |
ns32kum |
CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL );
|
387 |
|
|
|
388 |
|
|
input [23:0] CVALID;
|
389 |
23 |
ns32kum |
input [2:0] DRAMSZ;
|
390 |
|
|
input [31:4] ADDR;
|
391 |
29 |
ns32kum |
input [28:12] TAG0,TAG1;
|
392 |
9 |
ns32kum |
input [1:0] CFG; // LDC , DC
|
393 |
|
|
input WRITE;
|
394 |
|
|
input MMU_HIT;
|
395 |
|
|
input CI;
|
396 |
|
|
input INVAL_L; // invalid cache line
|
397 |
|
|
input KDET;
|
398 |
|
|
input ENDRAM;
|
399 |
|
|
input DC_ILO; // CBITI/SBITI special case
|
400 |
|
|
|
401 |
|
|
output CA_HIT;
|
402 |
|
|
output CA_SET; // if no Hit then says SET where to store
|
403 |
|
|
output [23:0] UPDATE; // Update Information for CVALID memory
|
404 |
|
|
output IO_SPACE;
|
405 |
|
|
output USE_CA;
|
406 |
|
|
output WB_ACC;
|
407 |
|
|
output KILL;
|
408 |
|
|
|
409 |
|
|
reg [7:0] maske;
|
410 |
29 |
ns32kum |
reg acc_dram;
|
411 |
9 |
ns32kum |
|
412 |
|
|
wire match_0,match_1;
|
413 |
|
|
wire valid_0,valid_1;
|
414 |
|
|
wire select;
|
415 |
|
|
wire clear;
|
416 |
|
|
wire [7:0] update_0,update_1,lastinfo;
|
417 |
29 |
ns32kum |
wire sel_dram;
|
418 |
9 |
ns32kum |
|
419 |
|
|
always @(ADDR)
|
420 |
|
|
case (ADDR[6:4])
|
421 |
|
|
3'h0 : maske = 8'h01;
|
422 |
|
|
3'h1 : maske = 8'h02;
|
423 |
|
|
3'h2 : maske = 8'h04;
|
424 |
|
|
3'h3 : maske = 8'h08;
|
425 |
|
|
3'h4 : maske = 8'h10;
|
426 |
|
|
3'h5 : maske = 8'h20;
|
427 |
|
|
3'h6 : maske = 8'h40;
|
428 |
|
|
3'h7 : maske = 8'h80;
|
429 |
|
|
endcase
|
430 |
|
|
|
431 |
|
|
assign valid_0 = (( CVALID[7:0] & maske) != 8'h00);
|
432 |
|
|
assign valid_1 = ((CVALID[15:8] & maske) != 8'h00);
|
433 |
|
|
|
434 |
29 |
ns32kum |
assign match_0 = ( TAG0 == ADDR[28:12] ); // 4KB
|
435 |
|
|
assign match_1 = ( TAG1 == ADDR[28:12] ); // 4KB
|
436 |
9 |
ns32kum |
|
437 |
29 |
ns32kum |
assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0] & (sel_dram | KDET);
|
438 |
9 |
ns32kum |
|
439 |
|
|
// which SET is written in cache miss ? If both are valid the last used is not taken
|
440 |
11 |
ns32kum |
assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0; // Last-used field = CVALID[23:16]
|
441 |
9 |
ns32kum |
|
442 |
|
|
assign CA_SET = CA_HIT ? (valid_1 & match_1) : select;
|
443 |
|
|
|
444 |
|
|
assign clear = INVAL_L | KDET; // INVAL_L is from CINV
|
445 |
|
|
|
446 |
|
|
assign update_0 = CA_SET ? CVALID[7:0] : (clear ? (CVALID[7:0] & ~maske) : (CVALID[7:0] | maske));
|
447 |
11 |
ns32kum |
assign update_1 = CA_SET ? (clear ? (CVALID[15:8] & ~maske) : (CVALID[15:8] | maske)) : CVALID[15:8];
|
448 |
9 |
ns32kum |
|
449 |
11 |
ns32kum |
assign lastinfo = CA_HIT ? (CA_SET ? (CVALID[23:16] | maske) : (CVALID[23:16] & ~maske)) : CVALID[23:16];
|
450 |
9 |
ns32kum |
|
451 |
|
|
assign UPDATE = {lastinfo,update_1,update_0};
|
452 |
|
|
|
453 |
|
|
assign KILL = clear & CA_HIT & ~CFG[1]; // only if cache is not locked
|
454 |
|
|
|
455 |
29 |
ns32kum |
always @(DRAMSZ or ADDR) // Size of DRAM
|
456 |
|
|
case (DRAMSZ)
|
457 |
|
|
3'b000 : acc_dram = (ADDR[28:23] == 6'd0); // 8 MB 32016 Second Processor
|
458 |
|
|
3'b001 : acc_dram = (ADDR[28:24] == 5'd0); // 16 MB
|
459 |
|
|
3'b010 : acc_dram = (ADDR[28:25] == 4'd0); // 32 MB
|
460 |
|
|
3'b011 : acc_dram = (ADDR[28:26] == 3'd0); // 64 MB
|
461 |
|
|
3'b100 : acc_dram = (ADDR[28:27] == 2'd0); // 128 MB
|
462 |
|
|
3'b101 : acc_dram = ~ADDR[28]; // 256 MB
|
463 |
|
|
3'b110 : acc_dram = 1'b1; // 512 MB
|
464 |
|
|
3'b111 : acc_dram = ~(ADDR[28:27] == 2'b10); // 256 MB NetBSD + 128 MB
|
465 |
23 |
ns32kum |
endcase
|
466 |
|
|
|
467 |
29 |
ns32kum |
assign sel_dram = (ADDR[31:29] == 3'd0) & acc_dram & ENDRAM;
|
468 |
9 |
ns32kum |
assign IO_SPACE = ~sel_dram; // not DRAM or DRAM ist off
|
469 |
23 |
ns32kum |
|
470 |
9 |
ns32kum |
assign USE_CA = ~CI & ~DC_ILO & CFG[0] & ~CFG[1]; // CI ? ILO ? Cache on ? Locked Cache ?
|
471 |
|
|
assign WB_ACC = WRITE & MMU_HIT & sel_dram;
|
472 |
|
|
|
473 |
|
|
endmodule
|
474 |
|
|
|
475 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
476 |
9 |
ns32kum |
//
|
477 |
29 |
ns32kum |
// 8. FILTCMP Address Filter and Comparator
|
478 |
9 |
ns32kum |
//
|
479 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
480 |
23 |
ns32kum |
module FILTCMP ( DRAMSZ, RADR, DRAM_A, ADR_EQU, TAGDAT );
|
481 |
|
|
|
482 |
|
|
input [2:0] DRAMSZ;
|
483 |
29 |
ns32kum |
input [28:4] RADR,DRAM_A;
|
484 |
23 |
ns32kum |
|
485 |
|
|
output ADR_EQU;
|
486 |
29 |
ns32kum |
output reg [28:12] TAGDAT;
|
487 |
23 |
ns32kum |
|
488 |
29 |
ns32kum |
reg [28:23] adram;
|
489 |
23 |
ns32kum |
|
490 |
|
|
always @(DRAMSZ or RADR)
|
491 |
|
|
casex (DRAMSZ)
|
492 |
29 |
ns32kum |
3'b000 : TAGDAT = {6'd0,RADR[22:12]}; // 8 MB
|
493 |
|
|
3'b001 : TAGDAT = {5'd0,RADR[23:12]}; // 16 MB
|
494 |
|
|
3'b010 : TAGDAT = {4'd0,RADR[24:12]}; // 32 MB
|
495 |
|
|
3'b011 : TAGDAT = {3'd0,RADR[25:12]}; // 64 MB
|
496 |
|
|
3'b100 : TAGDAT = {2'd0,RADR[26:12]}; // 128 MB
|
497 |
|
|
3'b101 : TAGDAT = {1'b0,RADR[27:12]}; // 256 MB
|
498 |
|
|
3'b11x : TAGDAT = RADR[28:12] ; // 512 MB
|
499 |
23 |
ns32kum |
endcase
|
500 |
|
|
|
501 |
|
|
always @(DRAMSZ or DRAM_A) // The address comparator is only used in the data cache.
|
502 |
|
|
casex (DRAMSZ)
|
503 |
29 |
ns32kum |
3'b000 : adram = 6'd0; // 8 MB
|
504 |
|
|
3'b001 : adram = {5'd0,DRAM_A[23]}; // 16 MB
|
505 |
|
|
3'b010 : adram = {4'd0,DRAM_A[24:23]}; // 32 MB
|
506 |
|
|
3'b011 : adram = {3'd0,DRAM_A[25:23]}; // 64 MB
|
507 |
|
|
3'b100 : adram = {2'd0,DRAM_A[26:23]}; // 128 MB
|
508 |
|
|
3'b101 : adram = {1'd0,DRAM_A[27:23]}; // 256 MB
|
509 |
|
|
3'b11x : adram = DRAM_A[28:23] ; // 512 MB
|
510 |
23 |
ns32kum |
endcase
|
511 |
|
|
|
512 |
|
|
assign ADR_EQU = {TAGDAT,RADR[11:4]} == {adram,DRAM_A[22:4]};
|
513 |
|
|
|
514 |
|
|
endmodule
|
515 |
|
|
|
516 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
517 |
|
|
//
|
518 |
29 |
ns32kum |
// 9. DCACHE_SM Data cache state machine
|
519 |
23 |
ns32kum |
//
|
520 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
521 |
11 |
ns32kum |
module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW, CAPDAT, VADR_R, IC_VA,
|
522 |
23 |
ns32kum |
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, DMA_CHK, ICTODC,
|
523 |
12 |
ns32kum |
RWVAL, VIRTUELL, QWATWO,
|
524 |
11 |
ns32kum |
DRAM_ACC, DRAM_WR, IO_ACC, IO_RD, IO_WR, PTE_MUX, PD_MUX, PKEEP, PTE_ADR, PTE_DAT, HIT_ALL, ACC_OK,
|
525 |
|
|
ABORT, PROTECT, IACC_STAT, ABO_LEVEL1, WR_MRAM, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE, MMU_DIN, IC_SIGS, KOMUX,
|
526 |
9 |
ns32kum |
KDET, DMA_MUX, HLDA, RWVFLAG, PTE_STAT );
|
527 |
|
|
|
528 |
|
|
input BCLK;
|
529 |
|
|
input BRESET;
|
530 |
|
|
input IO_SPACE;
|
531 |
|
|
input MDONE; // Memory Done : feedback from DRAM Controller, BCLK aligned !
|
532 |
|
|
input IO_READY;
|
533 |
|
|
input MMU_HIT,CA_HIT;
|
534 |
|
|
input READ,WRITE,ZTEST,RMW;
|
535 |
|
|
input [31:0] CAPDAT;
|
536 |
|
|
input [31:12] VADR_R,IC_VA;
|
537 |
|
|
input USE_CA;
|
538 |
|
|
input PTB_WR,PTB_SEL;
|
539 |
|
|
input SEL_PTB1;
|
540 |
29 |
ns32kum |
input [28:12] CPU_OUT; // used for PTB0/1
|
541 |
9 |
ns32kum |
input USER;
|
542 |
|
|
input PROT_ERROR;
|
543 |
|
|
input WB_ACC;
|
544 |
|
|
input ENWR; // Enable WRITE from DRAM
|
545 |
|
|
input ADR_EQU;
|
546 |
|
|
input IC_PREQ;
|
547 |
23 |
ns32kum |
input DMA_CHK;
|
548 |
9 |
ns32kum |
input [3:0] ICTODC; // multiple signals from ICACHE, especially DMA
|
549 |
|
|
input [1:0] RWVAL; // RDVAL+WRVAL Operation
|
550 |
|
|
input VIRTUELL; // for RDVAL/WRVAL
|
551 |
12 |
ns32kum |
input QWATWO;
|
552 |
9 |
ns32kum |
|
553 |
|
|
output reg DRAM_ACC,DRAM_WR;
|
554 |
|
|
output IO_ACC,IO_RD,IO_WR;
|
555 |
|
|
output PTE_MUX,PD_MUX,PKEEP;
|
556 |
29 |
ns32kum |
output [28:0] PTE_ADR;
|
557 |
9 |
ns32kum |
output [19:0] PTE_DAT;
|
558 |
|
|
output HIT_ALL;
|
559 |
|
|
output ACC_OK;
|
560 |
|
|
output ABORT,PROTECT;
|
561 |
|
|
output [3:1] IACC_STAT;
|
562 |
|
|
output ABO_LEVEL1;
|
563 |
|
|
output WR_MRAM;
|
564 |
|
|
output CUPDATE;
|
565 |
|
|
output AUX_DAT;
|
566 |
|
|
output reg NEW_PTB;
|
567 |
|
|
output reg PTB_ONE;
|
568 |
|
|
output [23:0] MMU_DIN;
|
569 |
|
|
output [1:0] IC_SIGS;
|
570 |
|
|
output KOMUX;
|
571 |
|
|
output KDET; // Signal for detection of collision
|
572 |
|
|
output DMA_MUX;
|
573 |
|
|
output HLDA; // active low
|
574 |
|
|
output RWVFLAG; // RDVAL/WRVAL result
|
575 |
|
|
output [1:0] PTE_STAT;
|
576 |
|
|
|
577 |
|
|
reg IO_WR,IO_RD;
|
578 |
|
|
reg [1:0] pl_dat;
|
579 |
|
|
reg [6:0] new_state;
|
580 |
|
|
reg mem_done;
|
581 |
|
|
reg rd_done;
|
582 |
|
|
reg [2:0] pstate;
|
583 |
|
|
reg pte_run_wr;
|
584 |
|
|
reg [1:0] prot_level1;
|
585 |
|
|
reg card_flag;
|
586 |
29 |
ns32kum |
reg [28:12] ptb0,ptb1;
|
587 |
9 |
ns32kum |
reg write_ok;
|
588 |
|
|
reg icp_acc;
|
589 |
|
|
reg [2:0] ko_state;
|
590 |
|
|
reg dma_run;
|
591 |
|
|
reg dma_kdet;
|
592 |
|
|
reg rwv_bit;
|
593 |
|
|
reg prot_i;
|
594 |
|
|
reg rd_rdy;
|
595 |
|
|
|
596 |
29 |
ns32kum |
wire [28:12] ptb10;
|
597 |
9 |
ns32kum |
wire [31:12] virtual_adr;
|
598 |
|
|
wire io_busy;
|
599 |
|
|
wire dram_go;
|
600 |
|
|
wire pte_sel;
|
601 |
|
|
wire pte_acc;
|
602 |
|
|
wire do_ca_rd,pte_go,do_ic_p;
|
603 |
|
|
wire valid,valid_a,refer,modi;
|
604 |
|
|
wire level1,level2;
|
605 |
|
|
wire rd_level2;
|
606 |
|
|
wire wr_req;
|
607 |
|
|
wire wr_dram;
|
608 |
|
|
wire wr_icmram;
|
609 |
|
|
wire rd_ende;
|
610 |
|
|
wire pte_dat_8;
|
611 |
|
|
wire pte_wr_sig;
|
612 |
|
|
wire run_dc;
|
613 |
|
|
wire kostart;
|
614 |
|
|
wire dma;
|
615 |
|
|
wire dma_go;
|
616 |
|
|
wire zugriff;
|
617 |
|
|
wire mmu_hit_i;
|
618 |
|
|
wire do_zt;
|
619 |
|
|
wire zt_ok;
|
620 |
|
|
wire [1:0] acc_level;
|
621 |
|
|
wire user_ptw,wr_ptw;
|
622 |
|
|
wire pte_puls;
|
623 |
|
|
|
624 |
|
|
// if USER not virtual then ZTEST is quickly done
|
625 |
|
|
assign zugriff = READ | WRITE | (ZTEST & VIRTUELL);
|
626 |
|
|
assign mmu_hit_i = MMU_HIT & ~ZTEST;
|
627 |
|
|
|
628 |
|
|
// WB_ACC is a successful WRITE access, ICTODC[0] is coherent Logik release : >=3 entries in FIFO
|
629 |
11 |
ns32kum |
assign wr_req = WB_ACC & ((ENWR & ICTODC[0]) | (DRAM_WR & ADR_EQU)); // release done by DRAM signal ENWR
|
630 |
9 |
ns32kum |
|
631 |
|
|
assign rd_ende = CA_HIT | rd_rdy; // CA_HIT only when Cache activ !
|
632 |
|
|
|
633 |
|
|
always @( zugriff // READ or WRITE or ZTEST , global control
|
634 |
|
|
or PROT_ERROR // must not be
|
635 |
|
|
//
|
636 |
|
|
or IO_SPACE // access of IO world
|
637 |
|
|
or io_busy // is access already running ?
|
638 |
|
|
//
|
639 |
|
|
or mmu_hit_i // Hit in MMU , now only a READ can happen
|
640 |
|
|
or READ
|
641 |
|
|
or wr_req
|
642 |
|
|
or rd_ende // Cache Hit
|
643 |
|
|
//
|
644 |
|
|
or DRAM_ACC // DRAM Access : shows an active state
|
645 |
|
|
or pte_acc // PTE access is running
|
646 |
|
|
//
|
647 |
|
|
or IC_PREQ // PTE Request from ICACHE
|
648 |
|
|
//
|
649 |
|
|
or dma // DMA Request
|
650 |
|
|
or dma_run ) // DMA running
|
651 |
|
|
// #_# #_# #_# #_#
|
652 |
11 |
ns32kum |
casex ({zugriff,PROT_ERROR,IO_SPACE,io_busy,mmu_hit_i,READ,wr_req,rd_ende,DRAM_ACC,pte_acc,IC_PREQ,dma,dma_run})
|
653 |
9 |
ns32kum |
// MMU Miss : PTE load from memory , valid too if WRITE and M=0
|
654 |
|
|
13'b10_xx_0xxx_x0_x_x0 : new_state = 7'b0001010; // start PTE access
|
655 |
|
|
// IO-Address selected : external access starts if not busy because of WRITE
|
656 |
|
|
13'b10_10_1xxx_x0_x_x0 : new_state = 7'b0000001;
|
657 |
|
|
// DRAM access : Cache Miss at READ :
|
658 |
|
|
13'b10_0x_1100_00_x_x0 : new_state = 7'b0010010;
|
659 |
|
|
// DRAM access : WRITE
|
660 |
|
|
13'b10_0x_101x_x0_x_x0 : new_state = 7'b0000100;
|
661 |
|
|
// PTE Request ICACHE , IO access with WRITE is stored - parallel DRAM access possible
|
662 |
23 |
ns32kum |
13'b0x_xx_xxxx_x0_1_x0 : new_state = 7'b0101010; // no access
|
663 |
11 |
ns32kum |
13'b10_0x_1101_x0_1_x0 : new_state = 7'b0101010; // if successful READ a PTE access can happen in parallel
|
664 |
9 |
ns32kum |
// DMA access. Attention : no IO-Write access in background and no ICACHE PTE access !
|
665 |
23 |
ns32kum |
13'b0x_x0_xxxx_x0_0_10 : new_state = 7'b1000000; // DMA access is started
|
666 |
9 |
ns32kum |
default : new_state = 7'b0;
|
667 |
|
|
endcase
|
668 |
|
|
|
669 |
|
|
assign IO_ACC = new_state[0]; // to load registers for data, addr und BE, signal one pulse
|
670 |
|
|
assign dram_go = new_state[1] | rd_level2 ;
|
671 |
|
|
assign wr_dram = new_state[2]; // pulse only
|
672 |
|
|
assign pte_go = new_state[3];
|
673 |
|
|
assign do_ca_rd = new_state[4];
|
674 |
|
|
assign do_ic_p = new_state[5];
|
675 |
|
|
assign dma_go = new_state[6];
|
676 |
|
|
|
677 |
|
|
// ZTEST logic is for the special case when a write access is crossing page boundaries
|
678 |
|
|
|
679 |
|
|
assign do_zt = ZTEST & ~icp_acc;
|
680 |
|
|
|
681 |
11 |
ns32kum |
// 0 is pass , 1 is blocked. RWVAL[0] is 1 if WRVAL. Level 1 can only be blocked, otherwise ABORT or Level 2 is following.
|
682 |
29 |
ns32kum |
always @(posedge BCLK) if (mem_done) rwv_bit <= level2 ? ~(CAPDAT[2] & (~RWVAL[0] | CAPDAT[1])) : 1'b1;
|
683 |
9 |
ns32kum |
|
684 |
|
|
assign RWVFLAG = VIRTUELL & rwv_bit;
|
685 |
|
|
|
686 |
29 |
ns32kum |
assign zt_ok = mem_done & (RWVAL[1] ? (~CAPDAT[2] | (RWVAL[0] & ~CAPDAT[1]) | level2) // Level 2 always ok
|
687 |
|
|
: (CAPDAT[0] & ~prot_i & level2) ); // "normal" access
|
688 |
9 |
ns32kum |
|
689 |
|
|
// PTE access logic, normal state machine
|
690 |
|
|
// Updates to the PTEs are normal WRITE request to DRAM, therefore no MDONE at Write
|
691 |
|
|
|
692 |
|
|
assign modi = ~CAPDAT[8] & WRITE & write_ok & ~icp_acc; // is "1" if the Modified Bit must be set
|
693 |
|
|
assign refer = CAPDAT[7] | do_zt; // Assumption "R" Bit is set if RDVAL/WRVAL and page border test
|
694 |
29 |
ns32kum |
assign valid = (do_zt & RWVAL[1]) ? (CAPDAT[2] & (CAPDAT[1] | ~RWVAL[0]) & CAPDAT[0] & level1)
|
695 |
|
|
: (CAPDAT[0] & ~prot_i);
|
696 |
9 |
ns32kum |
|
697 |
|
|
always @(posedge BCLK) mem_done <= MDONE & pte_acc;
|
698 |
|
|
|
699 |
|
|
always @(posedge BCLK or negedge BRESET)
|
700 |
|
|
if (!BRESET) pstate <= 3'h0;
|
701 |
|
|
else
|
702 |
|
|
casex ({pte_go,mem_done,valid,refer,modi,pte_run_wr,pstate})
|
703 |
|
|
9'b0x_xxxx_000 : pstate <= 3'd0; // nothing to do
|
704 |
|
|
9'b1x_xxxx_000 : pstate <= 3'd4; // start
|
705 |
|
|
9'bx0_xxxx_100 : pstate <= 3'd4; // wait for Level 1
|
706 |
|
|
9'bx1_0xxx_100 : pstate <= 3'd0; // THAT'S ABORT !
|
707 |
|
|
9'bx1_11xx_100 : pstate <= 3'd6; // PTE Level 1 was referenced , next is Level 2
|
708 |
|
|
9'bx1_10xx_100 : pstate <= 3'd5; // for writing of modified Level 1 : R=1
|
709 |
|
|
9'bxx_xxx0_101 : pstate <= 3'd5; // write must wait
|
710 |
|
|
9'bxx_xxx1_101 : pstate <= 3'd6; // one wait cycle
|
711 |
|
|
9'bx0_xxxx_110 : pstate <= 3'd6; // wait for Level 2
|
712 |
|
|
9'bx1_0xxx_110 : pstate <= 3'd0; // THAT'S ABORT !
|
713 |
|
|
9'bx1_10xx_110 : pstate <= 3'd7; // Update neccesary : R=0
|
714 |
|
|
9'bx1_110x_110 : pstate <= 3'd0; // all ok - end
|
715 |
|
|
9'bx1_111x_110 : pstate <= 3'd7; // Update neccesary : M=0
|
716 |
|
|
9'bxx_xxx0_111 : pstate <= 3'd7; // write must wait
|
717 |
|
|
9'bxx_xxx1_111 : pstate <= 3'd0; // continues to end of DRAM write
|
718 |
|
|
default : pstate <= 3'd0;
|
719 |
|
|
endcase
|
720 |
|
|
|
721 |
|
|
assign pte_acc = pstate[2];
|
722 |
|
|
assign level1 = ~pstate[1];
|
723 |
|
|
assign level2 = pstate[1];
|
724 |
|
|
|
725 |
29 |
ns32kum |
assign valid_a = (ZTEST & RWVAL[1]) ? (CAPDAT[2] & (CAPDAT[1] | ~RWVAL[0]) & ~CAPDAT[0] & level1)
|
726 |
|
|
: ~CAPDAT[0]; // not do_zt because of icp_acc in ABORT
|
727 |
9 |
ns32kum |
|
728 |
|
|
assign ABORT = mem_done & valid_a & ~icp_acc;
|
729 |
11 |
ns32kum |
assign PROTECT = ((mem_done & prot_i & ~icp_acc) | PROT_ERROR) & ~(ZTEST & RWVAL[1]); // no Protection-Error at RDVAL/WRVAL
|
730 |
9 |
ns32kum |
|
731 |
29 |
ns32kum |
assign IACC_STAT[1] = mem_done & ~CAPDAT[0] & icp_acc;
|
732 |
9 |
ns32kum |
assign IACC_STAT[2] = level1;
|
733 |
|
|
assign IACC_STAT[3] = mem_done & prot_i & icp_acc;
|
734 |
|
|
|
735 |
|
|
assign ABO_LEVEL1 = level1; // is stored in case of ABORT in ADDR_UNIT
|
736 |
|
|
|
737 |
|
|
assign rd_level2 = (pstate == 3'd5) | (mem_done & (pstate == 3'd4) & refer & valid);
|
738 |
|
|
|
739 |
|
|
assign WR_MRAM = mem_done & (pstate == 3'd6) & valid & ~icp_acc & ~ZTEST;
|
740 |
|
|
assign wr_icmram = mem_done & (pstate == 3'd6) & valid & icp_acc;
|
741 |
|
|
|
742 |
|
|
// Signals to the Instruction Cache
|
743 |
|
|
// pte_acc combined with icp_acc for STATISTIK.
|
744 |
|
|
assign IC_SIGS = {(pte_acc & icp_acc),wr_icmram};
|
745 |
|
|
|
746 |
|
|
assign PTE_MUX = pte_go | (pte_acc & ~pstate[1]);
|
747 |
|
|
|
748 |
|
|
assign pte_puls = mem_done & pte_acc & ~pstate[1];
|
749 |
|
|
assign PTE_STAT = {(pte_puls & icp_acc),(pte_puls & ~icp_acc)}; // only for statistic
|
750 |
|
|
|
751 |
11 |
ns32kum |
assign PD_MUX = ((pstate == 3'd4) & mem_done & valid & ~refer) // switch data-MUX, write level 1 too
|
752 |
9 |
ns32kum |
| ((pstate == 3'd6) & mem_done & valid & (~refer | modi)) // write level 2
|
753 |
|
|
| (((pstate == 3'd5) | (pstate == 3'd7)) & ~pte_run_wr);
|
754 |
|
|
|
755 |
|
|
assign pte_wr_sig = ENWR & PD_MUX;
|
756 |
|
|
|
757 |
|
|
always @(posedge BCLK) pte_run_wr <= pte_wr_sig; // Ok-Signal for pstate State-machine
|
758 |
|
|
|
759 |
|
|
assign PKEEP = (pstate == 3'd6) | ((pstate == 3'd7) & ~pte_run_wr); // keep the DRAM address
|
760 |
|
|
|
761 |
11 |
ns32kum |
// If there is a PTE still in the data cache it must be deleted. If MMU Bits are set by the pte engine a following
|
762 |
9 |
ns32kum |
// READ would deliver wrong data if cache hit. Therefore access of the Tags.
|
763 |
|
|
always @(posedge BCLK or negedge BRESET)
|
764 |
|
|
if (!BRESET) ko_state <= 3'b000;
|
765 |
|
|
else
|
766 |
|
|
casex ({kostart,ko_state})
|
767 |
|
|
4'b0_000 : ko_state <= 3'b000;
|
768 |
|
|
4'b1_000 : ko_state <= 3'b110;
|
769 |
|
|
4'bx_110 : ko_state <= 3'b111;
|
770 |
|
|
4'bx_111 : ko_state <= 3'b100;
|
771 |
|
|
4'bx_100 : ko_state <= 3'b000;
|
772 |
|
|
default : ko_state <= 3'b000;
|
773 |
|
|
endcase
|
774 |
|
|
|
775 |
|
|
assign kostart = pte_go | rd_level2;
|
776 |
|
|
|
777 |
12 |
ns32kum |
// ko_state[2] suppresses ACC_OK at READ
|
778 |
|
|
assign run_dc = (~ko_state[2] | QWATWO) & ~dma_run; // Bugfix of 7.10.2015
|
779 |
|
|
assign KOMUX = ko_state[1] | DMA_MUX;
|
780 |
|
|
assign KDET = ko_state[0] | dma_kdet;
|
781 |
9 |
ns32kum |
|
782 |
11 |
ns32kum |
assign HIT_ALL = MMU_HIT & CA_HIT & run_dc & ~pte_acc; // for Update "Last-Set" , MMU_HIT contains ZUGRIFF
|
783 |
9 |
ns32kum |
|
784 |
|
|
always @(posedge BCLK or negedge BRESET)
|
785 |
|
|
if (!BRESET) card_flag <= 1'b0;
|
786 |
|
|
else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE);
|
787 |
|
|
|
788 |
|
|
assign CUPDATE = card_flag & USE_CA & MDONE;
|
789 |
|
|
|
790 |
|
|
always @(posedge BCLK) rd_rdy <= card_flag & MDONE;
|
791 |
|
|
|
792 |
11 |
ns32kum |
// The cache RAM can not provide fast enough the data after an Update. In this case a secondary data path is activated
|
793 |
9 |
ns32kum |
assign AUX_DAT = rd_rdy;
|
794 |
|
|
|
795 |
|
|
// DRAM interface :
|
796 |
|
|
|
797 |
|
|
always @(posedge BCLK) DRAM_WR <= wr_dram | pte_wr_sig; // pulse
|
798 |
|
|
always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1;
|
799 |
|
|
else
|
800 |
|
|
DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET;
|
801 |
|
|
// IO interface :
|
802 |
|
|
|
803 |
|
|
always @(posedge BCLK)
|
804 |
|
|
begin
|
805 |
|
|
if (IO_ACC) IO_RD <= READ; else IO_RD <= IO_RD & ~IO_READY & BRESET;
|
806 |
|
|
if (IO_ACC) IO_WR <= WRITE; else IO_WR <= IO_WR & ~IO_READY & BRESET;
|
807 |
|
|
end
|
808 |
|
|
|
809 |
11 |
ns32kum |
assign io_busy = IO_RD | IO_WR | rd_done; // access is gone in next clock cycle, therefore blocked with "rd_done"
|
810 |
9 |
ns32kum |
|
811 |
11 |
ns32kum |
always @(posedge BCLK) rd_done <= IO_RD & IO_READY; // For READ one clock later for data to come through
|
812 |
9 |
ns32kum |
|
813 |
|
|
assign dma = ICTODC[2]; // external request HOLD after FF in ICACHE
|
814 |
|
|
|
815 |
11 |
ns32kum |
always @(posedge BCLK) dma_run <= (dma_go | (dma_run & dma)) & BRESET; // stops the data access until HOLD becomes inactive
|
816 |
9 |
ns32kum |
|
817 |
|
|
assign HLDA = ~(ICTODC[1] & dma_run); // Signal for system that the CPU has stopped accesses
|
818 |
|
|
|
819 |
23 |
ns32kum |
always @(posedge BCLK) dma_kdet <= DMA_CHK;
|
820 |
|
|
assign DMA_MUX = DMA_CHK | dma_kdet;
|
821 |
9 |
ns32kum |
|
822 |
|
|
// global feedback to ADDR_UNIT, early feedback to Op-Dec : you can continue
|
823 |
|
|
|
824 |
|
|
assign ACC_OK = ZTEST ? (~VIRTUELL | zt_ok)
|
825 |
11 |
ns32kum |
: (IO_SPACE ? ((IO_ACC & WRITE) | rd_done) : (wr_dram | (READ & MMU_HIT & rd_ende & run_dc)) );
|
826 |
9 |
ns32kum |
|
827 |
|
|
// PTB1 and PTB0
|
828 |
|
|
|
829 |
29 |
ns32kum |
always @(posedge BCLK) if (PTB_WR && !PTB_SEL) ptb0 <= CPU_OUT;
|
830 |
|
|
always @(posedge BCLK) if (PTB_WR && PTB_SEL) ptb1 <= CPU_OUT;
|
831 |
9 |
ns32kum |
|
832 |
|
|
always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block
|
833 |
|
|
always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
|
834 |
|
|
|
835 |
|
|
assign ptb10 = SEL_PTB1 ? ptb1 : ptb0;
|
836 |
|
|
|
837 |
|
|
// Address multiplex between ICACHE=1 and DCACHE=0 :
|
838 |
|
|
always @(posedge BCLK) if (pte_go) icp_acc <= do_ic_p;
|
839 |
|
|
|
840 |
|
|
assign pte_sel = pte_go ? do_ic_p : icp_acc;
|
841 |
|
|
|
842 |
|
|
assign virtual_adr = pte_sel ? IC_VA : VADR_R;
|
843 |
|
|
|
844 |
|
|
// The 2 Address-LSB's : no full access : USE_CA = 0
|
845 |
29 |
ns32kum |
assign PTE_ADR = rd_level2 ? {CAPDAT[28:12],virtual_adr[21:12],2'b00} : {ptb10,virtual_adr[31:22],2'b00};
|
846 |
9 |
ns32kum |
|
847 |
|
|
// PTE_DAT[8] is used for update of MMU_RAM.
|
848 |
|
|
assign pte_dat_8 = (level2 & WRITE & write_ok & ~icp_acc) | CAPDAT[8];
|
849 |
29 |
ns32kum |
assign PTE_DAT = {4'h3,CAPDAT[15:9],pte_dat_8,1'b1,CAPDAT[6:0]}; // the top 4 bits are Byte-Enable
|
850 |
9 |
ns32kum |
|
851 |
|
|
// The data for the MMU-RAM : 24 Bits , [6]=Cache Inhibit
|
852 |
|
|
assign MMU_DIN = {pl_dat,pte_dat_8,CAPDAT[6],CAPDAT[31:12]};
|
853 |
|
|
|
854 |
|
|
// Protection field
|
855 |
|
|
|
856 |
29 |
ns32kum |
always @(posedge BCLK) if (mem_done && (pstate[2:0] == 3'd4)) prot_level1 <= CAPDAT[2:1];
|
857 |
9 |
ns32kum |
|
858 |
29 |
ns32kum |
always @(prot_level1 or CAPDAT)
|
859 |
|
|
casex ({prot_level1,CAPDAT[2]})
|
860 |
|
|
3'b11_x : pl_dat = CAPDAT[2:1];
|
861 |
9 |
ns32kum |
3'b10_1 : pl_dat = 2'b10;
|
862 |
29 |
ns32kum |
3'b10_0 : pl_dat = CAPDAT[2:1];
|
863 |
9 |
ns32kum |
3'b01_1 : pl_dat = 2'b01;
|
864 |
29 |
ns32kum |
3'b01_0 : pl_dat = CAPDAT[2:1];
|
865 |
9 |
ns32kum |
3'b00_x : pl_dat = 2'b00;
|
866 |
|
|
endcase
|
867 |
|
|
|
868 |
11 |
ns32kum |
always @(USER or pl_dat) // is used if no PTE update is neccesary for M-Bit if writing is not allowed
|
869 |
9 |
ns32kum |
casex ({USER,pl_dat})
|
870 |
|
|
3'b1_11 : write_ok = 1'b1;
|
871 |
|
|
3'b0_1x : write_ok = 1'b1;
|
872 |
|
|
3'b0_01 : write_ok = 1'b1;
|
873 |
|
|
default : write_ok = 1'b0;
|
874 |
|
|
endcase
|
875 |
|
|
|
876 |
29 |
ns32kum |
assign acc_level = level2 ? pl_dat : CAPDAT[2:1];
|
877 |
9 |
ns32kum |
assign user_ptw = icp_acc ? ICTODC[3] : USER;
|
878 |
|
|
assign wr_ptw = ~icp_acc & (WRITE | RMW | (ZTEST & ~RWVAL[1])); // only data cache can write
|
879 |
|
|
|
880 |
|
|
always @(acc_level or user_ptw or wr_ptw)
|
881 |
|
|
case (acc_level)
|
882 |
|
|
2'b00 : prot_i = user_ptw | wr_ptw;
|
883 |
|
|
2'b01 : prot_i = user_ptw;
|
884 |
|
|
2'b10 : prot_i = user_ptw & wr_ptw;
|
885 |
|
|
2'b11 : prot_i = 1'b0;
|
886 |
|
|
endcase
|
887 |
|
|
|
888 |
|
|
endmodule
|
889 |
|
|
|