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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v7/] [rtl/] [common/] [FT64_ipt.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
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2018  Robert Finch, Waterloo
4
//    \  __ /    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
 
31
module FT64_ipt(rst, clk, pkeys_i, ol_i, cti_i, cs_i, icl_i, cyc_i, stb_i, ack_o, we_i, sel_i, vadr_i, dat_i, dat_o,
32
        cyc_o, ack_i, we_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
33
input rst;
34
input clk;
35
input [63:0] pkeys_i;
36
input [1:0] ol_i;
37
input [2:0] cti_i;
38
input cs_i;
39
input icl_i;
40
input cyc_i;
41
input stb_i;
42
output reg ack_o;
43
input we_i;
44
input [7:0] sel_i;
45
input [63:0] vadr_i;
46
input [63:0] dat_i;
47
output reg [63:0] dat_o;
48
output reg cyc_o;
49
input ack_i;
50
output reg we_o;
51
output reg [31:0] padr_o;
52
output reg exv_o;
53
output reg rdv_o;
54
output reg wrv_o;
55
output reg prv_o;
56
output reg page_fault;
57
 
58
parameter S_IDLE = 4'd0;
59
parameter S_CMP1 = 4'd1;
60
parameter S_CMP2 = 4'd2;
61
parameter S_CMP3 = 4'd3;
62
parameter S_CMP4 = 4'd4;
63
parameter S_CMP5 = 4'd5;
64
parameter S_CMP6 = 4'd6;
65
parameter S_WAIT1 = 4'd7;
66
parameter S_ACK = 4'd8;
67
 
68
integer n;
69
wire [9:0] pkey [0:5];
70
assign pkey[0] = pkeys_i[9:0];
71
assign pkey[1] = pkeys_i[19:10];
72
assign pkey[2] = pkeys_i[29:20];
73
assign pkey[3] = pkeys_i[39:30];
74
assign pkey[4] = pkeys_i[49:40];
75
assign pkey[5] = pkeys_i[59:50];
76
reg [3:0] state;
77
reg [15:0] pt_ad;
78
reg upd;
79
reg upd_done;
80
reg probe, probe_done;
81
reg pte_last;
82
reg [7:0] pte_asid;
83
reg [3:0] pte_drwx;
84
reg [18:0] pte_vadr;
85
reg [9:0] pte_key;
86
reg pt_wr;
87
reg [41:0] pt_dati;
88
wire [41:0] pt_dat;
89
 
90
FT64_iptram uram1 (
91
  .clka(clk),
92
  .ena(1'b1),
93
  .wea(pt_wr),
94
  .addra(pt_ad),
95
  .dina(pt_dati),
96
  .douta(pt_dat)
97
);
98
 
99
wire pt_last = pt_dat[23];
100
wire [18:0] pt_vadr = pt_dat[22:4];
101
wire [7:0] pt_asid = pt_dat[31:24];
102
wire [3:0] pt_drwx = pt_dat[3:0];
103
wire [9:0] pt_key = pt_dat[41:32];
104
 
105
reg keymatch;
106
always @*
107
begin
108
keymatch = 1'b0;
109
for (n = 0; n < 6; n = n + 1)
110
        if (pt_key==pkey[n] || pt_key==10'h0)
111
                keymatch = 1'b1;
112
end
113
 
114
function [15:0] Hash1;
115
input [39:0] vadr;
116
begin
117
        Hash1 = {1'b0,vadr[37:32],vadr[21:13]};
118
end
119
endfunction
120
 
121
function [15:0] Hash2;
122
input [39:0] vadr;
123
begin
124
        Hash2 = {1'b1,vadr[37:32],vadr[21:13]};
125
end
126
endfunction
127
 
128
always @(posedge clk)
129
        case(vadr_i[5:3])
130
        3'd1:
131
                dat_o <= pt_ad;
132
        3'd2:
133
                begin
134
                        dat_o[41:32] <= pte_key;
135
                        dat_o[31:24] <= pte_asid;
136
                        dat_o[23] <= pte_last;
137
                        dat_o[2:0] <= pte_drwx[2:0];
138
                        dat_o[7] <= pte_drwx[3];
139
                end
140
        3'd3:
141
                dat_o <= pte_vadr;
142
        default:        dat_o <= 1'b0;
143
        endcase
144
 
145
always @(posedge clk)
146
if (rst) begin
147
        cyc_o <= 1'b0;
148
        padr_o <= 32'hFFFC0100;
149
        ack_o <= 1'b0;
150
        exv_o <= 1'b0;
151
        rdv_o <= 1'b0;
152
        wrv_o <= 1'b0;
153
        prv_o <= 1'b0;
154
        pt_wr <= 1'b0;
155
        upd <= 1'b0;
156
        probe <= 1'b0;
157
        upd_done <= 1'b0;
158
        probe_done <= 1'b0;
159
        goto(S_IDLE);
160
end
161
else begin
162
        pt_wr <= 1'b0;
163
        page_fault <= 1'b0;
164
        ack_o <= 1'b0;
165
case(state)
166
S_IDLE:
167
        if (cyc_i) begin
168
                if (cs_i) begin
169
                        ack_o <= 1'b1;
170
                        case(vadr_i[5:3])
171
                        3'd0:
172
                                begin
173
                                        if (dat_i[0] & !upd_done) begin
174
                                                pt_ad <= Hash1({pte_asid,pte_vadr});
175
                                                upd <= 1'b1;
176
                                                goto(S_CMP1);
177
                                        end
178
                                        else if (dat_i[1] & !probe_done) begin
179
                                                pt_ad <= Hash1({pte_asid,pte_vadr});
180
                                                probe <= 1'b1;
181
                                                goto(S_CMP1);
182
                                        end
183
                                end
184
                        3'd2:
185
                                begin
186
                                        pte_key  <= dat_i[41:32];
187
                                        pte_asid <= dat_i[31:24];
188
                                        pte_last <= dat_i[22];
189
                                        pte_drwx <= {dat_i[7],dat_i[2:0]};
190
                                end
191
                        3'd3:
192
                                begin
193
                                        pte_vadr <= dat_i[18:0];
194
                                end
195
                        endcase
196
                end
197
                else begin
198
                        upd_done <= 1'b0;
199
                        probe_done <= 1'b0;
200
                        upd <= 1'b0;
201
                        probe <= 1'b0;
202
                        if (ol_i==2'b0) begin
203
                                cyc_o <= 1'b1;
204
                                we_o <= we_i;
205
                                padr_o <= vadr_i;
206
                                goto(S_ACK);
207
                        end
208
                        else begin
209
                                // Video frame buffer ($00xxxxxx) and ROM / IO ($FFxxxxxx) regions are
210
                                // not mapped.
211
                                if (vadr_i[31:24]==8'hFF || vadr_i[31:24]==8'h00) begin
212
                                        cyc_o <= 1'b1;
213
                                        we_o <= we_i;
214
                                        padr_o <= vadr_i;
215
                                        goto(S_ACK);
216
                                end
217
                                else begin
218
                                        pt_ad <= Hash1({vadr_i[63:56],vadr_i});
219
                                        goto(S_CMP1);
220
                                end
221
                        end
222
                end
223
        end
224
        else begin
225
                exv_o <= 1'b0;
226
                rdv_o <= 1'b0;
227
                wrv_o <= 1'b0;
228
                prv_o <= 1'b0;
229
        end
230
 
231
S_CMP1:
232
        goto(S_CMP2);
233
S_CMP2:
234
        goto(S_CMP3);
235
S_CMP3:
236
        if (pt_drwx[2:0]==3'b0) begin
237
                if (upd) begin
238
                        pte_key  <= 10'h0;
239
                        pte_last <= 1'b0;
240
                        pte_drwx <= 4'd0;
241
                        pt_wr <= 1'b1;
242
                        pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
243
                        upd_done <= 1'b1;
244
                        goto(S_IDLE);
245
                end
246
                else if (probe) begin
247
                        pte_drwx <= 3'b0;
248
                        pte_vadr <= 19'b0;
249
                        pte_asid <= 8'b0;
250
                        pte_last <= 1'b0;
251
                        pte_key  <= 10'h0;
252
                        probe_done <= 1'b1;
253
                        goto(S_IDLE);
254
                end
255
                else begin
256
                        page_fault <= 1'b1;
257
                        goto(S_WAIT1);
258
                end
259
        end
260
        else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
261
                if (upd) begin
262
                        if (keymatch) begin
263
                                pte_key  <= pt_key;
264
                                pte_last <= pt_last;
265
                                pte_drwx <= pt_drwx;
266
                                pt_wr <= 1'b1;
267
                                pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
268
                        end
269
                        else
270
                                prv_o <= 1'b1;
271
                        upd_done <= 1'b1;
272
                        goto(S_IDLE);
273
                end
274
                else if (probe) begin
275
                        if (keymatch) begin
276
                                pte_key  <= pt_key;
277
                                pte_last <= pt_last;
278
                                pte_drwx <= pt_drwx;
279
                        end
280
                        else
281
                                prv_o <= 1'b1;
282
                        probe_done <= 1'b1;
283
                        goto(S_IDLE);
284
                end
285
                else if (~ack_i) begin
286
                        if (keymatch) begin
287
                                cyc_o <= 1'b1;
288
                                we_o <= we_i & pt_drwx[1];
289
                                if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
290
                                if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
291
                                if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
292
                                padr_o <= {pt_ad,vadr_i[12:0]};
293
                        end
294
                        else begin
295
                                cyc_o <= 1'b1;
296
                                we_o <= 1'b0;
297
                                padr_o <= 64'hFFFFFFFFFFFFFFF8;
298
                                prv_o <= 1'b1;
299
                        end
300
                        goto(S_ACK);
301
                end
302
        end
303
        else begin
304
                if (upd|probe)
305
                        pt_ad <= Hash2({pte_asid,pte_vadr});
306
                else
307
                        pt_ad <= Hash2({vadr_i[63:56],vadr_i});
308
                goto(S_CMP4);
309
        end
310
 
311
S_CMP4:
312
        goto(S_CMP5);
313
S_CMP5:
314
        goto(S_CMP6);
315
S_CMP6:
316
        if (pt_drwx[2:0]==3'b0) begin
317
                if (upd) begin
318
                        pte_key  <= 10'h0;
319
                        pte_last <= 1'b0;
320
                        pte_drwx <= 4'd0;
321
                        pt_wr <= 1'b1;
322
                        pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
323
                        upd_done <= 1'b1;
324
                        goto(S_IDLE);
325
                end
326
                else if (probe) begin
327
                        pte_key  <= 10'h0;
328
                        pte_drwx <= 43'b0;
329
                        pte_vadr <= 19'b0;
330
                        pte_asid <= 8'b0;
331
                        pte_last <= 1'b0;
332
                        probe_done <= 1'b1;
333
                        goto(S_IDLE);
334
                end
335
                else begin
336
                        page_fault <= 1'b1;
337
                        goto(S_WAIT1);
338
                end
339
        end
340
        else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
341
                if (upd) begin
342
                        if (keymatch) begin
343
                                pte_key  <= pt_key;
344
                                pte_last <= pt_last;
345
                                pte_drwx <= pt_drwx;
346
                                pt_wr <= 1'b1;
347
                                pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
348
                        end
349
                        else
350
                                prv_o <= 1'b1;
351
                        upd_done <= 1'b1;
352
                        goto(S_IDLE);
353
                end
354
                else if (probe) begin
355
                        if (keymatch) begin
356
                                pte_key  <= pt_key;
357
                                pte_last <= pt_last;
358
                                pte_drwx <= pt_drwx;
359
                                probe_done <= 1'b1;
360
                        end
361
                        else
362
                                prv_o <= 1'b1;
363
                        goto(S_IDLE);
364
                end
365
                else if (~ack_i) begin
366
                        if (keymatch) begin
367
                                cyc_o <= 1'b1;
368
                                we_o <= we_i & pt_drwx[1];
369
                                if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
370
                                if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
371
                                if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
372
                                padr_o <= {pt_ad,vadr_i[12:0]};
373
                        end
374
                        else begin
375
                                cyc_o <= 1'b1;
376
                                we_o <= 1'b0;
377
                                padr_o <= 64'hFFFFFFFFFFFFFFF8;
378
                                prv_o <= 1'b1;
379
                        end
380
                        goto(S_ACK);
381
                end
382
        end
383
        else begin
384
                pt_ad <= {pt_ad+8'd65};
385
                goto(S_CMP4);
386
        end
387
 
388
// Wait a clock cycle for a page fault to register.
389
S_WAIT1:
390
        goto(S_IDLE);
391
 
392
S_ACK:
393
        if (ack_i) begin
394
                if (cti_i==3'b000 || cti_i==3'b111) begin
395
                        cyc_o <= 1'b0;
396
                        we_o <= 1'b0;
397
                        goto(S_WAIT1);
398
                end
399
        end
400
 
401
endcase
402
end
403
 
404
task goto;
405
input [3:0] nst;
406
begin
407
        state <= nst;
408
end
409
endtask
410
 
411
endmodule
412
 

powered by: WebSVN 2.1.0

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