/* Direct mapped cache 5-bit address 5-bit word 4 two-word blocks */ module DataCache(Address,Write,WriteData,ReadData,Hit,Clock); input Write, Clock; input [4:0] Address; // Memory address: 5 bits input [4:0] WriteData; output reg [4:0] ReadData; output reg Hit; reg [4:0] Memory [31:0]; // Memory: 32 5-bit words, word addressed reg [9:0] CacheData [3:0]; // 4 two-word blocks, 5-bit word reg [1:0] CacheTag [3:0]; // 2-bit cache tag reg CacheValidBit [3:0]; // valid bit wire [1:0] CacheIndex; // 2-bit cache index = Address [2:1] assign CacheIndex = Address[2:1]; wire BlockOffset; // 1-bit block offset = Arrdess[0] assign BlockOffset = Address[0]; reg [31:0] i; // temp reg [4:0] X; // no valid data // Clear cache initial for (i=0; i<4; i=i+1) begin CacheData [i] = 0; CacheTag [i] = 0; CacheValidBit[i] = 0; end // Read always @(negedge Clock) if (Write==0) begin if (CacheTag[CacheIndex] == Address[4:3] & CacheValidBit[CacheIndex]==1) begin Hit = 1; // cache hit if (BlockOffset==0) // choose word from cach ReadData <= CacheData[CacheIndex][4:0]; // get lower word else ReadData <= CacheData[CacheIndex][9:5]; // get upper word end else begin Hit = 0; // cache miss // write 2 memory words into cache block CacheData[CacheIndex][4:0] = Memory[Address & 5'b11110]; CacheData[CacheIndex][9:5] = Memory[Address | 5'b00001]; CacheTag[CacheIndex] = Address[4:3]; // set up tag CacheValidBit[CacheIndex] = 1; // set valid bit if (BlockOffset==0) // choose word from cach ReadData <= CacheData[CacheIndex][4:0]; // get lower word else ReadData <= CacheData[CacheIndex][9:5]; // get upper word end end // Write always @(negedge Clock) if (Write==1) begin if (CacheTag[CacheIndex] == Address[4:3] & CacheValidBit[CacheIndex]==1) Hit = 1; // cache hit else begin Hit = 0; // cache miss CacheTag[CacheIndex] = Address[4:3]; // set up tag CacheValidBit[CacheIndex] = 1; // set valid bit end // write through: Memory[Address] = WriteData; // write into memory CacheData[CacheIndex][4:0] <= Memory[Address & 5'b11110]; // write into cache CacheData[CacheIndex][9:5] <= Memory[Address | 5'b00001]; // write into cache end endmodule module test; reg[4:0] Address; reg Clock, Write; reg [4:0] WriteData; wire [4:0] ReadData; wire Hit; reg [31:0] i; DataCache cache(Address,Write,WriteData,ReadData,Hit,Clock); initial begin // Writing Write=1; // Fill the whole memory through the cache $display ("Address Hit WriteData"); for (i=0; i<32; i=i+1) begin #1 Address=i; WriteData=i; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,WriteData); end // Reading #1 Write=0; #1 $display ("Address Hit ReadData"); #1 Address=1; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); #1 Address=4; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); #1 Address=0; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); #1 Address=5; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); #1 Address=9; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); #1 Address=0; Clock=1; #1 Clock=0; #1 $display ("%2d(%b) %b %b",Address,Address,Hit,ReadData); end endmodule /* Test output Address Hit WriteData 0(00000) 0 00000 1(00001) 1 00001 2(00010) 0 00010 3(00011) 1 00011 4(00100) 0 00100 5(00101) 1 00101 6(00110) 0 00110 7(00111) 1 00111 8(01000) 0 01000 9(01001) 1 01001 10(01010) 0 01010 11(01011) 1 01011 12(01100) 0 01100 13(01101) 1 01101 14(01110) 0 01110 15(01111) 1 01111 16(10000) 0 10000 17(10001) 1 10001 18(10010) 0 10010 19(10011) 1 10011 20(10100) 0 10100 21(10101) 1 10101 22(10110) 0 10110 23(10111) 1 10111 24(11000) 0 11000 25(11001) 1 11001 26(11010) 0 11010 27(11011) 1 11011 28(11100) 0 11100 29(11101) 1 11101 30(11110) 0 11110 31(11111) 1 11111 Address Hit ReadData 1(00001) 0 00001 4(00100) 0 00100 0(00000) 1 00000 5(00101) 1 00101 9(01001) 0 01001 0(00000) 0 00000 */