Line 1... |
Line 1... |
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// AltOR32
|
// AltOR32
|
// Alternative Lightweight OpenRisc
|
// Alternative Lightweight OpenRisc
|
// V2.0
|
// V2.1
|
// Ultra-Embedded.com
|
// Ultra-Embedded.com
|
// Copyright 2011 - 2013
|
// Copyright 2011 - 2014
|
//
|
//
|
// Email: admin@ultra-embedded.com
|
// Email: admin@ultra-embedded.com
|
//
|
//
|
// License: LGPL
|
// License: LGPL
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 53... |
Line 53... |
input [31:0] pc_i /*verilator public*/,
|
input [31:0] pc_i /*verilator public*/,
|
output [31:0] instruction_o /*verilator public*/,
|
output [31:0] instruction_o /*verilator public*/,
|
output valid_o /*verilator public*/,
|
output valid_o /*verilator public*/,
|
input invalidate_i /*verilator public*/,
|
input invalidate_i /*verilator public*/,
|
|
|
// Status
|
|
output miss_o /*verilator public*/,
|
|
output busy_o /*verilator public*/,
|
|
|
|
// Memory interface
|
// Memory interface
|
output reg [31:0] wbm_addr_o /*verilator public*/,
|
output reg [31:0] wbm_addr_o /*verilator public*/,
|
input [31:0] wbm_dat_i /*verilator public*/,
|
input [31:0] wbm_dat_i /*verilator public*/,
|
output reg [2:0] wbm_cti_o /*verilator public*/,
|
output reg [2:0] wbm_cti_o /*verilator public*/,
|
output reg wbm_cyc_o /*verilator public*/,
|
output reg wbm_cyc_o /*verilator public*/,
|
Line 110... |
Line 106... |
// Tag address
|
// Tag address
|
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
|
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
|
|
|
// Data memory read / write
|
// Data memory read / write
|
wire [CACHE_DWIDTH-1:0] cache_address_rd;
|
wire [CACHE_DWIDTH-1:0] cache_address_rd;
|
reg [CACHE_DWIDTH-1:0] cache_address_wr;
|
wire [CACHE_DWIDTH-1:0] cache_address_wr;
|
reg [31:0] cache_data_in;
|
reg [31:0] cache_data_in;
|
reg cache_wr;
|
wire cache_wr;
|
|
|
// Word currently being fetched within a line
|
// Word currently being fetched within a line
|
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_fetch_word;
|
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_fetch_word;
|
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_resp_idx;
|
reg [CACHE_LINE_SIZE_WIDTH-3:0] mem_resp_idx;
|
|
|
Line 135... |
Line 131... |
|
|
// Current state
|
// Current state
|
parameter STATE_CHECK = 0;
|
parameter STATE_CHECK = 0;
|
parameter STATE_FETCH = 1;
|
parameter STATE_FETCH = 1;
|
parameter STATE_WAIT = 2;
|
parameter STATE_WAIT = 2;
|
parameter STATE_WAIT2 = 3;
|
parameter STATE_FLUSH = 3;
|
parameter STATE_FLUSH = 4;
|
|
reg [3:0] state;
|
reg [3:0] state;
|
|
|
// Tag address from input PC or flopped version of it
|
// Tag address from input PC or flopped version of it
|
assign tag_entry = (state != STATE_CHECK) ?
|
assign tag_entry = (state != STATE_CHECK) ?
|
miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] :
|
miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] :
|
Line 148... |
Line 143... |
|
|
// Cache read address
|
// Cache read address
|
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
|
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
|
|
|
// Cache miss output if requested PC is not in the tag memory
|
// Cache miss output if requested PC is not in the tag memory
|
assign miss_o = (!tag_data_out[CACHE_TAG_VALID_BIT] ||
|
wire miss = (!tag_data_out[CACHE_TAG_VALID_BIT] ||
|
(last_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_data_out[14:0])) ? 1'b1: 1'b0;
|
(last_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_data_out[14:0])) ? 1'b1: 1'b0;
|
|
|
// Cache output valid
|
|
assign valid_o = !miss_o && !busy_o;
|
|
|
|
// Stall the CPU if cache state machine is not idle!
|
// Stall the CPU if cache state machine is not idle!
|
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
|
wire busy = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
|
|
|
|
// Cache output valid
|
|
assign valid_o = !miss && !busy;
|
|
|
// Final word to fetch from memory
|
// Final word to fetch from memory
|
wire mem_fetch_final_word = (mem_fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}});
|
wire mem_fetch_final_word = (mem_fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}});
|
|
|
// Flushing: Last line to flush
|
// Flushing: Last line to flush
|
wire flush_final_line = (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}});
|
wire flush_final_line = (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}});
|
|
|
// Is this a cache miss?
|
// Is this a cache miss?
|
wire cache_miss = (miss_o && // Tag lookup failed
|
wire cache_miss = (miss && // Tag lookup failed
|
!initial_fetch && // NOT initial fetch after reset
|
!initial_fetch && // NOT initial fetch after reset
|
!rd_i && // NOT new read request cycle
|
!rd_i && // NOT new read request cycle
|
!read_while_busy && // NOT pending read whilst busy
|
!read_while_busy && // NOT pending read whilst busy
|
!flush_req && // NOT flush request
|
!flush_req && // NOT flush request
|
!invalidate_i);
|
!invalidate_i);
|
Line 219... |
Line 214... |
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WAIT - Wait cycle
|
// WAIT - Wait cycle
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WAIT :
|
STATE_WAIT :
|
// Allow extra wait state to handle write & read collision
|
|
next_state_r = STATE_WAIT2;
|
|
//-----------------------------------------
|
|
// WAIT2 - Wait cycle
|
|
//-----------------------------------------
|
|
STATE_WAIT2 :
|
|
next_state_r = STATE_CHECK;
|
next_state_r = STATE_CHECK;
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
Line 354... |
Line 343... |
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Cache Data Write
|
|
//-----------------------------------------------------------------
|
|
always @ (posedge rst_i or posedge clk_i )
|
|
begin
|
|
if (rst_i == 1'b1)
|
|
begin
|
|
cache_address_wr<= {CACHE_DWIDTH{1'b0}};
|
|
cache_data_in <= 32'h00000000;
|
|
cache_wr <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
cache_wr <= 1'b0;
|
|
|
|
// FETCH - Fetch row from memory
|
|
if (state == STATE_FETCH)
|
|
begin
|
|
// Data ready from memory?
|
|
if (wbm_ack_i)
|
|
begin
|
|
// Write data into cache
|
|
cache_address_wr <= {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], mem_resp_idx};
|
|
cache_data_in <= wbm_dat_i;
|
|
cache_wr <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
//-----------------------------------------------------------------
|
|
// Flush Logic
|
// Flush Logic
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ (posedge rst_i or posedge clk_i )
|
always @ (posedge rst_i or posedge clk_i )
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
Line 517... |
Line 476... |
STATE_FLUSH :
|
STATE_FLUSH :
|
begin
|
begin
|
// Fetch current PC line again
|
// Fetch current PC line again
|
if (flush_final_line)
|
if (flush_final_line)
|
begin
|
begin
|
|
if (read_while_busy)
|
|
wbm_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
|
|
else
|
wbm_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
|
wbm_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
|
|
|
// Incrementing linear burst
|
// Incrementing linear burst
|
wbm_cti_o <= 3'b010;
|
wbm_cti_o <= 3'b010;
|
|
|
Line 669... |
Line 631... |
|
|
// Data write port
|
// Data write port
|
.bclk_i(clk_i),
|
.bclk_i(clk_i),
|
.badr_i(cache_address_wr),
|
.badr_i(cache_address_wr),
|
.bdat_o(/*open*/),
|
.bdat_o(/*open*/),
|
.bdat_i(cache_data_in),
|
.bdat_i(wbm_dat_i),
|
.bwr_i(cache_wr)
|
.bwr_i(cache_wr)
|
);
|
);
|
|
|
|
// Write to cache on wishbone response
|
|
assign cache_address_wr = {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], mem_resp_idx};
|
|
|
|
assign cache_wr = (state == STATE_FETCH) & wbm_ack_i;
|
|
|
endmodule
|
endmodule
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|