Line 1... |
Line 1... |
// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2013 Robert Finch, Stratford
|
// \\__/ o\ (C) 2013 Robert Finch, Stratford
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@opencores.org
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// 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
|
Line 21... |
Line 21... |
// ============================================================================
|
// ============================================================================
|
//
|
//
|
// Cache controller
|
// Cache controller
|
// Also takes care of loading the instruction buffer for non-cached access
|
// Also takes care of loading the instruction buffer for non-cached access
|
//
|
//
|
|
|
//IDLE:
|
|
// begin
|
|
// if (!cyc_o) begin
|
|
//`ifdef SUPPORT_DCACHE
|
|
// // A write to a cacheable address does not cause a cache load
|
|
// if (dmiss) begin
|
|
// isDataCacheLoad <= `TRUE;
|
|
// if (isRMW)
|
|
// lock_o <= 1'b1;
|
|
// cti_o <= 3'b001;
|
|
// bl_o <= 6'd3;
|
|
// cyc_o <= 1'b1;
|
|
// stb_o <= 1'b1;
|
|
// sel_o <= 4'hF;
|
|
// adr_o <= {radr[31:2],4'h0};
|
|
// cstate <= LOAD_DCACHE;
|
|
// end
|
|
// else
|
|
//`endif
|
|
//`ifdef SUPPORT_ICACHE
|
|
// if (!unCachedInsn && imiss && !hit0) begin
|
|
// isInsnCacheLoad <= `TRUE;
|
|
// bte_o <= 2'b00;
|
|
// cti_o <= 3'd001;
|
|
// bl_o <= 6'd3;
|
|
// cyc_o <= 1'b1;
|
|
// stb_o <= 1'b1;
|
|
// sel_o <= 4'hF;
|
|
// adr_o <= {pc[31:4],4'h0};
|
|
// cstate <= LOAD_ICACHE;
|
|
// end
|
|
// else if (!unCachedInsn && imiss && !hit1) begin
|
|
// isInsnCacheLoad <= `TRUE;
|
|
// bte_o <= 2'b00;
|
|
// cti_o <= 3'd001;
|
|
// bl_o <= 6'd3;
|
|
// cyc_o <= 1'b1;
|
|
// stb_o <= 1'b1;
|
|
// sel_o <= 4'hF;
|
|
// adr_o <= {pcp8[31:4],4'h0};
|
|
// cstate <= LOAD_ICACHE;
|
|
// end
|
|
// else
|
|
//`endif
|
|
// if (unCachedInsn && imiss) begin
|
|
// bte_o <= 2'b00;
|
|
// cti_o <= 3'b001;
|
|
// bl_o <= 6'd2;
|
|
// cyc_o <= 1'b1;
|
|
// stb_o <= 1'b1;
|
|
// sel_o <= 4'hf;
|
|
// adr_o <= {pc[31:2],2'b00};
|
|
// cstate <= LOAD_IBUF1;
|
|
// end
|
|
// end
|
|
// end
|
|
|
|
|
|
`ifdef SUPPORT_DCACHE
|
`ifdef SUPPORT_DCACHE
|
DCACHE1:
|
DCACHE1:
|
begin
|
begin
|
isDataCacheLoad <= `TRUE;
|
isDataCacheLoad <= `TRUE;
|
if (isRMW)
|
if (isRMW)
|
lock_o <= 1'b1;
|
lock_o <= 1'b1;
|
cti_o <= 3'b001;
|
wb_burst(6'd3,{radr[31:2],4'h0});
|
bl_o <= 6'd3;
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 4'hF;
|
|
adr_o <= {radr[31:2],4'h0};
|
|
state <= LOAD_DCACHE;
|
state <= LOAD_DCACHE;
|
end
|
end
|
LOAD_DCACHE:
|
LOAD_DCACHE:
|
if (ack_i) begin
|
if (ack_i) begin
|
|
if (adr_o[3:2]==2'b10)
|
|
cti_o <= 3'b111;
|
if (adr_o[3:2]==2'b11) begin
|
if (adr_o[3:2]==2'b11) begin
|
dmiss <= `FALSE;
|
dmiss <= `FALSE;
|
isDataCacheLoad <= `FALSE;
|
isDataCacheLoad <= `FALSE;
|
cti_o <= 3'b000;
|
wb_nack();
|
bl_o <= 6'd0;
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 4'h0;
|
|
adr_o <= 34'h0;
|
|
state <= retstate;
|
state <= retstate;
|
end
|
end
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
end
|
end
|
`ifdef SUPPORT_BERR
|
`ifdef SUPPORT_BERR
|
else if (err_i) begin
|
else if (err_i) begin
|
|
if (adr_o[3:2]==2'b10)
|
|
cti_o <= 3'b111;
|
if (adr_o[3:2]==2'b11) begin
|
if (adr_o[3:2]==2'b11) begin
|
dmiss <= `FALSE;
|
dmiss <= `FALSE;
|
isDataCacheLoad <= `FALSE;
|
isDataCacheLoad <= `FALSE;
|
cti_o <= 3'b000;
|
wb_nack();
|
bl_o <= 6'd0;
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 4'h0;
|
|
adr_o <= 34'h0;
|
|
// The state machine will be waiting for a dhit.
|
// The state machine will be waiting for a dhit.
|
// Override the next state and send the processor to the bus error state.
|
// Override the next state and send the processor to the bus error state.
|
|
intno <= 9'd508;
|
state <= BUS_ERROR;
|
state <= BUS_ERROR;
|
end
|
end
|
|
derr_address <= adr_o[33:2];
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
end
|
end
|
`endif
|
`endif
|
`endif
|
`endif
|
`ifdef SUPPORT_ICACHE
|
`ifdef SUPPORT_ICACHE
|
ICACHE1:
|
ICACHE1:
|
if (!hit0) begin
|
if (!hit0) begin
|
isInsnCacheLoad <= `TRUE;
|
isInsnCacheLoad <= `TRUE;
|
bte_o <= 2'b00;
|
wb_burst(6'd3,{pc[31:4],4'h0});
|
cti_o <= 3'b001;
|
|
bl_o <= 6'd3;
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 4'hF;
|
|
adr_o <= {pc[31:4],4'h0};
|
|
state <= LOAD_ICACHE;
|
state <= LOAD_ICACHE;
|
end
|
end
|
else if (!hit1) begin
|
else if (!hit1) begin
|
isInsnCacheLoad <= `TRUE;
|
isInsnCacheLoad <= `TRUE;
|
bte_o <= 2'b00;
|
wb_burst(6'd3,{pcp8[31:4],4'h0});
|
cti_o <= 3'b001;
|
|
bl_o <= 6'd3;
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 4'hF;
|
|
adr_o <= {pcp8[31:4],4'h0};
|
|
state <= LOAD_ICACHE;
|
state <= LOAD_ICACHE;
|
end
|
end
|
else
|
else
|
state <= em ? BYTE_IFETCH : IFETCH;
|
state <= em ? BYTE_IFETCH : IFETCH;
|
LOAD_ICACHE:
|
LOAD_ICACHE:
|
if (ack_i) begin
|
if (ack_i) begin
|
|
if (adr_o[3:2]==2'b10)
|
|
cti_o <= 3'b111;
|
if (adr_o[3:2]==2'b11) begin
|
if (adr_o[3:2]==2'b11) begin
|
isInsnCacheLoad <= `FALSE;
|
isInsnCacheLoad <= `FALSE;
|
cti_o <= 3'b000;
|
wb_nack();
|
bl_o <= 6'd0;
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 4'h0;
|
|
adr_o <= 34'd0;
|
|
`ifdef ICACHE_2WAY
|
`ifdef ICACHE_2WAY
|
clfsr <= {clfsr,clfsr_fb};
|
clfsr <= {clfsr,clfsr_fb};
|
`endif
|
`endif
|
state <= ICACHE1;
|
state <= ICACHE1;
|
end
|
end
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
end
|
end
|
`ifdef SUPPORT_BERR
|
`ifdef SUPPORT_BERR
|
else if (err_i) begin
|
else if (err_i) begin
|
|
if (adr_o[3:2]==2'b10)
|
|
cti_o <= 3'b111;
|
if (adr_o[3:2]==2'b11) begin
|
if (adr_o[3:2]==2'b11) begin
|
isInsnCacheLoad <= `FALSE;
|
isInsnCacheLoad <= `FALSE;
|
cti_o <= 3'b000;
|
wb_nack();
|
bl_o <= 6'd0;
|
derr_address <= 32'd0;
|
cyc_o <= 1'b0;
|
intno <= 9'd509;
|
stb_o <= 1'b0;
|
state <= BUS_ERROR;
|
sel_o <= 4'h0;
|
|
adr_o <= 34'd0;
|
|
state <= INSN_BUS_ERROR;
|
|
`ifdef ICACHE_2WAY
|
`ifdef ICACHE_2WAY
|
clfsr <= {clfsr,clfsr_fb};
|
clfsr <= {clfsr,clfsr_fb};
|
`endif
|
`endif
|
end
|
end
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
adr_o[3:2] <= adr_o[3:2] + 2'd1;
|
end
|
end
|
`endif
|
`endif
|
`endif
|
`endif
|
//IBUF1:
|
|
// begin
|
|
// bte_o <= 2'b00;
|
|
// cti_o <= 3'b001;
|
|
// bl_o <= 6'd2;
|
|
// cyc_o <= 1'b1;
|
|
// stb_o <= 1'b1;
|
|
// sel_o <= 4'hf;
|
|
// adr_o <= {pc[31:2],2'b00};
|
|
// state <= LOAD_IBUF1;
|
|
// end
|
|
LOAD_IBUF1:
|
LOAD_IBUF1:
|
if (!cyc_o) begin
|
if (!cyc_o) begin
|
bte_o <= 2'b00;
|
// Emulation mode never needs to read more than two words.
|
cti_o <= 3'b001;
|
// Native mode might need up to three words.
|
bl_o <= 6'd2;
|
wb_burst((em ? 6'd1: 6'd2),{pc[31:2],2'b00});
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 4'hF;
|
|
adr_o <= {pc[31:2],2'b00};
|
|
end
|
end
|
else if (ack_i|err_i) begin
|
else if (ack_i|err_i) begin
|
|
if (em)
|
|
cti_o <= 3'b111;
|
case(pc[1:0])
|
case(pc[1:0])
|
2'd0: ibuf <= dat_i;
|
2'd0: ibuf <= dat_i;
|
2'd1: ibuf <= dat_i[31:8];
|
2'd1: ibuf <= dat_i[31:8];
|
2'd2: ibuf <= dat_i[31:16];
|
2'd2: ibuf <= dat_i[31:16];
|
2'd3: ibuf <= dat_i[31:24];
|
2'd3: ibuf <= dat_i[31:24];
|
endcase
|
endcase
|
state <= LOAD_IBUF2;
|
state <= LOAD_IBUF2;
|
adr_o <= adr_o + 34'd4;
|
|
end
|
end
|
LOAD_IBUF2:
|
LOAD_IBUF2:
|
if (ack_i|err_i) begin
|
if (ack_i|err_i) begin
|
cyc_o <= 1'b0;
|
state <= em ? BYTE_IFETCH : LOAD_IBUF3;
|
stb_o <= 1'b0;
|
|
sel_o <= 4'h0;
|
|
case(pc[1:0])
|
case(pc[1:0])
|
2'd0: ibuf[55:32] <= dat_i[23:0];
|
2'd0: ibuf[55:32] <= dat_i[23:0];
|
2'd1: ibuf[55:24] <= dat_i;
|
2'd1: ibuf[55:24] <= dat_i;
|
2'd2: ibuf[47:16] <= dat_i;
|
2'd2: ibuf[47:16] <= dat_i;
|
2'd3: ibuf[39:8] <= dat_i;
|
2'd3: ibuf[39:8] <= dat_i;
|
endcase
|
endcase
|
state <= LOAD_IBUF3;
|
if (em) begin
|
adr_o <= adr_o + 34'd4;
|
wb_nack();
|
|
if (err_i) begin
|
|
derr_address <= 32'd0;
|
|
intno <= 9'd509;
|
|
state <= BUS_ERROR;
|
|
end
|
|
bufadr <= pc; // clears the miss
|
|
end
|
|
else
|
|
cti_o <= 3'b111;
|
end
|
end
|
LOAD_IBUF3:
|
LOAD_IBUF3:
|
if (ack_i) begin
|
if (ack_i) begin
|
cti_o <= 3'b000;
|
wb_nack();
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 4'h0;
|
|
case(pc[1:0])
|
case(pc[1:0])
|
2'd0: ;
|
2'd0: ;
|
2'd1: ;
|
2'd1: ;
|
2'd2: ibuf[55:48] <= dat_i[7:0];
|
2'd2: ibuf[55:48] <= dat_i[7:0];
|
2'd3: ibuf[55:40] <= dat_i[15:0];
|
2'd3: ibuf[55:40] <= dat_i[15:0];
|
endcase
|
endcase
|
adr_o <= 34'd0;
|
|
state <= IFETCH;
|
state <= IFETCH;
|
bufadr <= pc; // clears the miss
|
bufadr <= pc; // clears the miss
|
end
|
end
|
`ifdef SUPPORT_BERR
|
`ifdef SUPPORT_BERR
|
else if (err_i) begin
|
else if (err_i) begin
|
|
wb_nack();
|
case(pc[1:0])
|
case(pc[1:0])
|
2'd0: ;
|
2'd0: ;
|
2'd1: ;
|
2'd1: ;
|
2'd2: ibuf[55:48] <= dat_i[7:0];
|
2'd2: ibuf[55:48] <= dat_i[7:0];
|
2'd3: ibuf[55:40] <= dat_i[15:0];
|
2'd3: ibuf[55:40] <= dat_i[15:0];
|
endcase
|
endcase
|
cti_o <= 3'b000;
|
derr_address <= 32'd0;
|
cyc_o <= 1'b0;
|
intno <= 9'd509;
|
stb_o <= 1'b0;
|
state <= BUS_ERROR;
|
sel_o <= 4'h0;
|
|
adr_o <= 34'd0;
|
|
state <= INSN_BUS_ERROR;
|
|
bufadr <= pc; // clears the miss
|
bufadr <= pc; // clears the miss
|
end
|
end
|
`endif
|
`endif
|
|
|
No newline at end of file
|
No newline at end of file
|