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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v7/] [rtl/] [twoway/] [FT64_TLB.v] - Blame information for rev 60

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 robfinch
`include "FT64_defines.vh"
2
`include "FT64_config.vh"
3
//=============================================================================
4
//        __
5
//   \\__/ o\    (C) 2011-2018  Robert Finch, Waterloo
6
//    \  __ /    All rights reserved.
7
//     \/_//     robfinch<remove>@finitron.ca
8
//       ||
9
//  
10
//      FT64_TLB.v
11
//
12
//  
13
// This source file is free software: you can redistribute it and/or modify 
14
// it under the terms of the GNU Lesser General Public License as published 
15
// by the Free Software Foundation, either version 3 of the License, or     
16
// (at your option) any later version.                                      
17
//                                                                          
18
// This source file is distributed in the hope that it will be useful,      
19
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
20
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
21
// GNU General Public License for more details.                             
22
//                                                                          
23
// You should have received a copy of the GNU General Public License        
24
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
25
//                                                                          
26
//
27
// TLB
28
// The TLB contains 256 entries, that are 16 way set associative.
29
// The TLB is shared between the instruction and data streams.
30
//
31
//=============================================================================
32
//
33
`define TLBMissPage             {DBW-13{1'b1}}
34
 
35
module FT64_TLB(rst, clk, ld, done, idle, ol,
36
        ASID, op, regno, dati, dato,
37
        uncached,
38
        icl_i, cyc_i, we_i, vadr_i, cyc_o, we_o, padr_o,
39
        wrv_o, rdv_o, exv_o,
40
        TLBMiss, HTLBVirtPageo);
41
parameter DBW=64;
42
parameter ABW=32;
43
parameter ENTRIES=256;
44
parameter IDLE = 4'd0;
45
parameter ONE = 4'd1;
46
parameter TWO = 4'd2;
47
parameter READ = 4'd1;
48
parameter INC1 = 4'd2;
49
parameter INC2 = 4'd3;
50
parameter INC3 = 4'd4;
51
parameter AGE1 = 4'd5;
52
parameter AGE2 = 4'd6;
53
input rst;
54
input clk;
55
input ld;
56
output done;
57
output idle;
58
input [1:0] ol;                                  // operating level
59
input [ABW-1:0] vadr_i;
60
output reg [ABW-1:0] padr_o;
61
output uncached;
62
 
63
input icl_i;
64
input cyc_i;
65
input we_i;
66
output reg cyc_o;
67
output reg we_o;
68
output reg exv_o;
69
output reg wrv_o;
70
output reg rdv_o;
71
input [7:0] ASID;
72
input [3:0] op;
73
input [3:0] regno;
74
input [DBW-1:0] dati;
75
output reg [DBW-1:0] dato;
76
output TLBMiss;
77
output [DBW-1:0] HTLBVirtPageo;
78
 
79
integer n;
80
 
81
reg [3:0] state;
82
assign done = state==(IDLE && !ld) || state==TWO;
83
assign idle = state==IDLE && !ld;
84
 
85
// Holding registers
86
// These allow the TLB to updated in a single cycle as a unit
87
reg [DBW-1:0] HTLBVirtPage;
88
assign HTLBVirtPageo = {HTLBVirtPage,13'b0};
89
reg [DBW-1:0] HTLBPhysPage;
90
reg [7:0] HTLBASID;
91
reg HTLBG;
92
reg HTLBD;
93
reg HTLBR, HTLBW, HTLBX, HTLBA, HTLBU, HTLBS;
94
reg [2:0] HTLBC;
95
reg [7:0] HTLBPL;
96
reg [2:0] HTLBPageSize;
97
reg HTLBValid;
98
reg [ABW-1:0] miss_addr;
99
 
100
reg TLBenabled;
101
reg [7:0] i;
102
reg [DBW-1:0] Index;
103
reg [3:0] Random;
104
reg [3:0] Wired;
105
reg [2:0] PageSize;
106
reg [15:0] Match;
107
 
108
reg [4:0] q;
109
wire doddpage;
110
reg [DBW-1:0] TLBVirtPage [ENTRIES-1:0];
111
reg [ENTRIES-1:0] TLBG;
112
reg [ENTRIES-1:0] TLBD;
113
reg [ENTRIES-1:0] TLBU;
114
reg [ENTRIES-1:0] TLBS;
115
reg [ENTRIES-1:0] TLBA;
116
reg [2:0] TLBC [ENTRIES-1:0];
117
reg [7:0] TLBASID [ENTRIES-1:0];
118
reg [7:0] TLBPL [ENTRIES-1:0];
119
reg [2:0] TLBPageSize [255:0];
120
reg [ENTRIES-1:0] TLBValid;
121
reg [DBW-1:0] imiss_addr;
122
reg [DBW-1:0] dmiss_addr;
123
reg [DBW-1:0] PageTblAddr;
124
reg [DBW-1:0] PageTblCtrl;
125
 
126
reg [23:0] age_lmt;
127
reg [23:0] age_ctr;
128
wire age_tick = age_ctr < 24'd5;
129
reg cyc_en, age_en;
130
reg [3:0] ar_state;
131
reg ar_wr;
132
reg [7:0] age_adr, ar_adr;
133
reg [32:0] count;
134
reg [31:0] ar_dati;
135
wire [31:0] ar_dato;
136
reg [31:0] ar_cdato;
137
reg getset_age;
138
reg doLoad;
139
 
140
/*
141
initial begin
142
        for (n = 0; n < ENTRIES; n = n + 1)
143
        begin
144
                TLBVirtPage[n] = 0;
145
                TLBG[n] = 0;
146
                TLBASID[n] = 0;
147
                TLBD[n] = 0;
148
                TLBC[n] = 0;
149
                TLBA[n] = 0;
150
                TLBR[n] = 0;
151
                TLBW[n] = 0;
152
                TLBX[n] = 0;
153
                TLBS[n] = 0;
154
                TLBU[n] = 0;
155
                TLBValid[n] = 0;
156
        end
157
end
158
*/
159
 
160
// Assume the instruction doesn't overlap between a mapped and unmapped area.
161
wire unmappedArea = vadr_i[ABW-1:ABW-8]==8'hFF || !TLBenabled;
162
wire m1UnmappedArea = padr_o[ABW-1:ABW-8]==8'hFF || !TLBenabled;
163
wire hitIOPage = vadr_i[ABW-1:ABW-12]==12'hFFD;
164
 
165
always @(posedge clk)
166
        PageSize <= TLBPageSize[ASID];
167
 
168
wire [ABW-1:0] vadrs = vadr_i[ABW-1:13] >> {PageSize,1'b0};
169
wire [DBW-1:0] TLBPhysPage_rdo;
170
wire [ABW-1:0] PFN;
171
 
172
// Toolset didn't like the simpler distributed code where the RAM was inferred.
173
// Resulted in combinatorial loop error message. Even though there weren't any
174
// combinatorial loops.
175
 
176
TLBPhysPageRam #(DBW) upgrm1
177
(
178
  .clk(clk),
179
  .we(state==TWO && (op==`TLB_WR || op==`TLB_WI)),
180
  .wa(i),
181
  .i(HTLBPhysPage),
182
  .ra0(i),
183
  .ra1({q[3:0],vadrs[3:0]}),
184
  .o0(TLBPhysPage_rdo),
185
  .o1(PFN)
186
);
187
 
188
wire tlbRo0,tlbRo1;
189
TLBRam #(1) uR
190
(
191
  .clk(clk),
192
  .we(state==TWO && (op==`TLB_WR || op==`TLB_WI)),
193
  .wa(i),
194
  .i(HTLBR),
195
  .ra0(i),
196
  .ra1({q[3:0],vadrs[3:0]}),
197
  .o0(tlbRo0),
198
  .o1(tlbRo1)
199
);
200
 
201
wire tlbWo0,tlbWo1;
202
TLBRam #(1) uW
203
(
204
  .clk(clk),
205
  .we(state==TWO && (op==`TLB_WR || op==`TLB_WI)),
206
  .wa(i),
207
  .i(HTLBW),
208
  .ra0(i),
209
  .ra1({q[3:0],vadrs[3:0]}),
210
  .o0(tlbWo0),
211
  .o1(tlbWo1)
212
);
213
 
214
wire tlbXo0,tlbXo1;
215
TLBRam #(1) uX
216
(
217
  .clk(clk),
218
  .we(state==TWO && (op==`TLB_WR || op==`TLB_WI)),
219
  .wa(i),
220
  .i(HTLBX),
221
  .ra0(i),
222
  .ra1({q[3:0],vadrs[3:0]}),
223
  .o0(tlbXo0),
224
  .o1(tlbXo1)
225
);
226
 
227
always @(posedge clk)
228
if (rst) begin
229
        age_ctr <= 24'd0;
230
end
231
else begin
232
        if (age_ctr==24'd0)
233
                age_ctr <= age_lmt;
234
        else
235
                age_ctr <= age_ctr - 4'd1;
236
end
237
 
238
// Handle Random register
239
always @(posedge clk)
240
if (rst) begin
241
        Random <= 4'hF;
242
end
243
else begin
244
        if (Random==Wired)
245
    Random <= 4'hF;
246
  else
247
    Random <= Random - 4'd1;
248
  // Why would we want to update since random changes on the next clock
249
  // anyways ?
250
  if (state==ONE) begin
251
    if (op==`TLB_WRREG && regno==`TLBRandom)
252
      Random <= dati[3:0];
253
  end
254
end
255
 
256
always @(posedge clk)
257
if (rst) begin
258
        state <= IDLE;
259
end
260
else begin
261
case(state)
262
IDLE:
263
        if (ld)
264
                state <= ONE;
265
ONE:
266
        if (op==`TLB_RDAGE || op==`TLB_WRAGE) begin
267
                if (getset_age)
268
                        state <= TWO;
269
        end
270
        else
271
                state <= TWO;
272
TWO:
273
        state <= IDLE;
274
default:
275
        state <= IDLE;
276
endcase
277
end
278
 
279
// Set index to page table
280
always @(posedge clk)
281
if (rst) begin
282
  i <= 8'd0;
283
end
284
else begin
285
        if (state==ONE) begin
286
    case(op)
287
    `TLB_RD,`TLB_WI:
288
      i <= {Index[7:4],(HTLBVirtPage >> {HTLBPageSize,1'b0}) & 4'hF};
289
    `TLB_WR:
290
      i <= {Random,(HTLBVirtPage >> {HTLBPageSize,1'b0}) & 4'hF};
291
    endcase
292
  end
293
end
294
 
295
always @(posedge clk)
296
if (rst) begin
297
        TLBenabled <= 1'b0;
298
        Wired <= 4'd0;
299
        PageTblAddr <= {DBW{1'b0}};
300
        PageTblCtrl <= {DBW{1'b0}};
301
        age_lmt <= 24'd20000;
302
end
303
else begin
304
        if (miss_addr == {DBW{1'b0}} && TLBMiss)
305
                miss_addr <= vadr_i;
306
 
307
        if (state==ONE) begin
308
                case(op)
309
                `TLB_WRREG:
310
                        begin
311
                        case(regno)
312
                        `TLBWired:              Wired <= dati[2:0];
313
                        `TLBIndex:              Index <= dati[5:0];
314
                        //`TLBPageSize: PageSize <= dati[2:0];
315
                        `TLBVirtPage:   HTLBVirtPage <= dati;
316
                        `TLBPhysPage:   HTLBPhysPage <= dati;
317
                        `TLBASID:       begin
318
                                                HTLBValid <= |dati[2:0];
319
                                                HTLBX <= dati[0];
320
                                                HTLBW <= dati[1];
321
                                                HTLBR <= dati[2];
322
                                                HTLBC <= dati[5:3];
323
                                                HTLBA <= dati[6];
324
                                                HTLBS <= dati[7];
325
                                                HTLBU <= dati[8];
326
                                                HTLBD <= dati[9];
327
                                                HTLBG <= dati[10];
328
                                                HTLBPageSize <= dati[13:11];
329
                                                HTLBASID <= dati[23:16];
330
                                                HTLBPL <= dati[31:24];
331
                                                end
332
                        `TLBMissAdr:    miss_addr <= dati;
333
                        `TLBPageTblAddr:        PageTblAddr <= dati;
334
                        `TLBPageTblCtrl:        PageTblCtrl <= dati;
335
                        `TLBAFC:        age_lmt <= dati[23:0];
336
                        default: ;
337
                        endcase
338
                        end
339
                `TLB_EN:
340
                        TLBenabled <= 1'b1;
341
                `TLB_DIS:
342
                        TLBenabled <= 1'b0;
343
                `TLB_INVALL:
344
                        TLBValid <= 256'd0;
345
                default:  ;
346
                endcase
347
        end
348
        else if (state==TWO) begin
349
                case(op)
350
                `TLB_P:
351
                        begin
352
                                Index[DBW-1] <= ~|Match;
353
                        end
354
                `TLB_RD:
355
                        begin
356
                                HTLBVirtPage <= TLBVirtPage[i];
357
                                HTLBPhysPage <= TLBPhysPage_rdo;
358
                                HTLBASID <= TLBASID[i];
359
                                HTLBPL <= TLBPL[i];
360
                                HTLBPageSize <= TLBPageSize[i];
361
                                HTLBG <= TLBG[i];
362
                                HTLBD <= TLBD[i];
363
                                HTLBC <= TLBC[i];
364
                                HTLBR <= tlbRo0;
365
                                HTLBW <= tlbWo0;
366
                                HTLBX <= tlbXo0;
367
                                HTLBU <= TLBU[i];
368
                                HTLBS <= TLBS[i];
369
                                HTLBA <= TLBA[i];
370
                                HTLBValid <= TLBValid[i];
371
                        end
372
                `TLB_WR,`TLB_WI:
373
                        begin
374
                                TLBVirtPage[i] <= HTLBVirtPage;
375
                                TLBASID[i] <= HTLBASID;
376
                                TLBPL[i] <= HTLBPL;
377
                                TLBPageSize[i] <= HTLBPageSize;
378
                                TLBG[i] <= HTLBG;
379
                                TLBD[i] <= HTLBD;
380
                                TLBC[i] <= HTLBC;
381
                                TLBA[i] <= HTLBA;
382
                                TLBU[i] <= HTLBU;
383
                                TLBS[i] <= HTLBS;
384
                                TLBValid[i] <= HTLBValid;
385
                        end
386
                default:  ;
387
                endcase
388
        end
389
 
390
        // Set the dirty bit on a store
391
        if (we_i)
392
                if (!m1UnmappedArea & !q[4]) begin
393
                        TLBD[{q[3:0],vadrs[3:0]}] <= 1'b1;
394
                end
395
end
396
 
397
always @(posedge clk)
398
        case(regno)
399
        `TLBWired:              dato <= Wired;
400
        `TLBIndex:              dato <= Index;
401
        `TLBRandom:             dato <= Random;
402
        `TLBPhysPage:   dato <= HTLBPhysPage;
403
        `TLBVirtPage:   dato <= HTLBVirtPage;
404
        `TLBPageSize:   dato <= PageSize;
405
        `TLBASID:       begin
406
                                dato <= {DBW{1'b0}};
407
                                dato[0] <= HTLBX;
408
                                dato[1] <= HTLBW;
409
                                dato[2] <= HTLBR;
410
                                dato[5:3] <= HTLBC;
411
                                dato[6] <= HTLBA;
412
                                dato[7] <= HTLBS;
413
                                dato[8] <= HTLBU;
414
                                dato[9] <= HTLBD;
415
                                dato[10] <= HTLBG;
416
                                dato[13:11] <= HTLBPageSize;
417
                                dato[23:16] <= HTLBASID;
418
                                dato[31:24] <= HTLBPL;
419
                                end
420
        `TLBMissAdr:    dato <= miss_addr;
421
        `TLBPageTblAddr:        dato <= PageTblAddr;
422
        `TLBPageTblCtrl:        dato <= PageTblCtrl;
423
        `TLBPageCount:          dato <= {16'd0,ar_cdato};
424
        default:        dato <= {DBW{1'b0}};
425
        endcase
426
 
427
TLBAgeRam uar1(clk,ar_wr,ar_adr,ar_dati,ar_dato);
428
 
429
always @(posedge clk)
430
if (rst) begin
431
        age_adr <= 4'd0;
432
        ar_wr <= 1'b0;
433
        ar_adr <= 4'd0;
434
        ar_state <= IDLE;
435
        cyc_en <= 1'b1;
436
        age_en <= 1'b1;
437
        doLoad <= 1'b0;
438
end
439
else begin
440
ar_wr <= 1'b0;
441
getset_age <= 1'b0;
442
if (ld)
443
        doLoad <= 1'b1;
444
case(ar_state)
445
IDLE:
446
        begin
447
                if (~cyc_i)
448
                        cyc_en <= 1'b1;
449
                if (~age_tick)
450
                        age_en <= 1'b1;
451
                if ((ld|doLoad) && (op==`TLB_RDAGE || op==`TLB_WRAGE)) begin
452
                        doLoad <= 1'b0;
453
                        ar_wr <= op==`TLB_WRAGE;
454
                        ar_adr <= i;
455
                        ar_dati <= dati[31:0];
456
                        ar_state <= READ;
457
                end
458
                else if (cyc_i & |Match & cyc_en) begin
459
                        cyc_en <= 1'b0;
460
                        ar_adr <= {q[3:0],vadrs[3:0]};
461
                        ar_state <= INC1;
462
                end
463
                else if (age_tick & age_en) begin
464
                        age_en <= 1'b0;
465
                        ar_adr <= age_adr;
466
                        age_adr <= age_adr + 4'd1;
467
                        ar_state <= AGE1;
468
                end
469
        end
470
READ:
471
        begin
472
                getset_age <= 1'b1;
473
                ar_cdato <= ar_dato;
474
                ar_state <= IDLE;
475
        end
476
INC1:
477
        begin
478
                count <= ar_dato;
479
                ar_state <= INC2;
480
        end
481
INC2:
482
        begin
483
                count <= {count[31:8] + 4'd1,count[7:0]};
484
                ar_state <= INC3;
485
        end
486
INC3:
487
        begin
488
                ar_wr <= 1'b1;
489
                ar_dati <= {count[32] ? 24'hFFFFFF :count[31:8],count[7:0]};
490
                ar_state <= IDLE;
491
        end
492
AGE1:
493
        begin
494
                count <= ar_dato;
495
                ar_state <= AGE2;
496
        end
497
AGE2:
498
        begin
499
                ar_wr <= 1'b1;
500
                ar_dati <= count >> 1;
501
                ar_state <= IDLE;
502
        end
503
endcase
504
end
505
 
506
always @*
507
for (n = 0; n < 16; n = n + 1)
508
        Match[n[3:0]] = (vadrs[ABW-1:4]==TLBVirtPage[{n[3:0],vadrs[3:0]}]) &&
509
                                ((TLBASID[{n[3:0],vadrs[3:0]}]==ASID) || TLBG[{n[3:0],vadrs[3:0]}]) &&
510
                                TLBValid[{q[3:0],vadrs[3:0]}];
511
 
512
always @*
513
begin
514
        q = 5'd31;
515
        for (n = 15; n >= 0; n = n - 1)
516
                if (Match[n]) q = n;
517
end
518
 
519
assign uncached = TLBC[{q[3:0],vadrs[3:0]}]==3'd1;// || unmappedDataArea;
520
 
521
assign TLBMiss = TLBenabled & (!unmappedArea & (q[4] | ~TLBValid[{q[3:0],vadrs[3:0]}]) ||
522
                                        (ol!=2'b00 && hitIOPage));
523
 
524
always @(posedge clk)
525
        cyc_o <= cyc_i & (~TLBMiss | ~TLBenabled);
526
 
527
always @(posedge clk)
528
        we_o <= we_i & ((~TLBMiss & tlbWo1) | ~TLBenabled);
529
 
530
always @(posedge clk)
531
        wrv_o <= we_i & ~TLBMiss & ~tlbWo1 & TLBenabled;
532
 
533
always @(posedge clk)
534
        rdv_o <= ~we_i & ~TLBMiss & ~tlbRo1 & TLBenabled;
535
 
536
always @(posedge clk)
537
        exv_o <= icl_i & ~TLBMiss & ~tlbXo1 & TLBenabled;
538
 
539
always @(posedge clk)
540
if (rst)
541
        padr_o <= 32'hFFFC0100;
542
else begin
543
if (TLBenabled && ol != 2'b00) begin
544
        case(PageSize)
545
        3'd0:   padr_o[ABW-1:13] <=  unmappedArea ? vadr_i[ABW-1:13] : TLBMiss ? `TLBMissPage: PFN;
546
        3'd1:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:15] : TLBMiss ? `TLBMissPage: PFN,vadr_i[14:13]};
547
        3'd2:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:17] : TLBMiss ? `TLBMissPage: PFN,vadr_i[16:13]};
548
        3'd3:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:19] : TLBMiss ? `TLBMissPage: PFN,vadr_i[18:13]};
549
        3'd4:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:21] : TLBMiss ? `TLBMissPage: PFN,vadr_i[20:13]};
550
        3'd5:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:23] : TLBMiss ? `TLBMissPage: PFN,vadr_i[22:13]};
551
        default:        padr_o[ABW-1:13] <= vadr_i[ABW-1:13];
552
        endcase
553
        padr_o[12:0] <= vadr_i[12:0];
554
end
555
else
556
        padr_o <= vadr_i;
557
end
558
 
559
endmodule
560
 
561
module TLBRam(clk,we,wa,i,ra0,ra1,o0,o1);
562
parameter DBW=1;
563
input clk;
564
input we;
565
input [7:0] wa;
566
input [DBW-1:0] i;
567
input [7:0] ra0;
568
input [7:0] ra1;
569
output [DBW-1:0] o0;
570
output [DBW-1:0] o1;
571
 
572
reg [DBW-1:0] mem [0:255];
573
 
574
always @(posedge clk)
575
  if (we)
576
    mem[wa] <= i;
577
 
578
assign o0 = mem[ra0];
579
assign o1 = mem[ra1];
580
 
581
endmodule
582
 
583
module TLBPhysPageRam(clk,we,wa,i,ra0,ra1,o0,o1);
584
parameter DBW=64;
585
input clk;
586
input we;
587
input [7:0] wa;
588
input [DBW-1:0] i;
589
input [7:0] ra0;
590
input [7:0] ra1;
591
output [DBW-1:0] o0;
592
output [DBW-1:0] o1;
593
 
594
reg [DBW-1:0] mem [0:255];
595
 
596
always @(posedge clk)
597
  if (we)
598
    mem[wa] <= i;
599
 
600
assign o0 = mem[ra0];
601
assign o1 = mem[ra1];
602
 
603
endmodule
604
 
605
module TLBAgeRam(clk,we,a,i,o);
606
parameter DBW=32;
607
input clk;
608
input we;
609
input [7:0] a;
610
input [DBW-1:0] i;
611
output [DBW-1:0] o;
612
 
613
reg [DBW-1:0] mem [0:255];
614
 
615
always @(posedge clk)
616
  if (we)
617
    mem[a] <= i;
618
 
619
assign o = mem[a];
620
 
621
endmodule
622
 

powered by: WebSVN 2.1.0

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