@@ -0,0 +1,34 @@ | |||
module TLB_tb(); | |||
reg clock; | |||
reg tlb_en; | |||
reg clear_refer; | |||
//reg [21:0] VPN; | |||
reg [33:0] VA; | |||
//wire [19:0] PPN_o; | |||
wire [31:0] PA; | |||
wire tlb_hit; | |||
tlb uut(.clock(clock),.tlb_en(tlb_en),.clear_refer(clear_refer),.VA(VA),.PA(PA),.tlb_hit(tlb_hit)); | |||
initial begin | |||
clock=1'b0; | |||
tlb_en=1'b1; | |||
clear_refer=1'b1; | |||
//#3 | |||
//clear_refer=1'b0; | |||
VA=34'b1000000000000000000110011010100101; | |||
#50 | |||
VA=34'b0101111000001010010101000111110001; | |||
#50 | |||
VA=34'b1100000000000111100000000000011110; | |||
#50 | |||
VA=34'b0101001010001110100101001110100101; | |||
#50 clear_refer =1'b0; | |||
VA=34'b1010000001111000000000010111111001; | |||
end | |||
always #10 clock = ~clock; | |||
endmodule |
@@ -0,0 +1,164 @@ | |||
module cache_coherence ( input RMS, // read miss, shared | |||
input RME, // read miss, exclusive | |||
input WM, // write miss | |||
input WH, // write hit | |||
input SHR, // snoop hit on read | |||
input SHW, // snoop hit on write | |||
input READ_DONE, | |||
input clk, | |||
input reset, | |||
input send_abort, | |||
input write_back_done, | |||
input AllInvDone, | |||
input [2:0] state, | |||
output reg [2:0] new_state, | |||
output reg Cache_Sector_Fill, Invalidate, AdrRetry | |||
); | |||
parameter | |||
INVALID = 3'b000, | |||
SHARED_1 = 3'b001, | |||
EXCLUSIVE = 3'b010, | |||
MODIFIED = 3'b011, | |||
Cache_Fill = 3'b100, | |||
start_write_back = 3'b101, | |||
WaitUntilAllInv = 3'b110; | |||
// Declare current_state and next_state variable. | |||
reg [2:0] present_state; | |||
reg [2:0] next_state; | |||
always @(present_state or RMS or RME or WM or WH or SHW or READ_DONE | |||
or SHR or write_back_done or AllInvDone or send_abort or state or reset) | |||
begin | |||
Cache_Sector_Fill = 0; // Default values | |||
Invalidate = 0; | |||
AdrRetry = 0; | |||
next_state = present_state; | |||
if (reset) | |||
next_state = state; | |||
else begin | |||
case(present_state) | |||
INVALID: | |||
// ReadMiss (shared/exclusive), Write Miss | |||
if (RMS || RME || WM) | |||
begin | |||
Cache_Sector_Fill = 1; | |||
next_state = Cache_Fill ; | |||
end | |||
else | |||
begin | |||
next_state = INVALID; | |||
end | |||
Cache_Fill: | |||
if (send_abort) | |||
begin | |||
next_state = INVALID; | |||
end | |||
else if (READ_DONE) | |||
begin | |||
if (RMS) | |||
begin | |||
next_state = SHARED_1; | |||
end | |||
else if (RME) | |||
begin | |||
next_state = EXCLUSIVE; | |||
end | |||
else if (WM) | |||
begin | |||
Invalidate = 1; | |||
next_state = WaitUntilAllInv; | |||
end | |||
else | |||
begin | |||
next_state = Cache_Fill ; | |||
end | |||
end | |||
else | |||
begin | |||
next_state = Cache_Fill ; | |||
end | |||
SHARED_1: | |||
if (SHW) // Snoop Hit on a Write. | |||
begin | |||
next_state = INVALID; | |||
end | |||
else if (WH) // Write Hit | |||
begin | |||
Invalidate = 1; | |||
next_state = WaitUntilAllInv; | |||
end | |||
else | |||
begin // Snoop Hit on a Read or Read Hit or any other | |||
next_state = SHARED_1; | |||
end | |||
WaitUntilAllInv: | |||
if (AllInvDone) | |||
begin | |||
next_state = MODIFIED; | |||
end | |||
else | |||
begin | |||
next_state = WaitUntilAllInv; | |||
end | |||
EXCLUSIVE: | |||
if (SHR) // Snoop Hit on a Read: | |||
begin | |||
AdrRetry = 0; | |||
next_state = SHARED_1; | |||
end | |||
else if (SHW) // Snoop Hit on a Write | |||
begin | |||
next_state = INVALID; | |||
end | |||
else if (WH) // Write Hit | |||
begin | |||
next_state = MODIFIED; | |||
end | |||
else | |||
begin // Read Hit | |||
next_state = EXCLUSIVE; | |||
end | |||
MODIFIED: | |||
if (SHW) // Snoop Hit on a Write | |||
begin | |||
next_state = INVALID; | |||
end | |||
else if (SHR) // Snoop Hit on a Read | |||
begin | |||
AdrRetry = 1; | |||
next_state = start_write_back; | |||
end | |||
else // Read Hit or Write Hit or anything else. | |||
begin | |||
next_state = MODIFIED; | |||
end | |||
start_write_back: | |||
if (write_back_done) | |||
begin | |||
next_state = SHARED_1; | |||
end | |||
else | |||
begin | |||
next_state = start_write_back; | |||
end | |||
endcase | |||
end | |||
end | |||
/* Sequential */ | |||
always @(posedge clk) | |||
begin | |||
present_state = next_state; | |||
new_state = next_state; | |||
end | |||
endmodule | |||
@@ -0,0 +1,102 @@ | |||
module cache_coherence_tb; | |||
reg RMS, RME, WM, WH, RH, SHR, SHW, clk, READ_DONE , reset,send_abort, write_back_done, AllInvDone, PA, PB, countE; | |||
reg [2:0] state, SectorInCacheA, SectorInCacheB; | |||
reg [3:0] count; | |||
wire [2:0] new_state; | |||
wire Cache_Sector_Fill, Invalidate, AdrRetry; | |||
cache_coherence uut (.new_state(new_state), .Cache_Sector_Fill(Cache_Sector_Fill), .Invalidate(Invalidate), .AdrRetry(AdrRetry), .RMS(RMS), .RME(RME), .WM(WM), .WH(WH), .SHR(SHR), .SHW(SHW), .state(state), .READ_DONE(READ_DONE), .clk(clk), .reset(reset), .send_abort(send_abort), .write_back_done(write_back_done), .AllInvDone(AllInvDone)); | |||
initial | |||
begin | |||
/* The states of sector in both caches are initialized to Invalid (0). */ | |||
SectorInCacheA = 0; SectorInCacheB = 0; | |||
/* Signals set/rest by cache controller */ | |||
// Write Hit | |||
WH = 0; | |||
// ReadMiss (Shared) | |||
RMS = 0; | |||
// WriteMiss | |||
WM = 0; | |||
// Snoop hit on read operation | |||
SHR = 0; | |||
// Snoop hit on write operation | |||
SHW = 0; | |||
READ_DONE = 0; | |||
AllInvDone = 0; | |||
write_back_done = 0; | |||
send_abort = 0; | |||
state = SectorInCacheA ; PA = 1; PB = 0; RME = 1; | |||
reset = 1; #6 reset = 0; | |||
#40 PA = 0; PB = 1; RME = 0; RMS = 1; state = SectorInCacheB; | |||
reset = 1;#10 reset = 0; | |||
#50 PB = 0; PA = 1; SHR = 1; state = SectorInCacheA; | |||
reset = 1; #10 reset = 0; | |||
#20 SHR = 0; WH = 1; state = SectorInCacheA; | |||
reset = 1; #10 reset = 0; | |||
#50 PA = 0; PB = 1; RMS = 1; WH = 0; state = SectorInCacheB; | |||
reset = 1; #10 reset = 0; | |||
#30 SHR = 1; RMS = 0; PA = 1; PB = 0; state = SectorInCacheA; | |||
reset = 1; #10 reset = 0; | |||
#20 PB = 1; PA = 0; SHR = 0; state = SectorInCacheB; | |||
reset = 1; #10 reset = 0; | |||
// PA states writing back. | |||
#20 PB = 0; PA = 1; state = SectorInCacheA; | |||
reset = 1; #10 reset = 0; | |||
#30 write_back_done = 1; | |||
#10 write_back_done = 0; | |||
// PB retry. | |||
#10 PA = 0; PB = 1; RMS = 1; state = SectorInCacheB; | |||
reset = 1; #10 reset = 0; | |||
// #100 $stop; | |||
// #100 $finish; | |||
end | |||
always @(new_state) | |||
begin | |||
if (PA == 1) SectorInCacheA = new_state ; | |||
else if (PB == 1) SectorInCacheB = new_state ; | |||
end | |||
always @(posedge clk) | |||
begin | |||
if (Invalidate) | |||
begin | |||
#10 SectorInCacheB = 0; | |||
#10 AllInvDone = 1; | |||
#15 AllInvDone = 0; | |||
end | |||
else if (Cache_Sector_Fill) | |||
begin | |||
count = 0; | |||
countE = 1; | |||
// Intialize the Read_Done variable to 0; | |||
READ_DONE = 0; | |||
end | |||
else if (AdrRetry) | |||
begin | |||
countE = 0; | |||
send_abort = 1; | |||
#40 send_abort = 0; | |||
end | |||
end | |||
always @(posedge clk) | |||
begin | |||
if (READ_DONE == 1) READ_DONE = 0; | |||
if (countE == 1) | |||
begin | |||
if ( count == 2 ) | |||
begin | |||
READ_DONE = 1; | |||
countE = 0; | |||
end | |||
else count = count + 1; | |||
end | |||
end | |||
initial clk = 0; | |||
always #5 clk = ~clk ; | |||
endmodule | |||
@@ -0,0 +1,52 @@ | |||
module cache_controller( | |||
input clk, | |||
input [6:0] tag, //tag field | |||
input [5:0] index,//cache line | |||
input wr_en, //write/read signal (1,0) | |||
input flush, //reset cache - set all valid bits to zero | |||
input ready, //data block ready sig from memory | |||
output stall, //stall the processor (1,0) | |||
output wr_en_mem,//write/read signal to memory (1,0) | |||
output update_cache,//update data array | |||
output reg cache_hit //indicate cache hit/loss (1,0) | |||
); | |||
integer i; //used to flush and initialize tag and validity fields | |||
reg [6:0] tag_field [63:0]; | |||
reg validity_field [63:0]; | |||
initial begin | |||
for (i=0;i<64;i=i+1) begin | |||
validity_field[i]=1'b0; | |||
tag_field[i]=1'b0; | |||
end | |||
end | |||
assign update_cache=ready; | |||
assign stall=~(cache_hit|wr_en); | |||
assign wr_en_mem=wr_en; | |||
always @(posedge clk) begin | |||
if (validity_field[index]) cache_hit=(tag_field[index]==tag); | |||
else cache_hit=0; | |||
if (~wr_en) begin | |||
if (ready) begin | |||
validity_field[index]=1; | |||
tag_field[index]=tag; | |||
end | |||
end | |||
if (flush) begin | |||
for (i=0;i<64;i=i+1) begin | |||
validity_field[i]=1'b0; | |||
end | |||
end | |||
end | |||
endmodule | |||
@@ -0,0 +1,47 @@ | |||
module cache_controller_tb; | |||
reg clk; | |||
reg [6:0] tag; //tag field | |||
reg [5:0] index; //cache line | |||
reg wr_en; //write/read signal (1,0) | |||
reg flush; //reset cache - set all valid bits to zero | |||
reg ready; //data block ready sig from memory | |||
wire stall; //stall the processor (1,0) | |||
wire wr_en_mem; //write/read signal to memory (1,0) | |||
wire update_cache; //update data array | |||
wire cache_hit; | |||
cache_controller uut(.clk(clk),.tag(tag),.index(index),.wr_en(wr_en),.flush(flush),.ready(ready),.stall(stall),.wr_en_mem(wr_en_mem),.update_cache(update_cache),.cache_hit(cache_hit)); | |||
initial begin | |||
clk=1'b0; | |||
wr_en=1'b1; | |||
ready=1'b1; | |||
tag=7'h00; | |||
index=6'h01; | |||
#10 | |||
tag=7'h24; | |||
index=6'h02; | |||
#10 | |||
tag=7'h26; | |||
index=6'h45; | |||
#10 | |||
tag=7'h56; | |||
index=6'h08; | |||
#10 | |||
wr_en=1'b0; | |||
tag=7'h00; | |||
index=6'h01; | |||
#10 | |||
tag=7'h24; | |||
index=6'h02; | |||
#10 | |||
tag=7'h26; | |||
index=6'h45; | |||
#10 | |||
tag=7'h56; | |||
index=6'h08; | |||
#10 flush=1'b1; | |||
end | |||
always #5 clk=~clk; | |||
endmodule | |||
@@ -0,0 +1,583 @@ | |||
`define TAG 31:13 // position of tag in address | |||
`define INDEX 12:3 // position of index in address | |||
`define OFFSET 2:0 // position of offset in address | |||
module data_cache | |||
#( | |||
// Cache parameters | |||
parameter SIZE = 32*1024*8, | |||
parameter NWAYS = 8, | |||
parameter NSETS =1024 , | |||
parameter BLOCK_SIZE = 64, | |||
parameter WIDTH = 32, | |||
// Memory related paramter, make sure it matches memory module | |||
parameter MWIDTH = 64, // same as block size | |||
// More cache related parameters | |||
parameter INDEX_WIDTH = 10, | |||
parameter TAG_WIDTH = 19, | |||
parameter OFFSET_WIDTH = 3, | |||
parameter WORD1 = 3, | |||
parameter WORD2 = 7 | |||
) | |||
( | |||
input wire clock, | |||
input wire [WIDTH-1:0] address, // address form CPU | |||
input wire [WIDTH-1:0] din, // data from CPU (if st inst) | |||
input wire rden, // 1 if ld instruction | |||
input wire wren, // 1 if st instruction | |||
output wire hit_miss, // 1 if hit, 0 while handling miss | |||
output wire [WIDTH-1:0] q, // data from cache to CPU | |||
output wire [MWIDTH-1:0] mdout, // data from cache to memory | |||
output wire [WIDTH-1:0] mrdaddress, // memory read address | |||
output wire mrden, // read enable, 1 if reading from memory | |||
output wire [WIDTH-1:0] mwraddress, // memory write address | |||
output wire mwren, // write enable, 1 if writing to memory | |||
input wire [MWIDTH-1:0] mq // data coming from memory | |||
); | |||
/******************************************************************* | |||
* Global Parameters and Initializations | |||
*******************************************************************/ | |||
// WAY 1 cache data | |||
reg valid1 [0:NSETS-1]; | |||
reg dirty1 [0:NSETS-1]; | |||
reg [1:0] lru1 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag1 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem1 [0:NSETS-1]; | |||
// WAY 2 cache data | |||
reg valid2 [0:NSETS-1]; | |||
reg dirty2 [0:NSETS-1]; | |||
reg [1:0] lru2 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag2 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem2 [0:NSETS-1]; | |||
// WAY 3 cache data | |||
reg valid3 [0:NSETS-1]; | |||
reg dirty3 [0:NSETS-1]; | |||
reg [1:0] lru3 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag3 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem3 [0:NSETS-1]; | |||
// WAY 4 cache data | |||
reg valid4 [0:NSETS-1]; | |||
reg dirty4 [0:NSETS-1]; | |||
reg [1:0] lru4 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag4 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem4 [0:NSETS-1]; | |||
// WAY 5 cache data | |||
reg valid5 [0:NSETS-1]; | |||
reg dirty5 [0:NSETS-1]; | |||
reg [1:0] lru5 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag5 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem5 [0:NSETS-1]; | |||
// WAY 6 cache data | |||
reg valid6 [0:NSETS-1]; | |||
reg dirty6 [0:NSETS-1]; | |||
reg [1:0] lru6 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag6 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem6 [0:NSETS-1]; | |||
// WAY 7 cache data | |||
reg valid7 [0:NSETS-1]; | |||
reg dirty7 [0:NSETS-1]; | |||
reg [1:0] lru7 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag7 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem7 [0:NSETS-1]; /*synthesis ramstyle = "M20K" */ | |||
// WAY 8 cache data | |||
reg valid8 [0:NSETS-1]; | |||
reg dirty8 [0:NSETS-1]; | |||
reg [1:0] lru8 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag8 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem8 [0:NSETS-1]; | |||
// initialize the cache to zero | |||
integer k; | |||
initial | |||
begin | |||
for(k = 0; k < NSETS; k = k +1) | |||
begin | |||
valid1[k] = 0; | |||
valid2[k] = 0; | |||
valid3[k] = 0; | |||
valid4[k] = 0; | |||
valid5[k] = 0; | |||
valid6[k] = 0; | |||
valid7[k] = 0; | |||
valid8[k] = 0; | |||
dirty1[k] = 0; | |||
dirty2[k] = 0; | |||
dirty3[k] = 0; | |||
dirty4[k] = 0; | |||
dirty5[k] = 0; | |||
dirty6[k] = 0; | |||
dirty7[k] = 0; | |||
dirty8[k] = 0; | |||
lru1[k] = 2'b00; | |||
lru2[k] = 2'b00; | |||
lru3[k] = 2'b00; | |||
lru4[k] = 2'b00; | |||
lru5[k] = 2'b00; | |||
lru6[k] = 2'b00; | |||
lru7[k] = 2'b00; | |||
lru8[k] = 2'b00; | |||
end | |||
end | |||
// internal registers | |||
reg _hit_miss = 1'b0; | |||
reg [WIDTH-1:0] _q = {WIDTH{1'b0}}; | |||
reg [MWIDTH-1:0] _mdout = {MWIDTH{1'b0}}; | |||
reg [WIDTH-1:0] _mwraddress = {WIDTH{1'b0}}; | |||
reg _mwren = 1'b0; | |||
// output assignments of internal registers | |||
assign hit_miss = _hit_miss; | |||
assign mrden = !((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
|| (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
|| (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
|| (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
|| (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
|| (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
|| (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
|| (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); | |||
assign mwren = _mwren; | |||
assign mdout = _mdout; | |||
assign mrdaddress = {address[`TAG],address[`INDEX]}; | |||
assign mwraddress = _mwraddress; | |||
assign q = _q; | |||
// state parameters | |||
localparam idle = 1'b0; // receive requests from CPU | |||
localparam miss = 1'b1; // write back dirty block and put in new data | |||
// state register | |||
reg currentState = idle; | |||
/******************************************************************* | |||
* State Machine | |||
*******************************************************************/ | |||
always @(posedge clock) | |||
begin | |||
case (currentState) | |||
idle: begin | |||
// reset write enable, if it was turned on | |||
_mwren <= 0; | |||
// set _hit_miss register | |||
_hit_miss <= ((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
|| (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
|| (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
|| (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
|| (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
|| (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
|| (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
|| (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); | |||
// do nothing on a null request | |||
if(~rden && ~wren) currentState <= idle; | |||
// check way 1 | |||
else if(valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem1[address[`INDEX]][WIDTH-1:0] : mem1[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty1[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem1[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem1[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru2[address[`INDEX]] <= lru1[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru1[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru1[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru1[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru1[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru1[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru1[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru1[address[`INDEX]] <= 0; | |||
end | |||
// check way 2 | |||
else if(valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem2[address[`INDEX]][WIDTH-1:0] : mem2[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty2[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem2[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem2[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru2[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru2[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru2[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru2[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru2[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru2[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru2[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru2[address[`INDEX]] <= 0; | |||
end | |||
// check way 3 | |||
else if(valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem3[address[`INDEX]][WIDTH-1:0] : mem3[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty3[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem3[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem3[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru3[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru3[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru3[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru3[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru3[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru3[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru3[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru3[address[`INDEX]] <= 0; | |||
end | |||
// check way 4 | |||
else if(valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem4[address[`INDEX]][WIDTH-1:0] : mem4[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty4[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem4[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem4[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru4[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru4[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru4[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru4[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru4[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru4[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru4[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru4[address[`INDEX]] <= 0; | |||
end | |||
// check way 5 | |||
else if(valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem5[address[`INDEX]][WIDTH-1:0] : mem5[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty5[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem5[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem5[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru5[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru5[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru5[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru5[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru5[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru5[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru5[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru5[address[`INDEX]] <= 0; | |||
end | |||
// check way 6 | |||
else if(valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem6[address[`INDEX]][WIDTH-1:0] : mem6[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty6[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem6[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem6[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru6[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru6[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru6[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru6[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru6[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru6[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru6[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru6[address[`INDEX]] <= 0; | |||
end | |||
// check way 7 | |||
else if(valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem7[address[`INDEX]][WIDTH-1:0] : mem7[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty7[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem7[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem7[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru7[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru7[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru7[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru7[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru7[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru7[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru7[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru7[address[`INDEX]] <= 0; | |||
end | |||
// check way 8 | |||
else if(valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= (address[`OFFSET] <= WORD1) ? mem8[address[`INDEX]][WIDTH-1:0] : mem8[address[`INDEX]][2*WIDTH-1:WIDTH]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
dirty8[address[`INDEX]] <= 1; | |||
if(address[`OFFSET] <= WORD1) mem8[address[`INDEX]][WIDTH-1:0] <= din; | |||
else mem8[address[`INDEX]][2*WIDTH-1:WIDTH] <= din; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru8[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru8[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru8[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru8[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru8[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru8[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru8[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
lru8[address[`INDEX]] <= 0; | |||
end | |||
// miss | |||
else currentState <= miss; | |||
end | |||
miss: begin | |||
// one of the ways is invalid -- no need to evict | |||
if(~valid1[address[`INDEX]]) | |||
begin | |||
mem1[address[`INDEX]] <= mq; | |||
tag1[address[`INDEX]] <= address[`TAG]; | |||
dirty1[address[`INDEX]] <= 0; | |||
valid1[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid2[address[`INDEX]]) | |||
begin | |||
mem2[address[`INDEX]] <= mq; | |||
tag2[address[`INDEX]] <= address[`TAG]; | |||
dirty2[address[`INDEX]] <= 0; | |||
valid2[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid3[address[`INDEX]]) | |||
begin | |||
mem3[address[`INDEX]] <= mq; | |||
tag3[address[`INDEX]] <= address[`TAG]; | |||
dirty3[address[`INDEX]] <= 0; | |||
valid3[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid4[address[`INDEX]]) | |||
begin | |||
mem4[address[`INDEX]] <= mq; | |||
tag4[address[`INDEX]] <= address[`TAG]; | |||
dirty4[address[`INDEX]] <= 0; | |||
valid4[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid5[address[`INDEX]]) | |||
begin | |||
mem5[address[`INDEX]] <= mq; | |||
tag5[address[`INDEX]] <= address[`TAG]; | |||
dirty5[address[`INDEX]] <= 0; | |||
valid5[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid6[address[`INDEX]]) | |||
begin | |||
mem6[address[`INDEX]] <= mq; | |||
tag6[address[`INDEX]] <= address[`TAG]; | |||
dirty6[address[`INDEX]] <= 0; | |||
valid6[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid7[address[`INDEX]]) | |||
begin | |||
mem7[address[`INDEX]] <= mq; | |||
tag7[address[`INDEX]] <= address[`TAG]; | |||
dirty7[address[`INDEX]] <= 0; | |||
valid7[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid8[address[`INDEX]]) | |||
begin | |||
mem8[address[`INDEX]] <= mq; | |||
tag8[address[`INDEX]] <= address[`TAG]; | |||
dirty8[address[`INDEX]] <= 0; | |||
valid8[address[`INDEX]] <= 1; | |||
end | |||
// way 1 is LRU | |||
else if(lru1[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty1[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag1[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem1[address[`INDEX]]; | |||
end | |||
mem1[address[`INDEX]] <= mq; | |||
tag1[address[`INDEX]] <= address[`TAG]; | |||
dirty1[address[`INDEX]] <= 0; | |||
valid1[address[`INDEX]] <= 1; | |||
end | |||
// way 2 is LRU | |||
else if(lru2[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty2[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag2[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem2[address[`INDEX]]; | |||
end | |||
mem2[address[`INDEX]] <= mq; | |||
tag2[address[`INDEX]] <= address[`TAG]; | |||
dirty2[address[`INDEX]] <= 0; | |||
valid2[address[`INDEX]] <= 1; | |||
end | |||
// way 3 is LRU | |||
else if(lru3[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty3[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag3[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem3[address[`INDEX]]; | |||
end | |||
mem3[address[`INDEX]] <= mq; | |||
tag3[address[`INDEX]] <= address[`TAG]; | |||
dirty3[address[`INDEX]] <= 0; | |||
valid3[address[`INDEX]] <= 1; | |||
end | |||
// way 4 is LRU | |||
else if(lru4[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty4[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag4[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem4[address[`INDEX]]; | |||
end | |||
mem4[address[`INDEX]] <= mq; | |||
tag4[address[`INDEX]] <= address[`TAG]; | |||
dirty4[address[`INDEX]] <= 0; | |||
valid4[address[`INDEX]] <= 1; | |||
end | |||
// way 5 is LRU | |||
else if(lru5[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty5[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag5[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem5[address[`INDEX]]; | |||
end | |||
mem5[address[`INDEX]] <= mq; | |||
tag5[address[`INDEX]] <= address[`TAG]; | |||
dirty5[address[`INDEX]] <= 0; | |||
valid5[address[`INDEX]] <= 1; | |||
end | |||
// way 6 is LRU | |||
else if(lru6[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty6[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag6[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem6[address[`INDEX]]; | |||
end | |||
mem6[address[`INDEX]] <= mq; | |||
tag6[address[`INDEX]] <= address[`TAG]; | |||
dirty6[address[`INDEX]] <= 0; | |||
valid6[address[`INDEX]] <= 1; | |||
end | |||
// way 7 is LRU | |||
else if(lru7[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty7[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag7[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem4[address[`INDEX]]; | |||
end | |||
mem7[address[`INDEX]] <= mq; | |||
tag7[address[`INDEX]] <= address[`TAG]; | |||
dirty7[address[`INDEX]] <= 0; | |||
valid7[address[`INDEX]] <= 1; | |||
end | |||
// way 8 is LRU | |||
else if(lru8[address[`INDEX]] == 3) | |||
begin | |||
// dirty block writeback | |||
if(dirty8[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag8[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem8[address[`INDEX]]; | |||
end | |||
mem8[address[`INDEX]] <= mq; | |||
tag8[address[`INDEX]] <= address[`TAG]; | |||
dirty8[address[`INDEX]] <= 0; | |||
valid8[address[`INDEX]] <= 1; | |||
end | |||
currentState <= idle; | |||
end | |||
default: currentState <= idle; | |||
endcase | |||
end | |||
endmodule | |||
@@ -0,0 +1,236 @@ | |||
module data_cache_tb; | |||
reg clk; | |||
wire [31:0] data_in; | |||
wire [63:0] data_out; | |||
wire [31:0] rd_addr; | |||
wire rd_en; | |||
wire [31:0] wr_addr; | |||
wire wr_en; | |||
reg [31:0] d_cache_addr = 0; | |||
reg [63:0] d_cache_din = 0; | |||
reg d_cache_rden = 0; | |||
reg d_cache_wren = 0; | |||
wire d_cache_hit_miss; | |||
wire [31:0] d_cache_q; | |||
data_cache DUT_CACHE ( | |||
.clock(clk), | |||
.address(d_cache_addr), | |||
.din(d_cache_din), | |||
.rden(d_cache_rden), | |||
.wren(d_cache_wren), | |||
.hit_miss(d_cache_hit_miss), | |||
.q(d_cache_q), | |||
.mdout(data_in), | |||
.mrdaddress(rd_addr), | |||
.mrden(rd_en), | |||
.mwraddress(wr_addr), | |||
.mwren(wr_en), | |||
.mq(data_out) | |||
); | |||
defparam DUT_CACHE.SIZE = 32*1024*8; | |||
defparam DUT_CACHE.NWAYS = 8; | |||
defparam DUT_CACHE.NSETS = 1024; | |||
defparam DUT_CACHE.BLOCK_SIZE = 64; | |||
defparam DUT_CACHE.WIDTH = 32; | |||
defparam DUT_CACHE.MWIDTH = 64; | |||
main_memory DUT_MEM ( | |||
.clock(clk), | |||
.data(data_in), | |||
.rdaddress(rd_addr), | |||
.rden(rd_en), | |||
.wraddress(wr_addr), | |||
.wren(wr_en), | |||
.q(data_out) | |||
); | |||
defparam DUT_MEM.WIDTH = 32; | |||
defparam DUT_MEM.DEPTH = 128; | |||
defparam DUT_MEM.FILE = "main_mem_text.txt"; | |||
always | |||
begin | |||
// basic writeback ///////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 32'hBADDBEEF; | |||
d_cache_rden <= 0; | |||
d_cache_wren <= 1; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h10000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h20000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h30000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss and eviction | |||
d_cache_addr <= 32'h40000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss (evicted) | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h30000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
// repeated writes (w/ offset) ///////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 32'hBADDBEEF; | |||
d_cache_rden <= 0; | |||
d_cache_wren <= 1; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h0000000B; | |||
d_cache_din <= 32'h00000000; | |||
d_cache_rden <= 0; | |||
d_cache_wren <= 1; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h0000000C; | |||
d_cache_din <= 32'hAAAAAAAA; | |||
d_cache_rden <= 0; | |||
d_cache_wren <= 1; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h10000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h20000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h30000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss and eviction | |||
d_cache_addr <= 32'h40000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss (evicted) | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h10000008; | |||
d_cache_din <= 32'hBADDBEEF; | |||
d_cache_rden <= 0; | |||
d_cache_wren <= 1; | |||
// repeated reads (w/ offset) ///////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
# 100; // This should be a miss | |||
d_cache_addr <= 32'h00000008; | |||
d_cache_din <= 0; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h0000000B; | |||
d_cache_din <= 32'hBADDBEEF; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h0000000C; | |||
d_cache_din <= 32'h00000000; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
d_cache_addr <= 32'h0000000F; | |||
d_cache_din <= 32'hAAAAAAAA; | |||
d_cache_rden <= 1; | |||
d_cache_wren <= 0; | |||
#50; | |||
$finish; | |||
end | |||
initial | |||
begin | |||
$monitor("time=%4d | addr=%10d | hm=%b | q=%08x | way1=%08h | way2=%08h | way3=%08h | way4=%08h | way5=%08h | way6=%08h | way7=%08h | way8=%08h | mem[1]=%08h | lru1=%d | lru2=%d | lru3=%d | lru4=%d | lru5=%d | lru6=%d | lru7=%d | lru8=%d " ,$time,d_cache_addr,d_cache_hit_miss,DUT_CACHE.q,DUT_CACHE.mem1[1],DUT_CACHE.mem2[1],DUT_CACHE.mem3[1],DUT_CACHE.mem4[1],DUT_CACHE.mem5[1],DUT_CACHE.mem6[1],DUT_CACHE.mem7[1],DUT_CACHE.mem8[1],DUT_MEM.mem[1],DUT_CACHE.lru1[1],DUT_CACHE.lru2[1],DUT_CACHE.lru3[1],DUT_CACHE.lru4[1],DUT_CACHE.lru5[1],DUT_CACHE.lru6[1],DUT_CACHE.lru7[1],DUT_CACHE.lru8[1]); | |||
end | |||
always | |||
begin | |||
clk = 1'b1; | |||
#5; | |||
clk = 1'b0; | |||
#5; | |||
end | |||
endmodule |
@@ -0,0 +1,576 @@ | |||
`define TAG 31:13 // position of tag in address | |||
`define INDEX 12:2 // position of index in address | |||
`define OFFSET 1:0 // position of offset in address | |||
module inst_cache | |||
#( | |||
// Cache parameters | |||
parameter SIZE = 16*1024*8, | |||
parameter NWAYS = 8, | |||
parameter NSETS = 2048, | |||
parameter BLOCK_SIZE = 32, | |||
parameter WIDTH = 32, | |||
// Memory related paramter, make sure it matches memory module | |||
parameter MWIDTH = 32, // same as block size | |||
// More cache related parameters | |||
parameter INDEX_WIDTH = 11, | |||
parameter TAG_WIDTH = 19, | |||
parameter OFFSET_WIDTH = 2 | |||
) | |||
( | |||
input wire clock, | |||
input wire [WIDTH-1:0] address, // address form CPU | |||
input wire [WIDTH-1:0] din, // data from CPU (if st inst) | |||
input wire rden, // 1 if ld instruction | |||
input wire wren, // 1 if st instruction | |||
output wire hit_miss, // 1 if hit, 0 while handling miss | |||
output wire [WIDTH-1:0] q, // data from cache to CPU | |||
output wire [MWIDTH-1:0] mdout, // data from cache to memory | |||
output wire [WIDTH-1:0] mrdaddress, // memory read address | |||
output wire mrden, // read enable, 1 if reading from memory | |||
output wire [WIDTH-1:0] mwraddress, // memory write address | |||
output wire mwren, // write enable, 1 if writing to memory | |||
input wire [MWIDTH-1:0] mq // data coming from memory | |||
); | |||
/*********************** | |||
* Global Parameters and Initializations | |||
***********************/ | |||
// WAY 1 cache data | |||
reg valid1 [0:NSETS-1]; | |||
reg dirty1 [0:NSETS-1]; | |||
reg lru1 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag1 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem1 [0:NSETS-1] ; | |||
// WAY 2 cache data | |||
reg valid2 [0:NSETS-1]; | |||
reg dirty2 [0:NSETS-1]; | |||
reg lru2 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag2 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem2 [0:NSETS-1] ; | |||
// WAY 3 cache data | |||
reg valid3 [0:NSETS-1]; | |||
reg dirty3 [0:NSETS-1]; | |||
reg lru3 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag3 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem3 [0:NSETS-1] ; | |||
// WAY 4 cache data | |||
reg valid4 [0:NSETS-1]; | |||
reg dirty4 [0:NSETS-1]; | |||
reg lru4 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag4 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem4 [0:NSETS-1]; | |||
// WAY 5 cache data | |||
reg valid5 [0:NSETS-1]; | |||
reg dirty5 [0:NSETS-1]; | |||
reg lru5 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag5 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem5 [0:NSETS-1] ; | |||
// WAY 6 cache data | |||
reg valid6 [0:NSETS-1]; | |||
reg dirty6 [0:NSETS-1]; | |||
reg lru6 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag6 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem6 [0:NSETS-1]; | |||
// WAY 7 cache data | |||
reg valid7 [0:NSETS-1]; | |||
reg dirty7 [0:NSETS-1]; | |||
reg lru7 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag7 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem7 [0:NSETS-1] ; | |||
// WAY 8 cache data | |||
reg valid8 [0:NSETS-1]; | |||
reg dirty8 [0:NSETS-1]; | |||
reg lru8 [0:NSETS-1]; | |||
reg [TAG_WIDTH-1:0] tag8 [0:NSETS-1]; | |||
reg [MWIDTH-1:0] mem8 [0:NSETS-1] ; | |||
// initialize everything to 0 | |||
integer k; | |||
initial | |||
begin | |||
for(k = 0; k < NSETS; k = k +1) | |||
begin | |||
valid1[k] = 0; | |||
valid2[k] = 0; | |||
valid3[k] = 0; | |||
valid4[k] = 0; | |||
valid5[k] = 0; | |||
valid6[k] = 0; | |||
valid7[k] = 0; | |||
valid8[k] = 0; | |||
dirty1[k] = 0; | |||
dirty2[k] = 0; | |||
dirty3[k] = 0; | |||
dirty4[k] = 0; | |||
dirty5[k] = 0; | |||
dirty6[k] = 0; | |||
dirty7[k] = 0; | |||
dirty8[k] = 0; | |||
lru1[k] = 0; | |||
lru2[k] = 0; | |||
lru3[k] = 0; | |||
lru4[k] = 0; | |||
lru5[k] = 0; | |||
lru6[k] = 0; | |||
lru7[k] = 0; | |||
lru8[k] = 0; | |||
end | |||
end | |||
// internal registers | |||
reg _hit_miss = 1'b0; | |||
reg [WIDTH-1:0] _q = {WIDTH{1'b0}}; | |||
reg [MWIDTH-1:0] _mdout = {MWIDTH{1'b0}}; | |||
reg [WIDTH-1:0] _mwraddress = {WIDTH{1'b0}}; | |||
reg _mwren = 1'b0; | |||
// output assignments of internal registers | |||
assign hit_miss = _hit_miss; | |||
assign mrden = !((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
|| (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
|| (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
|| (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
|| (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
|| (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
|| (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
|| (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); | |||
assign mwren = _mwren; | |||
assign mdout = _mdout; | |||
assign mrdaddress = {address[`TAG],address[`INDEX]}; | |||
assign mwraddress = _mwraddress; | |||
assign q = _q; | |||
// state parameters | |||
localparam idle = 1'b0; // receive requests from CPU | |||
localparam miss = 1'b1; // miss state: write back dirty block and request memory data | |||
// state register | |||
reg currentState = idle; | |||
/*********************** | |||
* State Machine | |||
***********************/ | |||
always @(posedge clock) | |||
begin | |||
case (currentState) | |||
idle: begin | |||
// reset write enable, if it was turned on | |||
_mwren <= 0; | |||
// set _hit_miss register | |||
_hit_miss <= ((valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
|| (valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
|| (valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
|| (valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
|| (valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
|| (valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
|| (valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
|| (valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG]))); | |||
// do nothing on null request | |||
if(~rden && ~wren) currentState <= idle; | |||
// check way 1 | |||
else if(valid1[address[`INDEX]] && (tag1[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem1[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem1[address[`INDEX]] <= din; | |||
dirty1[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
lru1[address[`INDEX]] <= 0; | |||
if(lru2[address[`INDEX]] <= lru1[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru1[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru1[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru1[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru1[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru1[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru1[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
end | |||
// check way 2 | |||
else if(valid2[address[`INDEX]] && (tag2[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem2[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem2[address[`INDEX]] <= din; | |||
dirty2[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru2[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru2[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru2[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru2[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru2[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru2[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru2[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru2[address[`INDEX]] <= 0; | |||
end | |||
// check way 3 | |||
else if(valid3[address[`INDEX]] && (tag3[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem3[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem3[address[`INDEX]] <= din; | |||
dirty3[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru3[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru3[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru3[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru3[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru3[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru3[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru3[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru3[address[`INDEX]] <= 0; | |||
end | |||
// check way 4 | |||
else if(valid4[address[`INDEX]] && (tag4[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem4[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem4[address[`INDEX]] <= din; | |||
dirty4[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru4[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru4[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru4[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru4[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru4[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru4[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru4[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru4[address[`INDEX]] <= 0; | |||
end | |||
// check way 5 | |||
else if(valid5[address[`INDEX]] && (tag5[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem5[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem5[address[`INDEX]] <= din; | |||
dirty5[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru5[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru5[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru5[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru5[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru5[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru5[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru5[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru5[address[`INDEX]] <= 0; | |||
end | |||
// check way 6 | |||
else if(valid6[address[`INDEX]] && (tag6[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem6[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem6[address[`INDEX]] <= din; | |||
dirty6[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru6[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru6[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru6[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru6[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru6[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru6[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru6[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru6[address[`INDEX]] <= 0; | |||
end | |||
// check way 7 | |||
else if(valid7[address[`INDEX]] && (tag7[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem7[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem7[address[`INDEX]] <= din; | |||
dirty7[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru7[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru7[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru7[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru7[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru7[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru7[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru8[address[`INDEX]] <= lru7[address[`INDEX]]) lru8[address[`INDEX]] <= lru8[address[`INDEX]] + 1; | |||
lru7[address[`INDEX]] <= 0; | |||
end | |||
// check way 8 | |||
else if(valid8[address[`INDEX]] && (tag8[address[`INDEX]] == address[`TAG])) | |||
begin | |||
// read hit | |||
if(rden) _q <= mem8[address[`INDEX]]; | |||
// write hit | |||
else if(wren) | |||
begin | |||
_q = {WIDTH{1'b0}}; | |||
mem8[address[`INDEX]] <= din; | |||
dirty8[address[`INDEX]] <= 1; | |||
end | |||
// update LRU data | |||
if(lru1[address[`INDEX]] <= lru8[address[`INDEX]]) lru1[address[`INDEX]] <= lru1[address[`INDEX]] + 1; | |||
if(lru2[address[`INDEX]] <= lru8[address[`INDEX]]) lru2[address[`INDEX]] <= lru2[address[`INDEX]] + 1; | |||
if(lru3[address[`INDEX]] <= lru8[address[`INDEX]]) lru3[address[`INDEX]] <= lru3[address[`INDEX]] + 1; | |||
if(lru4[address[`INDEX]] <= lru8[address[`INDEX]]) lru4[address[`INDEX]] <= lru4[address[`INDEX]] + 1; | |||
if(lru5[address[`INDEX]] <= lru8[address[`INDEX]]) lru5[address[`INDEX]] <= lru5[address[`INDEX]] + 1; | |||
if(lru6[address[`INDEX]] <= lru8[address[`INDEX]]) lru6[address[`INDEX]] <= lru6[address[`INDEX]] + 1; | |||
if(lru7[address[`INDEX]] <= lru8[address[`INDEX]]) lru7[address[`INDEX]] <= lru7[address[`INDEX]] + 1; | |||
lru8[address[`INDEX]] <= 0; | |||
end | |||
// miss | |||
else currentState <= miss; | |||
end | |||
miss: begin | |||
// one of the ways is invalid -- no need to evict | |||
if(~valid1[address[`INDEX]]) | |||
begin | |||
mem1[address[`INDEX]] <= mq; | |||
tag1[address[`INDEX]] <= address[`TAG]; | |||
dirty1[address[`INDEX]] <= 0; | |||
valid1[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid2[address[`INDEX]]) | |||
begin | |||
mem2[address[`INDEX]] <= mq; | |||
tag2[address[`INDEX]] <= address[`TAG]; | |||
dirty2[address[`INDEX]] <= 0; | |||
valid2[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid3[address[`INDEX]]) | |||
begin | |||
mem3[address[`INDEX]] <= mq; | |||
tag3[address[`INDEX]] <= address[`TAG]; | |||
dirty3[address[`INDEX]] <= 0; | |||
valid3[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid4[address[`INDEX]]) | |||
begin | |||
mem4[address[`INDEX]] <= mq; | |||
tag4[address[`INDEX]] <= address[`TAG]; | |||
dirty4[address[`INDEX]] <= 0; | |||
valid4[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid5[address[`INDEX]]) | |||
begin | |||
mem5[address[`INDEX]] <= mq; | |||
tag5[address[`INDEX]] <= address[`TAG]; | |||
dirty5[address[`INDEX]] <= 0; | |||
valid5[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid6[address[`INDEX]]) | |||
begin | |||
mem6[address[`INDEX]] <= mq; | |||
tag6[address[`INDEX]] <= address[`TAG]; | |||
dirty6[address[`INDEX]] <= 0; | |||
valid6[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid7[address[`INDEX]]) | |||
begin | |||
mem7[address[`INDEX]] <= mq; | |||
tag7[address[`INDEX]] <= address[`TAG]; | |||
dirty7[address[`INDEX]] <= 0; | |||
valid7[address[`INDEX]] <= 1; | |||
end | |||
else if(~valid8[address[`INDEX]]) | |||
begin | |||
mem8[address[`INDEX]] <= mq; | |||
tag8[address[`INDEX]] <= address[`TAG]; | |||
dirty8[address[`INDEX]] <= 0; | |||
valid8[address[`INDEX]] <= 1; | |||
end | |||
// way 1 is LRU | |||
else if(lru1[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty1[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag1[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem1[address[`INDEX]]; | |||
end | |||
mem1[address[`INDEX]] <= mq; | |||
tag1[address[`INDEX]] <= address[`TAG]; | |||
dirty1[address[`INDEX]] <= 0; | |||
valid1[address[`INDEX]] <= 1; | |||
end | |||
// way 2 is LRU | |||
else if(lru2[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty2[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag2[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem2[address[`INDEX]]; | |||
end | |||
mem2[address[`INDEX]] <= mq; | |||
tag2[address[`INDEX]] <= address[`TAG]; | |||
dirty2[address[`INDEX]] <= 0; | |||
valid2[address[`INDEX]] <= 1; | |||
end | |||
// way 3 is LRU | |||
else if(lru3[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty3[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag3[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem3[address[`INDEX]]; | |||
end | |||
mem3[address[`INDEX]] <= mq; | |||
tag3[address[`INDEX]] <= address[`TAG]; | |||
dirty3[address[`INDEX]] <= 0; | |||
valid3[address[`INDEX]] <= 1; | |||
end | |||
// way 4 is LRU | |||
else if(lru4[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty4[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag4[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem4[address[`INDEX]]; | |||
end | |||
mem4[address[`INDEX]] <= mq; | |||
tag4[address[`INDEX]] <= address[`TAG]; | |||
dirty4[address[`INDEX]] <= 0; | |||
valid4[address[`INDEX]] <= 1; | |||
end | |||
// way 5 is LRU | |||
else if(lru5[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty5[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag5[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem5[address[`INDEX]]; | |||
end | |||
mem5[address[`INDEX]] <= mq; | |||
tag5[address[`INDEX]] <= address[`TAG]; | |||
dirty5[address[`INDEX]] <= 0; | |||
valid5[address[`INDEX]] <= 1; | |||
end | |||
// way 6 is LRU | |||
else if(lru6[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty6[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag6[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem6[address[`INDEX]]; | |||
end | |||
mem6[address[`INDEX]] <= mq; | |||
tag6[address[`INDEX]] <= address[`TAG]; | |||
dirty6[address[`INDEX]] <= 0; | |||
valid6[address[`INDEX]] <= 1; | |||
end | |||
// way 7 is LRU | |||
else if(lru7[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty7[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag7[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem7[address[`INDEX]]; | |||
end | |||
mem7[address[`INDEX]] <= mq; | |||
tag7[address[`INDEX]] <= address[`TAG]; | |||
dirty7[address[`INDEX]] <= 0; | |||
valid7[address[`INDEX]] <= 1; | |||
end | |||
// way 8 is LRU | |||
else if(lru8[address[`INDEX]] == 1) | |||
begin | |||
// dirty block writeback | |||
if(dirty8[address[`INDEX]] == 1) | |||
begin | |||
_mwraddress <= {tag8[address[`INDEX]],address[`INDEX]}; | |||
_mwren <= 1; | |||
_mdout <= mem8[address[`INDEX]]; | |||
end | |||
mem8[address[`INDEX]] <= mq; | |||
tag8[address[`INDEX]] <= address[`TAG]; | |||
dirty8[address[`INDEX]] <= 0; | |||
valid8[address[`INDEX]] <= 1; | |||
end | |||
currentState <= idle; | |||
end | |||
default: currentState <= idle; | |||
endcase | |||
end | |||
endmodule |
@@ -0,0 +1,111 @@ | |||
`timescale 1ns / 1ps | |||
module inst_cache_tb; | |||
reg clk; | |||
wire [31:0] data_in; | |||
wire [31:0] data_out; | |||
wire [31:0] rd_addr; | |||
wire rd_en; | |||
wire [31:0] wr_addr; | |||
wire wr_en; | |||
reg [31:0] i_cache_addr = 0; | |||
reg [31:0] i_cache_din = 0; | |||
reg i_cache_rden = 0; | |||
reg i_cache_wren = 0; | |||
wire i_cache_hit_miss; | |||
wire [31:0] i_cache_q; | |||
inst_cache DUT_CACHE ( | |||
.clock(clk), | |||
.address(i_cache_addr), | |||
.din(i_cache_din), | |||
.rden(i_cache_rden), | |||
.wren(i_cache_wren), | |||
.hit_miss(i_cache_hit_miss), | |||
.q(i_cache_q), | |||
.mdout(data_in), | |||
.mrdaddress(rd_addr), | |||
.mrden(rd_en), | |||
.mwraddress(wr_addr), | |||
.mwren(wr_en), | |||
.mq(data_out) | |||
); | |||
defparam DUT_CACHE.SIZE = 16*1024*8; | |||
defparam DUT_CACHE.NWAYS = 8; | |||
defparam DUT_CACHE.NSETS = 2048; | |||
defparam DUT_CACHE.BLOCK_SIZE = 64; | |||
defparam DUT_CACHE.WIDTH = 32; | |||
defparam DUT_CACHE.MWIDTH = 64; | |||
main_memory DUT_MEM ( | |||
.clock(clk), | |||
.data(data_in), | |||
.rdaddress(rd_addr), | |||
.rden(rd_en), | |||
.wraddress(wr_addr), | |||
.wren(wr_en), | |||
.q(data_out) | |||
); | |||
defparam DUT_MEM.WIDTH = 32; | |||
defparam DUT_MEM.DEPTH = 128; | |||
defparam DUT_MEM.FILE = "main_mem_text.txt"; | |||
always | |||
begin | |||
# 100; // This should be a miss | |||
i_cache_addr <= 32'h00000004; | |||
i_cache_din <= 0; | |||
i_cache_rden <= 1; | |||
i_cache_wren <= 0; | |||
# 100; // This should be a miss | |||
i_cache_addr <= 32'h10000004; | |||
i_cache_din <= 0; | |||
i_cache_rden <= 1; | |||
i_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
i_cache_addr <= 32'h00000005; | |||
i_cache_din <= 32'hBADDBEEF; | |||
i_cache_rden <= 1; | |||
i_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
i_cache_addr <= 32'h10000006; | |||
i_cache_din <= 32'h00000000; | |||
i_cache_rden <= 1; | |||
i_cache_wren <= 0; | |||
# 100; // This should be a hit | |||
i_cache_addr <= 32'h00000007; | |||
i_cache_din <= 32'hAAAAAAAA; | |||
i_cache_rden <= 1; | |||
i_cache_wren <= 0; | |||
#50; | |||
$finish; | |||
end | |||
initial | |||
begin | |||
$monitor("time=%4d | addr=%10d | hm=%b | q=%08x | way1=%08h | way2=%08h | way3=%08h | way4=%08h | way5=%08h | way6=%08h | way7=%08h | way8=%08h | mem1=%08h | lru1=%d | lru2=%d | lru3=%d | lru4=%d | lru5=%d | lru6=%d | lru7=%d | lru8=%d" ,$time,i_cache_addr,i_cache_hit_miss,DUT_CACHE.q,DUT_CACHE.mem1[1],DUT_CACHE.mem2[1],DUT_CACHE.mem3[1],DUT_CACHE.mem4[1],DUT_CACHE.mem5[1],DUT_CACHE.mem6[1],DUT_CACHE.mem7[1],DUT_CACHE.mem8[1],DUT_MEM.mem[1],DUT_CACHE.lru1[1],DUT_CACHE.lru2[1],DUT_CACHE.lru3[1],DUT_CACHE.lru4[1],DUT_CACHE.lru5[1],DUT_CACHE.lru6[1],DUT_CACHE.lru7[1],DUT_CACHE.lru8[1]); | |||
end | |||
always | |||
begin | |||
clk = 1'b1; | |||
#5; | |||
clk = 1'b0; | |||
#5; | |||
end | |||
endmodule |
@@ -0,0 +1,83 @@ | |||
`define CLOG2(x) ( \ | |||
(x <= 2) ? 1 : \ | |||
(x <= 4) ? 2 : \ | |||
(x <= 8) ? 3 : \ | |||
(x <= 16) ? 4 : \ | |||
(x <= 32) ? 5 : \ | |||
(x <= 64) ? 6 : \ | |||
(x <= 128) ? 7 : \ | |||
(x <= 256) ? 8 : \ | |||
(x <= 512) ? 9 : \ | |||
(x <= 1024) ? 10 : \ | |||
(x <= 2048) ? 11 : \ | |||
(x <= 4096) ? 12 : \ | |||
(x <= 8192) ? 13 : \ | |||
(x <= 16384) ? 14 : \ | |||
(x <= 32768) ? 15 : \ | |||
(x <= 65536) ? 16 : \ | |||
(x <= 131072) ? 17 : \ | |||
(x <= 262144) ? 18 : \ | |||
(x <= 524288) ? 19 : \ | |||
(x <= 1048576) ? 20 : \ | |||
(x <= 2097152) ? 21 : \ | |||
(x <= 4194304) ? 22 : \ | |||
(x <= 8388608) ? 23 : \ | |||
(x <= 16777216) ? 24 : \ | |||
(x <= 33554432) ? 25 : \ | |||
(x <= 67108864) ? 26 : \ | |||
(x <= 134217728) ? 27 : \ | |||
(x <= 268435456) ? 28 : \ | |||
(x <= 536870912) ? 29 : \ | |||
(x <= 1073741824) ? 30 : \ | |||
-1) | |||
module main_memory | |||
#( | |||
parameter WIDTH = 8, | |||
parameter DEPTH = 64, | |||
parameter FILE = "", | |||
parameter INIT = 0 | |||
) | |||
( | |||
input wire clock, | |||
input wire [WIDTH-1:0] data, | |||
input wire [`CLOG2(DEPTH)-1:0] rdaddress, | |||
input wire rden, | |||
input wire [`CLOG2(DEPTH)-1:0] wraddress, | |||
input wire wren, | |||
output reg [WIDTH-1:0] q | |||
); | |||
reg [WIDTH-1:0] mem [0:DEPTH-1] ; | |||
integer file; | |||
integer scan; | |||
integer i; | |||
initial | |||
begin | |||
// read file contents if FILE is given | |||
if (FILE != "") | |||
// If you get error here, check path to FILE | |||
$readmemh(FILE, mem); | |||
// set all data to 0 if INIT is true | |||
if (INIT) | |||
for (i = 0; i < DEPTH; i = i + 1) | |||
mem[i] = {WIDTH{1'b0}}; | |||
end | |||
always @ (posedge clock) | |||
begin | |||
if (wren) | |||
mem[wraddress] <= data; | |||
end | |||
always @ (posedge clock) | |||
begin | |||
if (rden) | |||
q <= mem[rdaddress]; | |||
end | |||
endmodule |
@@ -0,0 +1,50 @@ | |||
module page_table( | |||
input clock, | |||
input [21:0] VPN, | |||
output reg [19:0] PPN_o, | |||
output reg valid_o | |||
); | |||
parameter PTE_ENTRIES = 4194304; | |||
reg [31:0] PPN [PTE_ENTRIES-1:0]; | |||
reg valid [PTE_ENTRIES-1:0]; | |||
integer i; | |||
integer ppn_curr; | |||
initial begin | |||
ppn_curr = 4194304; | |||
for(i = 0; i < 4194304 ; i = i + 1) | |||
begin | |||
if(i<4194286) | |||
begin | |||
valid[i]=1'b1; | |||
PPN[i] = { i % 1048576 +1'b1 }; | |||
end | |||
else | |||
begin | |||
valid[i]=1'b0; | |||
PPN[i] = { i % 1048576 +1'b1}; | |||
end | |||
end | |||
end | |||
always @(posedge clock) begin | |||
if(valid[VPN])begin | |||
PPN_o=PPN[VPN]; | |||
valid_o=valid[VPN]; | |||
end else begin | |||
PPN[VPN]=ppn_curr; | |||
valid[VPN]=1'b1; | |||
PPN_o=PPN[VPN]; | |||
ppn_curr=ppn_curr+1;//PPN_curr++ | |||
end | |||
end | |||
endmodule |
@@ -0,0 +1,102 @@ | |||
module page_table_tb(); | |||
reg clk; | |||
reg tlb_en; | |||
reg read_write; | |||
wire tlb_hit; | |||
wire hit_miss; | |||
reg clear_refer; | |||
reg [33:0] _address2; | |||
reg [31:0] din; | |||
wire [31:0] PA; | |||
integer time_curr=0; | |||
TLB tlb(clk, | |||
tlb_en, | |||
read_write, | |||
clear_refer, | |||
_address2,//virtual address | |||
PA,//PYHSICAL ADDRESS | |||
tlb_hit | |||
); | |||
data_cache cache(clk, | |||
_address, // address form CPU | |||
_address2, | |||
din, // data from CPU (if st inst) | |||
rden, // 1 if ld instruction | |||
wren, // 1 if st instruction | |||
hit_miss, // 1 if hit, 0 while handling miss | |||
q, // data from cache to CPU | |||
mdout, // data from cache to memory | |||
mrdaddress, // memory read address | |||
mrden, // read enable, 1 if reading from memory | |||
mwraddress, // memory write address | |||
mwren, // write enable, 1 if writing to memory | |||
mq // data coming from memory | |||
); | |||
always #5 clk = ~clk; | |||
always #5 time_curr =time_curr+5; | |||
initial | |||
begin | |||
clk=1'b1; | |||
tlb_en=1'b1; | |||
clear_refer=1'b0; | |||
assign clear_refer= (time_curr /(16*10))%2; | |||
#10 read_write = 0; _address2 = 34'h0; //should miss | |||
#10 read_write = 1; _address2 = 34'h0; din = 32'h11111111; //should hit | |||
#10 read_write = 0; _address2 = 34'h0; //should hit and read out 0xff | |||
#10 read_write = 0; _address2 = 34'h200; //should miss | |||
#10 read_write = 0; _address2 = 34'h0; //should hit | |||
#10 read_write = 0; _address2 = 34'h300; //should miss | |||
#10 read_write = 0; _address2 = 34'h200; //should miss | |||
#10 read_write = 0; _address2 = 34'h240; //should miss | |||
#10 read_write = 0; _address2 = 34'h50; | |||
#10 read_write = 0; _address2 = 34'h360; //should miss | |||
#10 read_write = 0; _address2 = 34'h270; | |||
#10 read_write = 0; _address2 = 34'h80; | |||
#10 read_write = 1; _address2 = 34'h90; din = 32'h11111111; | |||
#10 read_write = 0; _address2 = 34'hA0; //should hit | |||
#10 read_write = 0; _address2 = 34'h2B0; //should miss | |||
#10 read_write = 0; _address2 = 34'hC0; | |||
#10 read_write = 0; _address2 = 34'h3D0; //should miss | |||
#10 read_write = 0; _address2 = 34'h2E0; | |||
#10 read_write = 0; _address2 = 34'hF0; | |||
#10 read_write = 1; _address2 = 34'h100; din = 32'h11111111; | |||
#10 read_write = 0; _address2 = 34'h110; //should hit | |||
#10 read_write = 0; _address2 = 34'h200; | |||
#10 read_write = 0; _address2 = 34'h0; | |||
#10 read_write = 0; _address2 = 34'h300; | |||
#10 read_write = 0; _address2 = 34'h200; | |||
end | |||
endmodule |
@@ -0,0 +1,325 @@ | |||
`include "page_table.v" | |||
module tlb( | |||
input clock, | |||
input tlb_en, | |||
input clear_refer, | |||
input [33:0] VA,//virtual address | |||
output reg [31:0] PA,//PYHSICAL ADDRESS | |||
//input [16:0] PT_DATA | |||
output reg tlb_hit | |||
); | |||
reg [19:0] PPN [52:0]; | |||
reg [21:0] VPN [52:0]; | |||
reg refer [52:0]; | |||
reg valid [52:0]; | |||
integer i=0; | |||
reg [2:0] visit_entry; | |||
wire [11:0]_VA = VA[11:0]; | |||
wire [19:0] page_table_PPN_out; | |||
wire page_table_valid_out; | |||
page_table pt(clock,VA[33:12],page_table_PPN_out,page_table_valid_out); | |||
initial | |||
begin | |||
VPN[0]=22'b0101001010001110100101; | |||
PPN[0]=20'b01001010001110100110; | |||
VPN[1]=22'b1010001110101110101011; | |||
PPN[1]=20'b10001110101110101100; | |||
VPN[2]=22'b0000101111111111111111; | |||
PPN[2]=20'b00110000000000000000; | |||
VPN[3]=22'b0101111000001010010101; | |||
PPN[3]=20'b01111000001010010110; | |||
VPN[4]=22'b1101011010001010001011; | |||
PPN[4]=20'b01011010001010001100; | |||
VPN[5]=22'b0001101001111100010101; | |||
PPN[5]=20'b01101001111100010110; | |||
VPN[6]=22'b0010100101111110000011; | |||
PPN[6]=20'b10100101111110000100; | |||
VPN[7]=22'b1101011010000101111111; | |||
PPN[7]=20'b01011010000110000000; | |||
end | |||
always @(posedge clock) begin | |||
if(tlb_en) begin | |||
/*if(clear_refer) begin | |||
for(i=0; i<8; i=i+1) | |||
begin | |||
refer[i] <= 1'b0; | |||
end | |||
end | |||
for(i = 0 ;i < 7; i = i + 1) begin | |||
if (VA[33:12]==VPN[i]) begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
end*/ | |||
case(i) | |||
0: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
1: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit = 1; | |||
visit_entry = i; | |||
end | |||
else tlb_hit = 0; | |||
end | |||
2: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
3: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
4: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
5: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
6: begin | |||
if(clear_refer) | |||
begin | |||
refer[i] <= 1'b0; | |||
i <= i+1; | |||
end | |||
else | |||
begin | |||
refer[i] <= 1'b1; | |||
i <= i+1; | |||
end | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
7: begin | |||
if(clear_refer) refer[i] <= 1'b0; | |||
else refer[i] <= 1'b1; | |||
if(VA[33:12] == VPN[i]) | |||
begin | |||
tlb_hit <= 1; | |||
visit_entry <= i; | |||
end | |||
else tlb_hit <= 0; | |||
end | |||
default: tlb_hit = 1'bx; | |||
endcase | |||
case(i) | |||
0: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA = {PPN[visit_entry],_VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry = i; end | |||
valid[visit_entry]=page_table_valid_out; | |||
#10 PA = {page_table_PPN_out,_VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
end | |||
1: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA = {PPN[visit_entry],_VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry = i; end | |||
valid[visit_entry]=page_table_valid_out; | |||
#10 PA = {page_table_PPN_out,_VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
end | |||
2: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA = {PPN[visit_entry],_VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry = i; end | |||
valid[visit_entry]=page_table_valid_out; | |||
#10 PA = {page_table_PPN_out,_VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
end | |||
3: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA <= {PPN[visit_entry],_VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry <= i; end | |||
valid[visit_entry]<=page_table_valid_out; | |||
#10 PA <= {page_table_PPN_out,_VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
end | |||
4: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA <= {PPN[visit_entry],VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry <= i; end | |||
valid[visit_entry]<=page_table_valid_out; | |||
#10 PA <= {page_table_PPN_out,VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
end | |||
5: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA <= {PPN[visit_entry],VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry <= i; end | |||
valid[visit_entry]<=page_table_valid_out; | |||
#10 PA <= {page_table_PPN_out,VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
end | |||
6: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA <= {PPN[visit_entry],VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry <= i; end | |||
valid[visit_entry]<=page_table_valid_out; | |||
#10 PA <= {page_table_PPN_out,VA[11:0]}; | |||
refer[visit_entry] <= 1; | |||
end | |||
end | |||
7: begin | |||
if(tlb_hit) | |||
begin | |||
#10 PA = {PPN[visit_entry],VA[11:0]}; | |||
refer[visit_entry] = 1; | |||
end | |||
else | |||
begin | |||
if(refer[i]==0) begin | |||
visit_entry = i; end | |||
#10 PA = {page_table_PPN_out,VA[11:0]}; | |||
valid[visit_entry]=page_table_valid_out; | |||
refer[visit_entry] = 1; | |||
end | |||
end | |||
default: #10 PA <= 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; | |||
endcase | |||
end | |||
end | |||
endmodule |