@@ -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 |