Line 88... |
Line 88... |
input [31:0] i_address, // registered address from execute
|
input [31:0] i_address, // registered address from execute
|
input [31:0] i_address_nxt, // un-registered version of address from execute stage
|
input [31:0] i_address_nxt, // un-registered version of address from execute stage
|
input i_cache_enable, // from co-processor 15 configuration register
|
input i_cache_enable, // from co-processor 15 configuration register
|
input i_cache_flush, // from co-processor 15 register
|
input i_cache_flush, // from co-processor 15 register
|
|
|
output [31:0] o_read_data,
|
output [127:0] o_read_data,
|
|
|
// WB Read Request
|
// WB Read Request
|
output o_wb_req, // Read Request
|
output o_wb_req, // Read Request
|
input [31:0] i_wb_read_data,
|
input [127:0] i_wb_read_data,
|
input i_wb_ready
|
input i_wb_ready
|
);
|
);
|
|
|
`include "a25_localparams.v"
|
`include "a25_localparams.v"
|
`include "a25_functions.v"
|
`include "a25_functions.v"
|
Line 138... |
Line 138... |
|
|
wire [CACHE_ADDR_WIDTH-1:0] tag_address;
|
wire [CACHE_ADDR_WIDTH-1:0] tag_address;
|
wire [TAG_WIDTH-1:0] tag_wdata;
|
wire [TAG_WIDTH-1:0] tag_wdata;
|
wire tag_wenable;
|
wire tag_wenable;
|
|
|
wire [CACHE_LINE_WIDTH-1:0] data_wdata;
|
|
wire [CACHE_ADDR_WIDTH-1:0] data_address;
|
wire [CACHE_ADDR_WIDTH-1:0] data_address;
|
wire [31:0] write_data_word;
|
wire [31:0] write_data_word;
|
|
|
wire idle_hit;
|
wire idle_hit;
|
wire read_miss;
|
wire read_miss;
|
Line 159... |
Line 158... |
wire enable;
|
wire enable;
|
wire [CACHE_ADDR_WIDTH-1:0] address;
|
wire [CACHE_ADDR_WIDTH-1:0] address;
|
wire [31:0] address_c;
|
wire [31:0] address_c;
|
reg [31:0] address_r = 'd0;
|
reg [31:0] address_r = 'd0;
|
|
|
reg [CACHE_LINE_WIDTH-1:0] wb_rdata_burst_r = 'd0;
|
|
wire [CACHE_LINE_WIDTH-1:0] wb_rdata_burst;
|
|
|
|
reg [31:0] wb_address = 'd0;
|
reg [31:0] wb_address = 'd0;
|
wire rbuf_hit = 'd0;
|
|
wire wb_hit;
|
wire wb_hit;
|
|
wire read_buf_hit;
|
|
reg [127:0] read_buf_data_r;
|
|
reg [31:0] read_buf_addr_r;
|
|
reg read_buf_valid_r;
|
genvar i;
|
genvar i;
|
|
|
// ======================================
|
// ======================================
|
// Address to use for cache access
|
// Address to use for cache access
|
// ======================================
|
// ======================================
|
// If currently stalled then the address for the next
|
// If currently stalled then the address for the next
|
// cycle will be the same as it is in the current cycle
|
// cycle will be the same as it is in the current cycle
|
//
|
//
|
assign address_c = i_core_stall ? i_address : //[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
|
assign address_c = i_core_stall ? i_address :
|
i_address_nxt; //[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] ;
|
i_address_nxt;
|
|
|
assign address = address_c[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB];
|
assign address = address_c[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB];
|
|
|
|
|
// ======================================
|
// ======================================
|
// Outputs
|
// Outputs
|
// ======================================
|
// ======================================
|
assign o_read_data = wb_hit ? i_wb_read_data :
|
assign o_read_data = wb_hit ? i_wb_read_data :
|
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? hit_rdata [31:0] :
|
read_buf_hit ? read_buf_data_r :
|
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? hit_rdata [63:32] :
|
hit_rdata ;
|
i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? hit_rdata [95:64] :
|
|
hit_rdata [127:96] ;
|
|
|
|
// Don't allow the cache to stall the wb i/f for an exclusive access
|
// Don't allow the cache to stall the wb i/f for an exclusive access
|
// The cache needs a couple of cycles to flush a potential copy of the exclusive
|
// The cache needs a couple of cycles to flush a potential copy of the exclusive
|
// address, but the wb can do the access in parallel. So there is no
|
// address, but the wb can do the access in parallel. So there is no
|
// stall in the state CS_EX_DELETE, even though the cache is out of action.
|
// stall in the state CS_EX_DELETE, even though the cache is out of action.
|
Line 198... |
Line 197... |
|
|
assign o_wb_req = read_miss && c_state == CS_IDLE;
|
assign o_wb_req = read_miss && c_state == CS_IDLE;
|
|
|
|
|
// ======================================
|
// ======================================
|
|
// Read Buffer
|
|
// ======================================
|
|
always@(posedge i_clk)
|
|
if ( i_cache_flush )
|
|
read_buf_valid_r <= 1'd0;
|
|
else if (i_wb_ready && c_state == CS_FILL3)
|
|
begin
|
|
read_buf_data_r <= i_wb_read_data;
|
|
read_buf_addr_r <= miss_address;
|
|
read_buf_valid_r <= 1'd1;
|
|
end
|
|
else if (o_wb_req)
|
|
read_buf_valid_r <= 1'd0;
|
|
|
|
|
|
assign read_buf_hit = read_buf_valid_r && i_address[31:4] == read_buf_addr_r[31:4];
|
|
|
|
// ======================================
|
// Cache State Machine
|
// Cache State Machine
|
// ======================================
|
// ======================================
|
|
|
// Little State Machine to Flush Tag RAMS
|
// Little State Machine to Flush Tag RAMS
|
always @ ( posedge i_clk )
|
always @ ( posedge i_clk )
|
Line 232... |
Line 249... |
CS_IDLE :
|
CS_IDLE :
|
begin
|
begin
|
source_sel <= 1'd1 << C_CORE;
|
source_sel <= 1'd1 << C_CORE;
|
|
|
if ( read_miss )
|
if ( read_miss )
|
c_state <= CS_FILL0;
|
|
end
|
|
|
|
CS_FILL0 :
|
|
begin
|
|
// wb read request asserted, wait for ack
|
|
if ( i_wb_ready )
|
|
c_state <= CS_FILL1;
|
|
end
|
|
|
|
CS_FILL1 :
|
|
begin
|
|
// wb read request asserted, wait for ack
|
|
if ( i_wb_ready )
|
|
c_state <= CS_FILL2;
|
|
end
|
|
|
|
|
|
CS_FILL2 :
|
|
// first read of burst of 4
|
|
// wb read request asserted, wait for ack
|
|
if ( i_wb_ready )
|
|
c_state <= CS_FILL3;
|
c_state <= CS_FILL3;
|
|
end
|
|
|
|
|
CS_FILL3 :
|
CS_FILL3 :
|
begin
|
begin
|
|
// Pick a way to write the cache update into
|
|
// Either pick one of the invalid caches, or if all are valid, then pick
|
|
// one randomly
|
select_way <= next_way;
|
select_way <= next_way;
|
random_num <= {random_num[2], random_num[1], random_num[0],
|
random_num <= {random_num[2], random_num[1], random_num[0],
|
random_num[3]^random_num[2]};
|
random_num[3]^random_num[2]};
|
|
|
// third read of burst of 4
|
// third read of burst of 4
|
// wb read request asserted, wait for ack
|
// wb read request asserted, wait for ack
|
if ( i_wb_ready )
|
if ( i_wb_ready )
|
begin
|
begin
|
c_state <= CS_FILL_COMPLETE;
|
c_state <= CS_FILL_COMPLETE;
|
|
|
// Pick a way to write the cache update into
|
|
// Either pick one of the invalid caches, or if all are valid, then pick
|
|
// one randomly
|
|
|
|
end
|
end
|
end
|
end
|
|
|
|
|
// Write the read fetch data in this cycle
|
// Write the read fetch data in this cycle
|
Line 300... |
Line 294... |
|
|
endcase
|
endcase
|
|
|
|
|
// ======================================
|
// ======================================
|
// Capture WB Block Read - burst of 4 words
|
|
// ======================================
|
|
assign wb_rdata_burst = {i_wb_read_data, wb_rdata_burst_r[127:32]};
|
|
always @ ( posedge i_clk )
|
|
if ( i_wb_ready )
|
|
wb_rdata_burst_r <= wb_rdata_burst;
|
|
|
|
|
|
// ======================================
|
|
// Miss Address
|
// Miss Address
|
// ======================================
|
// ======================================
|
always @ ( posedge i_clk )
|
always @ ( posedge i_clk )
|
if ( c_state == CS_IDLE )
|
if ( c_state == CS_IDLE )
|
miss_address <= i_address;
|
miss_address <= i_address;
|
Line 328... |
Line 313... |
if ( o_wb_req )
|
if ( o_wb_req )
|
wb_address <= i_address;
|
wb_address <= i_address;
|
else if ( i_wb_ready && fill_state )
|
else if ( i_wb_ready && fill_state )
|
wb_address <= {wb_address[31:4], wb_address[3:2] + 1'd1, 2'd0};
|
wb_address <= {wb_address[31:4], wb_address[3:2] + 1'd1, 2'd0};
|
|
|
assign fill_state = c_state == CS_FILL0 || c_state == CS_FILL1 || c_state == CS_FILL2 || c_state == CS_FILL3 ;
|
assign fill_state = c_state == CS_FILL3;
|
assign wb_hit = i_address == wb_address && i_wb_ready && fill_state;
|
assign wb_hit = i_address == wb_address && i_wb_ready && fill_state;
|
|
|
assign tag_address = read_miss_fill ? miss_address [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
|
assign tag_address = read_miss_fill ? miss_address [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] :
|
source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0] :
|
source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0] :
|
address ;
|
address ;
|
Line 344... |
Line 329... |
|
|
assign tag_wdata = read_miss_fill ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} :
|
assign tag_wdata = read_miss_fill ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} :
|
{TAG_WIDTH{1'd0}} ;
|
{TAG_WIDTH{1'd0}} ;
|
|
|
|
|
// Data comes in off the WB bus in wrap4 with the missed data word first
|
|
assign data_wdata = miss_address[3:2] == 2'd0 ? { wb_rdata_burst[127:0] }:
|
|
miss_address[3:2] == 2'd1 ? { wb_rdata_burst[95:0], wb_rdata_burst[127:96] }:
|
|
miss_address[3:2] == 2'd2 ? { wb_rdata_burst[63:0], wb_rdata_burst[127:64] }:
|
|
{ wb_rdata_burst[31:0], wb_rdata_burst[127:32] };
|
|
|
|
|
|
assign read_miss_fill = c_state == CS_FILL3 && i_wb_ready;
|
assign read_miss_fill = c_state == CS_FILL3 && i_wb_ready;
|
|
|
|
|
|
|
assign tag_wenable = read_miss_fill ? 1'd1 :
|
assign tag_wenable = read_miss_fill ? 1'd1 :
|
Line 369... |
Line 347... |
|
|
assign idle_hit = |data_hit_way;
|
assign idle_hit = |data_hit_way;
|
|
|
assign read_miss = enable && !idle_hit && !invalid_read;
|
assign read_miss = enable && !idle_hit && !invalid_read;
|
|
|
assign read_stall = enable && !idle_hit && !rbuf_hit && !wb_hit;
|
assign read_stall = enable && !idle_hit && !wb_hit && !read_buf_hit;
|
|
|
assign cache_busy_stall = (c_state == CS_TURN_AROUND && enable) || c_state == CS_INIT;
|
assign cache_busy_stall = (c_state == CS_TURN_AROUND && enable && !read_buf_hit) || c_state == CS_INIT;
|
|
|
|
|
// ======================================
|
// ======================================
|
// Instantiate RAMS
|
// Instantiate RAMS
|
// ======================================
|
// ======================================
|
Line 425... |
Line 403... |
#(
|
#(
|
.DATA_WIDTH ( CACHE_LINE_WIDTH) ,
|
.DATA_WIDTH ( CACHE_LINE_WIDTH) ,
|
.ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )
|
.ADDRESS_WIDTH ( CACHE_ADDR_WIDTH) )
|
u_data (
|
u_data (
|
.i_clk ( i_clk ),
|
.i_clk ( i_clk ),
|
.i_write_data ( data_wdata ),
|
.i_write_data ( i_wb_read_data ),
|
.i_write_enable ( data_wenable_way[i] ),
|
.i_write_enable ( data_wenable_way[i] ),
|
.i_address ( data_address ),
|
.i_address ( data_address ),
|
.i_byte_enable ( {CACHE_LINE_WIDTH/8{1'd1}} ),
|
.i_byte_enable ( {CACHE_LINE_WIDTH/8{1'd1}} ),
|
.o_read_data ( data_rdata_way[i] )
|
.o_read_data ( data_rdata_way[i] )
|
);
|
);
|