Line 67... |
Line 67... |
`ifdef OR1200_BIST
|
`ifdef OR1200_BIST
|
// RAM BIST
|
// RAM BIST
|
mbist_si_i, mbist_so_o, mbist_ctrl_i,
|
mbist_si_i, mbist_so_o, mbist_ctrl_i,
|
`endif
|
`endif
|
|
|
|
`ifdef OR1200_RAM_PARITY
|
|
// Parity error indicator
|
|
p_err,
|
|
`endif
|
|
|
// QMEM i/f
|
// QMEM i/f
|
qmemimmu_rty_i, qmemimmu_err_i, qmemimmu_tag_i, qmemimmu_adr_o, qmemimmu_cycstb_o, qmemimmu_ci_o
|
qmemimmu_rty_i, qmemimmu_err_i, qmemimmu_tag_i, qmemimmu_adr_o, qmemimmu_cycstb_o, qmemimmu_ci_o
|
);
|
);
|
|
|
parameter dw = `OR1200_OPERAND_WIDTH;
|
parameter dw = `OR1200_OPERAND_WIDTH;
|
Line 120... |
Line 125... |
input mbist_si_i;
|
input mbist_si_i;
|
input [`OR1200_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i;
|
input [`OR1200_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i;
|
output mbist_so_o;
|
output mbist_so_o;
|
`endif
|
`endif
|
|
|
|
`ifdef OR1200_RAM_PARITY
|
|
output [1:0] p_err;
|
|
`endif
|
|
|
//
|
//
|
// IC I/F
|
// IC I/F
|
//
|
//
|
input qmemimmu_rty_i;
|
input qmemimmu_rty_i;
|
input qmemimmu_err_i;
|
input qmemimmu_err_i;
|
Line 156... |
Line 165... |
`else
|
`else
|
reg itlb_en_r;
|
reg itlb_en_r;
|
reg dis_spr_access_frst_clk;
|
reg dis_spr_access_frst_clk;
|
reg dis_spr_access_scnd_clk;
|
reg dis_spr_access_scnd_clk;
|
`endif
|
`endif
|
|
reg [31:0] spr_dat_reg;
|
|
|
//
|
//
|
// Implemented bits inside match and translate registers
|
// Implemented bits inside match and translate registers
|
//
|
//
|
// itlbwYmrX: vpn 31-10 v 0
|
// itlbwYmrX: vpn 31-10 v 0
|
Line 170... |
Line 180... |
// 13 bits for vpn
|
// 13 bits for vpn
|
// 1 bit for valid
|
// 1 bit for valid
|
// 2 bits for protection
|
// 2 bits for protection
|
// 1 bit for cache inhibit
|
// 1 bit for cache inhibit
|
|
|
|
|
|
assign icpu_adr_boot = `OR1200_BOOT_ADR;
|
|
|
//
|
//
|
// icpu_adr_o
|
// icpu_adr_o
|
//
|
//
|
`ifdef OR1200_REGISTERED_OUTPUTS
|
`ifdef OR1200_REGISTERED_OUTPUTS
|
always @(`OR1200_RST_EVENT rst or posedge clk)
|
always @(`OR1200_RST_EVENT rst or posedge clk)
|
// default value
|
// default value
|
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
// select async. value due to reset state
|
// select async. value due to reset state
|
icpu_adr_default <= 32'h0000_0100;
|
icpu_adr_o <= 32'h0000_0100;
|
icpu_adr_select <= 1'b1;
|
icpu_adr_select <= 1'b1;
|
end
|
end
|
// selected value (different from default) is written
|
// selected value (different from default) is written
|
// into FF after reset state
|
// into FF after reset state
|
else if (icpu_adr_select) begin
|
else if (icpu_adr_select) begin
|
// dynamic value can only be assigned to FF out of reset!
|
// dynamic value can only be assigned to FF out of reset!
|
icpu_adr_default <= icpu_adr_boot;
|
icpu_adr_o <= icpu_adr_boot;
|
// select FF value
|
// select FF value
|
icpu_adr_select <= 1'b0;
|
icpu_adr_select <= 1'b0;
|
end
|
end
|
else begin
|
else begin
|
icpu_adr_default <= icpu_adr_i;
|
icpu_adr_o <= icpu_adr_i;
|
end
|
end
|
|
|
// select async. value for boot address after reset - PC jumps to the address
|
|
// selected after boot!
|
|
//assign icpu_adr_boot = {(boot_adr_sel_i ? `OR1200_EXCEPT_EPH1_P :
|
|
// `OR1200_EXCEPT_EPH0_P), 12'h100} ;
|
|
assign icpu_adr_boot = `OR1200_BOOT_ADR; // jb
|
|
|
|
always @(icpu_adr_boot or icpu_adr_default or icpu_adr_select)
|
|
if (icpu_adr_select)
|
|
// async. value is selected due to reset state
|
|
icpu_adr_o = icpu_adr_boot ;
|
|
else
|
|
// FF value is selected 2nd clock after reset state
|
|
icpu_adr_o = icpu_adr_default ;
|
|
`else
|
`else
|
Unsupported !!!
|
Unsupported !!!
|
`endif
|
`endif
|
|
|
//
|
//
|
Line 218... |
Line 217... |
// Asserted when CPU address crosses page boundary. Most of the time it is zero.
|
// Asserted when CPU address crosses page boundary. Most of the time it is zero.
|
//
|
//
|
assign page_cross = icpu_adr_i[31:`OR1200_IMMU_PS] != icpu_vpn_r;
|
assign page_cross = icpu_adr_i[31:`OR1200_IMMU_PS] != icpu_vpn_r;
|
|
|
//
|
//
|
// Register icpu_adr_i's VPN for use when IMMU is not enabled but PPN is expected to come
|
// Register icpu_adr_i's VPN for use when IMMU is not enabled but PPN is
|
// one clock cycle after offset part.
|
// expected to come one clock cycle after offset part.
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
icpu_vpn_r <= {32-`OR1200_IMMU_PS{1'b0}};
|
icpu_vpn_r <= {32-`OR1200_IMMU_PS{1'b0}};
|
else
|
else
|
Line 242... |
Line 241... |
assign icpu_err_o = qmemimmu_err_i;
|
assign icpu_err_o = qmemimmu_err_i;
|
assign qmemimmu_ci_o = `OR1200_IMMU_CI;
|
assign qmemimmu_ci_o = `OR1200_IMMU_CI;
|
`ifdef OR1200_BIST
|
`ifdef OR1200_BIST
|
assign mbist_so_o = mbist_si_i;
|
assign mbist_so_o = mbist_si_i;
|
`endif
|
`endif
|
|
`ifdef OR1200_RAM_PARITY
|
|
assign p_err = 0;
|
|
`endif
|
|
|
`else
|
`else
|
|
|
//
|
//
|
// ITLB SPR access
|
// ITLB SPR access
|
//
|
//
|
Line 290... |
Line 293... |
// Tags:
|
// Tags:
|
//
|
//
|
// OR1200_ITAG_TE - TLB miss Exception
|
// OR1200_ITAG_TE - TLB miss Exception
|
// OR1200_ITAG_PE - Page fault Exception
|
// OR1200_ITAG_PE - Page fault Exception
|
//
|
//
|
assign icpu_tag_o = miss ? `OR1200_ITAG_TE : fault ? `OR1200_ITAG_PE : qmemimmu_tag_i;
|
assign icpu_tag_o = miss ? `OR1200_ITAG_TE :
|
|
fault ? `OR1200_ITAG_PE : qmemimmu_tag_i;
|
|
|
//
|
//
|
// icpu_rty_o
|
// icpu_rty_o
|
//
|
//
|
// assign icpu_rty_o = !icpu_err_o & qmemimmu_rty_i;
|
// assign icpu_rty_o = !icpu_err_o & qmemimmu_rty_i;
|
Line 302... |
Line 306... |
assign icpu_rty_o = qmemimmu_rty_i;
|
assign icpu_rty_o = qmemimmu_rty_i;
|
|
|
//
|
//
|
// icpu_err_o
|
// icpu_err_o
|
//
|
//
|
assign icpu_err_o = miss | fault | qmemimmu_err_i;
|
assign icpu_err_o = miss | fault | qmemimmu_err_i
|
|
`ifdef OR1200_RAM_PARITY
|
|
| (|p_err)
|
|
`endif
|
|
;
|
|
|
//
|
//
|
// Assert itlb_en_r after one clock cycle and when there is no
|
// Assert itlb_en_r after one clock cycle and when there is no
|
// ITLB SPR access
|
// ITLB SPR access
|
//
|
//
|
Line 320... |
Line 328... |
// ITLB lookup successful
|
// ITLB lookup successful
|
//
|
//
|
assign itlb_done = itlb_en_r & ~page_cross;
|
assign itlb_done = itlb_en_r & ~page_cross;
|
|
|
//
|
//
|
// Cut transfer when access (mtspr/mfspr) to/from ITLB occure or if something goes
|
// Cut transfer when access (mtspr/mfspr) to/from ITLB occurs or if something
|
// wrong with translation. If IC is disabled, use delayed signals.
|
// goes wrong with translation. If IC is disabled, use delayed signals.
|
//
|
//
|
// assign qmemimmu_cycstb_o = (!ic_en & immu_en) ? ~(miss | fault) & icpu_cycstb_i & ~page_cross : (miss | fault) ? 1'b0 : icpu_cycstb_i & ~page_cross; // DL
|
assign qmemimmu_cycstb_o = immu_en ?
|
//assign qmemimmu_cycstb_o = immu_en ? ~(miss | fault) & icpu_cycstb_i & ~page_cross & itlb_done : icpu_cycstb_i & ~page_cross;
|
~(miss | fault) & icpu_cycstb_i & ~page_cross &
|
assign qmemimmu_cycstb_o = immu_en ? ~(miss | fault) & icpu_cycstb_i & ~page_cross & itlb_done & ~itlb_spr_access : icpu_cycstb_i & ~page_cross;
|
itlb_done & ~itlb_spr_access :
|
|
icpu_cycstb_i & ~page_cross;
|
|
|
//
|
//
|
// Cache Inhibit
|
// Cache Inhibit
|
//
|
//
|
// Cache inhibit is not really needed for instruction memory subsystem.
|
// Cache inhibit is not really needed for instruction memory subsystem.
|
// If we would doq it, we would doq it like this.
|
// If we would doq it, we would doq it like this.
|
// assign qmemimmu_ci_o = immu_en ? itlb_done & itlb_ci : `OR1200_IMMU_CI;
|
// assign qmemimmu_ci_o = immu_en ? itlb_done & itlb_ci : `OR1200_IMMU_CI;
|
// However this causes an async combinatorial loop so we stick to
|
// However this causes an async combinatorial loop so we stick to
|
// no cache inhibit.
|
// no cache inhibit.
|
//assign qmemimmu_ci_o = `OR1200_IMMU_CI;
|
|
// Cache inhibit without an async combinatorial loop
|
|
assign qmemimmu_ci_o = immu_en ? itlb_ci : `OR1200_IMMU_CI;
|
assign qmemimmu_ci_o = immu_en ? itlb_ci : `OR1200_IMMU_CI;
|
|
|
|
|
//
|
//
|
// Physical address is either translated virtual address or
|
// Physical address is either translated virtual address or
|
// simply equal when IMMU is disabled
|
// simply equal when IMMU is disabled
|
//
|
//
|
//assign qmemimmu_adr_o = itlb_done ? {itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:0]} : {icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:0]}; // DL: immu_en
|
assign qmemimmu_adr_o = immu_en & itlb_done ?
|
assign qmemimmu_adr_o = immu_en & itlb_done ? {itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0} : {icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0};
|
{itlb_ppn, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0} :
|
|
{icpu_vpn_r, icpu_adr_i[`OR1200_IMMU_PS-1:2], 2'h0};
|
|
|
reg [31:0] spr_dat_reg;
|
|
//
|
//
|
// Output to SPRS unit
|
// Output to SPRS unit
|
//
|
//
|
// spr_dat_o is registered on the 1st clock of spr read
|
// spr_dat_o is registered on the 1st clock of spr read
|
// so itlb can continue with process during execution of mfspr.
|
// so itlb can continue with process during execution of mfspr.
|
Line 366... |
Line 373... |
//
|
//
|
// Page fault exception logic
|
// Page fault exception logic
|
//
|
//
|
assign fault = itlb_done &
|
assign fault = itlb_done &
|
( (!supv & !itlb_uxe) // Execute in user mode not enabled
|
( (!supv & !itlb_uxe) // Execute in user mode not enabled
|
|| (supv & !itlb_sxe)); // Execute in supv mode not enabled
|
|| (supv & !itlb_sxe));// Execute in supv mode not en.
|
|
|
//
|
//
|
// TLB Miss exception logic
|
// TLB Miss exception logic
|
//
|
//
|
assign miss = itlb_done & !itlb_hit;
|
assign miss = itlb_done & !itlb_hit;
|
Line 402... |
Line 409... |
.mbist_si_i(mbist_si_i),
|
.mbist_si_i(mbist_si_i),
|
.mbist_so_o(mbist_so_o),
|
.mbist_so_o(mbist_so_o),
|
.mbist_ctrl_i(mbist_ctrl_i),
|
.mbist_ctrl_i(mbist_ctrl_i),
|
`endif
|
`endif
|
|
|
|
`ifdef OR1200_RAM_PARITY
|
|
.p_err(p_err),
|
|
`endif
|
|
|
// SPR access
|
// SPR access
|
.spr_cs(itlb_spr_access),
|
.spr_cs(itlb_spr_access),
|
.spr_write(spr_write),
|
.spr_write(spr_write),
|
.spr_addr(spr_addr),
|
.spr_addr(spr_addr),
|
.spr_dat_i(spr_dat_i),
|
.spr_dat_i(spr_dat_i),
|