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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v7/] [rtl/] [common/] [FT64_pmmu.v] - Blame information for rev 60

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2007-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      FT64_pmmu.v
9
//  - 64 bit CPU paged memory management unit
10
//      - 512 entry TLB, 8 way associative
11
//  - variable page table depth
12
//      - address short-cutting for larger page sizes (8MB)
13
//  - hardware clearing of access bit
14
//
15
// This source file is free software: you can redistribute it and/or modify 
16
// it under the terms of the GNU Lesser General Public License as published 
17
// by the Free Software Foundation, either version 3 of the License, or     
18
// (at your option) any later version.                                      
19
//                                                                          
20
// This source file is distributed in the hope that it will be useful,      
21
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
23
// GNU General Public License for more details.                             
24
//                                                                          
25
// You should have received a copy of the GNU General Public License        
26
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
27
//
28
// ============================================================================
29
//
30
`ifndef TRUE
31
`define TRUE    1'b1
32
`define FALSE   1'b0
33
`endif
34
`define _8MBPG  5
35
 
36
module FT64_pmmu
37
#(
38
parameter
39
        AMSB = 31,
40
        pAssociativity = 8,             // number of ways (parallel compares)
41
        pTLB_size = 64,
42
        S_WAIT_MISS = 0,
43
        S_WR_PTL0L = 1,
44
        S_WR_PTL0H = 2,
45
        S_RD_PTL0L = 3,
46
        S_RD_PTL0H = 4,
47
        S_RD_PTL1L = 5,
48
        S_RD_PTL1H = 6,
49
        S_RD_PTL2 = 7,
50
        S_RD_PTL3 = 8,
51
        S_RD_PTL4 = 9,
52
        S_RD_PTL5 = 10,
53
        S_RD_PTL5_ACK = 11,
54
        S_RD_PTL = 12,
55
        S_WR_PTL = 13
56
)
57
(
58
// syscon
59
input rst_i,
60
input clk_i,
61
 
62
input age_tick_i,                       // indicates when to age reference counts
63
 
64
// master
65
output reg m_cyc_o,             // valid memory address
66
output reg m_lock_o,    // lock the bus
67
input      m_ack_i,             // acknowledge from memory system
68
output reg m_we_o,              // write enable output
69
output reg [15:0] m_sel_o,       // lane selects (always all active)
70
output reg [AMSB:0] m_adr_o,
71
input      [127:0] m_dat_i,      // data input from memory
72
output reg [127:0] m_dat_o,      // data to memory
73
 
74
// Translation request / control
75
input invalidate,               // invalidate a specific entry
76
input invalidate_all,   // causes all entries to be invalidated
77
input [47:0] pta,                // page directory/table address register
78
output reg page_fault,
79
 
80
input [7:0] asid_i,
81
input [7:0] pl_i,
82
input [1:0] ol_i,                // operating level
83
input icl_i,                            // instruction cache load
84
input cyc_i,
85
input we_i,                                 // cpu is performing write cycle
86
input [7:0] sel_i,
87
input [63:0] vadr_i,         // virtual address to translate
88
 
89
output reg cyc_o,
90
output reg we_o,
91
output reg [7:0] sel_o,
92
output reg [AMSB:0] padr_o,      // translated address
93
output reg cac_o,               // cachable
94
output reg prv_o,               // privilege violation
95
output reg exv_o,               // execute violation
96
output reg rdv_o,               // read violation
97
output reg wrv_o                // write violation
98
);
99
 
100
integer nn;
101
reg [8:0] tlb_wa;
102
reg [8:0] tlb_ra;
103
reg [8:0] tlb_ua;
104
reg [AMSB:0] tmpadr;
105
reg pv_o;
106
reg v_o;
107
reg r_o;
108
reg w_o;
109
reg x_o;
110
reg c_o;
111
reg a_o;
112
reg [2:0] nnx;
113
reg [127:0] pte;                 // holding place for data
114
reg [AMSB-4:0] pte_adr;
115
reg [3:0] state;
116
reg [3:0] stkstate;
117
reg [2:0] cnt;   // tlb replacement counter
118
reg [2:0] whichSet;              // which set to update
119
reg dbit;                               // temp dirty bit
120
reg miss;
121
reg proc;
122
reg [63:0] miss_adr;
123
wire pta_changed;
124
assign ack_o = !miss||page_fault;
125
wire pgen = pta[11];
126
 
127
wire [AMSB:0] tlb_pte_adr [pAssociativity-1:0];
128
wire [pAssociativity-1:0] tlb_d;
129
wire [ 6: 0] tlb_flags [pAssociativity-1:0];
130
wire [ 7: 0] tlb_pl [pAssociativity-1:0];
131
wire [ 7: 0] tlb_asid [pAssociativity-1:0];
132
wire [31: 0] tlb_refcount [pAssociativity-1:0];
133
wire tlb_g [pAssociativity-1:0];
134
wire [63:19] tlb_vadr  [pAssociativity-1:0];
135
wire [34:0] tlb_tadr  [pAssociativity-1:0];
136
 
137
//wire wr_tlb = state==S_WR_PTL0;
138
reg wr_tlb;
139
always @(posedge clk_i)
140
        cyc_o <= cyc_i & v_o & ~pv_o;
141
always @(posedge clk_i)
142
        we_o <= we_i & v_o & ~pv_o & w_o;
143
always @(posedge clk_i)
144
        sel_o <= sel_i & {8{~pv_o}};
145
always @(posedge clk_i)
146
        prv_o <= pv_o & v_o && ol_i!=2'b00;
147
always @(posedge clk_i)
148
        exv_o <= icl_i & v_o & ~x_o && ol_i!=2'b00;
149
always @(posedge clk_i)
150
        rdv_o <= ~icl_i & v_o & ~r_o && ol_i!=2'b00;
151
always @(posedge clk_i)
152
        wrv_o <= ~icl_i & v_o & ~w_o && ol_i!=2'b00;
153
always @(posedge clk_i)
154
        cac_o <= c_o & v_o;
155
 
156
genvar g;
157
generate
158
        for (g = 0; g < pAssociativity; g = g + 1)
159
        begin : genTLB
160
                ram_ar1w1r #(45,pTLB_size) tlbVadr
161
                (
162
                        .clk(clk_i),
163
                        .ce(whichSet==g),
164
                        .we(wr_tlb),
165
                        .wa(miss_adr[18:13]),
166
                        .ra(vadr_i[18:13]),
167
                        .i(miss_adr[63:19]),
168
                        .o(tlb_vadr[g])
169
                );
170
                ram_ar1w1r #(AMSB+1,pTLB_size) tlbPteAdr
171
                (
172
                        .clk(clk_i),
173
                        .ce(whichSet==g),
174
                        .we(wr_tlb),
175
                        .wa(miss_adr[18:13]),
176
                        .ra(vadr_i[18:13]),
177
                        .i(pte_adr),
178
                        .o(tlb_pte_adr[g])
179
                );
180
                ram_ar1w1r #( 7,pTLB_size) tlbFlag
181
                (
182
                        .clk(clk_i),
183
                        .ce(whichSet==g),
184
                        .we(wr_tlb),
185
                        .wa(miss_adr[18:13]),
186
                        .ra(vadr_i[18:13]),
187
                        .i(pte[6:0]),
188
                        .o(tlb_flags[g])
189
                );
190
                ram_ar1w1r #(8,pTLB_size) tlbPL
191
    (
192
      .clk(clk_i),
193
      .ce(whichSet==g),
194
      .we(wr_tlb),
195
      .wa(miss_adr[18:13]),
196
      .ra(vadr_i[18:13]),
197
      .i(pte[15:8]),
198
      .o(tlb_pl[g])
199
    );
200
                ram_ar1w1r #( 1,pTLB_size) tlbG
201
                (
202
                        .clk(clk_i),
203
                        .ce(whichSet==g),
204
                        .we(wr_tlb),
205
                        .wa(miss_adr[18:13]),
206
                        .ra(vadr_i[18:13]),
207
                        .i(pte[23]),
208
                        .o(tlb_g[g])
209
                );
210
                ram_ar1w1r #(8,pTLB_size) tlbASID
211
    (
212
      .clk(clk_i),
213
      .ce(whichSet==g),
214
      .we(wr_tlb),
215
      .wa(miss_adr[18:13]),
216
      .ra(vadr_i[18:13]),
217
      .i(pte[31:24]),
218
      .o(tlb_asid[g])
219
    );
220
                ram_ar1w1r #(32,pTLB_size) tlbRefCount
221
    (
222
      .clk(clk_i),
223
      .ce(whichSet==g),
224
      .we(wr_tlb),
225
      .wa(miss_adr[18:13]),
226
      .ra(vadr_i[18:13]),
227
      .i(pte[63:32]),
228
      .o(tlb_refcount[g])
229
    );
230
                ram_ar1w1r #(32,pTLB_size) tlbRefCount
231
                (
232
                        .clk(clk_i),
233
                        .ce(wr_tlb?whichSet==g:nnx==g),
234
                        .we(wr_tlb||state==S_WAIT_MISS && !miss && cyc_i),
235
                        .wa(wr_tlb?miss_adr[18:13]:vadr_i[18:13]),
236
                        .ra(vadr_i[18:13]),
237
                        .i(pte[63:32]),
238
                        .o(tlb_refcount[g])
239
                );
240
                ram_ar1w1r #(35,pTLB_size) tlbTadr
241
                (
242
                        .clk(clk_i),
243
                        .ce(whichSet==g),
244
                        .we(wr_tlb),
245
                        .wa(miss_adr[18:13]),
246
                        .ra(vadr_i[18:13]),
247
                        .i(pte[98:64]),
248
                        .o(tlb_tadr[g])
249
                );
250
                ram_ar1w1r #( 1,pTLB_size) tlbD
251
                (
252
                        .clk(clk_i),
253
                        .ce(wr_tlb?whichSet==g:nnx==g),
254
                        .we(wr_tlb||state==S_WAIT_MISS && wr && !miss && cyc_i),
255
                        .wa(wr_tlb?miss_adr[18:13]:vadr_i[18:13]),
256
                        .ra(vadr_i[18:13]),
257
                        .i(!wr_tlb),
258
                        .o(tlb_d[g])
259
                );
260
        end
261
endgenerate
262
 
263
reg [pAssociativity*pTLB_size-1:0] tlb_v;        // valid
264
 
265
// The following reg allows detection of when the page table address changes
266
change_det #(48) u1
267
(
268
        .rst(rst_i),
269
        .clk(clk_i),
270
        .ce(1'b1),
271
        .i(pta),
272
        .cd(pta_changed)
273
);
274
 
275
// This must be fast !!!
276
// Lookup the virtual address in the tlb
277
// Translate the address
278
// I/O and system BIOS addresses are not mapped
279
// Cxxx_xxxx_xxxx_xxxx to FFFF_FFFF_FFFF_FFFF not mapped (kernel segment)
280
// 0000_0000_0000_0000 to 0000_0000_0000_xxxx not mapped (kernel data segement)
281
always @(posedge clk_i)
282
begin
283
        miss <= 1;
284
        nnx <= pAssociativity;
285
        a_o <= 1;
286
        c_o <= 1;
287
        r_o <= 1;
288
        x_o <= 1;
289
        w_o <= 1;
290
        v_o <= 0;
291
        pv_o <= 0;
292
        padr_o[12: 0] <= vadr_i[12: 0];
293
        padr_o[47:13] <= vadr_i[47:13];
294
        if (vadr_i[63:16]==48'h0 || vadr_i[63:20]==44'hFFFF_FFFF_FFD) begin
295
    miss <= 0;
296
    c_o <= 1;
297
    v_o <= 1;
298
  end
299
        else if (&vadr_i[47:46]) begin
300
                miss <= 0;
301
                c_o <= vadr_i[45:44]==2'b00;    // C000_0000_0000 to CFFF_FFFF_FFFF is cacheable
302
                v_o <= 1;
303
        end
304
        else begin
305
                if (!pgen) begin
306
                        miss <= 0;
307
                        v_o <= 1;
308
                end
309
                else
310
                for (nn = 0; nn < pAssociativity; nn = nn + 1)
311
                        if (tlb_v[{nn,vadr_i[18:13]}] && vadr_i[63:19]==tlb_vadr[nn]) begin
312
                            if (tlb_flags[nn][`_8MBPG])
313
                                    padr_o[47:13] <= {tlb_tadr[nn][34:10],vadr_i[22:13]};
314
                            else
315
                                    padr_o[47:13] <= tlb_tadr[nn];
316
                                miss <= 1'b0;
317
                                nnx <= nn;
318
                                a_o <= tlb_flags[nn][4];
319
                                c_o <= tlb_flags[nn][3];
320
                                r_o <= tlb_flags[nn][2];
321
                                w_o <= tlb_flags[nn][1];
322
                                x_o <= tlb_flags[nn][0];
323
                                v_o <= tlb_flags[nn][2]|tlb_flags[nn][1]|tlb_flags[nn][0];
324
                                pv_o <= (cyc_i & icl_i) ? pl != tlb_pl[nn] && pl!=8'h00 : pl > tlb_pl[nn];
325
                        end
326
        end
327
end
328
 
329
reg age_tick_r;
330
wire pe_age_rtick;
331
edge_det ued1(.clk(clk_i), .ce(1'b1), .i(age_tick), .pe(pe_age_tick), .ne(), .ee());
332
 
333
// The following state machine loads the tlb buffer on a
334
// miss.
335
always @(posedge clk_i)
336
if (rst_i) begin
337
        nack();
338
        wr_tlb <= 1'b0;
339
        m_adr_o <= 1'b0;
340
        goto(S_WAIT_MISS);
341
        dbit  <= 1'b0;
342
        whichSet <= 1'b0;
343
        for (nn = 0; nn < pAssociativity * pTLB_size; nn = nn + 1)
344
                tlb_v[nn] <= 1'b0;              // all entries are invalid on reset
345
  page_fault <= `FALSE;
346
  age_tick_r <= 1'b0;
347
end
348
else begin
349
        wr_tlb <= 1'b0;
350
 
351
        // page fault pulses
352
        page_fault <= `FALSE;
353
 
354
        if (pe_age_tick)
355
                age_tick_r <= 1'b1;
356
 
357
        // changing the address of the page table invalidates all entries
358
        if (invalidate_all)
359
                for (nn = 0; nn < pAssociativity * pTLB_size; nn = nn + 1)
360
                        tlb_v[nn] <= 1'b0;
361
 
362
        // handle invalidate command
363
        if (invalidate)
364
                for (nn = 0; nn < pAssociativity; nn = nn + 1)
365
                        if (vadr_i[63:19]==tlb_vadr[nn] && (tlb_g[nn] || tlb_asid[nn]==asid_i))
366
                                tlb_v[{nn,vadr_i[18:13]}] <= 1'b0;
367
 
368
        case (state)    // synopsys full_case parallel_case
369
 
370
        // Wait for a miss to occur. then initiate bus cycle
371
        // Output either the page directory address
372
        // or the page table address, depending on the
373
        // size of the app.
374
        S_WAIT_MISS:
375
                begin
376
                        goto(S_WAIT_MISS);
377
                        dbit <= we_i;
378
                        proc <= `FALSE;
379
 
380
                        if (miss) begin
381
                          proc <= `TRUE;
382
                                miss_adr <= vadr_i;
383
                                // try and pick an empty tlb entry
384
                                whichSet <= cnt;
385
                                for (nn = 0; nn < pAssociativity; nn = nn + 1)
386
                                        if (!tlb_v[{nn,vadr_i[18:13]}])
387
                                                whichSet <= nn;
388
                                goto(S_RD_PTL5);
389
                        end
390
                        // If there's a write cycle, check to see if the
391
                        // dirty bit is set. If the dirty bit hasn't been
392
                        // set yet, then set it and write the dirty status
393
                        // to memory.
394
                        else if (cyc_i && we_i && !tlb_d[nnx]) begin
395
                                miss_adr <= vadr_i;
396
                                whichSet <= nnx;
397
                                goto(S_RD_PTL5);
398
                        end
399
                        else if (age_tick_r) begin
400
                                age_tick_r <= 1'b0;
401
                                tlb_wa <= tlb_ua + 3'd1;
402
                                tlb_ra <= tlb_ua + 3'd1;
403
                                tlb_ua <= tlb_ua + 3'd1;
404
                                goto(S_AGE);
405
                        end
406
                        else begin
407
                                tlb_wa <= {nnx,vadr_i[18:13]};
408
                                tlb_ra <= {nnx,vadr_i[18:13]};
409
                                goto(S_COUNT);
410
                        end
411
                end
412
 
413
        S_RD_PTL5:
414
                if (~m_ack_i & ~m_cyc_o) begin
415
                        tlb_ra <= {whichSet,miss_adr[18:13]};
416
                        tlb_wa <= {whichSet,miss_adr[18:13]};
417
                        m_cyc_o <= 1'b1;
418
                        m_sel_o <= 8'hFF;
419
                        m_lock_o <= 1'b0;
420
                        m_we_o  <= 1'b0;
421
                        case(pta[10:8])
422
                        3'd0:   state <= S_RD_PTL0L;
423
                        3'd1:   state <= S_RD_PTL1L;
424
                        3'd2:   state <= S_RD_PTL2;
425
                        3'd3:   state <= S_RD_PTL3;
426
                        3'd4:   state <= S_RD_PTL4;
427
                        3'd5:   state <= S_RD_PTL5_ACK;
428
                        default:        ;
429
                        endcase
430
                        // Set page table address for lookup
431
                        case(pta[10:8])
432
                        3'b000: m_adr_o <= {pta[47:14],miss_adr[22:13],4'h0};   // 8MB translations
433
                        3'b001: m_adr_o <= {pta[47:14],miss_adr[32:23],4'h0};   // 8GB translations
434
                        3'b010: m_adr_o <= {pta[47:14],miss_adr[42:33],4'h8};   // 8TB translations
435
                        3'b011: m_adr_o <= {pta[47:14],miss_adr[52:43],4'h8};   // 8XB translations
436
                        3'b100: m_adr_o <= {pta[47:14],miss_adr[62:53],4'h8};   //     translations
437
                        3'b101: m_adr_o <= {pta[47:14],9'b00,miss_adr[63],4'h8};        //  translations
438
                        default:        ;
439
                        endcase
440
                end
441
        // Wait for ack from system
442
        // Setup to access page table
443
        // If app uses a page directory, now address the page table
444
        S_RD_PTL5_ACK:
445
                if (m_ack_i) begin
446
                        nack();
447
                        if (|m_dat_i[2:0]) begin // pte valid bit
448
                                tmpadr <= {m_dat_i[33:0],miss_adr[62:53],4'h8};
449
                                call(S_RD_PTL,S_RD_PTL4);
450
                        end
451
                        else begin
452
                                if (clock) begin
453
                                        clock_adr[64:63] <= clock_adr[64:63] + 4'h1;
454
                                        clock_adr[62:0] <= 4'h0;
455
                                        goto (S_WAIT_MISS);
456
                                end
457
                                else
458
                          raise_page_fault();
459
                                // not a valid translation
460
                                // OS messed up ?
461
                        end
462
                end
463
 
464
        // Wait for ack from system
465
        // Setup to access page table
466
        // If app uses a page directory, now address the page table
467
        S_RD_PTL4:
468
                if (m_ack_i) begin
469
                        nack();
470
                        if (|m_dat_i[2:0]) begin // pte valid bit
471
                                tmpadr <= {m_dat_i[50:16],miss_adr[52:43],3'b0};
472
                                call(S_RD_PTL,S_RD_PTL3);
473
                        end
474
                        else begin
475
                                if (clock) begin
476
                                        clock_adr[64:53] <= clock_adr[64:53] + 4'h1;
477
                                        clock_adr[52:0] <= 4'h0;
478
                                        goto (S_WAIT_MISS);
479
                                end
480
                                else
481
                          raise_page_fault();
482
                  end
483
                end
484
 
485
        // Wait for ack from system
486
        // Setup to access page table
487
        // If app uses a page directory, now address the page table
488
        S_RD_PTL3:
489
                if (m_ack_i) begin
490
                        nack();
491
                        if (|m_dat_i[2:0]) begin // pte valid bit
492
                                tmpadr <= {m_dat_i[50:16],miss_adr[42:33],3'b0};
493
                                call(S_RD_PTL,S_RD_PTL2);
494
                        end
495
                        else begin
496
                                if (clock) begin
497
                                        clock_adr[64:43] <= clock_adr[64:43] + 4'h1;
498
                                        clock_adr[32:0] <= 4'h0;
499
                                        goto (S_WAIT_MISS);
500
                                end
501
                                else
502
                          raise_page_fault();
503
                  end
504
                end
505
 
506
        // Wait for ack from system
507
        // Setup to access page table
508
        // If app uses a page directory, now address the page table
509
        S_RD_PTL2:
510
                if (m_ack_i) begin
511
                        nack();
512
                        if (|m_dat_i[2:0]) begin // pte valid bit
513
                                tmpadr <= {m_dat_i[50:16],miss_adr[32:23],3'b0};
514
                                call(S_RD_PTL,S_RD_PTL1);
515
                        end
516
                        else begin
517
                                if (clock) begin
518
                                        clock_adr[64:33] <= clock_adr[64:33] + 4'h1;
519
                                        clock_adr[32:0] <= 4'h0;
520
                                        goto (S_WAIT_MISS);
521
                                end
522
                                else
523
                          raise_page_fault();
524
                  end
525
                end
526
 
527
        // Wait for ack from system
528
        // Setup to access page table
529
        // If app uses a page directory, now address the page table
530
        S_RD_PTL1:
531
                if (m_ack_i) begin
532
                        nack();
533
                        if (|m_dat_i[2:0]) begin // pte valid bit
534
                    // Shortcut 8MiB page ?
535
                    if (m_dat_i[`_8MBPG]) begin
536
                pte <= m_dat_i;
537
                        m_dat_o <= m_dat_i|{dbit,2'b00,~clock,4'b0};
538
                        m_dat_o[4] <= ~clock;
539
                                        call(S_WR_PTL,S_WR_PTL0);
540
                    end
541
                    else begin
542
                            tmpadr <= {m_dat_i[50:16],miss_adr[22:13],3'b0};
543
                                        call(S_RD_PTL,S_RD_PTL0);
544
                                end
545
                        end
546
                        else begin
547
                                if (clock) begin
548
                                        clock_adr[64:23] <= clock_adr[64:23] + 4'h1;
549
                                        clock_adr[22:0] <= 4'h0;
550
                                        goto (S_WAIT_MISS);
551
                                end
552
                                else
553
                          raise_page_fault();
554
                  end
555
                end
556
 
557
        //---------------------------------------------------
558
        // This section of the state machine performs a
559
        // read then write of a PTE
560
        //---------------------------------------------------
561
        // Perform a read cycle of page table level 0 entry
562
        S_RD_PTL0:
563
        // The tlb has been updated so the page must have been accessed
564
    // set the accessed bit for the page table entry
565
    // Also set dirty bit if a write access.
566
                if (m_ack_i) begin
567
                        nack();
568
                        tlb_wr <= 1'b1;
569
                        pte_adr <= m_adr_o[AMSB:4];
570
                        m_dat_o <= m_dat_i|{dbit,2'b00,1'b1,4'b0};      // This line will only set bits
571
                        pte <= m_dat_i|{dbit,2'b00,1'b1,4'b0};
572
                        // If the tlb entry is already marked dirty don't bother with updating
573
                        // the pte in memory. Only write on a new dirty status.
574
                        if (tlb_d[tlb_ra[8:6]])
575
                                goto(S_WAIT_MISS);
576
                        else
577
                                call(S_WR_PTL,S_WR_PTL0);
578
                end
579
 
580
        S_WR_PTL0:
581
                if (m_ack_i) begin
582
                        tlb_wr <= 1'b1;
583
                        nack();
584
                        tlb_v[tlb_wa] <= |pte[2:0];
585
                        if (~|pte[2:0])
586
                    raise_page_fault();
587
                        goto(S_WAIT_MISS);
588
                end
589
 
590
        //---------------------------------------------------
591
        // Take care of reference counting and aging.
592
        //---------------------------------------------------
593
 
594
        S_COUNT:
595
                begin
596
                        pte[6:0] <= tlb_flags[tlb_ra[8:6]];
597
                        pte[7] <= tlb_d[tlb_ra[8:6]];
598
                        pte[15:8] <= tlb_pl[tlb_ra[8:6]];
599
                        pte[23] <= tlb_g[tlb_ra[8:6]];
600
                        pte[31:24] <= tlb_asid[tlb_ra[8:6]];
601
                        pte[63:32] <= {tlb_refcount[tlb_ra[8:6]][63:42] + 4'd1,tlb_refcount[tlb_ra[8:6]][41:32]};
602
                        pte[127:64] <= tlb_tadr[tlb_ra[8:6]];
603
                        tlb_wr <= 1'b1;
604
                        goto(S_WAIT_MISS);
605
                end
606
 
607
        S_AGE:
608
                begin
609
                        pte[6:0] <= tlb_flags[tlb_ra[8:6]];
610
                        pte[7] <= tlb_d[tlb_ra[8:6]];
611
                        pte[15:8] <= tlb_pl[tlb_ra[8:6]];
612
                        pte[23] <= tlb_g[tlb_ra[8:6]];
613
                        pte[31:24] <= tlb_asid[tlb_ra[8:6]];
614
                        pte[63:32] <= {1'b0,tlb_refcount[tlb_ra[8:6]][63:33]};
615
                        pte[127:64] <= tlb_tadr[tlb_ra[8:6]];
616
                        tlb_wr <= 1'b1;
617
                        goto(S_WAIT_MISS);
618
                end
619
 
620
        //---------------------------------------------------
621
        // Subroutine: initiate read cycle
622
        //---------------------------------------------------
623
        S_RD_PTL:
624
                if (~m_ack_i & ~m_cyc_o) begin
625
                        m_cyc_o <= 1'b1;
626
                        m_sel_o <= 8'hFF;
627
                        m_lock_o <= 1'b0;
628
                        m_we_o  <= 1'b0;
629
                        m_adr_o <= tmpadr;
630
                        return();
631
                end
632
 
633
        //---------------------------------------------------
634
        // Subroutine: initiate write cycle
635
        //---------------------------------------------------
636
        S_WR_PTL:
637
                if (~m_ack_i & ~m_cyc_o) begin
638
                        m_cyc_o <= 1'b1;
639
                        m_sel_o <= 8'hFF;
640
                        m_lock_o <= 1'b0;
641
                        m_we_o  <= 1'b1;
642
                        // Address comes from a previous read address
643
//                      m_adr_o <= tmpadr;
644
                        return();
645
                end
646
 
647
        //---------------------------------------------------
648
        // This state can't happen without a hardware error
649
        //---------------------------------------------------
650
        default:
651
                begin
652
                        nack();
653
                        goto(S_WAIT_MISS);
654
                end
655
 
656
        endcase
657
end
658
 
659
 
660
// This counter is used to select the tlb entry that gets
661
// replaced when a new entry is entered into the buffer.
662
// It just increments every time an entry is updated. 
663
always @(posedge clk_i)
664
if (rst_i)
665
        cnt <= 0;
666
else if (state==S_WAIT_MISS && miss) begin
667
        if (cnt == pAssociativity-1)
668
                cnt <= 0;
669
        else
670
                cnt <= cnt + 1;
671
end
672
 
673
task nack;
674
begin
675
        m_cyc_o <= 1'b0;
676
        m_sel_o <= 8'h00;
677
        m_lock_o <= 1'b0;
678
        m_we_o  <= 1'b0;
679
end
680
endtask
681
 
682
task raise_page_fault;
683
begin
684
        nack();
685
  if (proc)
686
    page_fault <= `TRUE;
687
  proc <= `FALSE;
688
  state <= S_WAIT_MISS;
689
end
690
endtask
691
 
692
task goto;
693
input [3:0] nst;
694
begin
695
        state <= nst;
696
end
697
endtask
698
 
699
task call;
700
input [3:0] nst;
701
input [3:0] rst;
702
begin
703
        goto(nst);
704
        stkstate <= rst;
705
end
706
endtask
707
 
708
task return;
709
begin
710
        state <= stkstate;
711
end
712
endtask
713
 
714
endmodule
715
 

powered by: WebSVN 2.1.0

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