`include "Def_StructureParameter.v"


module DataCacheController(	//signal between mem and DataCacheController
			in_DataCacheAddress,		//data address
			io_DataCacheBus,		//data value for write and read
			in_DataCacheAccessEnable,	//enable access
			in_DataCacheBW,			//1 means byte,0 means word
			in_DataCacheRW,			//1 means read,0 means write
			out_DataCacheWait,		//wait for free
			//signal between DataCacheController and MemoryCotroller
			out_DataMemoryAddress,		//address goto memory
			io_DataMemoryBus,	//data value for write to memory
			out_DataMemoryEnable,		//enable accesss
			out_DataMemoryRW,			//1 means read, 0 means write
			in_DataMemoryWait,		//wait for memory
			//signal between DataCacheController and its CacheMemory
			//signal for clock and reset
			clock,
			reset
			);
//signal between ALUShell and DataCache
input		[`AddressBusWidth-1:0]		in_DataCacheAddress;
input							in_DataCacheAccessEnable,
							in_DataCacheRW,
							in_DataCacheBW;
inout		[`WordWidth-1:0]			io_DataCacheBus;
output						out_DataCacheWait;

reg							out_DataCacheWait;

//signal between DataCache and MemoryCotroller
output	[`AddressBusWidth-1:0]		out_DataMemoryAddress;
inout		[`WordWidth-1:0]			io_DataMemoryBus;
output						out_DataMemoryEnable,
							out_DataMemoryRW;

reg		[`AddressBusWidth-1:0]		out_DataMemoryAddress;
reg							out_DataMemoryEnable,
							out_DataMemoryRW;

input							in_DataMemoryWait;

//signal for clock and reset
input							clock,
							reset;

//declaration of cache memory
reg [127:0] S0_L0,S0_L1,S0_L2,S0_L3;
reg [127:0] S1_L0,S1_L1,S1_L2,S1_L3;
reg [127:0] S2_L0,S2_L1,S2_L2,S2_L3;
reg [127:0] S3_L0,S3_L1,S3_L2,S3_L3;

//the tag for the correspone line
reg [`AddressBusWidth-1:0] tag00,tag01,tag02,tag03;
reg [`AddressBusWidth-1:0] tag10,tag11,tag12,tag13;
reg [`AddressBusWidth-1:0] tag20,tag21,tag22,tag23;
reg [`AddressBusWidth-1:0] tag30,tag31,tag32,tag33;

//if the correspone line valid?
reg V00,V01,V02,V03;
reg V10,V11,V12,V13;
reg V20,V21,V22,V23;
reg V30,V31,V32,V33;

//which line in this section have been previous access 
reg [1:0] PrevAccess0,PrevAccess1,PrevAccess2,PrevAccess3;


//the current and next state of access address
reg						OutStandAccessEnable;
reg	[`AddressBusWidth-1:0]		OutStandAccessAddress;
reg						OutStandAccessRW;
reg	[`WordWidth-1:0]			OutStandAccessValue;

reg						Next_OutStandAccessEnable;
reg	[`AddressBusWidth-1:0]		Next_OutStandAccessAddress;
reg						Next_OutStandAccessRW;
reg	[`WordWidth-1:0]			Next_OutStandAccessValue;

//the current state and next state of write back
reg						OutStandWriteBackEnable;
reg	[`AddressBusWidth-1:0]		OutStandWriteBackAddress;
reg	[`ByteWidth-1:0]			OutStandWriteBackWordCount


reg						Next_OutStandWriteBackEnable;
reg	[`AddressBusWidth-1:0]		Next_OutStandWriteBackAddress;
reg	[`ByteWidth-1:0]			Next_OutStandWriteBackWordCount

//the current and next state of read in
reg						OutStandReadInEnable;
reg	[`AddressBusWidth-1:0]		OutStandReadInAddress;
reg	[`ByteWidth-1:0]			OutStandReadInWordCount;

reg						Next_OutStandReadInEnable;
reg	[`AddressBusWidth-1:0]		Next_OutStandReadInAddress;
reg	[`ByteWidth-1:0]			Next_OutStandReadInWordCount;

//this reg wll not be infer
reg	[`WordWidth-1:0] DataCacheIOTmp;
reg	[`WordWidth-1:0] DataMemoryIOTmp;

//read to up bus
assign  io_DataCacheBus=(in_DataCacheAccessEnable==1'b1 && in_DataCacheRW==1'b1 && out_DataCacheWait==1'b0)?DataCacheIOTmp:`WordZ;

//the read to DataCacheIOTmp and write to DataCacheIOTmp
always @(tag00 or tag01 or tag02 or tag03 
	or tag10 or tag11 or tag12 or tag13 
	or tag20 or tag21 or tag22 or tag23 
	or tag30 or tag31 or tag32 or tag33 
	or S0_L0 or S0_L1 or S0_L2 or S0_L3
	or S1_L0 or S1_L1 or S1_L2 or S1_L3
	or S2_L0 or S2_L1 or S2_L2 or S2_L3
	or S3_L0 or S3_L1 or S3_L2 or S3_L3
	or V00 or V01 or V02 or V03
	or V10 or V11 or V12 or V13
	or V20 or V21 or V22 or V23
	or V30 or V31 or V32 or V33
	or in_DataCacheAddress
	or in_DataCacheAccessEnable
	or in_DataCacheRW
	or in_DataCacheBW
	or io_DataCacheBus
	)
begin
   if(in_DataCacheAccessEnable==1'b1)
   begin
	case(in_DataCacheAddress[5:4])
	2'b00:
		//section 0
		if(V00==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag00[`AddressBusWidth-1:6])
		begin
			//line 0
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 0 line 0
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S0_L0[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S0_L0[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S0_L0[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S0_L0[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S0_L0[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S0_L0[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S0_L0[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S0_L0[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S0_L0[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S0_L0[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S0_L0[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S0_L0[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S0_L0[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S0_L0[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S0_L0[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S0_L0[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 0 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S0_L0[31:0];
					2'b01:
						DataCacheIOTmp=S0_L0[63:32];
					2'b10:
						DataCacheIOTmp=S0_L0[95:64];
					2'b11:
						DataCacheIOTmp=S0_L0[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V01==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag01[`AddressBusWidth-1:6])
		begin
			//line 1
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 0 line 1
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S0_L1[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S0_L1[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S0_L1[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S0_L1[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S0_L1[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S0_L1[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S0_L1[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S0_L1[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S0_L1[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S0_L1[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S0_L1[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S0_L1[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S0_L1[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S0_L1[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S0_L1[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S0_L1[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 0 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S0_L1[31:0];
					2'b01:
						DataCacheIOTmp=S0_L1[63:32];
					2'b10:
						DataCacheIOTmp=S0_L1[95:64];
					2'b11:
						DataCacheIOTmp=S0_L1[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V02==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag02[`AddressBusWidth-1:6])
		begin
			//line 2
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 0 line 2
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S0_L2[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S0_L2[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S0_L2[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S0_L2[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S0_L2[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S0_L2[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S0_L2[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S0_L2[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S0_L2[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S0_L2[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S0_L2[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S0_L2[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S0_L2[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S0_L2[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S0_L2[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S0_L2[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 0 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S0_L2[31:0];
					2'b01:
						DataCacheIOTmp=S0_L2[63:32];
					2'b10:
						DataCacheIOTmp=S0_L2[95:64];
					2'b11:
						DataCacheIOTmp=S0_L2[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V03==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag03[`AddressBusWidth-1:6])
		begin
			//line 3
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 0 line 0
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S0_L3[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S0_L3[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S0_L3[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S0_L3[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S0_L3[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S0_L3[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S0_L3[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S0_L3[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S0_L3[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S0_L3[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S0_L3[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S0_L3[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S0_L3[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S0_L3[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S0_L3[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S0_L3[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 0 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S0_L3[31:0];
					2'b01:
						DataCacheIOTmp=S0_L3[63:32];
					2'b10:
						DataCacheIOTmp=S0_L3[95:64];
					2'b11:
						DataCacheIOTmp=S0_L3[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else
		begin
			out_DataCacheWait=1'b1;
			DataCacheIOTmp=`WordZ;
		end
	2'b01:
		//section 1
		if(V10==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag10[`AddressBusWidth-1:6])
		begin
			//line 0
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 1 line 0
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S1_L0[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S1_L0[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S1_L0[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S1_L0[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S1_L0[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S1_L0[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S1_L0[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S1_L0[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S1_L0[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S1_L0[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S1_L0[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S1_L0[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S1_L0[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S1_L0[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S1_L0[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S1_L0[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 1 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S1_L0[31:0];
					2'b01:
						DataCacheIOTmp=S1_L0[63:32];
					2'b10:
						DataCacheIOTmp=S1_L0[95:64];
					2'b11:
						DataCacheIOTmp=S1_L0[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V11==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag11[`AddressBusWidth-1:6])
		begin
			//line 1
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 1 line 1
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S1_L1[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S1_L1[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S1_L1[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S1_L1[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S1_L1[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S1_L1[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S1_L1[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S1_L1[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S1_L1[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S1_L1[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S1_L1[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S1_L1[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S1_L1[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S1_L1[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S1_L1[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S1_L1[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 1 and line 1
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S1_L1[31:0];
					2'b01:
						DataCacheIOTmp=S1_L1[63:32];
					2'b10:
						DataCacheIOTmp=S1_L1[95:64];
					2'b11:
						DataCacheIOTmp=S1_L1[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V12==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag12[`AddressBusWidth-1:6])
		begin
			//line 2
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 1 line 2
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S1_L2[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S1_L2[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S1_L2[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S1_L2[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S1_L2[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S1_L2[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S1_L2[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S1_L2[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S1_L2[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S1_L2[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S1_L2[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S1_L2[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S1_L2[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S1_L2[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S1_L2[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S1_L2[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 1 and line 2
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S1_L2[31:0];
					2'b01:
						DataCacheIOTmp=S1_L2[63:32];
					2'b10:
						DataCacheIOTmp=S1_L2[95:64];
					2'b11:
						DataCacheIOTmp=S1_L2[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V13==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag13[`AddressBusWidth-1:6])
		begin
			//line 3
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 1 line 3
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S1_L3[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S1_L3[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S1_L3[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S1_L3[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S1_L3[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S1_L3[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S1_L3[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S1_L3[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S1_L3[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S1_L3[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S1_L3[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S1_L3[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S1_L3[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S1_L3[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S1_L3[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S1_L3[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 1 and line 3
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S1_L3[31:0];
					2'b01:
						DataCacheIOTmp=S1_L3[63:32];
					2'b10:
						DataCacheIOTmp=S1_L3[95:64];
					2'b11:
						DataCacheIOTmp=S1_L3[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else
		begin
			out_DataCacheWait=1'b1;
			DataCacheTmp=`WordZ;
		end
	2'b10:
		//section 2
		if(V20==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag20[`AddressBusWidth-1:6])
		begin
			//line 0
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 2 line 0
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S2_L0[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S2_L0[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S2_L0[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S2_L0[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S2_L0[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S2_L0[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S2_L0[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S2_L0[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S2_L0[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S2_L0[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S2_L0[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S2_L0[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S2_L0[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S2_L0[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S2_L0[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S2_L0[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 2 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S2_L0[31:0];
					2'b01:
						DataCacheIOTmp=S2_L0[63:32];
					2'b10:
						DataCacheIOTmp=S2_L0[95:64];
					2'b11:
						DataCacheIOTmp=S2_L0[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V21==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag21[`AddressBusWidth-1:6])
		begin
			//line 1
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 2 line 1
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S2_L1[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S2_L1[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S2_L1[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S2_L1[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S2_L1[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S2_L1[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S2_L1[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S2_L1[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S2_L1[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S2_L1[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S2_L1[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S2_L1[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S2_L1[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S2_L1[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S2_L1[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S2_L1[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 2 and line 1
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S2_L1[31:0];
					2'b01:
						DataCacheIOTmp=S2_L1[63:32];
					2'b10:
						DataCacheIOTmp=S2_L1[95:64];
					2'b11:
						DataCacheIOTmp=S2_L1[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V22==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag22[`AddressBusWidth-1:6])
		begin
			//line 2
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 2 line 2
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S2_L2[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S2_L2[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S2_L2[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S2_L2[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S2_L2[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S2_L2[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S2_L2[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S2_L2[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S2_L2[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S2_L2[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S2_L2[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S2_L2[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S2_L2[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S2_L2[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S2_L2[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S2_L2[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 2 and line 2
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S2_L2[31:0];
					2'b01:
						DataCacheIOTmp=S2_L2[63:32];
					2'b10:
						DataCacheIOTmp=S2_L2[95:64];
					2'b11:
						DataCacheIOTmp=S2_L2[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V23==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag23[`AddressBusWidth-1:6])
		begin
			//line 3
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 2 line 3
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S2_L3[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S2_L3[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S2_L3[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S2_L3[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S2_L3[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S2_L3[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S2_L3[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S2_L3[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S2_L3[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S2_L3[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S2_L3[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S2_L3[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S2_L3[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S2_L3[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S2_L3[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S2_L3[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 2 and line 3
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S2_L3[31:0];
					2'b01:
						DataCacheIOTmp=S2_L3[63:32];
					2'b10:
						DataCacheIOTmp=S2_L3[95:64];
					2'b11:
						DataCacheIOTmp=S2_L3[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else
		begin
			out_DataCacheWait=1'b1;
			DataCacheIOTmp=`WordZ;
		end
	2'b11:
		//section 3
		if(V30==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag30[`AddressBusWidth-1:6])
		begin
			//line 0
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 3 line 0
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S3_L0[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S3_L0[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S3_L0[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S3_L0[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S3_L0[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S3_L0[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S3_L0[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S3_L0[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S3_L0[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S3_L0[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S3_L0[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S3_L0[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S3_L0[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S3_L0[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S3_L0[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S3_L0[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 3 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S3_L0[31:0];
					2'b01:
						DataCacheIOTmp=S3_L0[63:32];
					2'b10:
						DataCacheIOTmp=S3_L0[95:64];
					2'b11:
						DataCacheIOTmp=S3_L0[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V31==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag31[`AddressBusWidth-1:6])
		begin
			//line 1
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 3 line 1
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S3_L1[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S3_L1[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S3_L1[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S3_L1[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S3_L1[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S3_L1[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S3_L1[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S3_L1[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S3_L1[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S3_L1[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S3_L1[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S3_L1[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S3_L1[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S3_L1[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S3_L1[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S3_L1[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 3 and line 1
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S3_L1[31:0];
					2'b01:
						DataCacheIOTmp=S3_L1[63:32];
					2'b10:
						DataCacheIOTmp=S3_L1[95:64];
					2'b11:
						DataCacheIOTmp=S3_L1[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V32==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag32[`AddressBusWidth-1:6])
		begin
			//line 2
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 3 line 2
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S3_L2[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S3_L2[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S3_L2[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S3_L2[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S3_L2[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S3_L2[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S3_L2[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S3_L2[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S3_L2[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S3_L2[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S3_L2[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S3_L2[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S3_L2[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S3_L2[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S3_L2[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S3_L2[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 3 and line 2
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S3_L2[31:0];
					2'b01:
						DataCacheIOTmp=S3_L2[63:32];
					2'b10:
						DataCacheIOTmp=S3_L2[95:64];
					2'b11:
						DataCacheIOTmp=S3_L2[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else if(V33==1'b1 && in_DataCacheAddress[`AddressBusWidth-1:6]==tag33[`AddressBusWidth-1:6])
		begin
			//line 3
			//found
			out_DataCacheWait=1'b0;
			if(in_DataCacheRW=1'b1)
			begin
				//read 
				if(in_DataCacheBW==1'b1)
				begin
					//read byte in section 3 line 3
					case (in_DataCacheAddress[3:0])
					4'b0000:
						DataCacheIOTmp={4{S3_L3[7:0]}};
					4'b0001:
						DataCacheIOTmp={4{S3_L3[15:8]}};
					4'b0010:
						DataCacheIOTmp={4{S3_L3[23:16]}};
					4'b0011:
						DataCacheIOTmp={4{S3_L3[31:24]}};
					4'b0100:
						DataCacheIOTmp={4{S3_L3[39:32]}};
					4'b0101:
						DataCacheIOTmp={4{S3_L3[47:40]}};
					4'b0110:
						DataCacheIOTmp={4{S3_L3[55:48]}};
					4'b0111:
						DataCacheIOTmp={4{S3_L3[63:56]}};
					4'b1000:
						DataCacheIOTmp={4{S3_L3[71:64]}};
					4'b1001:
						DataCacheIOTmp={4{S3_L3[79:72]}};
					4'b1010:
						DataCacheIOTmp={4{S3_L3[87:80]}};
					4'b1011:
						DataCacheIOTmp={4{S3_L3[95:88]}};
					4'b1100:
						DataCacheIOTmp={4{S3_L3[103:96]}};
					4'b1101:
						DataCacheIOTmp={4{S3_L3[111:104]}};
					4'b1110:
						DataCacheIOTmp={4{S3_L3[119:112]}};
					4'b1111:
						DataCacheIOTmp={4{S3_L3[127:120]}};
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
				else
				begin
					//read word in section 0 and line 0
					case (in_DataCacheAddress[3:2])
					2'b00:
						DataCacheIOTmp=S3_L3[31:0];
					2'b01:
						DataCacheIOTmp=S3_L3[63:32];
					2'b10:
						DataCacheIOTmp=S3_L3[95:64];
					2'b11:
						DataCacheIOTmp=S3_L3[127:96];
					default:
						DataCacheIOTmp=`WordZ;
					endcase
				end
			end
			else
			begin
				//write
				DataCacheIOTmp=io_DataCacheBus;
			end
		end
		else
		begin
			out_DataCacheWait=1'b1;
			DataCacheIOTmp=`WordZ;
		end
	endcase
   end
   else
   begin
	//no access
	out_DataCacheWait=1'b0;
	DataCacheIOTmp=`WordZ;
   end
end


always @(posedge clock or negedge reset)
begin
	if(reset==1'b0)
	begin
		S0_L0=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S0_L1=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S0_L2=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S0_L3=128'h0000_0000_0000_0000_0000_0000_0000_0000;

		S1_L0=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S1_L1=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S1_L2=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S1_L3=128'h0000_0000_0000_0000_0000_0000_0000_0000;

		S2_L0=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S2_L1=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S2_L2=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S2_L3=128'h0000_0000_0000_0000_0000_0000_0000_0000;

		S3_L0=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S3_L1=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S3_L2=128'h0000_0000_0000_0000_0000_0000_0000_0000;
		S3_L3=128'h0000_0000_0000_0000_0000_0000_0000_0000;

		tag00=`AddressBusZero;
		tag01=`AddressBusZero;
		tag02=`AddressBusZero;
		tag03=`AddressBusZero;

		tag10=`AddressBusZero;
		tag11=`AddressBusZero;
		tag12=`AddressBusZero;
		tag13=`AddressBusZero;

		tag20=`AddressBusZero;
		tag21=`AddressBusZero;
		tag22=`AddressBusZero;
		tag23=`AddressBusZero;

		tag30=`AddressBusZero;
		tag31=`AddressBusZero;
		tag32=`AddressBusZero;
		tag33=`AddressBusZero;

		V00=1'b0;
		V01=1'b0;
		V02=1'b0;
		V03=1'b0;

		V10=1'b0;
		V11=1'b0;
		V12=1'b0;
		V13=1'b0;

		V20=1'b0;
		V21=1'b0;
		V22=1'b0;
		V23=1'b0;

		V30=1'b0;
		V31=1'b0;
		V32=1'b0;
		V33=1'b0;

		PrevAccess0=2'b00;
		PrevAccess1=2'b00;
		PrevAccess2=2'b00;
		PrevAccess3=2'b00;
	end
	else
	begin
	end
end



endmodule