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 51

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
                                o_busy = 1'd1;
177
 
178
                                /*
179
                                 * We need to page walk to get the page table.
180
                                 * Call for access to L1 level page table.
181
                                 */
182
                                tsk_prpr_wb_rd({i_baddr[`VA__TRANSLATION_BASE],
183
                                           i_address[`VA__TABLE_INDEX], 2'd0});
184
 
185
                                state_nxt = FETCH_L1_DESC_0;
186
                        end
187
                        else if ( i_fsr[3:0] != 4'b0000 ) /* Access Violation. */
188
                        begin
189
                                o_fault = 1'd1;
190
                                o_busy  = 1'd0;
191
                                o_fsr   = i_fsr;
192
                                o_far   = i_far;
193
                        end
194
                end
195
        end
196
 
197 29 Revanth
        FETCH_L1_DESC_0:
198
        begin
199
                o_busy = 1;
200
 
201
                if ( i_wb_ack )
202 28 Revanth
                begin
203 29 Revanth
                        dnxt = i_wb_dat;
204
                        state_nxt = FETCH_L1_DESC;
205 28 Revanth
                end
206 29 Revanth
                else tsk_hold_wb_access;
207
        end
208 26 Revanth
 
209
        FETCH_L1_DESC:
210
        begin
211
                /*
212
                 * What we would have fetched is the L1 descriptor.
213
                 * Examine it. dff holds the L1 descriptor.
214
                 */
215
 
216
                o_busy = 1'd1;
217
 
218
                if ( 1 )
219
                begin
220
                        case ( dff[`ID] )
221
 
222
                        SECTION_ID:
223
                        begin
224
                                /*
225
                                 * It is a section itself so there is no need
226
                                 * for another fetch. Simply reload the TLB
227
                                 * and we are good.
228
                                 */
229
                                o_setlb_wen       = 1'd1;
230
                                o_setlb_wdata     = {i_address[`VA__SECTION_TAG],
231
                                                     dff};
232
                                state_nxt       = REFRESH_CYCLE;
233
 
234 43 Revanth
                                $display($time, " - %m :: #########################################################");
235
                                $display($time, " - %m ::             SECTION DESCRIPTOR DETAILS                  #");
236
                                $display($time, " - %m :: #########################################################");
237
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_setlb_wdata[`SECTION_TLB__BASE]);
238
                                $display($time, " - %m :: # DAC           = 0b%b",  o_setlb_wdata[`SECTION_TLB__DAC_SEL]);
239
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_setlb_wdata[`SECTION_TLB__AP]);
240
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_setlb_wdata[`SECTION_TLB__CB] >> 1);
241
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_setlb_wdata[`SECTION_TLB__CB] & 2'b01);
242
                                $display($time, " - %m :: #########################################################");
243 26 Revanth
                        end
244
 
245
                        PAGE_ID:
246
                        begin
247
                                /*
248
                                 * Page ID requires that DAC from current
249
                                 * descriptor is remembered because when we
250
                                 * reload the TLB, it would be useful. Anyway,
251
                                 * we need to initiate another access.
252
                                 */
253
                                dac_nxt         = dff[`L1_PAGE__DAC_SEL];  // dac register holds the dac sel for future use.
254
                                state_nxt       = FETCH_L2_DESC_0;
255
 
256
                                tsk_prpr_wb_rd({dff[`L1_PAGE__PTBR],
257
                                                  i_address[`VA__L2_TABLE_INDEX], 2'd0});
258
                        end
259
 
260
                        default: /* Generate section translation fault. Fault Class II */
261
                        begin
262
                                o_fsr        = FSR_SECTION_TRANSLATION_FAULT;
263
                                o_fsr        = {dff[`L1_SECTION__DAC_SEL], o_fsr[3:0]};
264
                                o_far        = i_address;
265
                                o_fault      = 1'd1;
266
                                o_busy       = 1'd0;
267
                                state_nxt    = IDLE;
268
                        end
269
 
270
                        endcase
271
                end
272
                else tsk_hold_wb_access;
273
        end
274
 
275 28 Revanth
        FETCH_L2_DESC_0:
276
        begin
277
                        o_busy = 1;
278 26 Revanth
 
279 28 Revanth
                        if ( i_wb_ack )
280
                        begin
281
                                dnxt            = i_wb_dat;
282
                                state_nxt       = FETCH_L2_DESC;
283
                        end
284
                        else
285
                        begin
286
                                tsk_hold_wb_access;
287
                        end
288
        end
289
 
290 26 Revanth
        FETCH_L2_DESC:
291
        begin
292
                o_busy = 1'd1;
293
 
294
                if ( 1 )
295
                begin
296
                        case ( dff[`ID] ) // dff holds L2 descriptor. dac_ff holds L1 descriptor DAC.
297
                        SPAGE_ID:
298
                        begin
299
                                /* Update TLB */
300
                                o_sptlb_wen   = 1'd1;
301
 
302 28 Revanth
                                /* Define TLB fields to write */
303 26 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__TAG]     = i_address[`VA__SPAGE_TAG];
304 28 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__DAC_SEL] = dac_ff;                    /* DAC selector from L1. */
305 26 Revanth
                                o_sptlb_wdata[`SPAGE_TLB__AP]      = dff[`L2_SPAGE__AP];
306
                                o_sptlb_wdata[`SPAGE_TLB__CB]      = dff[`L2_SPAGE__CB];
307
                                o_sptlb_wdata[`SPAGE_TLB__BASE]    = dff[`L2_SPAGE__BASE];
308
 
309 43 Revanth
                                $display($time, " - %m :: #########################################################");
310
                                $display($time, " - %m ::               SPAGE DESCRIPTOR DETAILS                  #");
311
                                $display($time, " - %m :: #########################################################");
312
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_sptlb_wdata[`SPAGE_TLB__BASE]);
313
                                $display($time, " - %m :: # DAC           = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__DAC_SEL]);
314
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__AP]);
315
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__CB] >> 1);
316
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_sptlb_wdata[`SPAGE_TLB__CB] & 2'b01);
317
                                $display($time, " - %m :: #########################################################");
318 28 Revanth
 
319
                                /* Go to REFRESH */
320 26 Revanth
                                state_nxt   = REFRESH_CYCLE;
321
                        end
322
 
323
                        LPAGE_ID:
324
                        begin
325
                                /* Update TLB */
326
                                o_lptlb_wen   = 1'd1;
327
 
328
                                /* DAC is inserted in between to save bits */
329
                                o_lptlb_wdata = {i_address[`VA__LPAGE_TAG], dac_ff, dff};
330
 
331 43 Revanth
                                $display($time, " - %m :: #########################################################");
332
                                $display($time, " - %m ::               LPAGE DESCRIPTOR DETAILS                  #");
333
                                $display($time, " - %m :: #########################################################");
334
                                $display($time, " - %m :: # BASE ADDRESS  = 0x%x ", o_lptlb_wdata[`LPAGE_TLB__BASE]);
335
                                $display($time, " - %m :: # DAC           = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__DAC_SEL]);
336
                                $display($time, " - %m :: # AP bits       = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__AP]);
337
                                $display($time, " - %m :: # Cacheable     = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__CB] >> 1);
338
                                $display($time, " - %m :: # Bufferable    = 0b%b",  o_lptlb_wdata[`LPAGE_TLB__CB] & 2'b01);
339
                                $display($time, " - %m :: #########################################################");
340 28 Revanth
 
341 26 Revanth
                                state_nxt   = REFRESH_CYCLE;
342
                        end
343
 
344
                        default: /* Fault Class II */
345
                        begin
346
                                o_busy    = 1'd0;
347
                                o_fault   = 1'd1;
348
                                o_fsr     = FSR_PAGE_TRANSLATION_FAULT;
349
                                o_fsr     = {1'd0, dac_ff, o_fsr[3:0]};
350
                                o_far     = i_address;
351
                                state_nxt = IDLE;
352
                        end
353
                        endcase
354
                end
355
                else tsk_hold_wb_access;
356
        end
357
 
358
        REFRESH_CYCLE:
359
        begin
360
                o_busy    = 1'd1;
361
                state_nxt = IDLE;
362
        end
363
 
364
        endcase
365
end
366
 
367
// ----------------------------------------------------------------------------
368
 
369
// Clocked Logic.
370
always @ (posedge i_clk)
371
begin
372
        if ( i_reset )
373
        begin
374
                 state_ff        <=      IDLE;
375
                 wb_stb_ff       <=      0;
376
                 wb_cyc_ff       <=      0;
377 28 Revanth
                 wb_adr_ff       <=      0;
378
                 wb_sel_ff       <=      0;
379 26 Revanth
        end
380
        else
381
        begin
382
                state_ff        <=      state_nxt;
383
                wb_stb_ff       <=      wb_stb_nxt;
384
                wb_cyc_ff       <=      wb_cyc_nxt;
385 28 Revanth
                wb_adr_ff       <=      wb_adr_nxt;
386 26 Revanth
                dac_ff          <=      dac_nxt;
387 28 Revanth
                wb_sel_ff       <=      wb_sel_nxt;
388
                dff             <=      dnxt;
389 26 Revanth
        end
390
end
391
 
392
// ----------------------------------------------------------------------------
393
 
394
task tsk_hold_wb_access;
395
begin
396
        wb_stb_nxt = wb_stb_ff;
397
        wb_cyc_nxt = wb_cyc_ff;
398
        wb_adr_nxt = wb_adr_ff;
399
        wb_sel_nxt = wb_sel_ff;
400
end
401
endtask
402
 
403
task tsk_prpr_wb_rd ( input [31:0] adr );
404
begin
405 28 Revanth
        wb_stb_nxt      = 1'd1;
406
        wb_cyc_nxt      = 1'd1;
407
        wb_adr_nxt      = adr;
408
        wb_sel_nxt[3:0] = 4'b1111;
409 26 Revanth
end
410
endtask
411
 
412
endmodule // zap_tlb_fsm.v
413 28 Revanth
 
414 26 Revanth
`default_nettype wire
415 51 Revanth
 
416
// ----------------------------------------------------------------------------
417
// END OF FILE
418
// ----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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