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

Subversion Repositories thor

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

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 66 robfinch
//   \\__/ o\    (C) 2011-2019  Robert Finch, Waterloo
6 60 robfinch
//    \  __ /    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 66 robfinch
// The code is carefully constructed to not require reset signals.
31 60 robfinch
//
32
//=============================================================================
33
//
34
`define TLBMissPage             {DBW-13{1'b1}}
35
 
36 66 robfinch
module FT64_TLB(clk, ld, done, idle, ol,
37 60 robfinch
        ASID, op, regno, dati, dato,
38
        uncached,
39
        icl_i, cyc_i, we_i, vadr_i, cyc_o, we_o, padr_o,
40
        wrv_o, rdv_o, exv_o,
41
        TLBMiss, HTLBVirtPageo);
42
parameter DBW=64;
43
parameter ABW=32;
44
parameter ENTRIES=256;
45
parameter IDLE = 4'd0;
46
parameter ONE = 4'd1;
47
parameter TWO = 4'd2;
48
parameter READ = 4'd1;
49
parameter INC1 = 4'd2;
50
parameter INC2 = 4'd3;
51
parameter INC3 = 4'd4;
52
parameter AGE1 = 4'd5;
53
parameter AGE2 = 4'd6;
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 66 robfinch
output reg [ABW-1:0] padr_o = 64'hFFFFFFFFFFFC0100;
61 60 robfinch
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 66 robfinch
reg [1:0] state = IDLE;
82 60 robfinch
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 66 robfinch
reg TLBenabled = 1'b0;
101
reg [7:0] i = 8'h00;
102 60 robfinch
reg [DBW-1:0] Index;
103 66 robfinch
reg [3:0] Random = 4'hF;
104
reg [3:0] Wired = 4'd0;
105 60 robfinch
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 66 robfinch
reg [DBW-1:0] PageTblAddr = {DBW{1'b0}};
124
reg [DBW-1:0] PageTblCtrl = {DBW{1'b0}};
125 60 robfinch
 
126 66 robfinch
reg [23:0] age_lmt = 24'd20000;
127
reg [23:0] age_ctr = 24'd0;
128 60 robfinch
wire age_tick = age_ctr < 24'd5;
129 66 robfinch
reg cyc_en = 1'b1, age_en = 1'b1;
130
reg [3:0] ar_state = IDLE;
131
reg ar_wr = 1'b0;
132
reg [7:0] age_adr = 8'h00, ar_adr = 8'h00;
133 60 robfinch
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 66 robfinch
reg doLoad = 1'b0;
139 60 robfinch
 
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 66 robfinch
begin
229
        // age_ctr > age_lmt when counter hits -1, saves comparing to zero as well
230
        if (age_ctr > age_lmt)
231 60 robfinch
                age_ctr <= age_lmt;
232
        else
233
                age_ctr <= age_ctr - 4'd1;
234
end
235
 
236
// Handle Random register
237
always @(posedge clk)
238 66 robfinch
begin
239 60 robfinch
        if (Random==Wired)
240
    Random <= 4'hF;
241
  else
242
    Random <= Random - 4'd1;
243
  // Why would we want to update since random changes on the next clock
244
  // anyways ?
245
  if (state==ONE) begin
246
    if (op==`TLB_WRREG && regno==`TLBRandom)
247
      Random <= dati[3:0];
248
  end
249
end
250
 
251
always @(posedge clk)
252 66 robfinch
begin
253 60 robfinch
case(state)
254
IDLE:
255
        if (ld)
256
                state <= ONE;
257
ONE:
258
        if (op==`TLB_RDAGE || op==`TLB_WRAGE) begin
259
                if (getset_age)
260
                        state <= TWO;
261
        end
262
        else
263
                state <= TWO;
264
TWO:
265
        state <= IDLE;
266
default:
267
        state <= IDLE;
268
endcase
269
end
270
 
271
// Set index to page table
272
always @(posedge clk)
273 66 robfinch
if (state==ONE) begin
274
  case(op)
275
  `TLB_RD,`TLB_WI:
276
    i <= {Index[7:4],(HTLBVirtPage >> {HTLBPageSize,1'b0}) & 4'hF};
277
  `TLB_WR:
278
    i <= {Random,(HTLBVirtPage >> {HTLBPageSize,1'b0}) & 4'hF};
279
  endcase
280 60 robfinch
end
281
 
282
always @(posedge clk)
283 66 robfinch
begin
284 60 robfinch
        if (miss_addr == {DBW{1'b0}} && TLBMiss)
285
                miss_addr <= vadr_i;
286
 
287
        if (state==ONE) begin
288
                case(op)
289
                `TLB_WRREG:
290
                        begin
291
                        case(regno)
292
                        `TLBWired:              Wired <= dati[2:0];
293
                        `TLBIndex:              Index <= dati[5:0];
294
                        //`TLBPageSize: PageSize <= dati[2:0];
295
                        `TLBVirtPage:   HTLBVirtPage <= dati;
296
                        `TLBPhysPage:   HTLBPhysPage <= dati;
297
                        `TLBASID:       begin
298
                                                HTLBValid <= |dati[2:0];
299
                                                HTLBX <= dati[0];
300
                                                HTLBW <= dati[1];
301
                                                HTLBR <= dati[2];
302
                                                HTLBC <= dati[5:3];
303
                                                HTLBA <= dati[6];
304
                                                HTLBS <= dati[7];
305
                                                HTLBU <= dati[8];
306
                                                HTLBD <= dati[9];
307
                                                HTLBG <= dati[10];
308
                                                HTLBPageSize <= dati[13:11];
309
                                                HTLBASID <= dati[23:16];
310
                                                HTLBPL <= dati[31:24];
311
                                                end
312
                        `TLBMissAdr:    miss_addr <= dati;
313
                        `TLBPageTblAddr:        PageTblAddr <= dati;
314
                        `TLBPageTblCtrl:        PageTblCtrl <= dati;
315
                        `TLBAFC:        age_lmt <= dati[23:0];
316
                        default: ;
317
                        endcase
318
                        end
319
                `TLB_EN:
320
                        TLBenabled <= 1'b1;
321
                `TLB_DIS:
322
                        TLBenabled <= 1'b0;
323
                `TLB_INVALL:
324
                        TLBValid <= 256'd0;
325
                default:  ;
326
                endcase
327
        end
328
        else if (state==TWO) begin
329
                case(op)
330
                `TLB_P:
331
                        begin
332
                                Index[DBW-1] <= ~|Match;
333
                        end
334
                `TLB_RD:
335
                        begin
336
                                HTLBVirtPage <= TLBVirtPage[i];
337
                                HTLBPhysPage <= TLBPhysPage_rdo;
338
                                HTLBASID <= TLBASID[i];
339
                                HTLBPL <= TLBPL[i];
340
                                HTLBPageSize <= TLBPageSize[i];
341
                                HTLBG <= TLBG[i];
342
                                HTLBD <= TLBD[i];
343
                                HTLBC <= TLBC[i];
344
                                HTLBR <= tlbRo0;
345
                                HTLBW <= tlbWo0;
346
                                HTLBX <= tlbXo0;
347
                                HTLBU <= TLBU[i];
348
                                HTLBS <= TLBS[i];
349
                                HTLBA <= TLBA[i];
350
                                HTLBValid <= TLBValid[i];
351
                        end
352
                `TLB_WR,`TLB_WI:
353
                        begin
354
                                TLBVirtPage[i] <= HTLBVirtPage;
355
                                TLBASID[i] <= HTLBASID;
356
                                TLBPL[i] <= HTLBPL;
357
                                TLBPageSize[i] <= HTLBPageSize;
358
                                TLBG[i] <= HTLBG;
359
                                TLBD[i] <= HTLBD;
360
                                TLBC[i] <= HTLBC;
361
                                TLBA[i] <= HTLBA;
362
                                TLBU[i] <= HTLBU;
363
                                TLBS[i] <= HTLBS;
364
                                TLBValid[i] <= HTLBValid;
365
                        end
366
                default:  ;
367
                endcase
368
        end
369
 
370
        // Set the dirty bit on a store
371
        if (we_i)
372
                if (!m1UnmappedArea & !q[4]) begin
373
                        TLBD[{q[3:0],vadrs[3:0]}] <= 1'b1;
374
                end
375
end
376
 
377
always @(posedge clk)
378
        case(regno)
379
        `TLBWired:              dato <= Wired;
380
        `TLBIndex:              dato <= Index;
381
        `TLBRandom:             dato <= Random;
382
        `TLBPhysPage:   dato <= HTLBPhysPage;
383
        `TLBVirtPage:   dato <= HTLBVirtPage;
384
        `TLBPageSize:   dato <= PageSize;
385
        `TLBASID:       begin
386
                                dato <= {DBW{1'b0}};
387
                                dato[0] <= HTLBX;
388
                                dato[1] <= HTLBW;
389
                                dato[2] <= HTLBR;
390
                                dato[5:3] <= HTLBC;
391
                                dato[6] <= HTLBA;
392
                                dato[7] <= HTLBS;
393
                                dato[8] <= HTLBU;
394
                                dato[9] <= HTLBD;
395
                                dato[10] <= HTLBG;
396
                                dato[13:11] <= HTLBPageSize;
397
                                dato[23:16] <= HTLBASID;
398
                                dato[31:24] <= HTLBPL;
399
                                end
400
        `TLBMissAdr:    dato <= miss_addr;
401
        `TLBPageTblAddr:        dato <= PageTblAddr;
402
        `TLBPageTblCtrl:        dato <= PageTblCtrl;
403
        `TLBPageCount:          dato <= {16'd0,ar_cdato};
404
        default:        dato <= {DBW{1'b0}};
405
        endcase
406
 
407
TLBAgeRam uar1(clk,ar_wr,ar_adr,ar_dati,ar_dato);
408
 
409
always @(posedge clk)
410 66 robfinch
begin
411 60 robfinch
ar_wr <= 1'b0;
412
getset_age <= 1'b0;
413
if (ld)
414
        doLoad <= 1'b1;
415
case(ar_state)
416
IDLE:
417
        begin
418
                if (~cyc_i)
419
                        cyc_en <= 1'b1;
420
                if (~age_tick)
421
                        age_en <= 1'b1;
422
                if ((ld|doLoad) && (op==`TLB_RDAGE || op==`TLB_WRAGE)) begin
423
                        doLoad <= 1'b0;
424
                        ar_wr <= op==`TLB_WRAGE;
425
                        ar_adr <= i;
426
                        ar_dati <= dati[31:0];
427
                        ar_state <= READ;
428
                end
429
                else if (cyc_i & |Match & cyc_en) begin
430
                        cyc_en <= 1'b0;
431
                        ar_adr <= {q[3:0],vadrs[3:0]};
432
                        ar_state <= INC1;
433
                end
434
                else if (age_tick & age_en) begin
435
                        age_en <= 1'b0;
436
                        ar_adr <= age_adr;
437
                        age_adr <= age_adr + 4'd1;
438
                        ar_state <= AGE1;
439
                end
440
        end
441
READ:
442
        begin
443
                getset_age <= 1'b1;
444
                ar_cdato <= ar_dato;
445
                ar_state <= IDLE;
446
        end
447
INC1:
448
        begin
449
                count <= ar_dato;
450
                ar_state <= INC2;
451
        end
452
INC2:
453
        begin
454
                count <= {count[31:8] + 4'd1,count[7:0]};
455
                ar_state <= INC3;
456
        end
457
INC3:
458
        begin
459
                ar_wr <= 1'b1;
460
                ar_dati <= {count[32] ? 24'hFFFFFF :count[31:8],count[7:0]};
461
                ar_state <= IDLE;
462
        end
463
AGE1:
464
        begin
465
                count <= ar_dato;
466
                ar_state <= AGE2;
467
        end
468
AGE2:
469
        begin
470
                ar_wr <= 1'b1;
471
                ar_dati <= count >> 1;
472
                ar_state <= IDLE;
473
        end
474
endcase
475
end
476
 
477
always @*
478
for (n = 0; n < 16; n = n + 1)
479
        Match[n[3:0]] = (vadrs[ABW-1:4]==TLBVirtPage[{n[3:0],vadrs[3:0]}]) &&
480
                                ((TLBASID[{n[3:0],vadrs[3:0]}]==ASID) || TLBG[{n[3:0],vadrs[3:0]}]) &&
481
                                TLBValid[{q[3:0],vadrs[3:0]}];
482
 
483
always @*
484
begin
485
        q = 5'd31;
486
        for (n = 15; n >= 0; n = n - 1)
487
                if (Match[n]) q = n;
488
end
489
 
490
assign uncached = TLBC[{q[3:0],vadrs[3:0]}]==3'd1;// || unmappedDataArea;
491
 
492 66 robfinch
assign TLBMiss = (ol!=2'b00) && TLBenabled && (!unmappedArea & (q[4] | ~TLBValid[{q[3:0],vadrs[3:0]}]) ||
493 60 robfinch
                                        (ol!=2'b00 && hitIOPage));
494
 
495
always @(posedge clk)
496 66 robfinch
        cyc_o <= cyc_i && (!TLBMiss || !TLBenabled || (ol == 2'b00));
497 60 robfinch
 
498
always @(posedge clk)
499 66 robfinch
        we_o <= we_i & ((~TLBMiss & tlbWo1) | ~TLBenabled || (ol==2'b00));
500 60 robfinch
 
501
always @(posedge clk)
502 66 robfinch
        wrv_o <= we_i & ~TLBMiss & ~tlbWo1 & TLBenabled && (ol != 2'b00);
503 60 robfinch
 
504
always @(posedge clk)
505 66 robfinch
        rdv_o <= ~we_i & ~TLBMiss & ~tlbRo1 & TLBenabled && (ol != 2'b00);
506 60 robfinch
 
507
always @(posedge clk)
508 66 robfinch
        exv_o <= icl_i & ~TLBMiss & ~tlbXo1 & TLBenabled && (ol != 2'b00);
509 60 robfinch
 
510
always @(posedge clk)
511
if (TLBenabled && ol != 2'b00) begin
512
        case(PageSize)
513
        3'd0:   padr_o[ABW-1:13] <=  unmappedArea ? vadr_i[ABW-1:13] : TLBMiss ? `TLBMissPage: PFN;
514
        3'd1:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:15] : TLBMiss ? `TLBMissPage: PFN,vadr_i[14:13]};
515
        3'd2:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:17] : TLBMiss ? `TLBMissPage: PFN,vadr_i[16:13]};
516
        3'd3:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:19] : TLBMiss ? `TLBMissPage: PFN,vadr_i[18:13]};
517
        3'd4:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:21] : TLBMiss ? `TLBMissPage: PFN,vadr_i[20:13]};
518
        3'd5:   padr_o[ABW-1:13] <= {unmappedArea ? vadr_i[ABW-1:23] : TLBMiss ? `TLBMissPage: PFN,vadr_i[22:13]};
519
        default:        padr_o[ABW-1:13] <= vadr_i[ABW-1:13];
520
        endcase
521
        padr_o[12:0] <= vadr_i[12:0];
522
end
523
else
524
        padr_o <= vadr_i;
525
 
526
endmodule
527
 
528
module TLBRam(clk,we,wa,i,ra0,ra1,o0,o1);
529
parameter DBW=1;
530
input clk;
531
input we;
532
input [7:0] wa;
533
input [DBW-1:0] i;
534
input [7:0] ra0;
535
input [7:0] ra1;
536
output [DBW-1:0] o0;
537
output [DBW-1:0] o1;
538
 
539
reg [DBW-1:0] mem [0:255];
540
 
541
always @(posedge clk)
542
  if (we)
543
    mem[wa] <= i;
544
 
545
assign o0 = mem[ra0];
546
assign o1 = mem[ra1];
547
 
548
endmodule
549
 
550
module TLBPhysPageRam(clk,we,wa,i,ra0,ra1,o0,o1);
551
parameter DBW=64;
552
input clk;
553
input we;
554
input [7:0] wa;
555
input [DBW-1:0] i;
556
input [7:0] ra0;
557
input [7:0] ra1;
558
output [DBW-1:0] o0;
559
output [DBW-1:0] o1;
560
 
561
reg [DBW-1:0] mem [0:255];
562
 
563
always @(posedge clk)
564
  if (we)
565
    mem[wa] <= i;
566
 
567
assign o0 = mem[ra0];
568
assign o1 = mem[ra1];
569
 
570
endmodule
571
 
572
module TLBAgeRam(clk,we,a,i,o);
573
parameter DBW=32;
574
input clk;
575
input we;
576
input [7:0] a;
577
input [DBW-1:0] i;
578
output [DBW-1:0] o;
579
 
580
reg [DBW-1:0] mem [0:255];
581
 
582
always @(posedge clk)
583
  if (we)
584
    mem[a] <= i;
585
 
586
assign o = mem[a];
587
 
588
endmodule
589
 

powered by: WebSVN 2.1.0

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