data/full_repos/permissive/444465810/func/axi/mycpu_top.v
1: b'%Error: data/full_repos/permissive/444465810/func/axi/mycpu_top.v:91: syntax error, unexpected break, expecting IDENTIFIER or do or final\n    wire    break;\n            ^~~~~\n%Error: data/full_repos/permissive/444465810/func/axi/mycpu_top.v:101: syntax error, unexpected break\n   .break   (break   ),   \n    ^~~~~\n%Error: data/full_repos/permissive/444465810/func/axi/mycpu_top.v:105: syntax error, unexpected break, expecting TYPE-IDENTIFIER\n wire [ 5: 0] ID_Out_EXC = {reserve,break,syscall,PC_EXC_ID,delay,INT};   \n                                    ^~~~~\n%Error: Exiting due to 3 error(s)\n'
module mycpu_top(
    input         clk,
    input         resetn,
	input [5:0]   ext_int,

    output        inst_sram_en,
    output [ 3:0] inst_sram_wen,
    output [31:0] inst_sram_addr,
    output [31:0] inst_sram_wdata,
    input  [31:0] inst_sram_rdata,

    output        data_sram_en,
    output [ 3:0] data_sram_wen,
    output [31:0] data_sram_addr,
    output [31:0] data_sram_wdata,
    input  [31:0] data_sram_rdata,

    output [31:0] debug_wb_pc,
    output [ 3:0] debug_wb_rf_wen,
    output [ 4:0] debug_wb_rf_wnum,
    output [31:0] debug_wb_rf_wdata
);
	wire rst;
	assign rst = !resetn;
	
   `define op 31:26
   `define funct 5:0
   `define imm26 25:0
   `define imm16 15:0
   `define rs 25:21
   `define rt 20:16
   `define rd 15:11
   `define s 10:6
   	wire [31: 0] PC;
  	wire [31: 0] NPC;
   	wire 		 PCWr;
	wire 		 PC_EXC_IF;
	wire 		 flush;

   	PC U_PC(
		   .clk			(clk			),
		   .rst			(rst			),
		   .PCWr		(PCWr			),
		   .PC			(PC				),
		   .NPC			(NPC			)
	);
	assign PC_EXC_IF = PC[0] | PC[1];
	assign inst_sram_en    = PCWr;
	assign inst_sram_wen   = 4'h0;				
	assign inst_sram_addr  = PC;
	assign inst_sram_wdata = 32'b0;
   	wire [31: 0] Instr;
	assign Instr = inst_sram_rdata & {32{!flush}};

   	wire [31: 0] PC_4 = PC + 4;
   	wire [31: 0] PC_8 = PC + 8;
	wire         delay;

	wire [31: 0] N_PC4_D = PC_4;
	wire [31: 0] N_PC8_D = PC_8;
	wire [31: 0] PC4_D;
	wire [31: 0] PC8_D;
	wire [31: 0] debug_pc_D;
	wire 		 FD_En;
	wire 		 inst_vaild;
	wire 		 Delay_Next;
	wire [31: 0] Instr_D = Instr & {32{!inst_vaild}};
   FD U_FD(	
	   		.clk			(clk			),
		 	.rst			(rst			),
			.En				(FD_En			),
			.N_PC4_D		(N_PC4_D		),
			.N_PC8_D		(N_PC8_D		),
			.PC4_D			(PC4_D			),
			.PC8_D			(PC8_D			),
			.N_debug_pc_D	(PC				),
			.debug_pc_D		(debug_pc_D		),
			.PC_EXC_IF		(PC_EXC_IF		),
			.PC_EXC_ID		(PC_EXC_ID		),
			.flush			(flush			),
			.inst_vaild		(inst_vaild		),
			.Delay_Next		(Delay_Next		),
			.delay			(delay			)
	);

   	wire [ 2: 0] PC_Sel;
   	wire [ 1: 0] EXT_Sel;
   	wire [ 1: 0] RF_Sel;
   	wire [ 2: 0] NPC_Sel;
   	wire 		 syscall;
   	wire 		 break;
   	wire 		 reserve;
	wire 		 INT;
   	CTRL U_CTRL_D(	
		   	.Instr			(Instr_D		),
	   		.PC_Sel			(PC_Sel			),
			.EXT_Sel		(EXT_Sel		),
			.RF_Sel			(RF_Sel			),
			.NPC_Sel		(NPC_Sel		),
			.syscall		(syscall		),
			.break			(break			),
			.reserve		(reserve		),
			.Delay_Next		(Delay_Next		)
	);
	wire [ 5: 0] ID_Out_EXC = {reserve,break,syscall,PC_EXC_ID,delay,INT};
	wire [ 5: 0] EXE_In_EXC;

   	wire [ 4: 0] RF_A1 = Instr_D[`rs];
  	wire [ 4: 0] RF_A2 = Instr_D[`rt];
	wire [ 4: 0] RF_A3;
   	wire [31: 0] RF_WD;
   	wire [31: 0] RF_RD1;
   	wire [31: 0] RF_RD2;
   	wire RFWr;

	
   	RF U_RF(
		   .clk			(clk			),
		   .rst			(rst			),
		   .RFWr		(RFWr			),
		   .A1			(RF_A1			),
		   .A2			(RF_A2			),
		   .A3			(RF_A3			),
		   .WD			(RF_WD			),
		   .RD1			(RF_RD1			),
		   .RD2			(RF_RD2			)
	);
   	assign debug_wb_rf_wen = {4{RFWr}};
	assign debug_wb_rf_wnum = RF_A3;
    assign debug_wb_rf_wdata = RF_WD;
   	
	wire [31: 0] RS_D_MUX_In0 = RF_RD1;
	wire [31: 0] RS_D_MUX_In1;
	wire [31: 0] RS_D_MUX_In2;
	wire [31: 0] RS_D_MUX_In3;
	wire [31: 0] RS_D_MUX_In4;
	wire [31: 0] RS_D_MUX_In5;
	wire [31: 0] RS_D_MUX_In6;
	wire [ 2: 0] RS_D_MUX_Op;
	wire [31: 0] RS_D_MUX_Out;

   mux8 #(32) U_RS_D_MUX(
      	.In0			(RS_D_MUX_In0	),
		.In1			(RS_D_MUX_In1	),
		.In2			(RS_D_MUX_In2	),
		.In3			(RS_D_MUX_In3	),
		.In4			(RS_D_MUX_In4	),
		.In5			(RS_D_MUX_In5	),
		.In6			(RS_D_MUX_In6	),
		.Op				(RS_D_MUX_Op	),
		.Out			(RS_D_MUX_Out	)
   );

   	wire [31: 0] RT_D_MUX_In0 = RF_RD2;
	wire [31: 0] RT_D_MUX_In1;
	wire [31: 0] RT_D_MUX_In2;
	wire [31: 0] RT_D_MUX_In3;
	wire [31: 0] RT_D_MUX_In4;
	wire [31: 0] RT_D_MUX_In5;
	wire [31: 0] RT_D_MUX_In6;
	wire [ 2: 0] RT_D_MUX_Op;
	wire [31: 0] RT_D_MUX_Out;

   mux8 #(32) U_RT_D_MUX(
		.In0			(RT_D_MUX_In0	),
		.In1			(RT_D_MUX_In1	),
		.In2			(RT_D_MUX_In2	),
		.In3			(RT_D_MUX_In3	),
		.In4			(RT_D_MUX_In4	),
		.In5			(RT_D_MUX_In5	),
		.In6			(RT_D_MUX_In6	),
		.Op				(RT_D_MUX_Op	),
		.Out			(RT_D_MUX_Out	)
	);
   
   wire [15:0] EXT_In = Instr_D[`imm16];
   wire [31:0] EXT_Out;
   EXT U_EXT(
	   .In				(EXT_In			),
	   .Op				(EXT_Sel		),
	   .Out				(EXT_Out		)
	);

   wire [31: 0] Base = PC4_D;
   wire [31: 0] ImmB = EXT_Out;
   wire [25: 0] ImmJ = Instr_D[`imm26];
   wire [31: 0] Cmp1 = RS_D_MUX_Out;
   wire [31: 0] Cmp2 = RT_D_MUX_Out;
   wire [ 2: 0] CmpOp = PC_Sel;
   wire [31: 0] Branch;
   wire [31: 0] Jump;

   NPC U_NPC(
	   .PC				(Base			),
	   .ImmB			(ImmB			),
	   .ImmJ			(ImmJ			),
	   .Cmp1			(Cmp1			),
	   .Cmp2			(Cmp2			),
	   .CmpOp			(CmpOp			),
	   .Branch			(Branch			),
	   .Jump			(Jump			)
	);


    wire [ 4: 0] RF_A3_MUX_In0 = Instr_D[`rd];
	wire [ 4: 0] RF_A3_MUX_In1 = Instr_D[`rt];
	wire [ 4: 0] RF_A3_MUX_In2 = 31;
	wire [ 1: 0] RF_A3_MUX_Op  = RF_Sel;
	wire [ 4: 0] RF_A3_MUX_Out;

   mux4 #(5) U_RF_A3_MUX(
		.In0			(RF_A3_MUX_In0	),
		.In1			(RF_A3_MUX_In1	),
		.In2			(RF_A3_MUX_In2	),
		.Op				(RF_A3_MUX_Op	),
		.Out			(RF_A3_MUX_Out	)
	);
   
    wire [31: 0] PC_MUX_In0 = PC_4;
	wire [31: 0] PC_MUX_In1 = Branch;
	wire [31: 0] PC_MUX_In2 = Jump;
	wire [31: 0] PC_MUX_In3 = RS_D_MUX_Out;
	wire [ 2: 0] PC_MUX_Op  = NPC_Sel;
	wire [31: 0] PC_MUX_Out;

   	mux8 #(32) U_PC_MUX(
		.In0			(PC_MUX_In0		),
		.In1			(PC_MUX_In1		),
		.In2			(PC_MUX_In2		),
		.In3			(PC_MUX_In3		),
		.Op				(PC_MUX_Op		),
		.Out			(PC_MUX_Out		)
	);
	wire [31: 0]PC_WB_Out;
	mux2 #(32) U_NPC_MUX(
		.In0			(PC_MUX_Out		),
		.In1			(PC_WB_Out		),
		.Op				(flush			),
		.Out			(NPC			)
	);


    wire 		 DE_clear;
	wire [31: 0] N_Instr_E	= Instr_D;
	wire [31: 0] N_RS_E 	= RS_D_MUX_Out;
	wire [31: 0] N_RT_E 	= RT_D_MUX_Out;
	wire [31: 0] N_EXT_E 	= EXT_Out;
	wire [31: 0] N_PC8_E 	= PC8_D;
	wire [ 4: 0] N_WBA_E 	= RF_A3_MUX_Out;
	wire [31: 0] N_s_E 		= Instr_D[`s];
	wire [31: 0] Instr_E;
	wire [31: 0] RS_E;
	wire [31: 0] RT_E;
	wire [31: 0] EXT_E;
	wire [31: 0] PC8_E;
	wire [ 4: 0] WBA_E;
	wire [31: 0] s_E;
	wire [31: 0] debug_pc_E;
   	DE U_DE(
		.clk			(clk			),
		.rst			(rst			),
		.clear			(DE_clear		),
		.N_Instr_E		(N_Instr_E		),
		.N_RS_E			(N_RS_E			),
		.N_RT_E			(N_RT_E			),
		.N_EXT_E		(N_EXT_E		),
		.N_PC8_E		(N_PC8_E		),
		.N_WBA_E		(N_WBA_E		),
		.N_s_E			(N_s_E			),
		.Instr_E		(Instr_E		),
		.RS_E			(RS_E			),
		.RT_E			(RT_E			),
		.EXT_E			(EXT_E			),
		.PC8_E			(PC8_E			),
		.WBA_E			(WBA_E			),
		.s_E			(s_E			),
		.N_debug_pc_E	(debug_pc_D		),
		.debug_pc_E		(debug_pc_E		),
		.ID_Out_EXC		(ID_Out_EXC		),
		.EXE_In_EXC		(EXE_In_EXC		),
		.flush			(flush			)
	);
   	
    wire [ 3: 0] ALU_Sel;
	wire 		 ALU_A_Sel;
	wire 		 ALU_B_Sel;
	wire [ 2: 0] MDU_Sel;
	wire 		 Start;
	wire 		 MDU_RD_Sel;
	wire 		 ALU_MDU_Sel;
	wire 		 DM_wen;
	wire 		 DMWr;
	wire [ 1: 0] StoreType;
	wire 	 	 sign;
   	CTRL U_CTRL_E(
      .Instr			(Instr_E		),
      .ALU_Sel			(ALU_Sel		),
      .ALU_A_Sel		(ALU_A_Sel		),
      .ALU_B_Sel		(ALU_B_Sel		),
	  .MDU_Sel			(MDU_Sel		),
	  .Start			(Start			),
	  .MDU_RD_Sel		(MDU_RD_Sel		),
	  .ALU_MDU_Sel		(ALU_MDU_Sel	),
	  .DMWr				(DM_wen			),
	  .StoreType		(StoreType		),
	  .sign				(sign			)
   	);

   	wire [31: 0] RS_E_MUX_In0 = RS_E;
	wire [31: 0] RS_E_MUX_In1;
	wire [31: 0] RS_E_MUX_In2;
	wire [31: 0] RS_E_MUX_In3;
	wire [31: 0] RS_E_MUX_In4;
	wire [ 2: 0] RS_E_MUX_Op;
	wire [31: 0] RS_E_MUX_Out;

   mux8 #(32) U_RS_E_MUX(
		.In0			(RS_E_MUX_In0	),
		.In1			(RS_E_MUX_In1	),
		.In2			(RS_E_MUX_In2	),
		.In3			(RS_E_MUX_In3	),
		.In4			(RS_E_MUX_In4	),
		.Op				(RS_E_MUX_Op	),
		.Out			(RS_E_MUX_Out	)
	);

   	wire [31: 0] RT_E_MUX_In0 = RT_E;
	wire [31: 0] RT_E_MUX_In1;
	wire [31: 0] RT_E_MUX_In2;
	wire [31: 0] RT_E_MUX_In3;
	wire [31: 0] RT_E_MUX_In4;
	wire [ 2: 0] RT_E_MUX_Op;
	wire [31: 0] RT_E_MUX_Out;

   mux8 #(32) U_RT_E_MUX(
		.In0			(RT_E_MUX_In0	),
		.In1			(RT_E_MUX_In1	),
		.In2			(RT_E_MUX_In2	),
		.In3			(RT_E_MUX_In3	),
		.In4			(RT_E_MUX_In4	),
		.Op				(RT_E_MUX_Op	),
		.Out			(RT_E_MUX_Out	)
	);

    wire [31: 0] ALU_A_MUX_In0 = RS_E_MUX_Out;
	wire [31: 0] ALU_A_MUX_In1 = s_E;
	wire 		 ALU_A_MUX_Op  = ALU_A_Sel;
	wire [31: 0] ALU_A_MUX_Out;

   mux2 #(32) U_ALU_A_MUX(
		.In0			(ALU_A_MUX_In0	),
		.In1			(ALU_A_MUX_In1	),
		.Op				(ALU_A_MUX_Op	),
		.Out			(ALU_A_MUX_Out	)
	);

   	wire [31: 0] ALU_B_MUX_In0 = RT_E_MUX_Out;
	wire [31: 0] ALU_B_MUX_In1 = EXT_E;
	wire 		 ALU_B_MUX_Op  = ALU_B_Sel;
	wire [31: 0] ALU_B_MUX_Out;

   mux2 #(32) U_ALU_B_MUX(
		.In0			(ALU_B_MUX_In0	),
		.In1			(ALU_B_MUX_In1	),
		.Op				(ALU_B_MUX_Op	),
		.Out			(ALU_B_MUX_Out	)
	);


    wire [31: 0] A 		= ALU_A_MUX_Out;
	wire [31: 0] B 		= ALU_B_MUX_Out;
	wire [ 3: 0] ALU_Op = ALU_Sel;
	wire [31: 0] ALU_Out;
	wire overflow;
   	ALU U_ALU(
		.A				(A				),
		.B				(B				),
		.Op				(ALU_Op			),
		.sign			(sign			),
		.Out			(ALU_Out		),
		.overflow		(overflow		)
	);

	wire [ 2: 0] MDU_Op = MDU_Sel;
	wire [31: 0] MDU_Out;
	wire		 Busy;
	wire [ 8: 0] MEM_Out_EXC;
	MDU MDU(
		.clk			(clk			),
		.rst			(rst			),
		.Start			(Start			),
		.Sel			(MDU_RD_Sel		),
		.A				(RS_E_MUX_Out	),
		.B				(RT_E_MUX_Out	),
		.Op				(MDU_Op			),
		.MEM_Out_EXC	(MEM_Out_EXC[7:0]),
		.Out			(MDU_Out		),
		.Busy			(Busy			)
	);

	wire [31: 0] ALU_MDU_MUX_In0 = ALU_Out;
	wire [31: 0] ALU_MDU_MUX_In1 = MDU_Out;
	wire 		 ALU_MDU_MUX_Op  = ALU_MDU_Sel;
	wire [31: 0] ALU_MDU_MUX_Out;
	
	mux2 #(32) ALU_MDU_MUX(
		.In0			(ALU_MDU_MUX_In0),
		.In1			(ALU_MDU_MUX_In1),
		.Op				(ALU_MDU_MUX_Op	),
		.Out			(ALU_MDU_MUX_Out)
	);

	
	
	wire [31: 0] RT_M_MUX_In0 = RT_E_MUX_Out;
	wire [31: 0] RT_M_MUX_In1;
	wire 		 RT_M_MUX_Op;
	wire [31: 0] RT_M_MUX_Out;
	wire [31: 0] DM_A 		  = ALU_Out;
	wire [31: 0] DM_WD 		  = RT_M_MUX_Out;
	wire [31: 0] DM_RD;

	store_unit U_store_unit(
		.StoreType		(StoreType		),
		.addr			(DM_A			),
		.DMWr			(DMWr			),
		.MEM_Out_EXC	(MEM_Out_EXC[7:0]),
		.wdata			(RT_M_MUX_Out	),
		.sram_wen		(data_sram_wen	),
		.sram_wdata		(data_sram_wdata)
	);
	wire [ 1: 0] MEM_EXC;
	wire EXE_EXC = 	((Instr_E[`op] == 6'b101011) & DM_A[1:0] != 2'b00) | 
					((Instr_E[`op] == 6'b101001) & DM_A[0]   != 1'b0 );
	wire ERET;
	assign DMWr = DM_wen & !EXE_EXC & !ERET;


	assign data_sram_en   = 1'b1;
    assign data_sram_addr = {3'b0,DM_A[28:0]};
   	mux2 #(32) U_RT_M_MUX(
		.In0			(RT_M_MUX_In0	),
		.In1			(RT_M_MUX_In1	),
		.Op				(RT_M_MUX_Op	),
		.Out			(RT_M_MUX_Out	)
	);

	wire [6:0]EXE_Out_EXC = {overflow,EXE_In_EXC};
	wire [6:0]MEM_In_EXC;

	wire [31: 0] N_Instr_M 	= Instr_E;
	wire [31: 0] N_RT_M 	= RT_M_MUX_Out;
	wire [31: 0] N_ALU_M 	= ALU_MDU_MUX_Out;
	wire [31: 0] N_EXT_M 	= EXT_E;
	wire [31: 0] N_PC8_M 	= PC8_E;
	wire [ 4: 0] N_WBA_M 	= WBA_E;
	wire [31: 0] Instr_M;
	wire [31: 0] RT_M;
	wire [31: 0] ALU_M;
	wire [31: 0] EXT_M;
	wire [31: 0] PC8_M;
	wire [ 4: 0] WBA_M;
	wire [31: 0] debug_pc_M;
   	EM U_EM(
		.clk			(clk			),
		.rst			(rst			),
		.N_Instr_M		(N_Instr_M		),
		.N_RT_M			(N_RT_M			),
		.N_ALU_M		(N_ALU_M		),
		.N_EXT_M		(N_EXT_M		),
		.N_PC8_M		(N_PC8_M		),
		.N_WBA_M		(N_WBA_M		),
		.Instr_M		(Instr_M		),
		.RT_M			(RT_M			),
		.ALU_M			(ALU_M			),
		.EXT_M			(EXT_M			),
		.PC8_M			(PC8_M			),
		.WBA_M			(WBA_M			),
		.N_debug_pc_M	(debug_pc_E		),
		.debug_pc_M		(debug_pc_M		),
		.EXE_Out_EXC	(EXE_Out_EXC	),
		.MEM_In_EXC		(MEM_In_EXC		),
		.flush			(flush			)
	);
   
	wire [ 2: 0] LoadType;
   	wire [ 2: 0] RF_Data_Sel_M; 
	CTRL U_CTRL_M(
		.Instr			(Instr_M		),
		.LoadType		(LoadType		),
		.RF_Data_Sel	(RF_Data_Sel_M	)
	);

	load_unit U_load_unit(
		.LoadType		(LoadType		),
		.sram_rdata		(data_sram_rdata),
    	.addr			(ALU_M			),
    	.rdata			(DM_RD			)
	);
	assign MEM_EXC[0] = ((Instr_M[`op] == 6'b101011) & ALU_M[1:0] != 2'b00) | 
						((Instr_M[`op] == 6'b101001) & ALU_M[0] != 1'b0);
	assign MEM_EXC[1] = ((Instr_M[`op] == 6'b100011) & ALU_M[1:0] != 2'b00) |
						((Instr_M[`op] == 6'b100001 | Instr_M[`op] == 6'b100101) & ALU_M[0] != 1'b0);
	assign MEM_Out_EXC = {MEM_In_EXC[1],MEM_In_EXC[0],MEM_In_EXC[2],MEM_EXC,MEM_In_EXC[3],
							MEM_In_EXC[4],MEM_In_EXC[5],MEM_In_EXC[6]};
	assign ERET = (Instr_M == 32'b01000010000000000000000000011000);


	wire [31: 0] CP0_OUT;
	wire [31: 0] RF_WD_In0 = ALU_M;
	wire [31: 0] RF_WD_In1 = DM_RD;
	wire [31: 0] RF_WD_In2 = EXT_M;
	wire [31: 0] RF_WD_In3 = PC8_M;
	wire [ 2: 0] RF_WD_Op  = RF_Data_Sel_M;
	wire [31: 0] RF_WD_Out;

	mux8 #(32) RF_WD_MUX(
		.In0			(RF_WD_In0		),
		.In1			(RF_WD_In1		),
		.In2			(RF_WD_In2		),
		.In3			(RF_WD_In3		),
		.Op				(RF_WD_Op		),
		.Out			(RF_WD_Out		)
	);


    wire [31: 0] N_Instr_W 	= Instr_M;
	wire [31: 0] N_ALU_W 	= ALU_M;
	wire [31: 0] N_DM_W 	= DM_RD;
	wire [31: 0] N_EXT_W 	= EXT_M;
	wire [31: 0] N_PC8_W 	= PC8_M;
	wire [ 4: 0] N_WBA_W 	= WBA_M;
	wire [31: 0] N_RT_W 	= RT_M;
	wire [31: 0] Instr_W;
	wire [31: 0] ALU_W;
	wire [31: 0] DM_W;
	wire [31: 0] EXT_W;
	wire [31: 0] PC8_W;
	wire [ 4: 0] WBA_W;
	wire [31: 0] debug_pc_W;
	wire [ 8: 0] WB_In_EXC;
	wire [31: 0] RT_W;
    MW U_MW(
		.clk			(clk			),
		.rst			(rst			),
		.N_Instr_W		(N_Instr_W		),
		.N_ALU_W		(N_ALU_W		),
		.N_DM_W			(N_DM_W			),
		.N_EXT_W		(N_EXT_W		),
		.N_PC8_W		(N_PC8_W		),
		.N_WBA_W		(N_WBA_W		),
		.Instr_W		(Instr_W		),
		.ALU_W			(ALU_W			),
		.DM_W			(DM_W			),
		.EXT_W			(EXT_W			),
		.PC8_W			(PC8_W			),
		.WBA_W			(WBA_W			),
		.N_debug_pc_W	(debug_pc_M		),
		.debug_pc_W		(debug_pc_W		),
		.MEM_Out_EXC	(MEM_Out_EXC	),
		.WB_In_EXC		(WB_In_EXC		),
		.N_RT_W			(N_RT_W			),
		.RT_W			(RT_W			),
		.flush			(flush			)
	);
   	wire [ 2: 0] RF_Data_Sel;
	wire 		 RF_wen;
	assign debug_wb_pc = debug_pc_W;
   	CTRL U_CTRL_W(
		.Instr			(Instr_W		),
		.RF_Data_Sel	(RF_Data_Sel	),
		.RFWr			(RF_wen			)
	);
	assign RFWr = (WB_In_EXC[7:0] == 8'b00000000) & RF_wen;

	wire [15: 0] CP0_CONTROL;
	wire [31: 0] CP0D;
    wire [31: 0] CAUSE_OUT;
    wire [31: 0] BADADDR_OUT;
    wire [31: 0] STATUS_OUT;
    wire [31: 0] EPC_OUT;
	wire [31: 0] Count_OUT;
	wire [31: 0] Compare_OUT;
	wire 		 PC_Sel_W;
	wire 		 CP0DSel;
    wire[ 2: 0]  CP0OSel;
	wire 		 eret_flush;

   	wire [31: 0] RF_WD_MUX_In0 = ALU_W;
	wire [31: 0] RF_WD_MUX_In1 = DM_W;
	wire [31: 0] RF_WD_MUX_In2 = EXT_W;
	wire [31: 0] RF_WD_MUX_In3 = PC8_W;
	wire [31: 0] RF_WD_MUX_In4 = CP0_OUT;
	wire [ 2: 0] RF_WD_MUX_Op  = RF_Data_Sel;
	wire [31: 0] RF_WD_MUX_Out;

	mux8 #(32) GRF_WD_MUX(
		.In0			(RF_WD_MUX_In0	),
		.In1			(RF_WD_MUX_In1	),
		.In2			(RF_WD_MUX_In2	),
		.In3			(RF_WD_MUX_In3	),
		.In4			(RF_WD_MUX_In4	),
		.Op				(RF_WD_MUX_Op	),
		.Out			(RF_WD_MUX_Out	)
	);

   	assign RF_A3 = WBA_W;
	assign RF_WD = RF_WD_MUX_Out;



	mux2 U_CPOD_MUX(
		.In0				(ALU_W			),
		.In1				(RT_W			),
		.Op					(CP0DSel		),
		.Out				(CP0D			)
	);

	CP0_Control U_CP0_Control(
    	.inst_W				(Instr_W		),
    	.exception_reg		(WB_In_EXC		),
    	.CP0_CONTROL_BUS	(CP0_CONTROL	),
    	.flush				(flush			),	
    	.PC_Sel_W			(PC_Sel_W		),
		.CP0DSel			(CP0DSel		),
		.CP0OSel			(CP0OSel		)
	);
	
	CP0 U_CP0(
		.clk				(clk			),
    	.rst				(rst			),
    	.CP0_DATA_IN		(CP0D			),           
    	.CP0_PC_IN			(debug_pc_W		),             
    	.CP0_CONTROL		(CP0_CONTROL	),           
    	.Status_OUT			(STATUS_OUT		),          
    	.Cause_OUT			(CAUSE_OUT		),
    	.BadAddr_OUT		(BADADDR_OUT	),
    	.EPC_OUT			(EPC_OUT		),
		.Count_OUT			(Count_OUT		),
		.Compare_OUT		(Compare_OUT	),
		.INT 				(INT			)
	);

	mux8 U_CP0_O (
        .In0   				(EPC_OUT        ),
        .In1   				(STATUS_OUT     ),
        .In2   				(CAUSE_OUT      ),
        .In3   				(BADADDR_OUT    ),
		.In4				(Count_OUT		),
		.In5				(Compare_OUT    ),
        .Op        			(CP0OSel 		),
        .Out 				(CP0_OUT        )
    );
	mux2 U_PC_WB(
		.In0				(32'hbfc00380	),
		.In1				(CP0_OUT		),
		.Op 				(PC_Sel_W		),
		.Out				(PC_WB_Out		)
	);

    wire [2:0] RS_D_MUXsel;
	wire [2:0] RT_D_MUXsel;
	wire [2:0] RS_E_MUXsel;
	wire [2:0] RT_E_MUXsel;
	wire RT_M_MUXsel;
	wire Stall;
   HZD U_HZD(
		.Instr_D			(Instr_D		),
		.Instr_E			(Instr_E		),
		.Instr_M			(Instr_M		),
		.Instr_W			(Instr_W		),
		.Busy				(Busy			),
		.Start				(Start			),
		.RS_D_Sel			(RS_D_MUXsel	),
		.RT_D_Sel			(RT_D_MUXsel	),
		.RS_E_Sel			(RS_E_MUXsel	),
		.RT_E_Sel			(RT_E_MUXsel	),
		.RT_M_Sel			(RT_M_MUXsel	),
		.Stall				(Stall			)
	);

    assign RS_D_MUX_In1 = EXT_E;
	assign RS_D_MUX_In2 = PC8_E;
	assign RS_D_MUX_In3 = ALU_M;
	assign RS_D_MUX_In4 = EXT_M;
	assign RS_D_MUX_In5 = PC8_M;
	assign RS_D_MUX_In6 = RF_WD_MUX_Out;
	assign RS_D_MUX_Op  = RS_D_MUXsel;
	

	assign RT_D_MUX_In1 = EXT_E;
	assign RT_D_MUX_In2 = PC8_E;
	assign RT_D_MUX_In3 = ALU_M;
	assign RT_D_MUX_In4 = EXT_M;
	assign RT_D_MUX_In5 = PC8_M;
	assign RT_D_MUX_In6 = RF_WD_MUX_Out;
	assign RT_D_MUX_Op  = RT_D_MUXsel;
	

	assign RS_E_MUX_In1 = ALU_M;
	assign RS_E_MUX_In2 = EXT_M;
	assign RS_E_MUX_In3 = PC8_M;
	assign RS_E_MUX_In4 = RF_WD_MUX_Out;
	assign RS_E_MUX_Op  = RS_E_MUXsel;
	

	assign RT_E_MUX_In1 = ALU_M;
	assign RT_E_MUX_In2 = EXT_M;
	assign RT_E_MUX_In3 = PC8_M;
	assign RT_E_MUX_In4 = RF_WD_MUX_Out;
	assign RT_E_MUX_Op  = RT_E_MUXsel;
	

	assign RT_M_MUX_In1 = RF_WD_Out;
	assign RT_M_MUX_Op  = RT_M_MUXsel;
	

	assign PCWr = !Stall & !rst;
	assign FD_En = !Stall;
	assign DE_clear = Stall;

endmodule
module mycpu_top(
    input         clk,
    input         resetn,
	input [5:0]   ext_int,

    output        inst_sram_en,
    output [ 3:0] inst_sram_wen,
    output [31:0] inst_sram_addr,
    output [31:0] inst_sram_wdata,
    input  [31:0] inst_sram_rdata,

    output        data_sram_en,
    output [ 3:0] data_sram_wen,
    output [31:0] data_sram_addr,
    output [31:0] data_sram_wdata,
    input  [31:0] data_sram_rdata,

    output [31:0] debug_wb_pc,
    output [ 3:0] debug_wb_rf_wen,
    output [ 4:0] debug_wb_rf_wnum,
    output [31:0] debug_wb_rf_wdata
);

	wire rst;
	assign rst = !resetn;
	
   `define op 31:26
   `define funct 5:0
   `define imm26 25:0
   `define imm16 15:0
   `define rs 25:21
   `define rt 20:16
   `define rd 15:11
   `define s 10:6
   	wire [31: 0] PC;
  	wire [31: 0] NPC;
   	wire 		 PCWr;
	wire 		 PC_EXC_IF;
	wire 		 flush;

   	PC U_PC(
		   .clk			(clk			),
		   .rst			(rst			),
		   .PCWr		(PCWr			),
		   .PC			(PC				),
		   .NPC			(NPC			)
	);
	assign PC_EXC_IF = PC[0] | PC[1];
	assign inst_sram_en    = PCWr;
	assign inst_sram_wen   = 4'h0;				
	assign inst_sram_addr  = PC;
	assign inst_sram_wdata = 32'b0;
   	wire [31: 0] Instr;
	assign Instr = inst_sram_rdata & {32{!flush}};

   	wire [31: 0] PC_4 = PC + 4;
   	wire [31: 0] PC_8 = PC + 8;
	wire         delay;

	wire [31: 0] N_PC4_D = PC_4;
	wire [31: 0] N_PC8_D = PC_8;
	wire [31: 0] PC4_D;
	wire [31: 0] PC8_D;
	wire [31: 0] debug_pc_D;
	wire 		 FD_En;
	wire 		 inst_vaild;
	wire 		 Delay_Next;
	wire [31: 0] Instr_D = Instr & {32{!inst_vaild}};
   FD U_FD(	
	   		.clk			(clk			),
		 	.rst			(rst			),
			.En				(FD_En			),
			.N_PC4_D		(N_PC4_D		),
			.N_PC8_D		(N_PC8_D		),
			.PC4_D			(PC4_D			),
			.PC8_D			(PC8_D			),
			.N_debug_pc_D	(PC				),
			.debug_pc_D		(debug_pc_D		),
			.PC_EXC_IF		(PC_EXC_IF		),
			.PC_EXC_ID		(PC_EXC_ID		),
			.flush			(flush			),
			.inst_vaild		(inst_vaild		),
			.Delay_Next		(Delay_Next		),
			.delay			(delay			)
	);

   	wire [ 2: 0] PC_Sel;
   	wire [ 1: 0] EXT_Sel;
   	wire [ 1: 0] RF_Sel;
   	wire [ 2: 0] NPC_Sel;
   	wire 		 syscall;
   	wire 		 break;
   	wire 		 reserve;
	wire 		 INT;
   	CTRL U_CTRL_D(	
		   	.Instr			(Instr_D		),
	   		.PC_Sel			(PC_Sel			),
			.EXT_Sel		(EXT_Sel		),
			.RF_Sel			(RF_Sel			),
			.NPC_Sel		(NPC_Sel		),
			.syscall		(syscall		),
			.break			(break			),
			.reserve		(reserve		),
			.Delay_Next		(Delay_Next		)
	);
	wire [ 5: 0] ID_Out_EXC = {reserve,break,syscall,PC_EXC_ID,delay,INT};
	wire [ 5: 0] EXE_In_EXC;

   	wire [ 4: 0] RF_A1 = Instr_D[`rs];
  	wire [ 4: 0] RF_A2 = Instr_D[`rt];
	wire [ 4: 0] RF_A3;
   	wire [31: 0] RF_WD;
   	wire [31: 0] RF_RD1;
   	wire [31: 0] RF_RD2;
   	wire RFWr;

	
   	RF U_RF(
		   .clk			(clk			),
		   .rst			(rst			),
		   .RFWr		(RFWr			),
		   .A1			(RF_A1			),
		   .A2			(RF_A2			),
		   .A3			(RF_A3			),
		   .WD			(RF_WD			),
		   .RD1			(RF_RD1			),
		   .RD2			(RF_RD2			)
	);
   	assign debug_wb_rf_wen = {4{RFWr}};
	assign debug_wb_rf_wnum = RF_A3;
    assign debug_wb_rf_wdata = RF_WD;
   	
	wire [31: 0] RS_D_MUX_In0 = RF_RD1;
	wire [31: 0] RS_D_MUX_In1;
	wire [31: 0] RS_D_MUX_In2;
	wire [31: 0] RS_D_MUX_In3;
	wire [31: 0] RS_D_MUX_In4;
	wire [31: 0] RS_D_MUX_In5;
	wire [31: 0] RS_D_MUX_In6;
	wire [ 2: 0] RS_D_MUX_Op;
	wire [31: 0] RS_D_MUX_Out;

   mux8 #(32) U_RS_D_MUX(
      	.In0			(RS_D_MUX_In0	),
		.In1			(RS_D_MUX_In1	),
		.In2			(RS_D_MUX_In2	),
		.In3			(RS_D_MUX_In3	),
		.In4			(RS_D_MUX_In4	),
		.In5			(RS_D_MUX_In5	),
		.In6			(RS_D_MUX_In6	),
		.Op				(RS_D_MUX_Op	),
		.Out			(RS_D_MUX_Out	)
   );

   	wire [31: 0] RT_D_MUX_In0 = RF_RD2;
	wire [31: 0] RT_D_MUX_In1;
	wire [31: 0] RT_D_MUX_In2;
	wire [31: 0] RT_D_MUX_In3;
	wire [31: 0] RT_D_MUX_In4;
	wire [31: 0] RT_D_MUX_In5;
	wire [31: 0] RT_D_MUX_In6;
	wire [ 2: 0] RT_D_MUX_Op;
	wire [31: 0] RT_D_MUX_Out;

   mux8 #(32) U_RT_D_MUX(
		.In0			(RT_D_MUX_In0	),
		.In1			(RT_D_MUX_In1	),
		.In2			(RT_D_MUX_In2	),
		.In3			(RT_D_MUX_In3	),
		.In4			(RT_D_MUX_In4	),
		.In5			(RT_D_MUX_In5	),
		.In6			(RT_D_MUX_In6	),
		.Op				(RT_D_MUX_Op	),
		.Out			(RT_D_MUX_Out	)
	);
   
   wire [15:0] EXT_In = Instr_D[`imm16];
   wire [31:0] EXT_Out;
   EXT U_EXT(
	   .In				(EXT_In			),
	   .Op				(EXT_Sel		),
	   .Out				(EXT_Out		)
	);

   wire [31: 0] Base = PC4_D;
   wire [31: 0] ImmB = EXT_Out;
   wire [25: 0] ImmJ = Instr_D[`imm26];
   wire [31: 0] Cmp1 = RS_D_MUX_Out;
   wire [31: 0] Cmp2 = RT_D_MUX_Out;
   wire [ 2: 0] CmpOp = PC_Sel;
   wire [31: 0] Branch;
   wire [31: 0] Jump;

   NPC U_NPC(
	   .PC				(Base			),
	   .ImmB			(ImmB			),
	   .ImmJ			(ImmJ			),
	   .Cmp1			(Cmp1			),
	   .Cmp2			(Cmp2			),
	   .CmpOp			(CmpOp			),
	   .Branch			(Branch			),
	   .Jump			(Jump			)
	);


    wire [ 4: 0] RF_A3_MUX_In0 = Instr_D[`rd];
	wire [ 4: 0] RF_A3_MUX_In1 = Instr_D[`rt];
	wire [ 4: 0] RF_A3_MUX_In2 = 31;
	wire [ 1: 0] RF_A3_MUX_Op  = RF_Sel;
	wire [ 4: 0] RF_A3_MUX_Out;

   mux4 #(5) U_RF_A3_MUX(
		.In0			(RF_A3_MUX_In0	),
		.In1			(RF_A3_MUX_In1	),
		.In2			(RF_A3_MUX_In2	),
		.Op				(RF_A3_MUX_Op	),
		.Out			(RF_A3_MUX_Out	)
	);
   
    wire [31: 0] PC_MUX_In0 = PC_4;
	wire [31: 0] PC_MUX_In1 = Branch;
	wire [31: 0] PC_MUX_In2 = Jump;
	wire [31: 0] PC_MUX_In3 = RS_D_MUX_Out;
	wire [ 2: 0] PC_MUX_Op  = NPC_Sel;
	wire [31: 0] PC_MUX_Out;

   	mux8 #(32) U_PC_MUX(
		.In0			(PC_MUX_In0		),
		.In1			(PC_MUX_In1		),
		.In2			(PC_MUX_In2		),
		.In3			(PC_MUX_In3		),
		.Op				(PC_MUX_Op		),
		.Out			(PC_MUX_Out		)
	);
	wire [31: 0]PC_WB_Out;
	mux2 #(32) U_NPC_MUX(
		.In0			(PC_MUX_Out		),
		.In1			(PC_WB_Out		),
		.Op				(flush			),
		.Out			(NPC			)
	);


    wire 		 DE_clear;
	wire [31: 0] N_Instr_E	= Instr_D;
	wire [31: 0] N_RS_E 	= RS_D_MUX_Out;
	wire [31: 0] N_RT_E 	= RT_D_MUX_Out;
	wire [31: 0] N_EXT_E 	= EXT_Out;
	wire [31: 0] N_PC8_E 	= PC8_D;
	wire [ 4: 0] N_WBA_E 	= RF_A3_MUX_Out;
	wire [31: 0] N_s_E 		= Instr_D[`s];
	wire [31: 0] Instr_E;
	wire [31: 0] RS_E;
	wire [31: 0] RT_E;
	wire [31: 0] EXT_E;
	wire [31: 0] PC8_E;
	wire [ 4: 0] WBA_E;
	wire [31: 0] s_E;
	wire [31: 0] debug_pc_E;
   	DE U_DE(
		.clk			(clk			),
		.rst			(rst			),
		.clear			(DE_clear		),
		.N_Instr_E		(N_Instr_E		),
		.N_RS_E			(N_RS_E			),
		.N_RT_E			(N_RT_E			),
		.N_EXT_E		(N_EXT_E		),
		.N_PC8_E		(N_PC8_E		),
		.N_WBA_E		(N_WBA_E		),
		.N_s_E			(N_s_E			),
		.Instr_E		(Instr_E		),
		.RS_E			(RS_E			),
		.RT_E			(RT_E			),
		.EXT_E			(EXT_E			),
		.PC8_E			(PC8_E			),
		.WBA_E			(WBA_E			),
		.s_E			(s_E			),
		.N_debug_pc_E	(debug_pc_D		),
		.debug_pc_E		(debug_pc_E		),
		.ID_Out_EXC		(ID_Out_EXC		),
		.EXE_In_EXC		(EXE_In_EXC		),
		.flush			(flush			)
	);
   	
    wire [ 3: 0] ALU_Sel;
	wire 		 ALU_A_Sel;
	wire 		 ALU_B_Sel;
	wire [ 2: 0] MDU_Sel;
	wire 		 Start;
	wire 		 MDU_RD_Sel;
	wire 		 ALU_MDU_Sel;
	wire 		 DM_wen;
	wire 		 DMWr;
	wire [ 1: 0] StoreType;
	wire 	 	 sign;
   	CTRL U_CTRL_E(
      .Instr			(Instr_E		),
      .ALU_Sel			(ALU_Sel		),
      .ALU_A_Sel		(ALU_A_Sel		),
      .ALU_B_Sel		(ALU_B_Sel		),
	  .MDU_Sel			(MDU_Sel		),
	  .Start			(Start			),
	  .MDU_RD_Sel		(MDU_RD_Sel		),
	  .ALU_MDU_Sel		(ALU_MDU_Sel	),
	  .DMWr				(DM_wen			),
	  .StoreType		(StoreType		),
	  .sign				(sign			)
   	);

   	wire [31: 0] RS_E_MUX_In0 = RS_E;
	wire [31: 0] RS_E_MUX_In1;
	wire [31: 0] RS_E_MUX_In2;
	wire [31: 0] RS_E_MUX_In3;
	wire [31: 0] RS_E_MUX_In4;
	wire [ 2: 0] RS_E_MUX_Op;
	wire [31: 0] RS_E_MUX_Out;

   mux8 #(32) U_RS_E_MUX(
		.In0			(RS_E_MUX_In0	),
		.In1			(RS_E_MUX_In1	),
		.In2			(RS_E_MUX_In2	),
		.In3			(RS_E_MUX_In3	),
		.In4			(RS_E_MUX_In4	),
		.Op				(RS_E_MUX_Op	),
		.Out			(RS_E_MUX_Out	)
	);

   	wire [31: 0] RT_E_MUX_In0 = RT_E;
	wire [31: 0] RT_E_MUX_In1;
	wire [31: 0] RT_E_MUX_In2;
	wire [31: 0] RT_E_MUX_In3;
	wire [31: 0] RT_E_MUX_In4;
	wire [ 2: 0] RT_E_MUX_Op;
	wire [31: 0] RT_E_MUX_Out;

   mux8 #(32) U_RT_E_MUX(
		.In0			(RT_E_MUX_In0	),
		.In1			(RT_E_MUX_In1	),
		.In2			(RT_E_MUX_In2	),
		.In3			(RT_E_MUX_In3	),
		.In4			(RT_E_MUX_In4	),
		.Op				(RT_E_MUX_Op	),
		.Out			(RT_E_MUX_Out	)
	);

    wire [31: 0] ALU_A_MUX_In0 = RS_E_MUX_Out;
	wire [31: 0] ALU_A_MUX_In1 = s_E;
	wire 		 ALU_A_MUX_Op  = ALU_A_Sel;
	wire [31: 0] ALU_A_MUX_Out;

   mux2 #(32) U_ALU_A_MUX(
		.In0			(ALU_A_MUX_In0	),
		.In1			(ALU_A_MUX_In1	),
		.Op				(ALU_A_MUX_Op	),
		.Out			(ALU_A_MUX_Out	)
	);

   	wire [31: 0] ALU_B_MUX_In0 = RT_E_MUX_Out;
	wire [31: 0] ALU_B_MUX_In1 = EXT_E;
	wire 		 ALU_B_MUX_Op  = ALU_B_Sel;
	wire [31: 0] ALU_B_MUX_Out;

   mux2 #(32) U_ALU_B_MUX(
		.In0			(ALU_B_MUX_In0	),
		.In1			(ALU_B_MUX_In1	),
		.Op				(ALU_B_MUX_Op	),
		.Out			(ALU_B_MUX_Out	)
	);


    wire [31: 0] A 		= ALU_A_MUX_Out;
	wire [31: 0] B 		= ALU_B_MUX_Out;
	wire [ 3: 0] ALU_Op = ALU_Sel;
	wire [31: 0] ALU_Out;
	wire overflow;
   	ALU U_ALU(
		.A				(A				),
		.B				(B				),
		.Op				(ALU_Op			),
		.sign			(sign			),
		.Out			(ALU_Out		),
		.overflow		(overflow		)
	);

	wire [ 2: 0] MDU_Op = MDU_Sel;
	wire [31: 0] MDU_Out;
	wire		 Busy;
	wire [ 8: 0] MEM_Out_EXC;
	MDU MDU(
		.clk			(clk			),
		.rst			(rst			),
		.Start			(Start			),
		.Sel			(MDU_RD_Sel		),
		.A				(RS_E_MUX_Out	),
		.B				(RT_E_MUX_Out	),
		.Op				(MDU_Op			),
		.MEM_Out_EXC	(MEM_Out_EXC[7:0]),
		.Out			(MDU_Out		),
		.Busy			(Busy			)
	);

	wire [31: 0] ALU_MDU_MUX_In0 = ALU_Out;
	wire [31: 0] ALU_MDU_MUX_In1 = MDU_Out;
	wire 		 ALU_MDU_MUX_Op  = ALU_MDU_Sel;
	wire [31: 0] ALU_MDU_MUX_Out;
	
	mux2 #(32) ALU_MDU_MUX(
		.In0			(ALU_MDU_MUX_In0),
		.In1			(ALU_MDU_MUX_In1),
		.Op				(ALU_MDU_MUX_Op	),
		.Out			(ALU_MDU_MUX_Out)
	);

	
	
	wire [31: 0] RT_M_MUX_In0 = RT_E_MUX_Out;
	wire [31: 0] RT_M_MUX_In1;
	wire 		 RT_M_MUX_Op;
	wire [31: 0] RT_M_MUX_Out;
	wire [31: 0] DM_A 		  = ALU_Out;
	wire [31: 0] DM_WD 		  = RT_M_MUX_Out;
	wire [31: 0] DM_RD;

	store_unit U_store_unit(
		.StoreType		(StoreType		),
		.addr			(DM_A			),
		.DMWr			(DMWr			),
		.MEM_Out_EXC	(MEM_Out_EXC[7:0]),
		.wdata			(RT_M_MUX_Out	),
		.sram_wen		(data_sram_wen	),
		.sram_wdata		(data_sram_wdata)
	);
	wire [ 1: 0] MEM_EXC;
	wire EXE_EXC = 	((Instr_E[`op] == 6'b101011) & DM_A[1:0] != 2'b00) | 
					((Instr_E[`op] == 6'b101001) & DM_A[0]   != 1'b0 );
	wire ERET;
	assign DMWr = DM_wen & !EXE_EXC & !ERET;


	assign data_sram_en   = 1'b1;
    assign data_sram_addr = {3'b0,DM_A[28:0]};
   	mux2 #(32) U_RT_M_MUX(
		.In0			(RT_M_MUX_In0	),
		.In1			(RT_M_MUX_In1	),
		.Op				(RT_M_MUX_Op	),
		.Out			(RT_M_MUX_Out	)
	);

	wire [6:0]EXE_Out_EXC = {overflow,EXE_In_EXC};
	wire [6:0]MEM_In_EXC;

	wire [31: 0] N_Instr_M 	= Instr_E;
	wire [31: 0] N_RT_M 	= RT_M_MUX_Out;
	wire [31: 0] N_ALU_M 	= ALU_MDU_MUX_Out;
	wire [31: 0] N_EXT_M 	= EXT_E;
	wire [31: 0] N_PC8_M 	= PC8_E;
	wire [ 4: 0] N_WBA_M 	= WBA_E;
	wire [31: 0] Instr_M;
	wire [31: 0] RT_M;
	wire [31: 0] ALU_M;
	wire [31: 0] EXT_M;
	wire [31: 0] PC8_M;
	wire [ 4: 0] WBA_M;
	wire [31: 0] debug_pc_M;
   	EM U_EM(
		.clk			(clk			),
		.rst			(rst			),
		.N_Instr_M		(N_Instr_M		),
		.N_RT_M			(N_RT_M			),
		.N_ALU_M		(N_ALU_M		),
		.N_EXT_M		(N_EXT_M		),
		.N_PC8_M		(N_PC8_M		),
		.N_WBA_M		(N_WBA_M		),
		.Instr_M		(Instr_M		),
		.RT_M			(RT_M			),
		.ALU_M			(ALU_M			),
		.EXT_M			(EXT_M			),
		.PC8_M			(PC8_M			),
		.WBA_M			(WBA_M			),
		.N_debug_pc_M	(debug_pc_E		),
		.debug_pc_M		(debug_pc_M		),
		.EXE_Out_EXC	(EXE_Out_EXC	),
		.MEM_In_EXC		(MEM_In_EXC		),
		.flush			(flush			)
	);
   
	wire [ 2: 0] LoadType;
   	wire [ 2: 0] RF_Data_Sel_M; 
	CTRL U_CTRL_M(
		.Instr			(Instr_M		),
		.LoadType		(LoadType		),
		.RF_Data_Sel	(RF_Data_Sel_M	)
	);

	load_unit U_load_unit(
		.LoadType		(LoadType		),
		.sram_rdata		(data_sram_rdata),
    	.addr			(ALU_M			),
    	.rdata			(DM_RD			)
	);
	assign MEM_EXC[0] = ((Instr_M[`op] == 6'b101011) & ALU_M[1:0] != 2'b00) | 
						((Instr_M[`op] == 6'b101001) & ALU_M[0] != 1'b0);
	assign MEM_EXC[1] = ((Instr_M[`op] == 6'b100011) & ALU_M[1:0] != 2'b00) |
						((Instr_M[`op] == 6'b100001 | Instr_M[`op] == 6'b100101) & ALU_M[0] != 1'b0);
	assign MEM_Out_EXC = {MEM_In_EXC[1],MEM_In_EXC[0],MEM_In_EXC[2],MEM_EXC,MEM_In_EXC[3],
							MEM_In_EXC[4],MEM_In_EXC[5],MEM_In_EXC[6]};
	assign ERET = (Instr_M == 32'b01000010000000000000000000011000);


	wire [31: 0] CP0_OUT;
	wire [31: 0] RF_WD_In0 = ALU_M;
	wire [31: 0] RF_WD_In1 = DM_RD;
	wire [31: 0] RF_WD_In2 = EXT_M;
	wire [31: 0] RF_WD_In3 = PC8_M;
	wire [ 2: 0] RF_WD_Op  = RF_Data_Sel_M;
	wire [31: 0] RF_WD_Out;

	mux8 #(32) RF_WD_MUX(
		.In0			(RF_WD_In0		),
		.In1			(RF_WD_In1		),
		.In2			(RF_WD_In2		),
		.In3			(RF_WD_In3		),
		.Op				(RF_WD_Op		),
		.Out			(RF_WD_Out		)
	);


    wire [31: 0] N_Instr_W 	= Instr_M;
	wire [31: 0] N_ALU_W 	= ALU_M;
	wire [31: 0] N_DM_W 	= DM_RD;
	wire [31: 0] N_EXT_W 	= EXT_M;
	wire [31: 0] N_PC8_W 	= PC8_M;
	wire [ 4: 0] N_WBA_W 	= WBA_M;
	wire [31: 0] N_RT_W 	= RT_M;
	wire [31: 0] Instr_W;
	wire [31: 0] ALU_W;
	wire [31: 0] DM_W;
	wire [31: 0] EXT_W;
	wire [31: 0] PC8_W;
	wire [ 4: 0] WBA_W;
	wire [31: 0] debug_pc_W;
	wire [ 8: 0] WB_In_EXC;
	wire [31: 0] RT_W;
    MW U_MW(
		.clk			(clk			),
		.rst			(rst			),
		.N_Instr_W		(N_Instr_W		),
		.N_ALU_W		(N_ALU_W		),
		.N_DM_W			(N_DM_W			),
		.N_EXT_W		(N_EXT_W		),
		.N_PC8_W		(N_PC8_W		),
		.N_WBA_W		(N_WBA_W		),
		.Instr_W		(Instr_W		),
		.ALU_W			(ALU_W			),
		.DM_W			(DM_W			),
		.EXT_W			(EXT_W			),
		.PC8_W			(PC8_W			),
		.WBA_W			(WBA_W			),
		.N_debug_pc_W	(debug_pc_M		),
		.debug_pc_W		(debug_pc_W		),
		.MEM_Out_EXC	(MEM_Out_EXC	),
		.WB_In_EXC		(WB_In_EXC		),
		.N_RT_W			(N_RT_W			),
		.RT_W			(RT_W			),
		.flush			(flush			)
	);
   	wire [ 2: 0] RF_Data_Sel;
	wire 		 RF_wen;
	assign debug_wb_pc = debug_pc_W;
   	CTRL U_CTRL_W(
		.Instr			(Instr_W		),
		.RF_Data_Sel	(RF_Data_Sel	),
		.RFWr			(RF_wen			)
	);
	assign RFWr = (WB_In_EXC[7:0] == 8'b00000000) & RF_wen;

	wire [15: 0] CP0_CONTROL;
	wire [31: 0] CP0D;
    wire [31: 0] CAUSE_OUT;
    wire [31: 0] BADADDR_OUT;
    wire [31: 0] STATUS_OUT;
    wire [31: 0] EPC_OUT;
	wire [31: 0] Count_OUT;
	wire [31: 0] Compare_OUT;
	wire 		 PC_Sel_W;
	wire 		 CP0DSel;
    wire[ 2: 0]  CP0OSel;
	wire 		 eret_flush;

   	wire [31: 0] RF_WD_MUX_In0 = ALU_W;
	wire [31: 0] RF_WD_MUX_In1 = DM_W;
	wire [31: 0] RF_WD_MUX_In2 = EXT_W;
	wire [31: 0] RF_WD_MUX_In3 = PC8_W;
	wire [31: 0] RF_WD_MUX_In4 = CP0_OUT;
	wire [ 2: 0] RF_WD_MUX_Op  = RF_Data_Sel;
	wire [31: 0] RF_WD_MUX_Out;

	mux8 #(32) GRF_WD_MUX(
		.In0			(RF_WD_MUX_In0	),
		.In1			(RF_WD_MUX_In1	),
		.In2			(RF_WD_MUX_In2	),
		.In3			(RF_WD_MUX_In3	),
		.In4			(RF_WD_MUX_In4	),
		.Op				(RF_WD_MUX_Op	),
		.Out			(RF_WD_MUX_Out	)
	);

   	assign RF_A3 = WBA_W;
	assign RF_WD = RF_WD_MUX_Out;



	mux2 U_CPOD_MUX(
		.In0				(ALU_W			),
		.In1				(RT_W			),
		.Op					(CP0DSel		),
		.Out				(CP0D			)
	);

	CP0_Control U_CP0_Control(
    	.inst_W				(Instr_W		),
    	.exception_reg		(WB_In_EXC		),
    	.CP0_CONTROL_BUS	(CP0_CONTROL	),
    	.flush				(flush			),	
    	.PC_Sel_W			(PC_Sel_W		),
		.CP0DSel			(CP0DSel		),
		.CP0OSel			(CP0OSel		)
	);
	
	CP0 U_CP0(
		.clk				(clk			),
    	.rst				(rst			),
    	.CP0_DATA_IN		(CP0D			),           
    	.CP0_PC_IN			(debug_pc_W		),             
    	.CP0_CONTROL		(CP0_CONTROL	),           
    	.Status_OUT			(STATUS_OUT		),          
    	.Cause_OUT			(CAUSE_OUT		),
    	.BadAddr_OUT		(BADADDR_OUT	),
    	.EPC_OUT			(EPC_OUT		),
		.Count_OUT			(Count_OUT		),
		.Compare_OUT		(Compare_OUT	),
		.INT 				(INT			)
	);

	mux8 U_CP0_O (
        .In0   				(EPC_OUT        ),
        .In1   				(STATUS_OUT     ),
        .In2   				(CAUSE_OUT      ),
        .In3   				(BADADDR_OUT    ),
		.In4				(Count_OUT		),
		.In5				(Compare_OUT    ),
        .Op        			(CP0OSel 		),
        .Out 				(CP0_OUT        )
    );
	mux2 U_PC_WB(
		.In0				(32'hbfc00380	),
		.In1				(CP0_OUT		),
		.Op 				(PC_Sel_W		),
		.Out				(PC_WB_Out		)
	);

    wire [2:0] RS_D_MUXsel;
	wire [2:0] RT_D_MUXsel;
	wire [2:0] RS_E_MUXsel;
	wire [2:0] RT_E_MUXsel;
	wire RT_M_MUXsel;
	wire Stall;
   HZD U_HZD(
		.Instr_D			(Instr_D		),
		.Instr_E			(Instr_E		),
		.Instr_M			(Instr_M		),
		.Instr_W			(Instr_W		),
		.Busy				(Busy			),
		.Start				(Start			),
		.RS_D_Sel			(RS_D_MUXsel	),
		.RT_D_Sel			(RT_D_MUXsel	),
		.RS_E_Sel			(RS_E_MUXsel	),
		.RT_E_Sel			(RT_E_MUXsel	),
		.RT_M_Sel			(RT_M_MUXsel	),
		.Stall				(Stall			)
	);

    assign RS_D_MUX_In1 = EXT_E;
	assign RS_D_MUX_In2 = PC8_E;
	assign RS_D_MUX_In3 = ALU_M;
	assign RS_D_MUX_In4 = EXT_M;
	assign RS_D_MUX_In5 = PC8_M;
	assign RS_D_MUX_In6 = RF_WD_MUX_Out;
	assign RS_D_MUX_Op  = RS_D_MUXsel;
	

	assign RT_D_MUX_In1 = EXT_E;
	assign RT_D_MUX_In2 = PC8_E;
	assign RT_D_MUX_In3 = ALU_M;
	assign RT_D_MUX_In4 = EXT_M;
	assign RT_D_MUX_In5 = PC8_M;
	assign RT_D_MUX_In6 = RF_WD_MUX_Out;
	assign RT_D_MUX_Op  = RT_D_MUXsel;
	

	assign RS_E_MUX_In1 = ALU_M;
	assign RS_E_MUX_In2 = EXT_M;
	assign RS_E_MUX_In3 = PC8_M;
	assign RS_E_MUX_In4 = RF_WD_MUX_Out;
	assign RS_E_MUX_Op  = RS_E_MUXsel;
	

	assign RT_E_MUX_In1 = ALU_M;
	assign RT_E_MUX_In2 = EXT_M;
	assign RT_E_MUX_In3 = PC8_M;
	assign RT_E_MUX_In4 = RF_WD_MUX_Out;
	assign RT_E_MUX_Op  = RT_E_MUXsel;
	

	assign RT_M_MUX_In1 = RF_WD_Out;
	assign RT_M_MUX_Op  = RT_M_MUXsel;
	

	assign PCWr = !Stall & !rst;
	assign FD_En = !Stall;
	assign DE_clear = Stall;

endmodule