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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_tlb_fsm.v] - Blame information for rev 43

Go to most recent revision | 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
// --  An automatic page fetching system.                                     --
25
// --                                                                         --
26
// -----------------------------------------------------------------------------
27
 
28
`default_nettype none
29
 
30
`include "zap_defines.vh"
31
 
32
module zap_tlb_fsm #(
33
 
34
// Pass from top.
35
parameter LPAGE_TLB_ENTRIES   = 8,
36
parameter SPAGE_TLB_ENTRIES   = 8,
37
parameter SECTION_TLB_ENTRIES = 8
38
 
39
)(
40
 
41
/* Clock and Reset */
42
input   wire                    i_clk,
43
input   wire                    i_reset,
44
 
45
/* From CP15 */
46
input   wire                    i_mmu_en,
47
input   wire   [31:0]           i_baddr,
48
 
49
/* From cache FSM */
50
input   wire   [31:0]           i_address,
51
 
52
/* From TLB check unit */
53
input   wire                    i_walk,
54
input   wire    [7:0]           i_fsr,
55
input   wire    [31:0]          i_far,
56
input   wire                    i_cacheable,
57
input   wire    [31:0]          i_phy_addr,
58
 
59
/* To main cache FSM */
60
output reg    [7:0]             o_fsr,
61
output  reg   [31:0]            o_far,
62
output  reg                     o_fault,
63
output  reg   [31:0]            o_phy_addr,
64
output  reg                     o_cacheable,
65
output  reg                     o_busy,
66
 
67
/* To TLBs */
68
output reg      [`SECTION_TLB_WDT-1:0] o_setlb_wdata,
69
output reg                      o_setlb_wen,
70
output reg      [`SPAGE_TLB_WDT-1:0] o_sptlb_wdata,
71
output reg                      o_sptlb_wen,
72
output  reg     [`LPAGE_TLB_WDT-1:0] o_lptlb_wdata,
73
output  reg                     o_lptlb_wen,
74
 
75
/* Wishbone signals NXT */
76
output  wire                    o_wb_cyc_nxt,
77
output  wire                    o_wb_stb_nxt,
78
output  wire    [31:0]          o_wb_adr_nxt,
79
 
80
/* Wishbone Signals */
81
output wire                     o_wb_cyc,
82
output wire                     o_wb_stb,
83
output wire                     o_wb_wen,
84
output wire [3:0]               o_wb_sel, o_wb_sel_nxt,
85
output wire [31:0]              o_wb_adr,
86
input  wire [31:0]              i_wb_dat,
87
input  wire                     i_wb_ack,
88
 
89
// Unused.
90
output wire o_unused_ok
91
 
92
);
93
 
94
`include "zap_localparams.vh"
95
`include "zap_defines.vh"
96
`include "zap_functions.vh"
97
 
98
// ----------------------------------------------------------------------------
99
 
100
/* States */
101
localparam IDLE                 = 0; /* Idle State */
102
localparam FETCH_L1_DESC        = 1; /* Fetch L1 descriptor */
103
localparam FETCH_L2_DESC        = 2; /* Fetch L2 descriptor */
104
localparam REFRESH_CYCLE        = 3; /* Refresh TLBs and cache */
105
localparam FETCH_L1_DESC_0      = 4;
106
localparam FETCH_L2_DESC_0      = 5;
107
localparam NUMBER_OF_STATES     = 6;
108
 
109
// ----------------------------------------------------------------------------
110
 
111
reg [3:0] dac_ff, dac_nxt;                              /* Scratchpad register */
112
reg [$clog2(NUMBER_OF_STATES)-1:0] state_ff, state_nxt; /* State register */
113
 
114
/* Wishbone related */
115
reg        wb_stb_nxt, wb_stb_ff;
116
reg        wb_cyc_nxt, wb_cyc_ff;
117
reg [31:0] wb_adr_nxt, wb_adr_ff;
118
 
119
// ----------------------------------------------------------------------------
120
 
121
/* Tie output flops to ports. */
122
assign o_wb_cyc         = wb_cyc_ff;
123
assign o_wb_stb         = wb_stb_ff;
124
assign o_wb_adr         = wb_adr_ff;
125
 
126
assign o_wb_cyc_nxt     = wb_cyc_nxt;
127
assign o_wb_stb_nxt     = wb_stb_nxt;
128
assign o_wb_adr_nxt     = wb_adr_nxt;
129
 
130
reg [3:0] wb_sel_nxt, wb_sel_ff;
131
 
132
/* Tied PORTS */
133
assign o_wb_wen = 1'd0;
134
assign o_wb_sel = wb_sel_ff;
135
assign o_wb_sel_nxt = wb_sel_nxt;
136
 
137
assign o_unused_ok = 0 || i_baddr[13:0];
138
 
139
reg [31:0] dff, dnxt; /* Wishbone memory buffer. */
140
 
141
/* Combinational logic */
142
always @*
143
begin: blk1
144
 
145
        o_fsr           = 0;
146
        o_far           = 0;
147
        o_fault         = 0;
148
        o_busy          = 0;
149
        o_phy_addr      = i_phy_addr;
150
        o_cacheable     = i_cacheable;
151
        o_setlb_wen     = 0;
152
        o_lptlb_wen     = 0;
153
        o_sptlb_wen     = 0;
154
        o_setlb_wdata  = 0;
155
        o_sptlb_wdata   = 0;
156
        o_lptlb_wdata   = 0;
157
 
158
        /* Kill wishbone access unless overridden */
159
        wb_stb_nxt      = 0;
160
        wb_cyc_nxt      = 0;
161
        wb_adr_nxt      = 0;
162 28 Revanth
        wb_sel_nxt      = 0;
163 26 Revanth
 
164
        dac_nxt         = dac_ff;
165
        state_nxt       = state_ff;
166
 
167 28 Revanth
        dnxt            = dff;
168 26 Revanth
 
169
        case ( state_ff )
170
        IDLE:
171
        begin
172
                if ( i_mmu_en )
173
                begin
174
                        if ( i_walk )
175
                        begin
176 43 Revanth
                                $display($time, " - %m :: Page fault! Need to page walk! i_walk = %b", i_walk);
177
                                $display($time, " - %m :: Core generated address %x", i_address);
178
                                $display($time, " - %m :: Moving to FETCH_L1_DESC. i_baddr = %x baddr_tran_base = %x addr_va_table_index = %x",
179 26 Revanth
                                         i_baddr, i_baddr[`VA__TRANSLATION_BASE], i_address[`VA__TABLE_INDEX]);
180
 
181 28 Revanth
                                `ifdef TLB_DEBUG
182
                                        $stop;
183
                                `endif
184
 
185 26 Revanth
                                o_busy = 1'd1;
186
 
187
                                /*
188
                                 * We need to page walk to get the page table.
189
                                 * Call for access to L1 level page table.
190
                                 */
191
                                tsk_prpr_wb_rd({i_baddr[`VA__TRANSLATION_BASE],
192
                                           i_address[`VA__TABLE_INDEX], 2'd0});
193
 
194
                                state_nxt = FETCH_L1_DESC_0;
195
                        end
196
                        else if ( i_fsr[3:0] != 4'b0000 ) /* Access Violation. */
197
                        begin
198 43 Revanth
                                $display($time, " - %m :: Access violation fsr = %x far = %x...", i_fsr, i_far);
199 26 Revanth
 
200 28 Revanth
                                `ifdef TLB_DEBUG
201
                                        $stop;
202
                                `endif
203
 
204 26 Revanth
                                o_fault = 1'd1;
205
                                o_busy  = 1'd0;
206
                                o_fsr   = i_fsr;
207
                                o_far   = i_far;
208
                        end
209
                        else
210
                        begin
211
                                `ifdef DISP_TLB_SUCCESS
212 43 Revanth
                                        $display($time, " - %m :: TLB Hit for address = %x MMU enable = %x!", i_address, i_mmu_en);
213 26 Revanth
                                `endif
214 28 Revanth
 
215
                                `ifdef TLB_DEBUG
216
                                        $stop;
217
                                `endif
218 26 Revanth
                        end
219
                end
220
        end
221
 
222 29 Revanth
        FETCH_L1_DESC_0:
223
        begin
224 43 Revanth
                $display($time, " - %m :: In state FETCH_L1_DESC_0");
225 29 Revanth
 
226
                o_busy = 1;
227
 
228
                if ( i_wb_ack )
229 28 Revanth
                begin
230 29 Revanth
                        dnxt = i_wb_dat;
231
                        state_nxt = FETCH_L1_DESC;
232 28 Revanth
 
233 43 Revanth
                        $display($time, " - %m :: Received %x from WB. Moving to FETCH_L1_DESC...", dnxt );
234 28 Revanth
                end
235 29 Revanth
                else tsk_hold_wb_access;
236
        end
237 26 Revanth
 
238
        FETCH_L1_DESC:
239
        begin
240
                /*
241
                 * What we would have fetched is the L1 descriptor.
242
                 * Examine it. dff holds the L1 descriptor.
243
                 */
244
 
245 43 Revanth
                $display($time, " - %m :: In FETCH_L1_DESC state...");
246 26 Revanth
 
247
                o_busy = 1'd1;
248
 
249
                if ( 1 )
250
                begin
251 43 Revanth
                        $display($time, " - %m :: ACK received. Read data is %x", i_wb_dat);
252 28 Revanth
 
253
                        `ifdef TLB_DEBUG
254
                                $stop;
255
                        `endif
256
 
257 26 Revanth
                        case ( dff[`ID] )
258
 
259
                        SECTION_ID:
260
                        begin
261
                                /*
262
                                 * It is a section itself so there is no need
263
                                 * for another fetch. Simply reload the TLB
264
                                 * and we are good.
265
                                 */
266
                                o_setlb_wen       = 1'd1;
267
                                o_setlb_wdata     = {i_address[`VA__SECTION_TAG],
268
                                                     dff};
269
                                state_nxt       = REFRESH_CYCLE;
270
 
271 43 Revanth
                                $display($time, " - %m :: It is a section ID. Writing to section TLB as %x. Moving to refresh cycle...", o_setlb_wdata);
272 28 Revanth
 
273 43 Revanth
                                $display($time, " - %m :: #########################################################");
274
                                $display($time, " - %m ::             SECTION DESCRIPTOR DETAILS                  #");
275
                                $display($time, " - %m :: #########################################################");
276
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_setlb_wdata[`SECTION_TLB__BASE]);
277
                                $display($time, " - %m :: # DAC           = 0b%b",  o_setlb_wdata[`SECTION_TLB__DAC_SEL]);
278
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_setlb_wdata[`SECTION_TLB__AP]);
279
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_setlb_wdata[`SECTION_TLB__CB] >> 1);
280
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_setlb_wdata[`SECTION_TLB__CB] & 2'b01);
281
                                $display($time, " - %m :: #########################################################");
282 28 Revanth
 
283
                                `ifdef TLB_DEBUG
284
                                        $stop;
285
                                `endif
286 26 Revanth
                        end
287
 
288
                        PAGE_ID:
289
                        begin
290
                                /*
291
                                 * Page ID requires that DAC from current
292
                                 * descriptor is remembered because when we
293
                                 * reload the TLB, it would be useful. Anyway,
294
                                 * we need to initiate another access.
295
                                 */
296
                                dac_nxt         = dff[`L1_PAGE__DAC_SEL];  // dac register holds the dac sel for future use.
297
                                state_nxt       = FETCH_L2_DESC_0;
298
 
299
                                tsk_prpr_wb_rd({dff[`L1_PAGE__PTBR],
300
                                                  i_address[`VA__L2_TABLE_INDEX], 2'd0});
301
 
302 43 Revanth
                                $display($time, " - %m :: L1 received Page ID.");
303 28 Revanth
 
304
                                `ifdef TLB_DEBUG
305
                                        $stop;
306
                                `endif
307 26 Revanth
                        end
308
 
309
                        default: /* Generate section translation fault. Fault Class II */
310
                        begin
311
                                o_fsr        = FSR_SECTION_TRANSLATION_FAULT;
312
                                o_fsr        = {dff[`L1_SECTION__DAC_SEL], o_fsr[3:0]};
313
                                o_far        = i_address;
314
                                o_fault      = 1'd1;
315
                                o_busy       = 1'd0;
316
                                state_nxt    = IDLE;
317
 
318 43 Revanth
                                $display($time, " - %m :: FSR section translation fault!");
319 28 Revanth
 
320
                                `ifdef TLB_DEBUG
321
                                        $stop;
322
                                `endif
323 26 Revanth
                        end
324
 
325
                        endcase
326
                end
327
                else tsk_hold_wb_access;
328
        end
329
 
330 28 Revanth
        FETCH_L2_DESC_0:
331
        begin
332
                        o_busy = 1;
333 26 Revanth
 
334 28 Revanth
                        if ( i_wb_ack )
335
                        begin
336
                                dnxt            = i_wb_dat;
337
                                state_nxt       = FETCH_L2_DESC;
338
                        end
339
                        else
340
                        begin
341
                                tsk_hold_wb_access;
342
                        end
343
        end
344
 
345 26 Revanth
        FETCH_L2_DESC:
346
        begin
347
                o_busy = 1'd1;
348
 
349
                if ( 1 )
350
                begin
351
                        case ( dff[`ID] ) // dff holds L2 descriptor. dac_ff holds L1 descriptor DAC.
352
                        SPAGE_ID:
353
                        begin
354
                                /* Update TLB */
355
                                o_sptlb_wen   = 1'd1;
356
 
357 28 Revanth
                                /* Define TLB fields to write */
358 26 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__TAG]     = i_address[`VA__SPAGE_TAG];
359 28 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__DAC_SEL] = dac_ff;                    /* DAC selector from L1. */
360 26 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__AP]      = dff[`L2_SPAGE__AP];
361
                                o_sptlb_wdata[`SPAGE_TLB__CB]      = dff[`L2_SPAGE__CB];
362
                                o_sptlb_wdata[`SPAGE_TLB__BASE]    = dff[`L2_SPAGE__BASE];
363
 
364 43 Revanth
                                $display($time, " - %m :: #########################################################");
365
                                $display($time, " - %m ::               SPAGE DESCRIPTOR DETAILS                  #");
366
                                $display($time, " - %m :: #########################################################");
367
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_sptlb_wdata[`SPAGE_TLB__BASE]);
368
                                $display($time, " - %m :: # DAC           = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__DAC_SEL]);
369
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__AP]);
370
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__CB] >> 1);
371
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__CB] & 2'b01);
372
                                $display($time, " - %m :: #########################################################");
373 28 Revanth
 
374
                                /* Go to REFRESH */
375 26 Revanth
                                state_nxt   = REFRESH_CYCLE;
376
                        end
377
 
378
                        LPAGE_ID:
379
                        begin
380
                                /* Update TLB */
381
                                o_lptlb_wen   = 1'd1;
382
 
383
                                /* DAC is inserted in between to save bits */
384
                                o_lptlb_wdata = {i_address[`VA__LPAGE_TAG], dac_ff, dff};
385
 
386 43 Revanth
                                $display($time, " - %m :: #########################################################");
387
                                $display($time, " - %m ::               LPAGE DESCRIPTOR DETAILS                  #");
388
                                $display($time, " - %m :: #########################################################");
389
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_lptlb_wdata[`LPAGE_TLB__BASE]);
390
                                $display($time, " - %m :: # DAC           = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__DAC_SEL]);
391
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__AP]);
392
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__CB] >> 1);
393
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__CB] & 2'b01);
394
                                $display($time, " - %m :: #########################################################");
395 28 Revanth
 
396 26 Revanth
                                state_nxt   = REFRESH_CYCLE;
397
                        end
398
 
399
                        default: /* Fault Class II */
400
                        begin
401
                                o_busy    = 1'd0;
402
                                o_fault   = 1'd1;
403
                                o_fsr     = FSR_PAGE_TRANSLATION_FAULT;
404
                                o_fsr     = {1'd0, dac_ff, o_fsr[3:0]};
405
                                o_far     = i_address;
406
                                state_nxt = IDLE;
407
                        end
408
                        endcase
409
                end
410
                else tsk_hold_wb_access;
411
        end
412
 
413
        REFRESH_CYCLE:
414
        begin
415 43 Revanth
                $display($time, " - %m :: Entered refresh cycle. Moving to IDLE...");
416 26 Revanth
 
417 28 Revanth
                `ifdef TLB_DEBUG
418
                        $stop;
419
                `endif
420
 
421 26 Revanth
                o_busy    = 1'd1;
422
                state_nxt = IDLE;
423
        end
424
 
425
        endcase
426
end
427
 
428
// ----------------------------------------------------------------------------
429
 
430
// Clocked Logic.
431
always @ (posedge i_clk)
432
begin
433
        if ( i_reset )
434
        begin
435
                 state_ff        <=      IDLE;
436
                 wb_stb_ff       <=      0;
437
                 wb_cyc_ff       <=      0;
438 28 Revanth
                 wb_adr_ff       <=      0;
439
                 wb_sel_ff       <=      0;
440 26 Revanth
        end
441
        else
442
        begin
443
                state_ff        <=      state_nxt;
444
                wb_stb_ff       <=      wb_stb_nxt;
445
                wb_cyc_ff       <=      wb_cyc_nxt;
446 28 Revanth
                wb_adr_ff       <=      wb_adr_nxt;
447 26 Revanth
                dac_ff          <=      dac_nxt;
448 28 Revanth
                wb_sel_ff       <=      wb_sel_nxt;
449
                dff             <=      dnxt;
450 26 Revanth
        end
451
end
452
 
453
// ----------------------------------------------------------------------------
454
 
455
task tsk_hold_wb_access;
456
begin
457
        wb_stb_nxt = wb_stb_ff;
458
        wb_cyc_nxt = wb_cyc_ff;
459
        wb_adr_nxt = wb_adr_ff;
460
        wb_sel_nxt = wb_sel_ff;
461
end
462
endtask
463
 
464
task tsk_prpr_wb_rd ( input [31:0] adr );
465
begin
466 43 Revanth
        $display($time, " - %m :: Reading from location %x", adr);
467 26 Revanth
 
468 28 Revanth
        `ifdef TLB_DEBUG
469
                $stop;
470
        `endif
471 26 Revanth
 
472 28 Revanth
        wb_stb_nxt      = 1'd1;
473
        wb_cyc_nxt      = 1'd1;
474
        wb_adr_nxt      = adr;
475
        wb_sel_nxt[3:0] = 4'b1111;
476 26 Revanth
end
477
endtask
478
 
479
// ----------------------------------------------------------------------------
480
 
481 43 Revanth
// assertions_start
482 26 Revanth
 
483
always @ (posedge i_mmu_en)
484
begin
485 43 Revanth
        $display($time, " - %m :: MMU Enabled!");
486 26 Revanth
end
487
 
488
always @ (negedge i_mmu_en)
489
begin
490 43 Revanth
        $display($time, " - %m :: MMU Disabled!");
491 26 Revanth
end
492
 
493 43 Revanth
// assertions_end
494 28 Revanth
 
495 26 Revanth
endmodule // zap_tlb_fsm.v
496 28 Revanth
 
497 26 Revanth
`default_nettype wire

powered by: WebSVN 2.1.0

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