Browse Source

Cache

master
Naga Sitaram M 10 months ago
parent
commit
0028411f84
13 changed files with 2465 additions and 0 deletions
  1. +34
    -0
      RISC_V/Cache/TLB_tb.v
  2. +164
    -0
      RISC_V/Cache/cache_coherence.v
  3. +102
    -0
      RISC_V/Cache/cache_coherence_tb.v
  4. +52
    -0
      RISC_V/Cache/cache_controller.v
  5. +47
    -0
      RISC_V/Cache/cache_controller_tb.v
  6. +583
    -0
      RISC_V/Cache/data_cache.v
  7. +236
    -0
      RISC_V/Cache/data_cache_tb.v
  8. +576
    -0
      RISC_V/Cache/inst_cache.v
  9. +111
    -0
      RISC_V/Cache/inst_cache_tb.v
  10. +83
    -0
      RISC_V/Cache/main_memory.v
  11. +50
    -0
      RISC_V/Cache/page_table.v
  12. +102
    -0
      RISC_V/Cache/page_table_tb.v
  13. +325
    -0
      RISC_V/Cache/tlb.v

+ 34
- 0
RISC_V/Cache/TLB_tb.v View File

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

+ 164
- 0
RISC_V/Cache/cache_coherence.v View File

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

+ 102
- 0
RISC_V/Cache/cache_coherence_tb.v View File

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

+ 52
- 0
RISC_V/Cache/cache_controller.v View File

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

+ 47
- 0
RISC_V/Cache/cache_controller_tb.v View File

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

+ 583
- 0
RISC_V/Cache/data_cache.v View File

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

+ 236
- 0
RISC_V/Cache/data_cache_tb.v View File

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

+ 576
- 0
RISC_V/Cache/inst_cache.v View File

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

+ 111
- 0
RISC_V/Cache/inst_cache_tb.v View File

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

+ 83
- 0
RISC_V/Cache/main_memory.v View File

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

+ 50
- 0
RISC_V/Cache/page_table.v View File

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

+ 102
- 0
RISC_V/Cache/page_table_tb.v View File

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

+ 325
- 0
RISC_V/Cache/tlb.v View File

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

Loading…
Cancel
Save