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