// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
|
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// FT64_ipt.v
|
// FT64_ipt.v
|
// - 64 bit CPU inverted page table memory management unit
|
// - 64 bit CPU inverted page table memory management unit
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
// it under the terms of the GNU Lesser General Public License as published
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// This source file is distributed in the hope that it will be useful,
|
// This source file is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
`ifndef TRUE
|
`ifndef TRUE
|
`define TRUE 1'b1
|
`define TRUE 1'b1
|
`define FALSE 1'b0
|
`define FALSE 1'b0
|
`endif
|
`endif
|
//`define BYPASS 1'b1
|
`define BYPASS 1'b1
|
|
|
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,
|
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,
|
bte_o, cti_o, cyc_o, ack_i, we_o, sel_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
|
bte_o, cti_o, cyc_o, ack_i, we_o, sel_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
|
input rst;
|
input rst;
|
input clk;
|
input clk;
|
input [63:0] pkeys_i;
|
input [63:0] pkeys_i;
|
input [1:0] ol_i;
|
input [1:0] ol_i;
|
input [1:0] bte_i;
|
input [1:0] bte_i;
|
input [2:0] cti_i;
|
input [2:0] cti_i;
|
input cs_i;
|
input cs_i;
|
input icl_i;
|
input icl_i;
|
input cyc_i;
|
input cyc_i;
|
input stb_i;
|
input stb_i;
|
output reg ack_o;
|
output reg ack_o;
|
input we_i;
|
input we_i;
|
input [7:0] sel_i;
|
input [7:0] sel_i;
|
input [63:0] vadr_i;
|
input [63:0] vadr_i;
|
input [63:0] dat_i;
|
input [63:0] dat_i;
|
output reg [63:0] dat_o;
|
output reg [63:0] dat_o;
|
output reg [1:0] bte_o;
|
output reg [1:0] bte_o;
|
output reg [2:0] cti_o;
|
output reg [2:0] cti_o;
|
output reg cyc_o;
|
output reg cyc_o;
|
input ack_i;
|
input ack_i;
|
output reg we_o;
|
output reg we_o;
|
output reg [7:0] sel_o;
|
output reg [7:0] sel_o;
|
output reg [31:0] padr_o;
|
output reg [31:0] padr_o;
|
output reg exv_o;
|
output reg exv_o;
|
output reg rdv_o;
|
output reg rdv_o;
|
output reg wrv_o;
|
output reg wrv_o;
|
output reg prv_o;
|
output reg prv_o;
|
output reg page_fault;
|
output reg page_fault;
|
|
|
parameter S_IDLE = 4'd0;
|
parameter S_IDLE = 4'd0;
|
parameter S_CMP1 = 4'd1;
|
parameter S_CMP1 = 4'd1;
|
parameter S_CMP2 = 4'd2;
|
parameter S_CMP2 = 4'd2;
|
parameter S_CMP3 = 4'd3;
|
parameter S_CMP3 = 4'd3;
|
parameter S_CMP4 = 4'd4;
|
parameter S_CMP4 = 4'd4;
|
parameter S_CMP5 = 4'd5;
|
parameter S_CMP5 = 4'd5;
|
parameter S_CMP6 = 4'd6;
|
parameter S_CMP6 = 4'd6;
|
parameter S_WAIT1 = 4'd7;
|
parameter S_WAIT1 = 4'd7;
|
parameter S_ACK = 4'd8;
|
parameter S_ACK = 4'd8;
|
parameter S_RESET = 4'd9;
|
parameter S_RESET = 4'd9;
|
|
|
integer n;
|
integer n;
|
wire [9:0] pkey [0:5];
|
wire [9:0] pkey [0:5];
|
assign pkey[0] = pkeys_i[9:0];
|
assign pkey[0] = pkeys_i[9:0];
|
assign pkey[1] = pkeys_i[19:10];
|
assign pkey[1] = pkeys_i[19:10];
|
assign pkey[2] = pkeys_i[29:20];
|
assign pkey[2] = pkeys_i[29:20];
|
assign pkey[3] = pkeys_i[39:30];
|
assign pkey[3] = pkeys_i[39:30];
|
assign pkey[4] = pkeys_i[49:40];
|
assign pkey[4] = pkeys_i[49:40];
|
assign pkey[5] = pkeys_i[59:50];
|
assign pkey[5] = pkeys_i[59:50];
|
reg [3:0] state;
|
reg [3:0] state;
|
reg [15:0] pt_ad;
|
reg [15:0] pt_ad;
|
reg upd;
|
reg upd;
|
reg upd_done;
|
reg upd_done;
|
reg probe, probe_done;
|
reg probe, probe_done;
|
reg pte_last;
|
reg pte_last;
|
reg [7:0] pte_asid;
|
reg [7:0] pte_asid;
|
reg [3:0] pte_drwx;
|
reg [3:0] pte_drwx;
|
reg [18:0] pte_vadr;
|
reg [18:0] pte_vadr;
|
reg [9:0] pte_key;
|
reg [9:0] pte_key;
|
reg pt_wr;
|
reg pt_wr;
|
reg [41:0] pt_dati;
|
reg [41:0] pt_dati;
|
wire [41:0] pt_dat;
|
wire [41:0] pt_dat;
|
|
|
FT64_iptram uram1 (
|
FT64_iptram uram1 (
|
.clka(clk),
|
.clka(clk),
|
.ena(1'b1),
|
.ena(1'b1),
|
.wea(pt_wr),
|
.wea(pt_wr),
|
.addra(pt_ad),
|
.addra(pt_ad),
|
.dina(pt_dati),
|
.dina(pt_dati),
|
.douta(pt_dat)
|
.douta(pt_dat)
|
);
|
);
|
|
|
wire pt_last = pt_dat[23];
|
wire pt_last = pt_dat[23];
|
wire [18:0] pt_vadr = pt_dat[22:4];
|
wire [18:0] pt_vadr = pt_dat[22:4];
|
wire [7:0] pt_asid = pt_dat[31:24];
|
wire [7:0] pt_asid = pt_dat[31:24];
|
wire [3:0] pt_drwx = pt_dat[3:0];
|
wire [3:0] pt_drwx = pt_dat[3:0];
|
wire [9:0] pt_key = pt_dat[41:32];
|
wire [9:0] pt_key = pt_dat[41:32];
|
|
|
reg keymatch;
|
reg keymatch;
|
always @*
|
always @*
|
begin
|
begin
|
keymatch = ol_i==2'b00;
|
keymatch = ol_i==2'b00;
|
for (n = 0; n < 6; n = n + 1)
|
for (n = 0; n < 6; n = n + 1)
|
if (pt_key==pkey[n] || pt_key==10'h0)
|
if (pt_key==pkey[n] || pt_key==10'h0)
|
keymatch = 1'b1;
|
keymatch = 1'b1;
|
end
|
end
|
|
|
function [15:0] Hash1;
|
function [15:0] Hash1;
|
input [39:0] vadr;
|
input [39:0] vadr;
|
begin
|
begin
|
Hash1 = {1'b0,vadr[37:32],vadr[21:13]};
|
Hash1 = {1'b0,vadr[37:32],vadr[21:13]};
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [15:0] Hash2;
|
function [15:0] Hash2;
|
input [39:0] vadr;
|
input [39:0] vadr;
|
begin
|
begin
|
Hash2 = {1'b1,vadr[37:32],vadr[21:13]};
|
Hash2 = {1'b1,vadr[37:32],vadr[21:13]};
|
end
|
end
|
endfunction
|
endfunction
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
case(vadr_i[5:3])
|
case(vadr_i[5:3])
|
3'd1:
|
3'd1:
|
dat_o <= pt_ad;
|
dat_o <= pt_ad;
|
3'd2:
|
3'd2:
|
begin
|
begin
|
dat_o[41:32] <= pte_key;
|
dat_o[41:32] <= pte_key;
|
dat_o[31:24] <= pte_asid;
|
dat_o[31:24] <= pte_asid;
|
dat_o[23] <= pte_last;
|
dat_o[23] <= pte_last;
|
dat_o[2:0] <= pte_drwx[2:0];
|
dat_o[2:0] <= pte_drwx[2:0];
|
dat_o[7] <= pte_drwx[3];
|
dat_o[7] <= pte_drwx[3];
|
end
|
end
|
3'd3:
|
3'd3:
|
dat_o <= pte_vadr;
|
dat_o <= pte_vadr;
|
default: dat_o <= 1'b0;
|
default: dat_o <= 1'b0;
|
endcase
|
endcase
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
bte_o <= bte_i;
|
bte_o <= bte_i;
|
always @(posedge clk)
|
always @(posedge clk)
|
cti_o <= cti_i;
|
cti_o <= cti_i;
|
always @(posedge clk)
|
always @(posedge clk)
|
sel_o <= sel_i;
|
sel_o <= sel_i;
|
`ifdef BYPASS
|
`ifdef BYPASS
|
always @(posedge clk)
|
always @(posedge clk)
|
|
pt_wr <= 1'b0;
|
|
always @(posedge clk)
|
|
pt_ad <= 16'h0;
|
|
always @(posedge clk)
|
|
pt_dati <= 42'h0;
|
|
always @(posedge clk)
|
cyc_o <= cyc_i;
|
cyc_o <= cyc_i;
|
always @(posedge clk)
|
always @(posedge clk)
|
we_o <= we_i;
|
we_o <= we_i;
|
always @(posedge clk)
|
always @(posedge clk)
|
padr_o <= vadr_i[31:0];
|
padr_o <= vadr_i[31:0];
|
always @(posedge clk)
|
always @(posedge clk)
|
exv_o <= 1'b0;
|
exv_o <= 1'b0;
|
always @(posedge clk)
|
always @(posedge clk)
|
rdv_o <= 1'b0;
|
rdv_o <= 1'b0;
|
always @(posedge clk)
|
always @(posedge clk)
|
wrv_o <= 1'b0;
|
wrv_o <= 1'b0;
|
always @(posedge clk)
|
always @(posedge clk)
|
prv_o <= 1'b0;
|
prv_o <= 1'b0;
|
always @(posedge clk)
|
always @(posedge clk)
|
page_fault <= 1'b0;
|
page_fault <= 1'b0;
|
|
always @(posedge clk)
|
|
ack_o <= 1'b0;
|
`else
|
`else
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst) begin
|
if (rst) begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
padr_o <= 32'hFFFC0100;
|
padr_o <= 32'hFFFC0100;
|
ack_o <= 1'b0;
|
ack_o <= 1'b0;
|
exv_o <= 1'b0;
|
exv_o <= 1'b0;
|
rdv_o <= 1'b0;
|
rdv_o <= 1'b0;
|
wrv_o <= 1'b0;
|
wrv_o <= 1'b0;
|
prv_o <= 1'b0;
|
prv_o <= 1'b0;
|
pt_wr <= 1'b1;
|
pt_wr <= 1'b1;
|
pt_ad <= 1'b0;
|
pt_ad <= 1'b0;
|
pt_dati <= 1'b0;
|
pt_dati <= 1'b0;
|
upd <= 1'b0;
|
upd <= 1'b0;
|
probe <= 1'b0;
|
probe <= 1'b0;
|
upd_done <= 1'b0;
|
upd_done <= 1'b0;
|
probe_done <= 1'b0;
|
probe_done <= 1'b0;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else begin
|
else begin
|
pt_wr <= 1'b0;
|
pt_wr <= 1'b0;
|
page_fault <= 1'b0;
|
page_fault <= 1'b0;
|
ack_o <= 1'b0;
|
ack_o <= 1'b0;
|
case(state)
|
case(state)
|
// Clear page table ram on reset.
|
// Clear page table ram on reset.
|
S_RESET:
|
S_RESET:
|
begin
|
begin
|
pt_ad <= pt_ad + 2'd1;
|
pt_ad <= pt_ad + 2'd1;
|
if (&pt_ad) begin
|
if (&pt_ad) begin
|
pt_wr <= 1'b0;
|
pt_wr <= 1'b0;
|
state <= S_IDLE;
|
state <= S_IDLE;
|
end
|
end
|
end
|
end
|
S_IDLE:
|
S_IDLE:
|
if (cyc_i) begin
|
if (cyc_i) begin
|
if (cs_i & stb_i) begin
|
if (cs_i & stb_i) begin
|
ack_o <= 1'b1;
|
ack_o <= 1'b1;
|
case(vadr_i[5:3])
|
case(vadr_i[5:3])
|
3'd0:
|
3'd0:
|
begin
|
begin
|
if (dat_i[0] & !upd_done) begin
|
if (dat_i[0] & !upd_done) begin
|
pt_ad <= Hash1({pte_asid,pte_vadr});
|
pt_ad <= Hash1({pte_asid,pte_vadr});
|
upd <= 1'b1;
|
upd <= 1'b1;
|
goto(S_CMP1);
|
goto(S_CMP1);
|
end
|
end
|
else if (dat_i[1] & !probe_done) begin
|
else if (dat_i[1] & !probe_done) begin
|
pt_ad <= Hash1({pte_asid,pte_vadr});
|
pt_ad <= Hash1({pte_asid,pte_vadr});
|
probe <= 1'b1;
|
probe <= 1'b1;
|
goto(S_CMP1);
|
goto(S_CMP1);
|
end
|
end
|
end
|
end
|
3'd2:
|
3'd2:
|
begin
|
begin
|
pte_key <= dat_i[41:32];
|
pte_key <= dat_i[41:32];
|
pte_asid <= dat_i[31:24];
|
pte_asid <= dat_i[31:24];
|
pte_last <= dat_i[22];
|
pte_last <= dat_i[22];
|
pte_drwx <= {dat_i[7],dat_i[2:0]};
|
pte_drwx <= {dat_i[7],dat_i[2:0]};
|
end
|
end
|
3'd3:
|
3'd3:
|
begin
|
begin
|
pte_vadr <= dat_i[18:0];
|
pte_vadr <= dat_i[18:0];
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
else begin
|
else begin
|
upd_done <= 1'b0;
|
upd_done <= 1'b0;
|
probe_done <= 1'b0;
|
probe_done <= 1'b0;
|
upd <= 1'b0;
|
upd <= 1'b0;
|
probe <= 1'b0;
|
probe <= 1'b0;
|
if (ol_i==2'b0) begin
|
if (ol_i==2'b0) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= we_i;
|
we_o <= we_i;
|
padr_o <= vadr_i[31:0];
|
padr_o <= vadr_i[31:0];
|
goto(S_ACK);
|
goto(S_ACK);
|
end
|
end
|
else begin
|
else begin
|
// Video frame buffer ($00xxxxxx) and ROM / IO ($FFxxxxxx) regions are
|
// Video frame buffer ($00xxxxxx) and ROM / IO ($FFxxxxxx) regions are
|
// not mapped.
|
// not mapped.
|
if (vadr_i[31:24]==8'hFF || vadr_i[31:24]==8'h00) begin
|
if (vadr_i[31:24]==8'hFF || vadr_i[31:24]==8'h00) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= we_i;
|
we_o <= we_i;
|
padr_o <= vadr_i[31:0];
|
padr_o <= vadr_i[31:0];
|
goto(S_ACK);
|
goto(S_ACK);
|
end
|
end
|
else begin
|
else begin
|
pt_ad <= Hash1({vadr_i[63:56],vadr_i});
|
pt_ad <= Hash1({vadr_i[63:56],vadr_i});
|
goto(S_CMP1);
|
goto(S_CMP1);
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
exv_o <= 1'b0;
|
exv_o <= 1'b0;
|
rdv_o <= 1'b0;
|
rdv_o <= 1'b0;
|
wrv_o <= 1'b0;
|
wrv_o <= 1'b0;
|
prv_o <= 1'b0;
|
prv_o <= 1'b0;
|
end
|
end
|
|
|
S_CMP1:
|
S_CMP1:
|
goto(S_CMP2);
|
goto(S_CMP2);
|
S_CMP2:
|
S_CMP2:
|
goto(S_CMP3);
|
goto(S_CMP3);
|
S_CMP3:
|
S_CMP3:
|
if (pt_drwx[2:0]==3'b0) begin
|
if (pt_drwx[2:0]==3'b0) begin
|
if (upd) begin
|
if (upd) begin
|
pte_key <= 10'h0;
|
pte_key <= 10'h0;
|
pte_last <= 1'b0;
|
pte_last <= 1'b0;
|
pte_drwx <= 4'd0;
|
pte_drwx <= 4'd0;
|
pt_wr <= 1'b1;
|
pt_wr <= 1'b1;
|
pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
|
pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
|
upd_done <= 1'b1;
|
upd_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (probe) begin
|
else if (probe) begin
|
pte_drwx <= 3'b0;
|
pte_drwx <= 3'b0;
|
pte_vadr <= 19'b0;
|
pte_vadr <= 19'b0;
|
pte_asid <= 8'b0;
|
pte_asid <= 8'b0;
|
pte_last <= 1'b0;
|
pte_last <= 1'b0;
|
pte_key <= 10'h0;
|
pte_key <= 10'h0;
|
probe_done <= 1'b1;
|
probe_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else begin
|
else begin
|
page_fault <= 1'b1;
|
page_fault <= 1'b1;
|
goto(S_WAIT1);
|
goto(S_WAIT1);
|
end
|
end
|
end
|
end
|
else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
|
else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
|
if (upd) begin
|
if (upd) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
pte_key <= pt_key;
|
pte_key <= pt_key;
|
pte_last <= pt_last;
|
pte_last <= pt_last;
|
pte_drwx <= pt_drwx;
|
pte_drwx <= pt_drwx;
|
pt_wr <= 1'b1;
|
pt_wr <= 1'b1;
|
pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
|
pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
|
end
|
end
|
else
|
else
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
upd_done <= 1'b1;
|
upd_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (probe) begin
|
else if (probe) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
pte_key <= pt_key;
|
pte_key <= pt_key;
|
pte_last <= pt_last;
|
pte_last <= pt_last;
|
pte_drwx <= pt_drwx;
|
pte_drwx <= pt_drwx;
|
end
|
end
|
else
|
else
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
probe_done <= 1'b1;
|
probe_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (~ack_i) begin
|
else if (~ack_i) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= we_i & pt_drwx[1];
|
we_o <= we_i & pt_drwx[1];
|
if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
|
if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
|
if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
|
if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
|
if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
|
if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
|
padr_o <= {pt_ad,vadr_i[12:0]};
|
padr_o <= {pt_ad,vadr_i[12:0]};
|
end
|
end
|
else begin
|
else begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
padr_o <= 32'hFFFFFFF8;
|
padr_o <= 32'hFFFFFFF8;
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
end
|
end
|
goto(S_ACK);
|
goto(S_ACK);
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (upd|probe)
|
if (upd|probe)
|
pt_ad <= Hash2({pte_asid,pte_vadr});
|
pt_ad <= Hash2({pte_asid,pte_vadr});
|
else
|
else
|
pt_ad <= Hash2({vadr_i[63:56],vadr_i});
|
pt_ad <= Hash2({vadr_i[63:56],vadr_i});
|
goto(S_CMP4);
|
goto(S_CMP4);
|
end
|
end
|
|
|
S_CMP4:
|
S_CMP4:
|
goto(S_CMP5);
|
goto(S_CMP5);
|
S_CMP5:
|
S_CMP5:
|
goto(S_CMP6);
|
goto(S_CMP6);
|
S_CMP6:
|
S_CMP6:
|
if (pt_drwx[2:0]==3'b0) begin
|
if (pt_drwx[2:0]==3'b0) begin
|
if (upd) begin
|
if (upd) begin
|
pte_key <= 10'h0;
|
pte_key <= 10'h0;
|
pte_last <= 1'b0;
|
pte_last <= 1'b0;
|
pte_drwx <= 4'd0;
|
pte_drwx <= 4'd0;
|
pt_wr <= 1'b1;
|
pt_wr <= 1'b1;
|
pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
|
pt_dati <= {pte_key,pte_asid,pte_last,pte_vadr[18:0],pte_drwx};
|
upd_done <= 1'b1;
|
upd_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (probe) begin
|
else if (probe) begin
|
pte_key <= 10'h0;
|
pte_key <= 10'h0;
|
pte_drwx <= 43'b0;
|
pte_drwx <= 43'b0;
|
pte_vadr <= 19'b0;
|
pte_vadr <= 19'b0;
|
pte_asid <= 8'b0;
|
pte_asid <= 8'b0;
|
pte_last <= 1'b0;
|
pte_last <= 1'b0;
|
probe_done <= 1'b1;
|
probe_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else begin
|
else begin
|
page_fault <= 1'b1;
|
page_fault <= 1'b1;
|
goto(S_WAIT1);
|
goto(S_WAIT1);
|
end
|
end
|
end
|
end
|
else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
|
else if (pt_asid==vadr_i[63:56] && pt_vadr==vadr_i[31:13]) begin
|
if (upd) begin
|
if (upd) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
pte_key <= pt_key;
|
pte_key <= pt_key;
|
pte_last <= pt_last;
|
pte_last <= pt_last;
|
pte_drwx <= pt_drwx;
|
pte_drwx <= pt_drwx;
|
pt_wr <= 1'b1;
|
pt_wr <= 1'b1;
|
pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
|
pt_dati <= {pte_key,pt_dat[31:4],pte_drwx};
|
end
|
end
|
else
|
else
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
upd_done <= 1'b1;
|
upd_done <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (probe) begin
|
else if (probe) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
pte_key <= pt_key;
|
pte_key <= pt_key;
|
pte_last <= pt_last;
|
pte_last <= pt_last;
|
pte_drwx <= pt_drwx;
|
pte_drwx <= pt_drwx;
|
probe_done <= 1'b1;
|
probe_done <= 1'b1;
|
end
|
end
|
else
|
else
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
goto(S_IDLE);
|
goto(S_IDLE);
|
end
|
end
|
else if (~ack_i) begin
|
else if (~ack_i) begin
|
if (keymatch) begin
|
if (keymatch) begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= we_i & pt_drwx[1];
|
we_o <= we_i & pt_drwx[1];
|
if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
|
if (!pt_drwx[1] & we_i) wrv_o <= 1'b1;
|
if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
|
if (!pt_drwx[2] & ~we_i) rdv_o <= 1'b1;
|
if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
|
if (!pt_drwx[0] & icl_i) exv_o <= 1'b1;
|
padr_o <= {pt_ad,vadr_i[12:0]};
|
padr_o <= {pt_ad,vadr_i[12:0]};
|
end
|
end
|
else begin
|
else begin
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
padr_o <= 32'hFFFFFFF8;
|
padr_o <= 32'hFFFFFFF8;
|
prv_o <= 1'b1;
|
prv_o <= 1'b1;
|
end
|
end
|
goto(S_ACK);
|
goto(S_ACK);
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
pt_ad <= {pt_ad+8'd65};
|
pt_ad <= {pt_ad+8'd65};
|
goto(S_CMP4);
|
goto(S_CMP4);
|
end
|
end
|
|
|
// Wait a clock cycle for a page fault to register.
|
// Wait a clock cycle for a page fault to register.
|
S_WAIT1:
|
S_WAIT1:
|
|
if (!ack_i)
|
goto(S_IDLE);
|
goto(S_IDLE);
|
|
|
S_ACK:
|
S_ACK:
|
if (ack_i) begin
|
if (ack_i) begin
|
if (cti_i==3'b000 || cti_i==3'b111) begin
|
if (cti_i==3'b000 || cti_i==3'b111) begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
goto(S_WAIT1);
|
goto(S_WAIT1);
|
end
|
end
|
end
|
end
|
|
|
endcase
|
endcase
|
end
|
end
|
`endif
|
`endif
|
|
|
task goto;
|
task goto;
|
input [3:0] nst;
|
input [3:0] nst;
|
begin
|
begin
|
state <= nst;
|
state <= nst;
|
end
|
end
|
endtask
|
endtask
|
|
|
endmodule
|
endmodule
|
|
|
|
|