module L1_cache(clk,reset,tag,index,block_offset,find_start,prefetch_hit,L2_cache_hit,cache_hit_count,found_in_cache,updated,done_L1,done_prefetch); | |
parameter way = 4; | |
parameter block_size_byte = 16; | |
parameter cache_size_byte = 32*1024; | |
parameter block_offset_index = $rtoi($ln(block_size_byte)/$ln(2)); | |
parameter set = cache_size_byte/(block_size_byte*way); | |
parameter set_index = $rtoi($ln(set)/$ln(2)); | |
parameter way_width = $rtoi($ln(way)/$ln(2)); | |
parameter cache_line_width = 32-set_index-block_offset_index+1; | |
input clk,find_start,L2_cache_hit,prefetch_hit,reset; | |
input [31-set_index-block_offset_index:0] tag; | |
input [set_index-1:0] index; | |
input [block_offset_index-1:0] block_offset; | |
output reg found_in_cache; | |
output reg [19:0] cache_hit_count; | |
output reg updated,done_L1,done_prefetch; | |
reg [1:0]find_state; | |
reg [1:0]flag; | |
reg bi_flag; | |
reg [way_width:0] way_index; | |
reg [way_width-1:0] hit_way; | |
reg [cache_line_width-1:0] cache [0:set-1][0:way-1]; | |
reg [cache_line_width-1:0] temp_content; | |
reg [cache_line_width-1:0] temp_content1 [0:way-1]; | |
integer i,j; | |
initial | |
begin | |
found_in_cache = 0; | |
cache_hit_count = 0; | |
find_state = 0; | |
flag = 0; | |
bi_flag = 0; | |
updated = 0; | |
done_prefetch = 0; | |
for (i=0;i<set;i=i+1) | |
for (j=0;j<way;j=j+1) | |
cache[i][j] = 0; | |
end | |
always @ (posedge clk) | |
begin | |
if (reset) | |
begin | |
found_in_cache = 0; | |
cache_hit_count = 0; | |
//cache_miss_count = 0; | |
find_state = 0; | |
flag = 0; | |
bi_flag = 0; | |
updated = 0; | |
done_prefetch = 0; | |
for (i=0;i<set;i=i+1) | |
for (j=0;j<way;j=j+1) | |
cache[i][j] = 0; | |
end | |
else | |
begin | |
case (find_state) | |
2'b00: begin | |
found_in_cache = 1'b0; | |
if(find_start) | |
begin | |
find_state = 2'b01; | |
done_L1 = 1'b0; | |
end | |
end | |
2'b01: begin | |
if (done_L1 && !found_in_cache) | |
begin | |
find_state = 2'b10; | |
done_L1 = 1'b0; | |
end | |
else if (done_L1 && found_in_cache) | |
begin | |
find_state = 2'b11; | |
done_L1 = 1'b0; | |
end | |
else | |
begin | |
for (way_index=0;way_index<way;way_index=way_index+1'b1) | |
begin | |
if(cache[index][way_index][cache_line_width-1]) // valid bit | |
begin | |
if(cache[index][way_index][cache_line_width-2:0]==tag) // tag comparison | |
begin | |
found_in_cache = 1'b1; | |
hit_way = way_index; | |
temp_content = cache[index][way_index]; | |
cache_hit_count = cache_hit_count + 1'b1; | |
done_L1 = 1'b1; | |
end | |
end | |
end | |
if (way_index==way&&!found_in_cache) | |
begin | |
//cache_miss_count = cache_miss_count + 1'b1; | |
found_in_cache = 1'b0; | |
done_L1 = 1'b1; | |
end | |
end | |
end | |
2'b10: begin | |
if(done_prefetch) | |
begin | |
find_state= 2'b11; | |
done_prefetch = 1'b0; | |
flag = 1'b0; | |
end | |
else | |
begin | |
if(!flag) | |
flag = 1'b1; | |
else | |
begin | |
if(prefetch_hit&flag) | |
begin | |
flag = 1'b0; | |
cache_hit_count = cache_hit_count + 1'b1; | |
end | |
//else | |
//cache_miss_count = cache_miss_count + 1'b1; | |
done_prefetch = 1'b1; | |
end | |
end | |
end | |
2'b11: begin | |
if(updated) | |
begin | |
find_state = 2'b00; | |
updated = 1'b0; | |
end | |
else | |
begin | |
if(found_in_cache) // hit | |
begin | |
if(hit_way != 0) | |
begin | |
cache[index][hit_way] = cache[index][hit_way-1]; | |
hit_way = hit_way - 1; | |
end | |
else | |
begin | |
cache[index][0] = temp_content; | |
updated = 1'b1; | |
end | |
end | |
else // miss | |
begin | |
for(way_index=way-2;way_index>0;way_index=way_index-1) | |
cache[index][way_index+1] = cache[index][way_index]; | |
cache[index][1] = cache[index][0]; | |
cache[index][0] = {1'b1,tag}; | |
updated = 1'b1; | |
end | |
end | |
end | |
endcase | |
end | |
end | |
endmodule |