//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// 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
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//
|
//
|
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
|
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
|
//
|
//
|
// This source file may be used and distributed without
|
// This source file may be used and distributed without
|
// restriction provided that this copyright statement is not
|
// restriction provided that this copyright statement is not
|
// removed from the file and that any derivative work contains
|
// removed from the file and that any derivative work contains
|
// the original copyright notice and the associated disclaimer.
|
// the original copyright notice and the associated disclaimer.
|
//
|
//
|
// This source file is free software; you can redistribute it
|
// This source file is free software; you can redistribute it
|
// and/or modify it under the terms of the GNU Lesser General
|
// and/or modify it under the terms of the GNU Lesser General
|
// Public License as published by the Free Software Foundation;
|
// Public License as published by the Free Software Foundation;
|
// either version 2.1 of the License, or (at your option) any
|
// either version 2.1 of the License, or (at your option) any
|
// later version.
|
// later version.
|
//
|
//
|
// This source is distributed in the hope that it will be
|
// This source is distributed in the hope that it will be
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// PURPOSE. See the GNU Lesser General Public License for more
|
// PURPOSE. See the GNU Lesser General Public License for more
|
// details.
|
// details.
|
//
|
//
|
// You should have received a copy of the GNU Lesser General
|
// You should have received a copy of the GNU Lesser General
|
// Public License along with this source; if not, write to the
|
// Public License along with this source; if not, write to the
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
// Boston, MA 02111-1307 USA
|
// Boston, MA 02111-1307 USA
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Module - Data Cache Memory Interface
|
// Module - Data Cache Memory Interface
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
module altor32_dcache_mem_if
|
module altor32_dcache_mem_if
|
(
|
(
|
input clk_i /*verilator public*/,
|
input clk_i /*verilator public*/,
|
input rst_i /*verilator public*/,
|
input rst_i /*verilator public*/,
|
|
|
// Cache interface
|
// Cache interface
|
input [31:0] address_i /*verilator public*/,
|
input [31:0] address_i /*verilator public*/,
|
input [31:0] data_i /*verilator public*/,
|
input [31:0] data_i /*verilator public*/,
|
output reg [31:0] data_o /*verilator public*/,
|
output reg [31:0] data_o /*verilator public*/,
|
input fill_i /*verilator public*/,
|
input fill_i /*verilator public*/,
|
input evict_i /*verilator public*/,
|
input evict_i /*verilator public*/,
|
input [31:0] evict_addr_i /*verilator public*/,
|
input [31:0] evict_addr_i /*verilator public*/,
|
input rd_single_i /*verilator public*/,
|
input rd_single_i /*verilator public*/,
|
input [3:0] wr_single_i /*verilator public*/,
|
input [3:0] wr_single_i /*verilator public*/,
|
output reg done_o /*verilator public*/,
|
output reg done_o /*verilator public*/,
|
|
|
// Cache memory (fill/evict)
|
// Cache memory (fill/evict)
|
output reg [31:2] cache_addr_o /*verilator public*/,
|
output reg [31:2] cache_addr_o /*verilator public*/,
|
output reg [31:0] cache_data_o /*verilator public*/,
|
output reg [31:0] cache_data_o /*verilator public*/,
|
input [31:0] cache_data_i /*verilator public*/,
|
input [31:0] cache_data_i /*verilator public*/,
|
output reg cache_wr_o /*verilator public*/,
|
output reg cache_wr_o /*verilator public*/,
|
|
|
// Memory interface (slave)
|
// Memory interface (slave)
|
output reg [31:0] mem_addr_o /*verilator public*/,
|
output reg [31:0] mem_addr_o /*verilator public*/,
|
input [31:0] mem_data_i /*verilator public*/,
|
input [31:0] mem_data_i /*verilator public*/,
|
output reg [31:0] mem_data_o /*verilator public*/,
|
output reg [31:0] mem_data_o /*verilator public*/,
|
output reg [2:0] mem_cti_o /*verilator public*/,
|
output reg [2:0] mem_cti_o /*verilator public*/,
|
output reg mem_cyc_o /*verilator public*/,
|
output reg mem_cyc_o /*verilator public*/,
|
output reg mem_stb_o /*verilator public*/,
|
output reg mem_stb_o /*verilator public*/,
|
output reg mem_we_o /*verilator public*/,
|
output reg mem_we_o /*verilator public*/,
|
output reg [3:0] mem_sel_o /*verilator public*/,
|
output reg [3:0] mem_sel_o /*verilator public*/,
|
input mem_stall_i/*verilator public*/,
|
input mem_stall_i/*verilator public*/,
|
input mem_ack_i/*verilator public*/
|
input mem_ack_i/*verilator public*/
|
);
|
);
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Params
|
// Params
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
|
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
|
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit -> 8 words */
|
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit -> 8 words */
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Registers / Wires
|
// Registers / Wires
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
reg [31:CACHE_LINE_SIZE_WIDTH] line_address;
|
reg [31:CACHE_LINE_SIZE_WIDTH] line_address;
|
|
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] response_idx;
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] response_idx;
|
|
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] request_idx;
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] request_idx;
|
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_request_idx = request_idx + 1'b1;
|
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_request_idx = request_idx + 1'b1;
|
|
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] cache_idx;
|
reg [CACHE_LINE_WORDS_IDX_MAX-1:0] cache_idx;
|
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_cache_idx = cache_idx + 1'b1;
|
wire [CACHE_LINE_WORDS_IDX_MAX-1:0] next_cache_idx = cache_idx + 1'b1;
|
|
|
|
|
// Current state
|
// Current state
|
parameter STATE_IDLE = 0;
|
parameter STATE_IDLE = 0;
|
parameter STATE_FETCH = 1;
|
parameter STATE_FETCH = 1;
|
parameter STATE_WRITE_SETUP = 2;
|
parameter STATE_WRITE_SETUP = 2;
|
parameter STATE_WRITE = 3;
|
parameter STATE_WRITE = 3;
|
parameter STATE_WRITE_WAIT = 4;
|
parameter STATE_WRITE_WAIT = 4;
|
parameter STATE_MEM_SINGLE = 5;
|
parameter STATE_MEM_SINGLE = 5;
|
parameter STATE_FETCH_WAIT = 6;
|
parameter STATE_FETCH_WAIT = 6;
|
|
|
reg [3:0] state;
|
reg [3:0] state;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next State Logic
|
// Next State Logic
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [3:0] next_state_r;
|
reg [3:0] next_state_r;
|
always @ *
|
always @ *
|
begin
|
begin
|
next_state_r = state;
|
next_state_r = state;
|
|
|
case (state)
|
case (state)
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
// Perform cache evict (write)
|
// Perform cache evict (write)
|
if (evict_i)
|
if (evict_i)
|
next_state_r = STATE_WRITE_SETUP;
|
next_state_r = STATE_WRITE_SETUP;
|
// Perform cache fill (read)
|
// Perform cache fill (read)
|
else if (fill_i)
|
else if (fill_i)
|
next_state_r = STATE_FETCH;
|
next_state_r = STATE_FETCH;
|
// Read/Write single
|
// Read/Write single
|
else if (rd_single_i | (|wr_single_i))
|
else if (rd_single_i | (|wr_single_i))
|
next_state_r = STATE_MEM_SINGLE;
|
next_state_r = STATE_MEM_SINGLE;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH :
|
STATE_FETCH :
|
begin
|
begin
|
// Line fetch complete?
|
// Line fetch complete?
|
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
next_state_r = STATE_FETCH_WAIT;
|
next_state_r = STATE_FETCH_WAIT;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH_WAIT - Wait for read responses
|
// FETCH_WAIT - Wait for read responses
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH_WAIT:
|
STATE_FETCH_WAIT:
|
begin
|
begin
|
// Read from memory complete
|
// Read from memory complete
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
next_state_r = STATE_IDLE;
|
next_state_r = STATE_IDLE;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE_SETUP - Wait for data from cache
|
// WRITE_SETUP - Wait for data from cache
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_SETUP :
|
STATE_WRITE_SETUP :
|
next_state_r = STATE_WRITE;
|
next_state_r = STATE_WRITE;
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE - Write word to memory
|
// WRITE - Write word to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE :
|
STATE_WRITE :
|
begin
|
begin
|
// Line write complete?
|
// Line write complete?
|
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (~mem_stall_i && request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
next_state_r = STATE_WRITE_WAIT;
|
next_state_r = STATE_WRITE_WAIT;
|
// Fetch next word for line
|
// Fetch next word for line
|
else if (~mem_stall_i | ~mem_stb_o)
|
else if (~mem_stall_i | ~mem_stb_o)
|
next_state_r = STATE_WRITE_SETUP;
|
next_state_r = STATE_WRITE_SETUP;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE_WAIT - Wait for write to complete
|
// WRITE_WAIT - Wait for write to complete
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_WAIT:
|
STATE_WRITE_WAIT:
|
begin
|
begin
|
// Write to memory complete
|
// Write to memory complete
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
next_state_r = STATE_IDLE;
|
next_state_r = STATE_IDLE;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// MEM_SINGLE - Single access to memory
|
// MEM_SINGLE - Single access to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_MEM_SINGLE:
|
STATE_MEM_SINGLE:
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
next_state_r = STATE_IDLE;
|
next_state_r = STATE_IDLE;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
// Update state
|
// Update state
|
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)
|
state <= STATE_IDLE;
|
state <= STATE_IDLE;
|
else
|
else
|
state <= next_state_r;
|
state <= next_state_r;
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Control logic
|
// Control 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)
|
begin
|
begin
|
line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}};
|
line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}};
|
done_o <= 1'b0;
|
done_o <= 1'b0;
|
data_o <= 32'h00000000;
|
data_o <= 32'h00000000;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
done_o <= 1'b0;
|
done_o <= 1'b0;
|
|
|
case (state)
|
case (state)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
// Perform cache evict (write)
|
// Perform cache evict (write)
|
if (evict_i)
|
if (evict_i)
|
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
|
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
|
// Perform cache fill (read)
|
// Perform cache fill (read)
|
else if (fill_i)
|
else if (fill_i)
|
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
|
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH/WRITE_WAIT - Wait for oustanding responses
|
// FETCH/WRITE_WAIT - Wait for oustanding responses
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_WAIT,
|
STATE_WRITE_WAIT,
|
STATE_FETCH_WAIT:
|
STATE_FETCH_WAIT:
|
begin
|
begin
|
// Write to memory complete
|
// Write to memory complete
|
if (mem_ack_i)
|
if (mem_ack_i)
|
begin
|
begin
|
// Line write complete?
|
// Line write complete?
|
if (response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
done_o <= 1'b1;
|
done_o <= 1'b1;
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// MEM_SINGLE - Single access to memory
|
// MEM_SINGLE - Single access to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_MEM_SINGLE:
|
STATE_MEM_SINGLE:
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
begin
|
begin
|
data_o <= mem_data_i;
|
data_o <= mem_data_i;
|
done_o <= 1'b1;
|
done_o <= 1'b1;
|
end
|
end
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Cache Read / Write
|
// Cache Read / Write
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
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)
|
begin
|
begin
|
cache_addr_o <= 30'h00000000;
|
cache_addr_o <= 30'h00000000;
|
cache_data_o <= 32'h00000000;
|
cache_data_o <= 32'h00000000;
|
cache_wr_o <= 1'b0;
|
cache_wr_o <= 1'b0;
|
|
|
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
end
|
end
|
else
|
else
|
begin
|
begin
|
cache_wr_o <= 1'b0;
|
cache_wr_o <= 1'b0;
|
|
|
case (state)
|
case (state)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
cache_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
|
|
// Perform cache evict (write)
|
// Perform cache evict (write)
|
if (evict_i)
|
if (evict_i)
|
begin
|
begin
|
// Read data from cache
|
// Read data from cache
|
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_WORDS_IDX_MAX{1'b0}}};
|
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_WORDS_IDX_MAX{1'b0}}};
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH,
|
STATE_FETCH,
|
STATE_FETCH_WAIT:
|
STATE_FETCH_WAIT:
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
begin
|
begin
|
// Write data into cache
|
// Write data into cache
|
cache_addr_o <= {line_address, cache_idx};
|
cache_addr_o <= {line_address, cache_idx};
|
cache_data_o <= mem_data_i;
|
cache_data_o <= mem_data_i;
|
cache_wr_o <= 1'b1;
|
cache_wr_o <= 1'b1;
|
|
|
cache_idx <= next_cache_idx;
|
cache_idx <= next_cache_idx;
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE - Write word to memory
|
// WRITE - Write word to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_SETUP:
|
STATE_WRITE_SETUP:
|
begin
|
begin
|
|
|
end
|
end
|
STATE_WRITE,
|
STATE_WRITE,
|
STATE_WRITE_WAIT:
|
STATE_WRITE_WAIT:
|
begin
|
begin
|
if (~mem_stall_i | ~mem_stb_o)
|
if (~mem_stall_i | ~mem_stb_o)
|
begin
|
begin
|
// Setup next word read from cache
|
// Setup next word read from cache
|
cache_addr_o <= {line_address, next_cache_idx};
|
cache_addr_o <= {line_address, next_cache_idx};
|
cache_idx <= next_cache_idx;
|
cache_idx <= next_cache_idx;
|
end
|
end
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Request
|
// Request
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
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)
|
begin
|
begin
|
mem_addr_o <= 32'h00000000;
|
mem_addr_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_sel_o <= 4'h0;
|
mem_sel_o <= 4'h0;
|
mem_cti_o <= 3'b0;
|
mem_cti_o <= 3'b0;
|
mem_stb_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (~mem_stall_i)
|
if (~mem_stall_i)
|
begin
|
begin
|
mem_stb_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
|
|
// TMP
|
// TMP
|
if (mem_cti_o == 3'b111)
|
if (mem_cti_o == 3'b111)
|
begin
|
begin
|
//mem_addr_o <= 32'h00000000;
|
//mem_addr_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_sel_o <= 4'h0;
|
mem_sel_o <= 4'h0;
|
mem_cti_o <= 3'b0;
|
mem_cti_o <= 3'b0;
|
mem_stb_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
end
|
end
|
end
|
end
|
|
|
case (state)
|
case (state)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
request_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
|
|
// Perform cache evict (write)
|
// Perform cache evict (write)
|
if (evict_i)
|
if (evict_i)
|
begin
|
begin
|
|
|
end
|
end
|
// Perform cache fill (read)
|
// Perform cache fill (read)
|
else if (fill_i)
|
else if (fill_i)
|
begin
|
begin
|
// Start fetch from memory
|
// Start fetch from memory
|
mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
|
mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
|
mem_data_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_sel_o <= 4'b1111;
|
mem_sel_o <= 4'b1111;
|
mem_cti_o <= 3'b010;
|
mem_cti_o <= 3'b010;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
|
|
request_idx <= next_request_idx;
|
request_idx <= next_request_idx;
|
end
|
end
|
// Read single
|
// Read single
|
else if (rd_single_i)
|
else if (rd_single_i)
|
begin
|
begin
|
// Start fetch from memory
|
// Start fetch from memory
|
mem_addr_o <= address_i;
|
mem_addr_o <= address_i;
|
mem_data_o <= 32'h00000000;
|
mem_data_o <= 32'h00000000;
|
mem_sel_o <= 4'b1111;
|
mem_sel_o <= 4'b1111;
|
mem_cti_o <= 3'b111;
|
mem_cti_o <= 3'b111;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
end
|
end
|
// Write single
|
// Write single
|
else if (|wr_single_i)
|
else if (|wr_single_i)
|
begin
|
begin
|
// Start fetch from memory
|
// Start fetch from memory
|
mem_addr_o <= address_i;
|
mem_addr_o <= address_i;
|
mem_data_o <= data_i;
|
mem_data_o <= data_i;
|
mem_sel_o <= wr_single_i;
|
mem_sel_o <= wr_single_i;
|
mem_cti_o <= 3'b111;
|
mem_cti_o <= 3'b111;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH :
|
STATE_FETCH :
|
begin
|
begin
|
// Previous request accepted?
|
// Previous request accepted?
|
if (~mem_stall_i)
|
if (~mem_stall_i)
|
begin
|
begin
|
// Fetch next word for line
|
// Fetch next word for line
|
mem_addr_o <= {line_address, request_idx, 2'b00};
|
mem_addr_o <= {line_address, request_idx, 2'b00};
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
|
|
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
mem_cti_o <= 3'b111;
|
mem_cti_o <= 3'b111;
|
|
|
request_idx <= next_request_idx;
|
request_idx <= next_request_idx;
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE - Write word to memory
|
// WRITE - Write word to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE :
|
STATE_WRITE :
|
begin
|
begin
|
// Memory interface can request command?
|
// Memory interface can request command?
|
if (~mem_stall_i | ~mem_stb_o)
|
if (~mem_stall_i | ~mem_stb_o)
|
begin
|
begin
|
// Write data into memory from cache
|
// Write data into memory from cache
|
mem_addr_o <= {line_address, request_idx, 2'b00};
|
mem_addr_o <= {line_address, request_idx, 2'b00};
|
mem_data_o <= cache_data_i;
|
mem_data_o <= cache_data_i;
|
mem_sel_o <= 4'b1111;
|
mem_sel_o <= 4'b1111;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
|
|
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (request_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
mem_cti_o <= 3'b111;
|
mem_cti_o <= 3'b111;
|
else
|
else
|
mem_cti_o <= 3'b010;
|
mem_cti_o <= 3'b010;
|
|
|
request_idx <= next_request_idx;
|
request_idx <= next_request_idx;
|
end
|
end
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Memory Response Counter
|
// Memory Response Counter
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
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)
|
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
else
|
else
|
begin
|
begin
|
case (state)
|
case (state)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
response_idx <= {CACHE_LINE_WORDS_IDX_MAX{1'b0}};
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH,
|
STATE_FETCH,
|
STATE_FETCH_WAIT :
|
STATE_FETCH_WAIT :
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
response_idx <= response_idx + 1'b1;
|
response_idx <= response_idx + 1'b1;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE_WAIT - Wait for write to complete
|
// WRITE_WAIT - Wait for write to complete
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE,
|
STATE_WRITE,
|
STATE_WRITE_SETUP,
|
STATE_WRITE_SETUP,
|
STATE_WRITE_WAIT:
|
STATE_WRITE_WAIT:
|
begin
|
begin
|
// Write to memory complete
|
// Write to memory complete
|
if (mem_ack_i)
|
if (mem_ack_i)
|
response_idx <= response_idx + 1'b1;
|
response_idx <= response_idx + 1'b1;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// CYC_O
|
// CYC_O
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
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)
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
else
|
else
|
begin
|
begin
|
case (state)
|
case (state)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE
|
// IDLE
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
// Perform cache evict (write)
|
// Perform cache evict (write)
|
if (evict_i)
|
if (evict_i)
|
begin
|
begin
|
|
|
end
|
end
|
// Perform cache fill (read)
|
// Perform cache fill (read)
|
else if (fill_i)
|
else if (fill_i)
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
// Read single
|
// Read single
|
else if (rd_single_i)
|
else if (rd_single_i)
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
// Write single
|
// Write single
|
else if (|wr_single_i)
|
else if (|wr_single_i)
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH :
|
STATE_FETCH :
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE - Write word to memory
|
// WRITE - Write word to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE :
|
STATE_WRITE :
|
begin
|
begin
|
// Write data into memory from cache
|
// Write data into memory from cache
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH/WRITE_WAIT - Wait for responses
|
// FETCH/WRITE_WAIT - Wait for responses
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_WAIT,
|
STATE_WRITE_WAIT,
|
STATE_FETCH_WAIT:
|
STATE_FETCH_WAIT:
|
begin
|
begin
|
// Write to memory complete
|
// Write to memory complete
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
if (mem_ack_i && response_idx == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// MEM_SINGLE - Single access to memory
|
// MEM_SINGLE - Single access to memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_MEM_SINGLE:
|
STATE_MEM_SINGLE:
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|