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

Subversion Repositories m32632

[/] [m32632/] [trunk/] [rtl/] [ICACHE_SM.v] - Blame information for rev 29

Details | Compare with Previous | View Log

Line No. Rev Author Line
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:       ICACHE_SM.v
7 29 ns32kum
//      Version:        3.0
8 23 ns32kum
//      History:        1.0 first release of 30 Mai 2015
9 29 ns32kum
//      Date:           2 December 2018
10 9 ns32kum
//
11 29 ns32kum
// Copyright (C) 2018 Udo Moeller
12 9 ns32kum
// 
13
// This source file may be used and distributed without 
14
// restriction provided that this copyright statement is not 
15
// removed from the file and that any derivative work contains 
16
// the original copyright notice and the associated disclaimer.
17
// 
18
// This source file is free software; you can redistribute it 
19
// and/or modify it under the terms of the GNU Lesser General 
20
// Public License as published by the Free Software Foundation;
21
// either version 2.1 of the License, or (at your option) any 
22
// later version. 
23
// 
24
// This source is distributed in the hope that it will be 
25
// useful, but WITHOUT ANY WARRANTY; without even the implied 
26
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
27
// PURPOSE. See the GNU Lesser General Public License for more 
28
// details. 
29
// 
30
// You should have received a copy of the GNU Lesser General 
31
// Public License along with this source; if not, download it 
32
// from http://www.opencores.org/lgpl.shtml 
33
// 
34 29 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
35 9 ns32kum
//
36
//      Modules contained in this file:
37
//      1. KOLDETECT    Collision Detection Unit
38 29 ns32kum
//      2. DMUX                 Data Multiplexor
39
//      3. ICACHE_SM    Instruction Cache State Machine
40 9 ns32kum
//
41 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42 9 ns32kum
 
43 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
44 9 ns32kum
//
45
//      1. KOLDETECT    Collision Detection Unit
46
//
47 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48
module KOLDETECT ( BCLK, BRESET, DRAM_WR, CVALID, ADDR, TAG0, TAG1 , CFG , C_VALID, READ_I, ACC_OK, HOLD, KDET, INVAL_A, ENA_HK,
49 9 ns32kum
                                   NEWCVAL, KOLLISION, STOP_ICRD, RUN_ICRD, KILL, KILLADR, ICTODC, STOP_CINV );
50
 
51
        input                   BCLK;
52
        input                   BRESET;
53
        input                   DRAM_WR;
54
        input   [23:0]   CVALID;         // Data from master Valid RAM
55 29 ns32kum
        input   [28:4]  ADDR;
56
        input  [28:12]  TAG0,TAG1;
57 9 ns32kum
        input    [1:0]   CFG;
58
        input   [23:0]   C_VALID;        // Data from secondary Valid RAM
59
        input                   READ_I;
60
        input                   ACC_OK;
61
        input                   HOLD;           // active low
62
        input                   KDET;
63
        input                   INVAL_A;        // Cache Invalidate All
64
        input                   ENA_HK;         // Enable HOLD and Kohaerenz
65
 
66
        output  [23:0]   NEWCVAL;
67
        output                  KOLLISION;
68
        output                  STOP_ICRD;
69
        output                  RUN_ICRD;
70
        output                  KILL;
71
        output  [11:7]  KILLADR;
72
        output   [2:0]   ICTODC;
73
        output                  STOP_CINV;
74
 
75 29 ns32kum
        reg             [28:4]  addr_r;
76 23 ns32kum
        reg              [7:0]   clear;
77 9 ns32kum
        reg                             do_koll;
78
        reg              [2:0]   counter;
79
        reg              [1:0]   wpointer,rpointer;
80
        reg             [35:0]   adrfifo;
81
        reg              [8:0]   fifo_q,fifo_c;
82
        reg              [1:0]   state;
83
        reg                             pipe;
84
        reg                             do_kill;
85
        reg                             dma;
86
 
87
        wire    [7:0]    set_0,set_1;
88
        wire                    match_0,match_1;
89
        wire                    valid_0,valid_1;
90
        wire                    found_0,found_1;
91
        wire                    kolli,dma_kolli;
92
        wire                    last_match;
93
        wire                    wr_entry;
94
        wire    [23:0]   cdaten;
95
        wire     [8:0]   kaddr;
96
        wire     [7:0]   new_0,new_1;
97
        wire                    dma_mode,ic_dma;
98
        wire                    free,ende;
99
        wire                    init_b;
100
 
101 11 ns32kum
        always @(posedge BCLK) do_koll <= DRAM_WR & CFG[0];      // one cycle pulse, without Cache Enable no collision
102 9 ns32kum
        always @(posedge BCLK) addr_r <= ADDR;
103
 
104
        // similar logic like in CA_MATCH
105
 
106
        assign set_0 = C_VALID[7:0];
107
        assign set_1 = C_VALID[15:8];
108
 
109
        assign valid_0 = set_0[addr_r[6:4]];
110
        assign valid_1 = set_1[addr_r[6:4]];
111
 
112 29 ns32kum
        assign match_0 = ( TAG0 == addr_r[28:12] );     // 4KB
113
        assign match_1 = ( TAG1 == addr_r[28:12] );     // 4KB
114 9 ns32kum
 
115
        assign found_0 = valid_0 & match_0;
116
        assign found_1 = valid_1 & match_1;
117
 
118
        assign kolli = (found_0 | found_1) & ~CFG[1] & do_koll; // Action only if ICACHE is not locked
119
 
120
        assign KOLLISION = (found_0 | found_1) & do_koll;       // to Statistik Modul, Register there
121
 
122
        assign dma_kolli = (found_0 | found_1) & ~CFG[1] & CFG[0];
123
 
124
        // the FIFO with 4 entries :
125
        assign init_b = CFG[0] & ~INVAL_A;       // initialise if CINV A too
126
 
127
        always @(posedge BCLK)
128
                if (!init_b) wpointer <= 2'b00;
129
                        else
130
                                wpointer <= wpointer + {1'b0,wr_entry};
131
 
132
        always @(posedge BCLK)
133
                if (!init_b) rpointer <= 2'b00;
134
                        else
135
                                rpointer <= rpointer + {1'b0,do_kill};
136
 
137
        always @(posedge BCLK)
138
          begin
139
                if (wr_entry && (wpointer == 2'b00)) adrfifo[8:0]   <= {addr_r[11:4],found_1};
140
                if (wr_entry && (wpointer == 2'b01)) adrfifo[17:9]  <= {addr_r[11:4],found_1};
141
                if (wr_entry && (wpointer == 2'b10)) adrfifo[26:18] <= {addr_r[11:4],found_1};
142
                if (wr_entry && (wpointer == 2'b11)) adrfifo[35:27] <= {addr_r[11:4],found_1};
143
          end
144
 
145
        always @(adrfifo or rpointer)
146
                case (rpointer)
147
                  2'b00 : fifo_q = adrfifo[8:0];
148
                  2'b01 : fifo_q = adrfifo[17:9];
149
                  2'b10 : fifo_q = adrfifo[26:18];
150
                  2'b11 : fifo_q = adrfifo[35:27];
151
                endcase
152
 
153
        always @(adrfifo or wpointer)   // for Match of last entry use wpointer
154
                case (wpointer)
155
                  2'b01 : fifo_c = adrfifo[8:0];
156
                  2'b10 : fifo_c = adrfifo[17:9];
157
                  2'b11 : fifo_c = adrfifo[26:18];
158
                  2'b00 : fifo_c = adrfifo[35:27];
159
                endcase
160
 
161
        // Control
162
 
163 11 ns32kum
        assign last_match = counter[2] & (fifo_c == {addr_r[11:4],found_1});    // if Match with last Entry no new Entry
164 9 ns32kum
 
165
        assign wr_entry = kolli & ~last_match;
166
 
167
        always @(posedge BCLK)
168
                casex ({init_b,wr_entry,do_kill,counter})
169
                  6'b0_xx_xxx : counter <= 3'b000;
170
                  6'b1_00_xxx : counter <= counter;
171
                  6'b1_11_xxx : counter <= counter;
172
                  6'b1_10_000 : counter <= 3'b100;
173 11 ns32kum
                  6'b1_10_1xx : counter <= (counter[1:0] == 2'b11) ? 3'b111 : {counter[2],(counter[1:0] + 2'b01)};        // Overflow avoid
174 9 ns32kum
                  6'b1_01_1xx : counter <= (counter[1:0] == 2'b00) ? 3'b000 : {counter[2],(counter[1:0] + 2'b11)};
175
                  default         : counter <= counter;
176
                endcase
177
 
178
        // DMA Access
179
        always @(posedge BCLK) dma <= ~HOLD;    // there is only one FF for this , from here to DCACHE
180
 
181
        // Controlling of ICACHE
182
 
183
        assign free = (~READ_I | ACC_OK) & ENA_HK;      // switch off if CINV
184
 
185
        always @(posedge BCLK)                                  //  state[1]  state[0]
186
                casex ({BRESET,dma,counter[2],free,ende,STOP_ICRD,dma_mode})
187
                  7'b0_xx_xx_xx : state <= 2'b00;
188
                  7'b1_00_xx_00 : state <= 2'b00;
189
                  7'b1_01_1x_00 : state <= 2'b10;       // Start of DCACHE Kohaerenz
190
                  7'b1_1x_1x_00 : state <= 2'b11;       // Start of DMA
191
        //
192
                  7'b1_xx_x0_10 : state <= 2'b10;       // without "ende" it stays as is
193
                  7'b1_0x_x1_10 : state <= 2'b00;       // DMA is not active
194
                  7'b1_1x_x1_10 : state <= 2'b11;       // to DMA !
195
        //
196
                  7'b1_00_xx_11 : state <= 2'b00;
197
                  7'b1_01_xx_11 : state <= 2'b10;
198
                  7'b1_1x_xx_11 : state <= 2'b11;
199
                  default               : state <= 2'b00;
200
                endcase
201
 
202
        assign STOP_ICRD = state[1];    // used for Multiplexer
203
        assign dma_mode  = state[0];     // internal Multiplexer
204
 
205
        assign STOP_CINV = state[1] & ~ENA_HK;  // stops CINV if DMA access or Kohaerenz access
206
 
207
        assign ende = (counter[1:0] == 2'b00) & do_kill;
208
 
209
        assign ic_dma = STOP_ICRD & dma_mode;   // Signal to DCACHE that ICACHE has stoped
210
 
211
        always @(posedge BCLK) pipe <= STOP_ICRD;
212
 
213
        assign RUN_ICRD = ~(STOP_ICRD | pipe);  // Release for IC_READ
214
 
215 11 ns32kum
        always @(posedge BCLK) do_kill <= STOP_ICRD & ~dma_mode & ~do_kill;     // Write pulse in Cache Valid RAM, 1 cycle on, 1 cycle off
216 9 ns32kum
 
217
        assign KILL = do_kill | (KDET & dma_kolli);
218
 
219
        // Valid Daten prepare : different sources for DMA and DCACHE Kohaerenz
220
 
221
        assign cdaten = dma_mode ? C_VALID : CVALID;
222
        assign kaddr  = dma_mode ? {addr_r[11:4],found_1} : fifo_q;
223
 
224
        assign KILLADR = kaddr[8:4];
225
 
226
        always @(kaddr)
227
                case (kaddr[3:1])
228
                  3'h0 : clear = 8'hFE;
229
                  3'h1 : clear = 8'hFD;
230
                  3'h2 : clear = 8'hFB;
231
                  3'h3 : clear = 8'hF7;
232
                  3'h4 : clear = 8'hEF;
233
                  3'h5 : clear = 8'hDF;
234
                  3'h6 : clear = 8'hBF;
235
                  3'h7 : clear = 8'h7F;
236
                endcase
237
 
238
        assign new_0 = kaddr[0] ? cdaten[7:0] : (cdaten[7:0] & clear);
239
        assign new_1 = kaddr[0] ? (cdaten[15:8] & clear) : cdaten[15:8];
240
 
241
        assign NEWCVAL = {cdaten[23:16],new_1,new_0};
242
 
243
        // multiple signals are needed in DCACHE :
244
        assign ICTODC = {dma,ic_dma,~(counter[2:1] == 2'b11)};
245
 
246
endmodule
247
 
248 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
249 9 ns32kum
//
250 29 ns32kum
//      2. DMUX         Data Multiplexor
251 9 ns32kum
//
252 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
253 29 ns32kum
module DMUX ( DRAM_Q, ADDR, CAP_Q );
254
 
255
        input  [127:0]   DRAM_Q;
256
        input    [3:2]  ADDR;
257
 
258
        output  reg     [31:0]   CAP_Q;
259
 
260
        always @(ADDR or DRAM_Q)
261
          case (ADDR)
262
            2'b00 : CAP_Q = DRAM_Q[31:0];
263
                2'b01 : CAP_Q = DRAM_Q[63:32];
264
                2'b10 : CAP_Q = DRAM_Q[95:64];
265
                2'b11 : CAP_Q = DRAM_Q[127:96];
266
          endcase
267
 
268
endmodule
269
 
270
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
271
//
272
//      3. ICACHE_SM    Instruction Cache State Machine
273
//
274
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
275 9 ns32kum
module ICACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, PTE_ACC,
276
                                   USE_CA, PTB_WR, PTB_SEL, USER, PROT_ERROR,
277
                                   DRAM_ACC, IO_RD, IO_ACC, IC_PREQ, ACC_OK, HIT_ALL, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE );
278
 
279
        input                   BCLK;
280
        input                   BRESET;
281
        input                   IO_SPACE;
282
        input                   MDONE;          // Memory Done : Feedback from DRAM Controller, BCLK aligned
283
        input                   IO_READY;
284
        input                   MMU_HIT,CA_HIT;
285
        input                   READ;
286
        input                   PTE_ACC;
287
        input                   USE_CA;
288
        input                   PTB_WR,PTB_SEL;
289
        input                   USER;
290
        input                   PROT_ERROR;
291
 
292
        output  reg             DRAM_ACC,IO_RD;
293
        output                  IO_ACC;
294
        output                  IC_PREQ;
295
        output                  ACC_OK;
296
        output                  HIT_ALL;
297
        output                  CUPDATE;
298
        output                  AUX_DAT;
299
        output  reg             NEW_PTB,PTB_ONE;
300
 
301
        reg              [3:0]   new_state;
302
        reg                             rd_done;
303
        reg                             card_flag;
304
        reg                             rd_rdy;
305
 
306
        wire                    io_busy;
307
        wire                    dram_go;
308
        wire                    rd_ende;
309
        wire                    do_ca_rd;
310
 
311
// Cycle :                      /-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
312
// Access :                     _/-----------------------------------\__
313
// State Machine :  ____/----------------------------\______
314
//                                                      Busy status ...
315
 
316
        assign rd_ende = CA_HIT | rd_rdy;       // CA_HIT only if Cache activ !
317
 
318
        always @(        READ           // only READ , global control
319
                          or PROT_ERROR // is not allowed !
320
                        //
321
                          or IO_SPACE   // indicates access in the IO_WELT
322
                          or io_busy    // is already active ?
323
                        //
324
                          or MMU_HIT    // Hit in the MMU , now only a READ can be active
325
                          or rd_ende    // Cache Hit
326
                          or DRAM_ACC   // DRAM Access running
327
                        //
328
                          or PTE_ACC )  // PTE Access running
329
                        //                                #_#                      #_#                                          #_#
330
                casex ({READ,PROT_ERROR,IO_SPACE,io_busy,MMU_HIT,rd_ende,DRAM_ACC,PTE_ACC})
331
                // MMU Miss : PTE load from memory 
332
                  8'b10_xx_0xx_0 : new_state = 4'b0100; // start PTE access
333
                // IO-Address selected : external access starts if not already BUSY
334
                  8'b10_10_1xx_x : new_state = 4'b0001;
335
                // DRAM Access : Cache Miss at READ
336
                  8'b10_0x_100_x : new_state = 4'b1010; // can start directly
337
                  default                : new_state = 4'b0;
338
                endcase
339
 
340
        assign IO_ACC   = new_state[0];  // to load the Register for Data and Addr
341
        assign dram_go  = new_state[1];
342
        assign IC_PREQ  = new_state[2]; // MMU to DCACHE !
343
        assign do_ca_rd = new_state[3];
344
 
345
        assign HIT_ALL = MMU_HIT & CA_HIT;      // for Update "Last-Set" , MMU_HIT contains ZUGRIFF
346
 
347
        always @(posedge BCLK or negedge BRESET)
348
                if (!BRESET) card_flag <= 1'b0;
349
                        else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE);
350
 
351
        assign CUPDATE = card_flag & USE_CA & MDONE;    // USE_CA = ~CI & ~LDC;
352
 
353
        always @(posedge BCLK) rd_rdy <= card_flag & MDONE;
354
 
355 11 ns32kum
        // The cache RAM can not provide fast enough the data after an Update. In this case a secondary data path is activated
356 9 ns32kum
        assign AUX_DAT = rd_rdy;
357
 
358
        // DRAM Interface :
359
 
360
        always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1;
361
                                                         else
362
                                                                DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET;
363
        // IO Interface :
364
 
365
        always @(posedge BCLK)
366
          begin
367
                if (IO_ACC) IO_RD <= READ;  else IO_RD <= IO_RD & ~IO_READY & BRESET;
368
          end
369
 
370 11 ns32kum
        assign io_busy = IO_RD | rd_done;       // access is gone in next clock cycle, therefore blocked with "rd_done"
371 9 ns32kum
 
372 11 ns32kum
        always @(posedge BCLK) rd_done <= READ & IO_READY;      // For READ one clock later for data to come through
373 9 ns32kum
 
374
        // global feedback to opcode fetch unit : you can continue
375
 
376
        assign ACC_OK = IO_SPACE ? rd_done : (READ & MMU_HIT & rd_ende);
377
 
378
        // PTB1 und PTB0
379
 
380
        always @(posedge BCLK) NEW_PTB <= PTB_WR;                       // to MMU Update Block
381
        always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
382
 
383
endmodule

powered by: WebSVN 2.1.0

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