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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v7/] [rtl/] [common/] [FT64_ipt.v] - Blame information for rev 66

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 robfinch
// ============================================================================
2
//        __
3 61 robfinch
//   \\__/ o\    (C) 2018-2019  Robert Finch, Waterloo
4 60 robfinch
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      FT64_ipt.v
9
//  - 64 bit CPU inverted page table memory management unit
10
//
11
// This source file is free software: you can redistribute it and/or modify 
12
// it under the terms of the GNU Lesser General Public License as published 
13
// by the Free Software Foundation, either version 3 of the License, or     
14
// (at your option) any later version.                                      
15
//                                                                          
16
// This source file is distributed in the hope that it will be useful,      
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
19
// GNU General Public License for more details.                             
20
//                                                                          
21
// You should have received a copy of the GNU General Public License        
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
23
//
24
// ============================================================================
25
//
26
`ifndef TRUE
27
`define TRUE    1'b1
28
`define FALSE   1'b0
29
`endif
30 66 robfinch
`define BYPASS  1'b1
31 60 robfinch
 
32 61 robfinch
module FT64_ipt(rst, clk, pkeys_i, ol_i, bte_i, cti_i, cs_i, icl_i, cyc_i, stb_i, ack_o, we_i, sel_i, vadr_i, dat_i, dat_o,
33
        bte_o, cti_o, cyc_o, ack_i, we_o, sel_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
34 60 robfinch
input rst;
35
input clk;
36
input [63:0] pkeys_i;
37
input [1:0] ol_i;
38 61 robfinch
input [1:0] bte_i;
39 60 robfinch
input [2:0] cti_i;
40
input cs_i;
41
input icl_i;
42
input cyc_i;
43
input stb_i;
44
output reg ack_o;
45
input we_i;
46
input [7:0] sel_i;
47
input [63:0] vadr_i;
48
input [63:0] dat_i;
49
output reg [63:0] dat_o;
50 61 robfinch
output reg [1:0] bte_o;
51
output reg [2:0] cti_o;
52 60 robfinch
output reg cyc_o;
53
input ack_i;
54
output reg we_o;
55 61 robfinch
output reg [7:0] sel_o;
56 60 robfinch
output reg [31:0] padr_o;
57
output reg exv_o;
58
output reg rdv_o;
59
output reg wrv_o;
60
output reg prv_o;
61
output reg page_fault;
62
 
63
parameter S_IDLE = 4'd0;
64
parameter S_CMP1 = 4'd1;
65
parameter S_CMP2 = 4'd2;
66
parameter S_CMP3 = 4'd3;
67
parameter S_CMP4 = 4'd4;
68
parameter S_CMP5 = 4'd5;
69
parameter S_CMP6 = 4'd6;
70
parameter S_WAIT1 = 4'd7;
71
parameter S_ACK = 4'd8;
72 61 robfinch
parameter S_RESET = 4'd9;
73 60 robfinch
 
74
integer n;
75
wire [9:0] pkey [0:5];
76
assign pkey[0] = pkeys_i[9:0];
77
assign pkey[1] = pkeys_i[19:10];
78
assign pkey[2] = pkeys_i[29:20];
79
assign pkey[3] = pkeys_i[39:30];
80
assign pkey[4] = pkeys_i[49:40];
81
assign pkey[5] = pkeys_i[59:50];
82
reg [3:0] state;
83
reg [15:0] pt_ad;
84
reg upd;
85
reg upd_done;
86
reg probe, probe_done;
87
reg pte_last;
88
reg [7:0] pte_asid;
89
reg [3:0] pte_drwx;
90
reg [18:0] pte_vadr;
91
reg [9:0] pte_key;
92
reg pt_wr;
93
reg [41:0] pt_dati;
94
wire [41:0] pt_dat;
95
 
96
FT64_iptram uram1 (
97
  .clka(clk),
98
  .ena(1'b1),
99
  .wea(pt_wr),
100
  .addra(pt_ad),
101
  .dina(pt_dati),
102
  .douta(pt_dat)
103
);
104
 
105
wire pt_last = pt_dat[23];
106
wire [18:0] pt_vadr = pt_dat[22:4];
107
wire [7:0] pt_asid = pt_dat[31:24];
108
wire [3:0] pt_drwx = pt_dat[3:0];
109
wire [9:0] pt_key = pt_dat[41:32];
110
 
111
reg keymatch;
112
always @*
113
begin
114 61 robfinch
keymatch = ol_i==2'b00;
115 60 robfinch
for (n = 0; n < 6; n = n + 1)
116
        if (pt_key==pkey[n] || pt_key==10'h0)
117
                keymatch = 1'b1;
118
end
119
 
120
function [15:0] Hash1;
121
input [39:0] vadr;
122
begin
123
        Hash1 = {1'b0,vadr[37:32],vadr[21:13]};
124
end
125
endfunction
126
 
127
function [15:0] Hash2;
128
input [39:0] vadr;
129
begin
130
        Hash2 = {1'b1,vadr[37:32],vadr[21:13]};
131
end
132
endfunction
133
 
134
always @(posedge clk)
135
        case(vadr_i[5:3])
136
        3'd1:
137
                dat_o <= pt_ad;
138
        3'd2:
139
                begin
140
                        dat_o[41:32] <= pte_key;
141
                        dat_o[31:24] <= pte_asid;
142
                        dat_o[23] <= pte_last;
143
                        dat_o[2:0] <= pte_drwx[2:0];
144
                        dat_o[7] <= pte_drwx[3];
145
                end
146
        3'd3:
147
                dat_o <= pte_vadr;
148
        default:        dat_o <= 1'b0;
149
        endcase
150
 
151
always @(posedge clk)
152 61 robfinch
        bte_o <= bte_i;
153
always @(posedge clk)
154
        cti_o <= cti_i;
155
always @(posedge clk)
156
        sel_o <= sel_i;
157
`ifdef BYPASS
158
always @(posedge clk)
159 66 robfinch
        pt_wr <= 1'b0;
160
always @(posedge clk)
161
        pt_ad <= 16'h0;
162
always @(posedge clk)
163
        pt_dati <= 42'h0;
164
always @(posedge clk)
165 61 robfinch
        cyc_o <= cyc_i;
166
always @(posedge clk)
167
        we_o <= we_i;
168
always @(posedge clk)
169
        padr_o <= vadr_i[31:0];
170
always @(posedge clk)
171
        exv_o <= 1'b0;
172
always @(posedge clk)
173
        rdv_o <= 1'b0;
174
always @(posedge clk)
175
        wrv_o <= 1'b0;
176
always @(posedge clk)
177
        prv_o <= 1'b0;
178
always @(posedge clk)
179
        page_fault <= 1'b0;
180 66 robfinch
always @(posedge clk)
181
        ack_o <= 1'b0;
182 61 robfinch
`else
183
always @(posedge clk)
184 60 robfinch
if (rst) begin
185
        cyc_o <= 1'b0;
186
        padr_o <= 32'hFFFC0100;
187
        ack_o <= 1'b0;
188
        exv_o <= 1'b0;
189
        rdv_o <= 1'b0;
190
        wrv_o <= 1'b0;
191
        prv_o <= 1'b0;
192 61 robfinch
        pt_wr <= 1'b1;
193
        pt_ad <= 1'b0;
194
        pt_dati <= 1'b0;
195 60 robfinch
        upd <= 1'b0;
196
        probe <= 1'b0;
197
        upd_done <= 1'b0;
198
        probe_done <= 1'b0;
199
        goto(S_IDLE);
200
end
201
else begin
202
        pt_wr <= 1'b0;
203
        page_fault <= 1'b0;
204
        ack_o <= 1'b0;
205
case(state)
206 61 robfinch
// Clear page table ram on reset.
207
S_RESET:
208
        begin
209
                pt_ad <= pt_ad + 2'd1;
210
                if (&pt_ad) begin
211
                        pt_wr <= 1'b0;
212
                        state <= S_IDLE;
213
                end
214
        end
215 60 robfinch
S_IDLE:
216
        if (cyc_i) begin
217 61 robfinch
                if (cs_i & stb_i) begin
218 60 robfinch
                        ack_o <= 1'b1;
219
                        case(vadr_i[5:3])
220
                        3'd0:
221
                                begin
222
                                        if (dat_i[0] & !upd_done) begin
223
                                                pt_ad <= Hash1({pte_asid,pte_vadr});
224
                                                upd <= 1'b1;
225
                                                goto(S_CMP1);
226
                                        end
227
                                        else if (dat_i[1] & !probe_done) begin
228
                                                pt_ad <= Hash1({pte_asid,pte_vadr});
229
                                                probe <= 1'b1;
230
                                                goto(S_CMP1);
231
                                        end
232
                                end
233
                        3'd2:
234
                                begin
235
                                        pte_key  <= dat_i[41:32];
236
                                        pte_asid <= dat_i[31:24];
237
                                        pte_last <= dat_i[22];
238
                                        pte_drwx <= {dat_i[7],dat_i[2:0]};
239
                                end
240
                        3'd3:
241
                                begin
242
                                        pte_vadr <= dat_i[18:0];
243
                                end
244
                        endcase
245
                end
246
                else begin
247
                        upd_done <= 1'b0;
248
                        probe_done <= 1'b0;
249
                        upd <= 1'b0;
250
                        probe <= 1'b0;
251
                        if (ol_i==2'b0) begin
252
                                cyc_o <= 1'b1;
253
                                we_o <= we_i;
254 61 robfinch
                                padr_o <= vadr_i[31:0];
255 60 robfinch
                                goto(S_ACK);
256
                        end
257
                        else begin
258
                                // Video frame buffer ($00xxxxxx) and ROM / IO ($FFxxxxxx) regions are
259
                                // not mapped.
260
                                if (vadr_i[31:24]==8'hFF || vadr_i[31:24]==8'h00) begin
261
                                        cyc_o <= 1'b1;
262
                                        we_o <= we_i;
263 61 robfinch
                                        padr_o <= vadr_i[31:0];
264 60 robfinch
                                        goto(S_ACK);
265
                                end
266
                                else begin
267
                                        pt_ad <= Hash1({vadr_i[63:56],vadr_i});
268
                                        goto(S_CMP1);
269
                                end
270
                        end
271
                end
272
        end
273
        else begin
274
                exv_o <= 1'b0;
275
                rdv_o <= 1'b0;
276
                wrv_o <= 1'b0;
277
                prv_o <= 1'b0;
278
        end
279
 
280
S_CMP1:
281
        goto(S_CMP2);
282
S_CMP2:
283
        goto(S_CMP3);
284
S_CMP3:
285
        if (pt_drwx[2:0]==3'b0) begin
286
                if (upd) begin
287
                        pte_key  <= 10'h0;
288
                        pte_last <= 1'b0;
289
                        pte_drwx <= 4'd0;
290
                        pt_wr <= 1'b1;
291
                        pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
292
                        upd_done <= 1'b1;
293
                        goto(S_IDLE);
294
                end
295
                else if (probe) begin
296
                        pte_drwx <= 3'b0;
297
                        pte_vadr <= 19'b0;
298
                        pte_asid <= 8'b0;
299
                        pte_last <= 1'b0;
300
                        pte_key  <= 10'h0;
301
                        probe_done <= 1'b1;
302
                        goto(S_IDLE);
303
                end
304
                else begin
305
                        page_fault <= 1'b1;
306
                        goto(S_WAIT1);
307
                end
308
        end
309
        else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
310
                if (upd) begin
311
                        if (keymatch) begin
312
                                pte_key  <= pt_key;
313
                                pte_last <= pt_last;
314
                                pte_drwx <= pt_drwx;
315
                                pt_wr <= 1'b1;
316
                                pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
317
                        end
318
                        else
319
                                prv_o <= 1'b1;
320
                        upd_done <= 1'b1;
321
                        goto(S_IDLE);
322
                end
323
                else if (probe) begin
324
                        if (keymatch) begin
325
                                pte_key  <= pt_key;
326
                                pte_last <= pt_last;
327
                                pte_drwx <= pt_drwx;
328
                        end
329
                        else
330
                                prv_o <= 1'b1;
331
                        probe_done <= 1'b1;
332
                        goto(S_IDLE);
333
                end
334
                else if (~ack_i) begin
335
                        if (keymatch) begin
336
                                cyc_o <= 1'b1;
337
                                we_o <= we_i & pt_drwx[1];
338
                                if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
339
                                if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
340
                                if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
341
                                padr_o <= {pt_ad,vadr_i[12:0]};
342
                        end
343
                        else begin
344
                                cyc_o <= 1'b1;
345
                                we_o <= 1'b0;
346 61 robfinch
                                padr_o <= 32'hFFFFFFF8;
347 60 robfinch
                                prv_o <= 1'b1;
348
                        end
349
                        goto(S_ACK);
350
                end
351
        end
352
        else begin
353
                if (upd|probe)
354
                        pt_ad <= Hash2({pte_asid,pte_vadr});
355
                else
356
                        pt_ad <= Hash2({vadr_i[63:56],vadr_i});
357
                goto(S_CMP4);
358
        end
359
 
360
S_CMP4:
361
        goto(S_CMP5);
362
S_CMP5:
363
        goto(S_CMP6);
364
S_CMP6:
365
        if (pt_drwx[2:0]==3'b0) begin
366
                if (upd) begin
367
                        pte_key  <= 10'h0;
368
                        pte_last <= 1'b0;
369
                        pte_drwx <= 4'd0;
370
                        pt_wr <= 1'b1;
371
                        pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
372
                        upd_done <= 1'b1;
373
                        goto(S_IDLE);
374
                end
375
                else if (probe) begin
376
                        pte_key  <= 10'h0;
377
                        pte_drwx <= 43'b0;
378
                        pte_vadr <= 19'b0;
379
                        pte_asid <= 8'b0;
380
                        pte_last <= 1'b0;
381
                        probe_done <= 1'b1;
382
                        goto(S_IDLE);
383
                end
384
                else begin
385
                        page_fault <= 1'b1;
386
                        goto(S_WAIT1);
387
                end
388
        end
389
        else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
390
                if (upd) begin
391
                        if (keymatch) begin
392
                                pte_key  <= pt_key;
393
                                pte_last <= pt_last;
394
                                pte_drwx <= pt_drwx;
395
                                pt_wr <= 1'b1;
396
                                pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
397
                        end
398
                        else
399
                                prv_o <= 1'b1;
400
                        upd_done <= 1'b1;
401
                        goto(S_IDLE);
402
                end
403
                else if (probe) begin
404
                        if (keymatch) begin
405
                                pte_key  <= pt_key;
406
                                pte_last <= pt_last;
407
                                pte_drwx <= pt_drwx;
408
                                probe_done <= 1'b1;
409
                        end
410
                        else
411
                                prv_o <= 1'b1;
412
                        goto(S_IDLE);
413
                end
414
                else if (~ack_i) begin
415
                        if (keymatch) begin
416
                                cyc_o <= 1'b1;
417
                                we_o <= we_i & pt_drwx[1];
418
                                if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
419
                                if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
420
                                if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
421
                                padr_o <= {pt_ad,vadr_i[12:0]};
422
                        end
423
                        else begin
424
                                cyc_o <= 1'b1;
425
                                we_o <= 1'b0;
426 61 robfinch
                                padr_o <= 32'hFFFFFFF8;
427 60 robfinch
                                prv_o <= 1'b1;
428
                        end
429
                        goto(S_ACK);
430
                end
431
        end
432
        else begin
433
                pt_ad <= {pt_ad+8'd65};
434
                goto(S_CMP4);
435
        end
436
 
437
// Wait a clock cycle for a page fault to register.
438
S_WAIT1:
439 66 robfinch
        if (!ack_i)
440
                goto(S_IDLE);
441 60 robfinch
 
442
S_ACK:
443
        if (ack_i) begin
444
                if (cti_i==3'b000 || cti_i==3'b111) begin
445
                        cyc_o <= 1'b0;
446
                        we_o <= 1'b0;
447
                        goto(S_WAIT1);
448
                end
449
        end
450
 
451
endcase
452
end
453 61 robfinch
`endif
454 60 robfinch
 
455
task goto;
456
input [3:0] nst;
457
begin
458
        state <= nst;
459
end
460
endtask
461
 
462
endmodule
463
 

powered by: WebSVN 2.1.0

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