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