dakies/OSS_Verilog huggingface dataset:
module openmips_min_sopc(
			 input wire clk,
			 input wire rst
			 );

   //连接指令存储器
   wire [`InstAddrBus] 		    inst_addr;
   wire [`InstBus] 		    inst;
   wire 			    rom_ce;
   

   openmips openmips0(
		      .clk(clk),
		      .rst(rst),
      
		      .rom_addr_o(inst_addr),
		      .rom_data_i(inst),
		      .rom_ce_o(rom_ce)
      
		      );
   
   inst_rom inst_rom0(
		      .addr(inst_addr),
		      .inst(inst),
		      .ce(rom_ce)	
		      );
   
endmodule // openmips_min_sopc
module mem_wb(
	      input wire 	       clk,
	      input wire 	       rst,


	      //来自访存阶段的信息	
	      input wire [`RegAddrBus] mem_wd,
	      input wire 	       mem_wreg,
	      input wire [`RegBus]     mem_wdata,

	      //送到回写阶段的信息
	      output reg [`RegAddrBus] wb_wd,
	      output reg 	       wb_wreg,
	      output reg [`RegBus]     wb_wdata	       

	      );

   always @ (posedge clk) 
     begin
	if(rst == `RstEnable) 
	  begin
	     wb_wd <= `NOPRegAddr;
	     wb_wreg <= `WriteDisable;
	     wb_wdata <= `ZeroWord;	
	  end 
	else 
	  begin
	     wb_wd <= mem_wd;
	     wb_wreg <= mem_wreg;
	     wb_wdata <= mem_wdata;
	  end // else: !if(rst == `RstEnable)
     end // always @ (posedge clk)

endmodule // mem_wb
module id_ex(

	     input wire 	      clk,
	     input wire 	      rst,


	     //从译码阶段传递的信息
	     input wire [`AluOpBus]   id_aluop,
	     input wire [`AluSelBus]  id_alusel,
	     input wire [`RegBus]     id_reg1,
	     input wire [`RegBus]     id_reg2,
	     input wire [`RegAddrBus] id_wd,
	     input wire 	      id_wreg, 

	     //传递到执行阶段的信息
	     output reg [`AluOpBus]   ex_aluop,
	     output reg [`AluSelBus]  ex_alusel,
	     output reg [`RegBus]     ex_reg1,
	     output reg [`RegBus]     ex_reg2,
	     output reg [`RegAddrBus] ex_wd,
	     output reg 	      ex_wreg

	     );

   always @ (posedge clk) 
     begin
	if (rst == `RstEnable) 
	  begin
	     ex_aluop <= `EXE_NOP_OP;
	     ex_alusel <= `EXE_RES_NOP;
	     ex_reg1 <= `ZeroWord;
	     ex_reg2 <= `ZeroWord;
	     ex_wd <= `NOPRegAddr;
	     ex_wreg <= `WriteDisable;
	  end 
	else 
	  begin		
	     ex_aluop <= id_aluop;
	     ex_alusel <= id_alusel;
	     ex_reg1 <= id_reg1;
	     ex_reg2 <= id_reg2;
	     ex_wd <= id_wd;
	     ex_wreg <= id_wreg;
	     // $write("%h %h\n",ex_reg1,ex_reg2);
	  end // else: !if(rst == `RstEnable)
     end // always @ (posedge clk)
   
endmodule // id_ex
module mem(
	   input wire 		    rst,
   
	   //来自执行阶段的信息	
	   input wire [`RegAddrBus] wd_i,
	   input wire 		    wreg_i,
	   input wire [`RegBus]     wdata_i,

	   //送到回写阶段的信息
	   output reg [`RegAddrBus] wd_o,
	   output reg 		    wreg_o,
	   output reg [`RegBus]     wdata_o
	   );

   always @ (*) 
     begin
	if (rst == `RstEnable) 
	  begin
	     wd_o <= `NOPRegAddr;
	     wreg_o <= `WriteDisable;
	     wdata_o <= `ZeroWord;
	  end 
	else
	  begin
	     wd_o <= wd_i;
	     wreg_o <= wreg_i;
	     wdata_o <= wdata_i;
	  end // else: !if(rst == `RstEnable)
     end // always @ (*)

endmodule // mem
module if_id(
	     input wire 	       clk,
	     input wire 	       rst,
	     input wire [`InstAddrBus] if_pc,
	     input wire [`InstBus]     if_inst,
	     output reg [`InstAddrBus] id_pc,
	     output reg [`InstBus]     id_inst
	     );
   always @ (posedge clk)
     begin
	if (rst == `RstEnable) 
	  begin
	     id_pc <= `ZeroWord;
	     id_inst <= `ZeroWord;
	  end 
	else 
	  begin
	     id_pc <= if_pc;
	     id_inst <= if_inst;
	  end
     end // always @ (posedge clk)
endmodule // if_id
module ex(

	  input wire 		   rst,
   
	  //送到执行阶段的信息
	  input wire [`AluOpBus]   aluop_i,
	  input wire [`AluSelBus]  alusel_i,
	  input wire [`RegBus] 	   reg1_i,
	  input wire [`RegBus] 	   reg2_i,
	  input wire [`RegAddrBus] wd_i,
	  input wire 		   wreg_i,


	  output reg [`RegAddrBus] wd_o,
	  output reg 		   wreg_o,
	  output reg [`RegBus] 	   wdata_o
	  );
   
   reg [`RegBus] 		   logicout;

   always @ (*)
     begin
	if (rst == `RstEnable) logicout <= `ZeroWord;
	else
	  begin
	     case (aluop_i)
	       `EXE_OR_OP: logicout <= reg1_i | reg2_i;
	       default: logicout <= `ZeroWord;
	     endcase // case (aluop_i)
	  end // else: !if(rst == `RstEnable)
     end // always @ (*)
   
   always @ (*) 
     begin
	wd_o <= wd_i;
	wreg_o <= wreg_i;
	case (alusel_i) 
	  `EXE_RES_LOGIC:	wdata_o <= logicout;
	  default: wdata_o <= `ZeroWord;
	endcase // case (alusel_i)
     end // always @ (*)
   
endmodule // ex
module inst_rom(
		input wire 		  ce,
		input wire [`InstAddrBus] addr,
		output reg [`InstBus] 	  inst
	      );

   reg[`InstBus]  inst_mem[0:3];
   
   initial $readmemh ("inst_rom.data",inst_mem);
   // initial
   //   begin
   // 	inst_mem[0] = 32'h34011100;
   // 	inst_mem[1] = 32'h34020020;
   // 	inst_mem[2] = 32'h3403ff00;
   // 	inst_mem[3] = 32'h3404ffff;
   //   end

   always @ (*)
     begin
	if (ce == `ChipDisable) inst <= `ZeroWord;
	else
	  inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
     end

endmodule // inst_rom
module id_ex(

	     input wire 	      clk,
	     input wire 	      rst,


	     //从译码阶段传递的信息
	     input wire [`AluOpBus]   id_aluop,
	     input wire [`AluSelBus]  id_alusel,
	     input wire [`RegBus]     id_reg1,
	     input wire [`RegBus]     id_reg2,
	     input wire [`RegAddrBus] id_wd,
	     input wire 	      id_wreg, 

	     //传递到执行阶段的信息
	     output reg [`AluOpBus]   ex_aluop,
	     output reg [`AluSelBus]  ex_alusel,
	     output reg [`RegBus]     ex_reg1,
	     output reg [`RegBus]     ex_reg2,
	     output reg [`RegAddrBus] ex_wd,
	     output reg 	      ex_wreg

	     );

   always @ (posedge clk) 
     begin
	if (rst == `RstEnable) 
	  begin
	     ex_aluop <= `EXE_NOP_OP;
	     ex_alusel <= `EXE_RES_NOP;
	     ex_reg1 <= `ZeroWord;
	     ex_reg2 <= `ZeroWord;
	     ex_wd <= `NOPRegAddr;
	     ex_wreg <= `WriteDisable;
	  end 
	else 
	  begin		
	     ex_aluop <= id_aluop;
	     ex_alusel <= id_alusel;
	     ex_reg1 <= id_reg1;
	     ex_reg2 <= id_reg2;
	     ex_wd <= id_wd;
	     ex_wreg <= id_wreg;		
	  end // else: !if(rst == `RstEnable)
     end // always @ (posedge clk)
   
endmodule // id_ex
module pc_reg(
	      input wire 		clk,
	      input wire 		rst,

	      // From ctrl
	      input wire [5:0] 		stall,
	      
	      // From id
	      input wire 		branch_flag_i,
	      input wire [`RegBus] 	branch_target_address_i,
	      
	      // From pdt
	      input wire 		branch_or_not,
	      input wire [`InstAddrBus] pdt_pc, 
	      
	      output reg [`InstAddrBus] pc,
	      output reg 		ce
	      );

   // always @ (stall)
   //   $display("stall: %b, pc: %h",stall,pc);
   
   always @ (posedge clk)
     begin
	if (ce == `ChipDisable) pc <= 32'h0000000;
	else if (stall[0] == 1'b0)
	  begin 
	     if (branch_flag_i == 1'b1)
	       begin
		  pc <= {branch_target_address_i[31:1],1'b0};
		  // $display("Pc register jumps to %d.",{2'b0,branch_target_address_i[31:2]});
	       end
	     else if (branch_or_not == 1'b1)
	       begin
		  pc <= {pdt_pc[31:1],1'b0};
		  // $display("Pc register jumps to %d.",{2'b0,branch_target_address_i[31:2]});
	       end
	     else pc <= pc+4'h4;
	  end // if (stall[0] == 1'b0)
     end

   always @ (posedge clk)
     begin
	if (rst == `RstEnable) ce <= `ChipDisable;
	else ce <= `ChipEnable;
     end

endmodule // pc_reg
module ctrl
  (
   input wire 	    rst,
   input wire 	    stallreq_from_id1,
   input wire 	    stallreq_from_id2,
   input wire 	    stallreq_from_if_cache,
   input wire 	    stallreq_from_mem_cache,

   output reg [5:0] stall
   );

   always @ (*) 
     begin
	if(rst == `RstEnable) stall <= 6'b000000;
	else if (stallreq_from_mem_cache == 1'b1) 
	     stall <= 6'b011111;
	else if (stallreq_from_if_cache == 1'b1)  
	     stall <= 6'b000111;
	else if (stallreq_from_id2 == 1'b1) 
	     stall <= 6'b000111;
	else if (stallreq_from_id1 == 1'b1) 
	     stall <= 6'b000010;
	else stall <= 6'b000000;
     end // always @ (*)
   
endmodule // ctrl
module openmips_min_sopc_tb();

   reg CLOCK_50;
   reg rst;

   integer i;
   
   initial
     begin
	CLOCK_50 = 1'b0;
	forever #10 CLOCK_50 = ~CLOCK_50;
     end

   initial
     begin
	rst = `RstEnable;
	#19 rst = `RstDisable;
	#2040 $finish;
     end

   openmips_min_sopc openmips_min_sopc0
     (
      .clk(CLOCK_50),
      .rst(rst)
      );
   
endmodule // openmips_min_sopc_tb
module ex_mem
  (
   input wire 		    clk,
   input wire 		    rst,

   input wire [5:0] 	    stall,

   //来自执行阶段的信息	
   input wire [`RegAddrBus] ex_wd,
   input wire 		    ex_wreg,
   input wire [`RegBus]     ex_wdata, 

   input wire [`AluOpBus]   ex_aluop,
   input wire [`RegBus]     ex_mem_addr,
   input wire [`RegBus]     ex_reg2,
   
   //送到访存阶段的信息
   output reg [`RegAddrBus] mem_wd,
   output reg 		    mem_wreg,
   output reg [`RegBus]     mem_wdata,

   output reg [`AluOpBus]   mem_aluop,
   output reg [`RegBus]     mem_mem_addr,
   output reg [`RegBus]     mem_reg2
   );

   always @ (posedge clk) 
     begin

	if(rst == `RstEnable) 
	  begin
	     mem_wd <= `NOPRegAddr;
	     mem_wreg <= `WriteDisable;
	     mem_wdata <= `ZeroWord;
	     mem_aluop <= `EXE_NOP_OP;
	     mem_mem_addr <= `ZeroWord;
	     mem_reg2 <= `ZeroWord;
	  end 

	if (stall[3] == 1'b1&&stall[4] == 1'b0)
	  begin
	     mem_wd <= `NOPRegAddr;
	     mem_wreg <= `WriteDisable;
	     mem_wdata <= `ZeroWord;
	     mem_aluop <= `EXE_NOP_OP;
	     mem_mem_addr <= `ZeroWord;
	     mem_reg2 <= `ZeroWord;
	  end
	
	else if (stall[3] == 1'b0)
	  begin
	     mem_wd <= ex_wd;
	     mem_wreg <= ex_wreg;
	     mem_wdata <= ex_wdata;	
	     mem_aluop <= ex_aluop;
	     mem_mem_addr <= ex_mem_addr;
	     mem_reg2 <= ex_reg2;
	  end // else: !if(rst == `RstEnable)

     end // always @ (posedge clk)

endmodule // ex_mem
module mem_wb
  (
   input wire 		    clk,
   input wire 		    rst,

   input wire [5:0] 	    stall, 

   //来自访存阶段的信息	
   input wire [`RegAddrBus] mem_wd,
   input wire 		    mem_wreg,
   input wire [`RegBus]     mem_wdata,

   //送到回写阶段的信息
   output reg [`RegAddrBus] wb_wd,
   output reg 		    wb_wreg,
   output reg [`RegBus]     wb_wdata	       
   );

   always @ (posedge clk) 
     begin

	if(rst == `RstEnable) 
	  begin
	     wb_wd <= `NOPRegAddr;
	     wb_wreg <= `WriteDisable;
	     wb_wdata <= `ZeroWord;	
	  end 

	if (stall[4] == 1'b1&&stall[5] == 1'b0)
	  begin
	     wb_wd <= `NOPRegAddr;
	     wb_wreg <= `WriteDisable;
	     wb_wdata <= `ZeroWord;	
	  end
	
	else if (stall[4] == 1'b0)
	  begin
	     wb_wd <= mem_wd;
	     wb_wreg <= mem_wreg;
	     wb_wdata <= mem_wdata;
	  end // else: !if(rst == `RstEnable)

     end // always @ (posedge clk)

endmodule // mem_wb
module id_ex
  (
   input wire 		    clk,
   input wire 		    rst,

   input wire [5:0] 	    stall,

   //从译码阶段传递的信息
   input wire [`AluOpBus]   id_aluop,
   input wire [`AluSelBus]  id_alusel,
   input wire [`RegBus]     id_reg1,
   input wire [`RegBus]     id_reg2,
   input wire [`RegAddrBus] id_wd,
   input wire 		    id_wreg,
   input wire [`RegBus]     id_link_address,
   input wire [`RegBus]     id_inst, 
   
   //传递到执行阶段的信息
   output reg [`AluOpBus]   ex_aluop,
   output reg [`AluSelBus]  ex_alusel,
   output reg [`RegBus]     ex_reg1,
   output reg [`RegBus]     ex_reg2,
   output reg [`RegAddrBus] ex_wd,
   output reg 		    ex_wreg,
   output reg [`RegBus]     ex_link_address,
   output reg [`RegBus]     ex_inst
   );

   always @ (posedge clk) 
     begin

	if (rst == `RstEnable) 
	  begin
	     ex_aluop <= `EXE_NOP_OP;
	     ex_alusel <= `EXE_RES_NOP;
	     ex_reg1 <= `ZeroWord;
	     ex_reg2 <= `ZeroWord;
	     ex_wd <= `NOPRegAddr;
	     ex_wreg <= `WriteDisable;
	     ex_link_address <= `ZeroWord;
	     ex_inst <= `ZeroWord;
	  end // if (rst == `RstEnable)
	
	else if (stall[2] == 1'b1&&stall[3] == 1'b0)
	  begin
	     ex_aluop <= `EXE_NOP_OP;
	     ex_alusel <= `EXE_RES_NOP;
	     ex_reg1 <= `ZeroWord;
	     ex_reg2 <= `ZeroWord;
	     ex_wd <= `NOPRegAddr;
	     ex_wreg <= `WriteDisable;
	     ex_link_address <= `ZeroWord;
	     ex_inst <= `ZeroWord;
	  end // if (stall[2] == 1'b1&&stall[2] == 1'b0)
	
	else if (stall[2] == 1'b0)
	  begin		
	     ex_aluop <= id_aluop;
	     ex_alusel <= id_alusel;
	     ex_reg1 <= id_reg1;
	     ex_reg2 <= id_reg2;
	     ex_wd <= id_wd;
	     ex_wreg <= id_wreg;
	     ex_link_address <= id_link_address;
	     ex_inst <= id_inst;
	  end
	
     end // always @ (posedge clk)
   
endmodule // id_ex
module buf_que
  #(
    parameter SIZE_BIT = 3,
    parameter WIDTH = 8
    )
  (
   input 	      clk,
   input 	      rst,

   input 	      read_flag,
   output [WIDTH-1:0] read_data,

   input 	      write_flag,
   input [WIDTH-1:0]  write_data,

   output 	      empty,
   output 	      full
   );

   localparam SIZE = 1<<SIZE_BIT;

   reg [WIDTH-1:0]     buffer[SIZE-1:0];
   reg [SIZE_BIT-1:0]  read_ptr;
   reg [SIZE_BIT-1:0]  write_ptr;
   reg [SIZE_BIT:0]    buffer_size;

   assign empty = (buffer_size == 0);
   assign full = (buffer_size == SIZE);

   wire 	       read,write;
   assign read = read_flag&&!empty;
   assign write = write_flag&&!full;

   assign read_data = buffer[read_ptr];

   integer 	       i;
   always @(posedge clk)
     begin
	
	if (rst == `RstEnable)
	  begin
	     read_ptr <= 0;
	     write_ptr <= 0;
	     buffer_size <= 0;
	     for (i = 0;i < SIZE;i = i+1) buffer[i] <= 0;
	  end
	
	else
	  begin
	     if (read&&write)
	       begin
		  buffer[write_ptr] <= write_data;
    		  read_ptr <= read_ptr+1;
    		  write_ptr <= write_ptr+1;
	       end
	     else if(read) 
	       begin
    		  read_ptr <= read_ptr+1;
    		  buffer_size <= buffer_size-1;
    	       end
	     else if(write) 
	       begin
    		  buffer[write_ptr] <= write_data;
    		  write_ptr <= write_ptr+1;
    		  buffer_size <= buffer_size+1;
    	       end
	  end // else: !if(rst == `RstEnable)

     end // always @ (negedge clk)
   
endmodule // buf_que
module if_id
  (
   input wire 		     clk,
   input wire 		     rst,

   input wire [5:0] 	     stall,

   input wire [`InstAddrBus] if_pc,
   input wire [`InstBus]     if_inst,

   input wire 		     pdt_res_i,
   input wire		     which_pdt_i,
   input wire [9:0] 	     history_i,
   
   output reg [`InstAddrBus] id_pc,
   output reg [`InstBus]     id_inst,

   output reg 		     pdt_res_o,
   output reg 		     which_pdt_o,
   output reg [9:0] 	     history_o
   );

   always @ (posedge clk)
     begin

	if (rst == `RstEnable) 
	  begin
	     id_pc <= `ZeroWord;
	     id_inst <= `ZeroWord;
	     pdt_res_o <= 0;
	     which_pdt_o <= 0;
	     history_o <= 10'b0;
	  end
	else if (stall[1] == 1'b1&&stall[2] == 1'b0)
	  begin
	     id_pc <= `ZeroWord;
	     id_inst <= `ZeroWord;
	     pdt_res_o <= 0;
	     which_pdt_o <= 0;
	     history_o <= 10'b0;
	  end
	else if (stall[1] == 1'b0)
	  begin
	     id_pc <= if_pc;
	     id_inst <= if_inst;
	     pdt_res_o <= pdt_res_i;
	     which_pdt_o <= which_pdt_i;
	     history_o <= history_i;
	  end
	
     end // always @ (posedge clk)

endmodule // if_id
module pc_reg(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,

	//À´×ÔÒëÂë½×¶ÎµÄÐÅÏ¢
	input wire                    branch_flag_i,
	input wire[`RegBus]           branch_target_address_i,
	
	output reg[`InstAddrBus]			pc,
	output reg                    ce
	
);

	always @ (posedge clk) begin
		if (ce == `ChipDisable) begin
			pc <= 32'h00000000;
		end else if(stall[0] == `NoStop) begin
		  	if(branch_flag_i == `Branch) begin
					pc <= branch_target_address_i;
				end else begin
		  		pc <= pc + 4'h4;
		  	end
		end
	end

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ce <= `ChipDisable;
		end else begin
			ce <= `ChipEnable;
		end
	end

endmodule
module ctrl(

	input wire										rst,

	input wire                   stallreq_from_id,

  //À´×ÔÖ´ÐÐ½×¶ÎµÄÔÝÍ£ÇëÇó
	input wire                   stallreq_from_ex,
	output reg[5:0]              stall       
	
);


	always @ (*) begin
		if(rst == `RstEnable) begin
			stall <= 6'b000000;
		end else if(stallreq_from_ex == `Stop) begin
			stall <= 6'b001111;
		end else if(stallreq_from_id == `Stop) begin
			stall <= 6'b000111;			
		end else begin
			stall <= 6'b000000;
		end    //if
	end      //always
			

endmodule
module openmips_min_sopc_tb();

  reg     CLOCK_50;
  reg     rst;
  
       
  initial begin
    CLOCK_50 = 1'b0;
    forever #10 CLOCK_50 = ~CLOCK_50;
  end
      
  initial begin
    rst = `RstEnable;
    #195 rst= `RstDisable;
    #4100 $stop;
  end
       
  openmips_min_sopc openmips_min_sopc0(
		.clk(CLOCK_50),
		.rst(rst)	
	);

endmodule
module ex_mem(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]							 stall,	
	
	//À´×ÔÖ´ÐÐ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       ex_wd,
	input wire                    ex_wreg,
	input wire[`RegBus]					 ex_wdata, 	
	input wire[`RegBus]           ex_hi,
	input wire[`RegBus]           ex_lo,
	input wire                    ex_whilo, 	

  //ÎªÊµÏÖ¼ÓÔØ¡¢·Ã´æÖ¸Áî¶øÌí¼Ó
  input wire[`AluOpBus]        ex_aluop,
	input wire[`RegBus]          ex_mem_addr,
	input wire[`RegBus]          ex_reg2,

	input wire[`DoubleRegBus]     hilo_i,	
	input wire[1:0]               cnt_i,	
	
	//ËÍµ½·Ã´æ½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]					 mem_wdata,
	output reg[`RegBus]          mem_hi,
	output reg[`RegBus]          mem_lo,
	output reg                   mem_whilo,

  //ÎªÊµÏÖ¼ÓÔØ¡¢·Ã´æÖ¸Áî¶øÌí¼Ó
  output reg[`AluOpBus]        mem_aluop,
	output reg[`RegBus]          mem_mem_addr,
	output reg[`RegBus]          mem_reg2,
		
	output reg[`DoubleRegBus]    hilo_o,
	output reg[1:0]              cnt_o	
	
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		  mem_wdata <= `ZeroWord;	
		  mem_hi <= `ZeroWord;
		  mem_lo <= `ZeroWord;
		  mem_whilo <= `WriteDisable;		
	    hilo_o <= {`ZeroWord, `ZeroWord};
			cnt_o <= 2'b00;	
  		mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;			
		end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		  mem_wdata <= `ZeroWord;
		  mem_hi <= `ZeroWord;
		  mem_lo <= `ZeroWord;
		  mem_whilo <= `WriteDisable;
	    hilo_o <= hilo_i;
			cnt_o <= cnt_i;	
  		mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;						  				    
		end else if(stall[3] == `NoStop) begin
			mem_wd <= ex_wd;
			mem_wreg <= ex_wreg;
			mem_wdata <= ex_wdata;	
			mem_hi <= ex_hi;
			mem_lo <= ex_lo;
			mem_whilo <= ex_whilo;	
	    hilo_o <= {`ZeroWord, `ZeroWord};
			cnt_o <= 2'b00;	
  		mem_aluop <= ex_aluop;
			mem_mem_addr <= ex_mem_addr;
			mem_reg2 <= ex_reg2;			
		end else begin
	    hilo_o <= hilo_i;
			cnt_o <= cnt_i;											
		end    //if
	end      //always
			

endmodule
module hilo_reg(

	input	wire										clk,
	input wire										rst,
	
	//Ð´¶Ë¿Ú
	input wire										we,
	input wire[`RegBus]				    hi_i,
	input wire[`RegBus]						lo_i,
	
	//¶Á¶Ë¿Ú1
	output reg[`RegBus]           hi_o,
	output reg[`RegBus]           lo_o
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
					hi_o <= `ZeroWord;
					lo_o <= `ZeroWord;
		end else if((we == `WriteEnable)) begin
					hi_o <= hi_i;
					lo_o <= lo_i;
		end
	end

endmodule
module LLbit_reg(

	input	wire										clk,
	input wire										rst,
	
	input wire                    flush,
	//Ð´¶Ë¿Ú
	input wire										LLbit_i,
	input wire                    we,
	
	//¶Á¶Ë¿Ú1
	output reg                    LLbit_o
	
);


	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
					LLbit_o <= 1'b0;
		end else if((flush == 1'b1)) begin
					LLbit_o <= 1'b0;
		end else if((we == `WriteEnable)) begin
					LLbit_o <= LLbit_i;
		end
	end

endmodule
module openmips_min_sopc(

	input	wire										clk,
	input wire										rst
	
);

  //Á¬½ÓÖ¸Áî´æ´¢Æ÷
  wire[`InstAddrBus] inst_addr;
  wire[`InstBus] inst;
  wire rom_ce;
  wire mem_we_i;
  wire[`RegBus] mem_addr_i;
  wire[`RegBus] mem_data_i;
  wire[`RegBus] mem_data_o;
  wire[3:0] mem_sel_i;
  wire mem_ce_i;    
 

 openmips openmips0(
		.clk(clk),
		.rst(rst),
	
		.rom_addr_o(inst_addr),
		.rom_data_i(inst),
		.rom_ce_o(rom_ce),

		.ram_we_o(mem_we_i),
		.ram_addr_o(mem_addr_i),
		.ram_sel_o(mem_sel_i),
		.ram_data_o(mem_data_i),
		.ram_data_i(mem_data_o),
		.ram_ce_o(mem_ce_i)		
	
	);
	
	inst_rom inst_rom0(
		.ce(rom_ce),
		.addr(inst_addr),
		.inst(inst)	
	);

	data_ram data_ram0(
		.clk(clk),
		.ce(mem_ce_i),
		.we(mem_we_i),
		.addr(mem_addr_i),
		.sel(mem_sel_i),
		.data_i(mem_data_i),
		.data_o(mem_data_o)	
	);

endmodule
module mem_wb(

	input	wire										clk,
	input wire										rst,

  //À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,	

	//À´×Ô·Ã´æ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       mem_wd,
	input wire                    mem_wreg,
	input wire[`RegBus]					 mem_wdata,
	input wire[`RegBus]           mem_hi,
	input wire[`RegBus]           mem_lo,
	input wire                    mem_whilo,	
	
	input wire                  mem_LLbit_we,
	input wire                  mem_LLbit_value,	

	//ËÍµ½»ØÐ´½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      wb_wd,
	output reg                   wb_wreg,
	output reg[`RegBus]					 wb_wdata,
	output reg[`RegBus]          wb_hi,
	output reg[`RegBus]          wb_lo,
	output reg                   wb_whilo,

	output reg                  wb_LLbit_we,
	output reg                  wb_LLbit_value			       
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;	
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;
		  wb_LLbit_we <= 1'b0;
		  wb_LLbit_value <= 1'b0;			  	
		end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;	
		  wb_LLbit_we <= 1'b0;
		  wb_LLbit_value <= 1'b0;			  	  	  
		end else if(stall[4] == `NoStop) begin
			wb_wd <= mem_wd;
			wb_wreg <= mem_wreg;
			wb_wdata <= mem_wdata;
			wb_hi <= mem_hi;
			wb_lo <= mem_lo;
			wb_whilo <= mem_whilo;		
		  wb_LLbit_we <= mem_LLbit_we;
		  wb_LLbit_value <= mem_LLbit_value;				
		end    //if
	end      //always
			

endmodule
module id_ex(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]							 stall,
	
	//´ÓÒëÂë½×¶Î´«µÝµÄÐÅÏ¢
	input wire[`AluOpBus]         id_aluop,
	input wire[`AluSelBus]        id_alusel,
	input wire[`RegBus]           id_reg1,
	input wire[`RegBus]           id_reg2,
	input wire[`RegAddrBus]       id_wd,
	input wire                    id_wreg,
	input wire[`RegBus]           id_link_address,
	input wire                    id_is_in_delayslot,
	input wire                    next_inst_in_delayslot_i,		
	input wire[`RegBus]           id_inst,		
	
	//´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	output reg[`AluOpBus]         ex_aluop,
	output reg[`AluSelBus]        ex_alusel,
	output reg[`RegBus]           ex_reg1,
	output reg[`RegBus]           ex_reg2,
	output reg[`RegAddrBus]       ex_wd,
	output reg                    ex_wreg,
	output reg[`RegBus]           ex_link_address,
  output reg                    ex_is_in_delayslot,
	output reg                    is_in_delayslot_o,
	output reg[`RegBus]           ex_inst	
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	    is_in_delayslot_o <= `NotInDelaySlot;		
	    ex_inst <= `ZeroWord;	
		end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;	
			ex_link_address <= `ZeroWord;
	    ex_is_in_delayslot <= `NotInDelaySlot;
	    ex_inst <= `ZeroWord;			
		end else if(stall[2] == `NoStop) begin		
			ex_aluop <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 <= id_reg1;
			ex_reg2 <= id_reg2;
			ex_wd <= id_wd;
			ex_wreg <= id_wreg;		
			ex_link_address <= id_link_address;
			ex_is_in_delayslot <= id_is_in_delayslot;
	    is_in_delayslot_o <= next_inst_in_delayslot_i;
	    ex_inst <= id_inst;				
		end
	end
	
endmodule
module regfile(

	input	wire										clk,
	input wire										rst,
	
	//Ð´¶Ë¿Ú
	input wire										we,
	input wire[`RegAddrBus]				waddr,
	input wire[`RegBus]						wdata,
	
	//¶Á¶Ë¿Ú1
	input wire										re1,
	input wire[`RegAddrBus]			  raddr1,
	output reg[`RegBus]           rdata1,
	
	//¶Á¶Ë¿Ú2
	input wire										re2,
	input wire[`RegAddrBus]			  raddr2,
	output reg[`RegBus]           rdata2
	
);

	reg[`RegBus]  regs[0:`RegNum-1];

	always @ (posedge clk) begin
		if (rst == `RstDisable) begin
			if((we == `WriteEnable) && (waddr != `RegNumLog2'h0)) begin
				regs[waddr] <= wdata;
			end
		end
	end
	
	always @ (*) begin
		if(rst == `RstEnable) begin
			  rdata1 <= `ZeroWord;
	  end else if(raddr1 == `RegNumLog2'h0) begin
	  		rdata1 <= `ZeroWord;
	  end else if((raddr1 == waddr) && (we == `WriteEnable) 
	  	            && (re1 == `ReadEnable)) begin
	  	  rdata1 <= wdata;
	  end else if(re1 == `ReadEnable) begin
	      rdata1 <= regs[raddr1];
	  end else begin
	      rdata1 <= `ZeroWord;
	  end
	end

	always @ (*) begin
		if(rst == `RstEnable) begin
			  rdata2 <= `ZeroWord;
	  end else if(raddr2 == `RegNumLog2'h0) begin
	  		rdata2 <= `ZeroWord;
	  end else if((raddr2 == waddr) && (we == `WriteEnable) 
	  	            && (re2 == `ReadEnable)) begin
	  	  rdata2 <= wdata;
	  end else if(re2 == `ReadEnable) begin
	      rdata2 <= regs[raddr2];
	  end else begin
	      rdata2 <= `ZeroWord;
	  end
	end

endmodule
module if_id(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,	

	input wire[`InstAddrBus]			if_pc,
	input wire[`InstBus]          if_inst,
	output reg[`InstAddrBus]      id_pc,
	output reg[`InstBus]          id_inst  
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;
		end else if(stall[1] == `Stop && stall[2] == `NoStop) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;	
	  end else if(stall[1] == `NoStop) begin
		  id_pc <= if_pc;
		  id_inst <= if_inst;
		end
	end

endmodule
module pc_reg(

	input	wire										clk,
	input wire										rst,
	
	output reg[`InstAddrBus]			pc,
	output reg                    ce
	
);

	always @ (posedge clk) begin
		if (ce == `ChipDisable) begin
			pc <= 32'h00000000;
		end else begin
	 		pc <= pc + 4'h4;
		end
	end
	
	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ce <= `ChipDisable;
		end else begin
			ce <= `ChipEnable;
		end
	end

endmodule
module openmips_min_sopc_tb();

  reg     CLOCK_50;
  reg     rst;
  
       
  initial begin
    CLOCK_50 = 1'b0;
    forever #10 CLOCK_50 = ~CLOCK_50;
  end
      
  initial begin
    rst = `RstEnable;
    #195 rst= `RstDisable;
    #1100 $stop;
  end
       
  openmips_min_sopc openmips_min_sopc0(
		.clk(CLOCK_50),
		.rst(rst)	
	);

endmodule
module ex_mem(

	input	wire										clk,
	input wire										rst,
	
	
	//À´×ÔÖ´ÐÐ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       ex_wd,
	input wire                    ex_wreg,
	input wire[`RegBus]					 ex_wdata, 	
	input wire[`RegBus]           ex_hi,
	input wire[`RegBus]           ex_lo,
	input wire                    ex_whilo, 	
	
	//ËÍµ½·Ã´æ½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]					 mem_wdata,
	output reg[`RegBus]          mem_hi,
	output reg[`RegBus]          mem_lo,
	output reg                   mem_whilo	
	
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		  mem_wdata <= `ZeroWord;	
		  mem_hi <= `ZeroWord;
		  mem_lo <= `ZeroWord;
		  mem_whilo <= `WriteDisable;		  
		end else begin
			mem_wd <= ex_wd;
			mem_wreg <= ex_wreg;
			mem_wdata <= ex_wdata;	
			mem_hi <= ex_hi;
			mem_lo <= ex_lo;
			mem_whilo <= ex_whilo;					
		end    //if
	end      //always
			

endmodule
module openmips_min_sopc(

	input	wire										clk,
	input wire										rst
	
);

  //Á¬½ÓÖ¸Áî´æ´¢Æ÷
  wire[`InstAddrBus] inst_addr;
  wire[`InstBus] inst;
  wire rom_ce;
 

 openmips openmips0(
		.clk(clk),
		.rst(rst),
	
		.rom_addr_o(inst_addr),
		.rom_data_i(inst),
		.rom_ce_o(rom_ce)
	
	);
	
	inst_rom inst_rom0(
		.ce(rom_ce),
		.addr(inst_addr),
		.inst(inst)	
	);


endmodule
module mem_wb(

	input	wire										clk,
	input wire										rst,
	

	//À´×Ô·Ã´æ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       mem_wd,
	input wire                    mem_wreg,
	input wire[`RegBus]					 mem_wdata,
	input wire[`RegBus]           mem_hi,
	input wire[`RegBus]           mem_lo,
	input wire                    mem_whilo,	

	//ËÍµ½»ØÐ´½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      wb_wd,
	output reg                   wb_wreg,
	output reg[`RegBus]					 wb_wdata,
	output reg[`RegBus]          wb_hi,
	output reg[`RegBus]          wb_lo,
	output reg                   wb_whilo		       
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;	
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;		  
		end else begin
			wb_wd <= mem_wd;
			wb_wreg <= mem_wreg;
			wb_wdata <= mem_wdata;
			wb_hi <= mem_hi;
			wb_lo <= mem_lo;
			wb_whilo <= mem_whilo;			
		end    //if
	end      //always
			

endmodule
module id_ex(

	input	wire										clk,
	input wire										rst,

	
	//´ÓÒëÂë½×¶Î´«µÝµÄÐÅÏ¢
	input wire[`AluOpBus]         id_aluop,
	input wire[`AluSelBus]        id_alusel,
	input wire[`RegBus]           id_reg1,
	input wire[`RegBus]           id_reg2,
	input wire[`RegAddrBus]       id_wd,
	input wire                    id_wreg,	
	
	//´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	output reg[`AluOpBus]         ex_aluop,
	output reg[`AluSelBus]        ex_alusel,
	output reg[`RegBus]           ex_reg1,
	output reg[`RegBus]           ex_reg2,
	output reg[`RegAddrBus]       ex_wd,
	output reg                    ex_wreg
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
		end else begin		
			ex_aluop <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 <= id_reg1;
			ex_reg2 <= id_reg2;
			ex_wd <= id_wd;
			ex_wreg <= id_wreg;		
		end
	end
	
endmodule
module mem(

	input wire										rst,
	
	//À´×ÔÖ´ÐÐ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       wd_i,
	input wire                    wreg_i,
	input wire[`RegBus]					  wdata_i,
	input wire[`RegBus]           hi_i,
	input wire[`RegBus]           lo_i,
	input wire                    whilo_i,	
	
	//ËÍµ½»ØÐ´½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      wd_o,
	output reg                   wreg_o,
	output reg[`RegBus]					 wdata_o,
	output reg[`RegBus]          hi_o,
	output reg[`RegBus]          lo_o,
	output reg                   whilo_o	
	
);

	
	always @ (*) begin
		if(rst == `RstEnable) begin
			wd_o <= `NOPRegAddr;
			wreg_o <= `WriteDisable;
		  wdata_o <= `ZeroWord;
		  hi_o <= `ZeroWord;
		  lo_o <= `ZeroWord;
		  whilo_o <= `WriteDisable;		  
		end else begin
		  wd_o <= wd_i;
			wreg_o <= wreg_i;
			wdata_o <= wdata_i;
			hi_o <= hi_i;
			lo_o <= lo_i;
			whilo_o <= whilo_i;			
		end    //if
	end      //always
			

endmodule
module if_id(

	input	wire										clk,
	input wire										rst,
	

	input wire[`InstAddrBus]			if_pc,
	input wire[`InstBus]          if_inst,
	output reg[`InstAddrBus]      id_pc,
	output reg[`InstBus]          id_inst  
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;
	  end else begin
		  id_pc <= if_pc;
		  id_inst <= if_inst;
		end
	end

endmodule
module ex_mem(

	      input wire 		 clk,
	      input wire 		 rst,

	      //À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	      input wire [5:0] 		 stall, 

	      //À´×ÔÖ´ÐÐ½×¶ÎµÄÐÅÏ¢	
	      input wire [`RegAddrBus] 	 ex_wd,
	      input wire 		 ex_wreg,
	      input wire [`RegBus] 	 ex_wdata, 
	      input wire [`RegBus] 	 ex_hi,
	      input wire [`RegBus] 	 ex_lo,
	      input wire 		 ex_whilo, 

	      //ÎªÊµÏÖ¼ÓÔØ¡¢·Ã´æÖ¸Áî¶øÌí¼Ó
	      input wire [`AluOpBus] 	 ex_aluop,
	      input wire [`RegBus] 	 ex_mem_addr,
	      input wire [`RegBus] 	 ex_reg2,

	      input wire [`DoubleRegBus] hilo_i, 
	      input wire [1:0] 		 cnt_i, 

	      //ËÍµ½·Ã´æ½×¶ÎµÄÐÅÏ¢
	      output reg [`RegAddrBus] 	 mem_wd,
	      output reg 		 mem_wreg,
	      output reg [`RegBus] 	 mem_wdata,
	      output reg [`RegBus] 	 mem_hi,
	      output reg [`RegBus] 	 mem_lo,
	      output reg 		 mem_whilo,

	      //ÎªÊµÏÖ¼ÓÔØ¡¢·Ã´æÖ¸Áî¶øÌí¼Ó
	      output reg [`AluOpBus] 	 mem_aluop,
	      output reg [`RegBus] 	 mem_mem_addr,
	      output reg [`RegBus] 	 mem_reg2,

	      output reg [`DoubleRegBus] hilo_o,
	      output reg [1:0] 		 cnt_o	


	      );


   always @ (posedge clk) begin
      if(rst == `RstEnable) begin
	 mem_wd <= `NOPRegAddr;
	 mem_wreg <= `WriteDisable;
	 mem_wdata <= `ZeroWord;	
	 mem_hi <= `ZeroWord;
	 mem_lo <= `ZeroWord;
	 mem_whilo <= `WriteDisable;		
	 hilo_o <= {`ZeroWord, `ZeroWord};
	 cnt_o <= 2'b00;	
  	 mem_aluop <= `EXE_NOP_OP;
	 mem_mem_addr <= `ZeroWord;
	 mem_reg2 <= `ZeroWord;			
      end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
	 mem_wd <= `NOPRegAddr;
	 mem_wreg <= `WriteDisable;
	 mem_wdata <= `ZeroWord;
	 mem_hi <= `ZeroWord;
	 mem_lo <= `ZeroWord;
	 mem_whilo <= `WriteDisable;
	 hilo_o <= hilo_i;
	 cnt_o <= cnt_i;	
  	 mem_aluop <= `EXE_NOP_OP;
	 mem_mem_addr <= `ZeroWord;
	 mem_reg2 <= `ZeroWord;						  				    
      end else if(stall[3] == `NoStop) begin
	 mem_wd <= ex_wd;
	 mem_wreg <= ex_wreg;
	 mem_wdata <= ex_wdata;	
	 mem_hi <= ex_hi;
	 mem_lo <= ex_lo;
	 mem_whilo <= ex_whilo;	
	 hilo_o <= {`ZeroWord, `ZeroWord};
	 cnt_o <= 2'b00;	
  	 mem_aluop <= ex_aluop;
	 mem_mem_addr <= ex_mem_addr;
	 mem_reg2 <= ex_reg2;			
      end else begin
	 hilo_o <= hilo_i;
	 cnt_o <= cnt_i;											
      end    //if
   end      //always
   

endmodule
module openmips_min_sopc(

	input	wire										clk,
	input wire										rst
	
);

  //Á¬½ÓÖ¸Áî´æ´¢Æ÷
  wire[`InstAddrBus] inst_addr;
  wire[`InstBus] inst;
  wire rom_ce;
  wire mem_we_i;
  wire[`RegBus] mem_addr_i;
  wire[`RegBus] mem_data_i;
  wire[`RegBus] mem_data_o;
  wire[3:0] mem_sel_i;  
  wire mem_ce_i;  
 

 openmips openmips0(
		.clk(clk),
		.rst(rst),
	
		.rom_addr_o(inst_addr),
		.rom_data_i(inst),
		.rom_ce_o(rom_ce),

		.ram_we_o(mem_we_i),
		.ram_addr_o(mem_addr_i),
		.ram_sel_o(mem_sel_i),
		.ram_data_o(mem_data_i),
		.ram_data_i(mem_data_o),
		.ram_ce_o(mem_ce_i)		
	
	);
	
	inst_rom inst_rom0(
		.ce(rom_ce),
		.addr(inst_addr),
		.inst(inst)	
	);

	data_ram data_ram0(
		.clk(clk),
		.we(mem_we_i),
		.addr(mem_addr_i),
		.sel(mem_sel_i),
		.data_i(mem_data_i),
		.data_o(mem_data_o),
		.ce(mem_ce_i)		
	);

endmodule
module mem_wb(

	input	wire										clk,
	input wire										rst,

  //À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,	

	//À´×Ô·Ã´æ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       mem_wd,
	input wire                    mem_wreg,
	input wire[`RegBus]					 mem_wdata,
	input wire[`RegBus]           mem_hi,
	input wire[`RegBus]           mem_lo,
	input wire                    mem_whilo,	

	//ËÍµ½»ØÐ´½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      wb_wd,
	output reg                   wb_wreg,
	output reg[`RegBus]					 wb_wdata,
	output reg[`RegBus]          wb_hi,
	output reg[`RegBus]          wb_lo,
	output reg                   wb_whilo		       
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;	
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;	
		end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;		  	  
		end else if(stall[4] == `NoStop) begin
			wb_wd <= mem_wd;
			wb_wreg <= mem_wreg;
			wb_wdata <= mem_wdata;
			wb_hi <= mem_hi;
			wb_lo <= mem_lo;
			wb_whilo <= mem_whilo;			
		end    //if
	end      //always
			

endmodule
module id_ex(

	     input wire 	      clk,
	     input wire 	      rst,

	     //À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	     input wire [5:0] 	      stall,

	     //´ÓÒëÂë½×¶Î´«µÝµÄÐÅÏ¢
	     input wire [`AluOpBus]   id_aluop,
	     input wire [`AluSelBus]  id_alusel,
	     input wire [`RegBus]     id_reg1,
	     input wire [`RegBus]     id_reg2,
	     input wire [`RegAddrBus] id_wd,
	     input wire 	      id_wreg,
	     input wire [`RegBus]     id_link_address,
	     input wire 	      id_is_in_delayslot,
	     input wire 	      next_inst_in_delayslot_i, 
	     input wire [`RegBus]     id_inst, 

	     //´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	     output reg [`AluOpBus]   ex_aluop,
	     output reg [`AluSelBus]  ex_alusel,
	     output reg [`RegBus]     ex_reg1,
	     output reg [`RegBus]     ex_reg2,
	     output reg [`RegAddrBus] ex_wd,
	     output reg 	      ex_wreg,
	     output reg [`RegBus]     ex_link_address,
	     output reg 	      ex_is_in_delayslot,
	     output reg 	      is_in_delayslot_o,
	     output reg [`RegBus]     ex_inst	

	     );

   always @ (posedge clk) begin
      if (rst == `RstEnable) begin
	 ex_aluop <= `EXE_NOP_OP;
	 ex_alusel <= `EXE_RES_NOP;
	 ex_reg1 <= `ZeroWord;
	 ex_reg2 <= `ZeroWord;
	 ex_wd <= `NOPRegAddr;
	 ex_wreg <= `WriteDisable;
	 ex_link_address <= `ZeroWord;
	 ex_is_in_delayslot <= `NotInDelaySlot;
	 is_in_delayslot_o <= `NotInDelaySlot;		
	 ex_inst <= `ZeroWord;	
      end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
	 ex_aluop <= `EXE_NOP_OP;
	 ex_alusel <= `EXE_RES_NOP;
	 ex_reg1 <= `ZeroWord;
	 ex_reg2 <= `ZeroWord;
	 ex_wd <= `NOPRegAddr;
	 ex_wreg <= `WriteDisable;	
	 ex_link_address <= `ZeroWord;
	 ex_is_in_delayslot <= `NotInDelaySlot;	
	 ex_inst <= `ZeroWord;			
      end else if(stall[2] == `NoStop) begin		
	 ex_aluop <= id_aluop;
	 ex_alusel <= id_alusel;
	 ex_reg1 <= id_reg1;
	 ex_reg2 <= id_reg2;
	 ex_wd <= id_wd;
	 ex_wreg <= id_wreg;		
	 ex_link_address <= id_link_address;
	 ex_is_in_delayslot <= id_is_in_delayslot;
	 is_in_delayslot_o <= next_inst_in_delayslot_i;
	 ex_inst <= id_inst;				
      end
   end
   
endmodule
module pc_reg(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,
	input wire                    flush,
	input wire[`RegBus]           new_pc,

	//À´×ÔÒëÂë½×¶ÎµÄÐÅÏ¢
	input wire                    branch_flag_i,
	input wire[`RegBus]           branch_target_address_i,
	
	output reg[`InstAddrBus]			pc,
	output reg                    ce
	
);

	always @ (posedge clk) begin
		if (ce == `ChipDisable) begin
			pc <= 32'h00000000;
		end else begin
			if(flush == 1'b1) begin
				pc <= new_pc;
			end else if(stall[0] == `NoStop) begin
				if(branch_flag_i == `Branch) begin
					pc <= branch_target_address_i;
				end else begin
		  		pc <= pc + 4'h4;
		  	end
			end
		end
	end

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ce <= `ChipDisable;
		end else begin
			ce <= `ChipEnable;
		end
	end

endmodule
module ctrl(

	input wire										rst,

	input wire[31:0]             excepttype_i,
	input wire[`RegBus]          cp0_epc_i,

	input wire                   stallreq_from_if,
	input wire                   stallreq_from_id,

  //À´×ÔÖ´ÐÐ½×¶ÎµÄÔÝÍ£ÇëÇó
	input wire                   stallreq_from_ex,
	input wire                   stallreq_from_mem,	

	output reg[`RegBus]          new_pc,
	output reg                   flush,	
	output reg[5:0]              stall       
	
);


	always @ (*) begin
		if(rst == `RstEnable) begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;
		end else if(excepttype_i != `ZeroWord) begin
		  flush <= 1'b1;
		  stall <= 6'b000000;
			case (excepttype_i)
				32'h00000001:		begin   //interrupt
					new_pc <= 32'h00000020;
				end
				32'h00000008:		begin   //syscall
					new_pc <= 32'h00000040;
				end
				32'h0000000a:		begin   //inst_invalid
					new_pc <= 32'h00000040;
				end
				32'h0000000d:		begin   //trap
					new_pc <= 32'h00000040;
				end
				32'h0000000c:		begin   //ov
					new_pc <= 32'h00000040;
				end
				32'h0000000e:		begin   //eret
					new_pc <= cp0_epc_i;
				end
				default	: begin
				end
			endcase 						
		end else if(stallreq_from_mem == `Stop) begin
			stall <= 6'b011111;
			flush <= 1'b0;					
		end else if(stallreq_from_ex == `Stop) begin
			stall <= 6'b001111;
			flush <= 1'b0;		
		end else if(stallreq_from_id == `Stop) begin
			stall <= 6'b000111;	
			flush <= 1'b0;		
    end else if(stallreq_from_if == `Stop) begin
			stall <= 6'b000111;
			flush <= 1'b0;						
		end else begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;		
		end    //if
	end      //always
			

endmodule
module mem_wb(

	input	wire										clk,
	input wire										rst,

  //À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,
	input wire                    flush,	

	//À´×Ô·Ã´æ½×¶ÎµÄÐÅÏ¢	
	input wire[`RegAddrBus]       mem_wd,
	input wire                    mem_wreg,
	input wire[`RegBus]					 mem_wdata,
	input wire[`RegBus]           mem_hi,
	input wire[`RegBus]           mem_lo,
	input wire                    mem_whilo,	
	
	input wire                  mem_LLbit_we,
	input wire                  mem_LLbit_value,	

	input wire                   mem_cp0_reg_we,
	input wire[4:0]              mem_cp0_reg_write_addr,
	input wire[`RegBus]          mem_cp0_reg_data,			

	//ËÍµ½»ØÐ´½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      wb_wd,
	output reg                   wb_wreg,
	output reg[`RegBus]					 wb_wdata,
	output reg[`RegBus]          wb_hi,
	output reg[`RegBus]          wb_lo,
	output reg                   wb_whilo,

	output reg                  wb_LLbit_we,
	output reg                  wb_LLbit_value,

	output reg                   wb_cp0_reg_we,
	output reg[4:0]              wb_cp0_reg_write_addr,
	output reg[`RegBus]          wb_cp0_reg_data								       
	
);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;	
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;
		  wb_LLbit_we <= 1'b0;
		  wb_LLbit_value <= 1'b0;		
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;		
		end else if(flush == 1'b1 ) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;
		  wb_LLbit_we <= 1'b0;
		  wb_LLbit_value <= 1'b0;	
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;				    					  	  	
		end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		  wb_wdata <= `ZeroWord;
		  wb_hi <= `ZeroWord;
		  wb_lo <= `ZeroWord;
		  wb_whilo <= `WriteDisable;	
		  wb_LLbit_we <= 1'b0;
		  wb_LLbit_value <= 1'b0;	
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;					  		  	  	  
		end else if(stall[4] == `NoStop) begin
			wb_wd <= mem_wd;
			wb_wreg <= mem_wreg;
			wb_wdata <= mem_wdata;
			wb_hi <= mem_hi;
			wb_lo <= mem_lo;
			wb_whilo <= mem_whilo;		
		  wb_LLbit_we <= mem_LLbit_we;
		  wb_LLbit_value <= mem_LLbit_value;		
			wb_cp0_reg_we <= mem_cp0_reg_we;
			wb_cp0_reg_write_addr <= mem_cp0_reg_write_addr;
			wb_cp0_reg_data <= mem_cp0_reg_data;			  		
		end    //if
	end      //always
			

endmodule
module id_ex(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]							 stall,
	input wire                   flush,
	
	//´ÓÒëÂë½×¶Î´«µÝµÄÐÅÏ¢
	input wire[`AluOpBus]         id_aluop,
	input wire[`AluSelBus]        id_alusel,
	input wire[`RegBus]           id_reg1,
	input wire[`RegBus]           id_reg2,
	input wire[`RegAddrBus]       id_wd,
	input wire                    id_wreg,
	input wire[`RegBus]           id_link_address,
	input wire                    id_is_in_delayslot,
	input wire                    next_inst_in_delayslot_i,		
	input wire[`RegBus]           id_inst,		
	input wire[`RegBus]           id_current_inst_address,
	input wire[31:0]              id_excepttype,
	
	//´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	output reg[`AluOpBus]         ex_aluop,
	output reg[`AluSelBus]        ex_alusel,
	output reg[`RegBus]           ex_reg1,
	output reg[`RegBus]           ex_reg2,
	output reg[`RegAddrBus]       ex_wd,
	output reg                    ex_wreg,
	output reg[`RegBus]           ex_link_address,
  output reg                    ex_is_in_delayslot,
	output reg                    is_in_delayslot_o,
	output reg[`RegBus]           ex_inst,
	output reg[31:0]              ex_excepttype,
	output reg[`RegBus]          ex_current_inst_address	
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	    is_in_delayslot_o <= `NotInDelaySlot;		
	    ex_inst <= `ZeroWord;	
	    ex_excepttype <= `ZeroWord;
	    ex_current_inst_address <= `ZeroWord;
		end else if(flush == 1'b1 ) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_excepttype <= `ZeroWord;
			ex_link_address <= `ZeroWord;
			ex_inst <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	    ex_current_inst_address <= `ZeroWord;	
	    is_in_delayslot_o <= `NotInDelaySlot;		    
		end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;	
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	    ex_inst <= `ZeroWord;			
	    ex_excepttype <= `ZeroWord;
	    ex_current_inst_address <= `ZeroWord;	
		end else if(stall[2] == `NoStop) begin		
			ex_aluop <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 <= id_reg1;
			ex_reg2 <= id_reg2;
			ex_wd <= id_wd;
			ex_wreg <= id_wreg;		
			ex_link_address <= id_link_address;
			ex_is_in_delayslot <= id_is_in_delayslot;
	    is_in_delayslot_o <= next_inst_in_delayslot_i;
	    ex_inst <= id_inst;			
	    ex_excepttype <= id_excepttype;
	    ex_current_inst_address <= id_current_inst_address;		
		end
	end
	
endmodule
module if_id(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,	
	input wire                    flush,

	input wire[`InstAddrBus]			if_pc,
	input wire[`InstBus]          if_inst,
	output reg[`InstAddrBus]      id_pc,
	output reg[`InstBus]          id_inst  
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;
		end else if(flush == 1'b1 ) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;					
		end else if(stall[1] == `Stop && stall[2] == `NoStop) begin
			id_pc <= `ZeroWord;
			id_inst <= `ZeroWord;	
	  end else if(stall[1] == `NoStop) begin
		  id_pc <= if_pc;
		  id_inst <= if_inst;
		end
	end

endmodule
module openmips_min_sopc(

	input	wire										clk,
	input wire										rst
	
);

  //Á¬½ÓÖ¸Áî´æ´¢Æ÷
  wire[`InstAddrBus] inst_addr;
  wire[`InstBus] inst;
  wire rom_ce;
  wire mem_we_i;
  wire[`RegBus] mem_addr_i;
  wire[`RegBus] mem_data_i;
  wire[`RegBus] mem_data_o;
  wire[3:0] mem_sel_i;   
  wire mem_ce_i; 
 

 openmips openmips0(
		.clk(clk),
		.rst(rst),
	
		.rom_addr_o(inst_addr),
		.rom_data_i(inst),
		.rom_ce_o(rom_ce),

		.ram_we_o(mem_we_i),
		.ram_addr_o(mem_addr_i),
		.ram_sel_o(mem_sel_i),
		.ram_data_o(mem_data_i),
		.ram_data_i(mem_data_o),
		.ram_ce_o(mem_ce_i)		
	
	);
	
	inst_rom inst_rom0(
		.ce(rom_ce),
		.addr(inst_addr),
		.inst(inst)	
	);

	data_ram data_ram0(
		.clk(clk),
		.ce(mem_ce_i),
		.we(mem_we_i),
		.addr(mem_addr_i),
		.sel(mem_sel_i),
		.data_i(mem_data_i),
		.data_o(mem_data_o)	
	);

endmodule