dakies/OSS_Verilog huggingface dataset:
module pc_reg(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,
	
	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
		  		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 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[`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[`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;	
		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;			  				    
		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;	
		end else begin
	    hilo_o <= hilo_i;
			cnt_o <= cnt_i;											
		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,	
	
	//´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	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 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;			
		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;		
		end
	end
	
endmodule
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 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 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,		
	
	//´«µÝµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	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	
	
);

	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;			
		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;			
		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;				
		end
	end
	
endmodule
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;
	reg[`RegBus] shiftres;
		
	always @ (*) begin
		if(rst == `RstEnable) begin
			logicout <= `ZeroWord;
		end else begin
			case (aluop_i)
				`EXE_OR_OP:			begin
					logicout <= reg1_i | reg2_i;
				end
				`EXE_AND_OP:		begin
					logicout <= reg1_i & reg2_i;
				end
				`EXE_NOR_OP:		begin
					logicout <= ~(reg1_i |reg2_i);
				end
				`EXE_XOR_OP:		begin
					logicout <= reg1_i ^ reg2_i;
				end
				default:				begin
					logicout <= `ZeroWord;
				end
			endcase
		end    //if
	end      //always

	always @ (*) begin
		if(rst == `RstEnable) begin
			shiftres <= `ZeroWord;
		end else begin
			case (aluop_i)
				`EXE_SLL_OP:			begin
					shiftres <= reg2_i << reg1_i[4:0] ;
				end
				`EXE_SRL_OP:		begin
					shiftres <= reg2_i >> reg1_i[4:0];
				end
				`EXE_SRA_OP:		begin
					shiftres <= ({32{reg2_i[31]}} << (6'd32-{1'b0, reg1_i[4:0]})) 
												| reg2_i >> reg1_i[4:0];
				end
				default:				begin
					shiftres <= `ZeroWord;
				end
			endcase
		end    //if
	end      //always


 always @ (*) begin
	 wd_o <= wd_i;	 	 	
	 wreg_o <= wreg_i;
	 case ( alusel_i ) 
	 	`EXE_RES_LOGIC:		begin
	 		wdata_o <= logicout;
	 	end
	 	`EXE_RES_SHIFT:		begin
	 		wdata_o <= shiftres;
	 	end	 	
	 	default:					begin
	 		wdata_o <= `ZeroWord;
	 	end
	 endcase
 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;
    #1000 $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, 	
	
	//ËÍµ½·Ã´æ½×¶ÎµÄÐÅÏ¢
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]					 mem_wdata
	
	
);


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

endmodule
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    //if
	end      //always
			

endmodule
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    //if
	end      //always
			

endmodule
module pc_reg(

	input	wire										clk,
	input wire										rst,

	//À´×Ô¿ØÖÆÄ£¿éµÄÐÅÏ¢
	input wire[5:0]               stall,
	
	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
		  		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 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) begin
			logicout <= `ZeroWord;
		end else begin
			case (aluop_i)
				`EXE_OR_OP:			begin
					logicout <= reg1_i | reg2_i;
				end
				default:				begin
					logicout <= `ZeroWord;
				end
			endcase
		end    //if
	end      //always


 always @ (*) begin
	 wd_o <= wd_i;	 	 	
	 wreg_o <= wreg_i;
	 case ( alusel_i ) 
	 	`EXE_RES_LOGIC:		begin
	 		wdata_o <= logicout;
	 	end
	 	default:					begin
	 		wdata_o <= `ZeroWord;
	 	end
	 endcase
 end	

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(
		.addr(inst_addr),
		.inst(inst),
		.ce(rom_ce)	
	);


endmodule
module id(

	input wire										rst,
	input wire[`InstAddrBus]			pc_i,
	input wire[`InstBus]          inst_i,

	input wire[`RegBus]           reg1_data_i,
	input wire[`RegBus]           reg2_data_i,

	//ËÍµ½regfileµÄÐÅÏ¢
	output reg                    reg1_read_o,
	output reg                    reg2_read_o,     
	output reg[`RegAddrBus]       reg1_addr_o,
	output reg[`RegAddrBus]       reg2_addr_o, 	      
	
	//ËÍµ½Ö´ÐÐ½×¶ÎµÄÐÅÏ¢
	output reg[`AluOpBus]         aluop_o,
	output reg[`AluSelBus]        alusel_o,
	output reg[`RegBus]           reg1_o,
	output reg[`RegBus]           reg2_o,
	output reg[`RegAddrBus]       wd_o,
	output reg                    wreg_o
);

  wire[5:0] op = inst_i[31:26];
  wire[4:0] op2 = inst_i[10:6];
  wire[5:0] op3 = inst_i[5:0];
  wire[4:0] op4 = inst_i[20:16];
  reg[`RegBus]	imm;
  reg instvalid;
  
 
	always @ (*) begin	
		if (rst == `RstEnable) begin
			aluop_o <= `EXE_NOP_OP;
			alusel_o <= `EXE_RES_NOP;
			wd_o <= `NOPRegAddr;
			wreg_o <= `WriteDisable;
			instvalid <= `InstValid;
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			reg1_addr_o <= `NOPRegAddr;
			reg2_addr_o <= `NOPRegAddr;
			imm <= 32'h0;			
	  end else begin
			aluop_o <= `EXE_NOP_OP;
			alusel_o <= `EXE_RES_NOP;
			wd_o <= inst_i[15:11];
			wreg_o <= `WriteDisable;
			instvalid <= `InstInvalid;	   
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			reg1_addr_o <= inst_i[25:21];
			reg2_addr_o <= inst_i[20:16];		
			imm <= `ZeroWord;			
		  case (op)
		  	`EXE_ORI:			begin                        //ORIÖ¸Áî
		  		wreg_o <= `WriteEnable;		aluop_o <= `EXE_OR_OP;
		  		alusel_o <= `EXE_RES_LOGIC; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {16'h0, inst_i[15:0]};		wd_o <= inst_i[20:16];
					instvalid <= `InstValid;	
		  	end 							 
		    default:			begin
		    end
		  endcase		  //case op			
		end       //if
	end         //always
	

	always @ (*) begin
		if(rst == `RstEnable) begin
			reg1_o <= `ZeroWord;
	  end else if(reg1_read_o == 1'b1) begin
	  	reg1_o <= reg1_data_i;
	  end else if(reg1_read_o == 1'b0) begin
	  	reg1_o <= imm;
	  end else begin
	    reg1_o <= `ZeroWord;
	  end
	end
	
	always @ (*) begin
		if(rst == `RstEnable) begin
			reg2_o <= `ZeroWord;
	  end else if(reg2_read_o == 1'b1) begin
	  	reg2_o <= reg2_data_i;
	  end else if(reg2_read_o == 1'b0) begin
	  	reg2_o <= imm;
	  end else begin
	    reg2_o <= `ZeroWord;
	  end
	end

endmodule
module ctrl(

	input wire										rst,

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

	input wire                   stallreq_from_id,

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

	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_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 begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;		
		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;
    #10000 $stop;
  end
       
  openmips_min_sopc openmips_min_sopc0(
		.clk(CLOCK_50),
		.rst(rst)	
	);

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 pc_reg(

	input	wire										clk,
	input wire										rst,
	
	output reg[5:0]			pc,
	output reg                    ce
	
);

	always @ (posedge clk) begin
		if (ce == 1'b0) begin
			pc <= 6'h00;
		end else begin
	 		pc <= pc + 1'b1;
		end
	end
	
	always @ (posedge clk) begin
		if (rst == 1'b1) begin
			ce <= 1'b0;
		end else begin
			ce <= 1'b1;
		end
	end

endmodule
module inst_fetch_tb;

  reg     CLOCK_50;
  reg     rst;
  wire[31:0]    inst;
  
       
  initial begin
    CLOCK_50 = 1'b0;
    forever #10 CLOCK_50 = ~CLOCK_50;
  end
      
  initial begin
    rst = 1'b1;
    #195 rst= 1'b0;
    #1000 $stop;
  end
       
  inst_fetch inst_fetch0(
		.clk(CLOCK_50),
		.rst(rst),
		.inst_o(inst)	
	);

endmodule
module inst_fetch(

	input	wire										clk,
	input wire										rst,

	output wire[31:0]           inst_o
	
);

	wire[5:0] pc;
	wire rom_ce;
	
 
  //pc_regÀý»¯
	pc_reg pc_reg0(
		.clk(clk),
		.rst(rst),
		.pc(pc),
		.ce(rom_ce)	
			
	);
	
  rom rom0(
    .ce(rom_ce),
    .addr(pc),
    .inst(inst_o)
  );
	


endmodule
module rom(

	input wire                    ce,
	input wire[5:0]			addr,
	output reg[31:0]					inst
	
);

	reg[31:0]  rom[63:0];

	initial $readmemh ( "rom.data", rom );

	always @ (*) begin
		if (ce == 1'b0) begin
			inst <= 32'h0;
	  end else begin
		  inst <= rom[addr];
		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,	

	input wire                   ex_cp0_reg_we,
	input wire[4:0]              ex_cp0_reg_write_addr,
	input wire[`RegBus]          ex_cp0_reg_data,	
	
	//ËÍµ½·Ã´æ½×¶ÎµÄÐÅÏ¢
	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                   mem_cp0_reg_we,
	output reg[4:0]              mem_cp0_reg_write_addr,
	output reg[`RegBus]          mem_cp0_reg_data,
		
	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;	
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `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;		
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `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;
			mem_cp0_reg_we <= ex_cp0_reg_we;
			mem_cp0_reg_write_addr <= ex_cp0_reg_write_addr;
			mem_cp0_reg_data <= ex_cp0_reg_data;						
		end else begin
	    hilo_o <= hilo_i;
			cnt_o <= cnt_i;											
		end    //if
	end      //always
			

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,	

	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(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[`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 flash_top(
    // Parallel FLASH Interface
    wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_o, wb_dat_i, wb_sel_i, wb_we_i,
    wb_stb_i, wb_cyc_i, wb_ack_o,
    flash_adr_o, flash_dat_i, flash_rst,
    flash_oe, flash_ce, flash_we
);

    //
    // Default address and data bus width
    //
    parameter aw = 19;   // number of address-bits
    parameter dw = 32;   // number of data-bits
    parameter ws = 4'h3; // number of wait-states

    //
    // FLASH interface
    //
    input   wb_clk_i;
    input   wb_rst_i;
    input   [31:0] wb_adr_i;
    output reg [dw-1:0] wb_dat_o;
    input   [dw-1:0] wb_dat_i;
    input   [3:0] wb_sel_i;
    input   wb_we_i;
    input   wb_stb_i;
    input   wb_cyc_i;
    output reg wb_ack_o;
    output reg [31:0] flash_adr_o;
    input   [7:0] flash_dat_i;
    output  flash_rst;
    output  flash_oe;
    output  flash_ce;
    output  flash_we;
    reg [3:0] waitstate;
    wire    [1:0] adr_low;

    // Wishbone read/write accesses
    wire wb_acc = wb_cyc_i & wb_stb_i;    // WISHBONE access
    wire wb_wr  = wb_acc & wb_we_i;       // WISHBONE write access
    wire wb_rd  = wb_acc & !wb_we_i;      // WISHBONE read access

    always @(posedge wb_clk_i) begin
        if( wb_rst_i == 1'b1 ) begin
            waitstate <= 4'h0;
            wb_ack_o <= 1'b0;
        end else if(wb_acc == 1'b0) begin
            waitstate <= 4'h0;
            wb_ack_o <= 1'b0;
            wb_dat_o <= 32'h00000000;
        end else if(waitstate == 4'h0) begin
            wb_ack_o <= 1'b0;
            if(wb_acc) begin
              waitstate <= waitstate + 4'h1;
            end
						flash_adr_o <= {10'b0000000000,wb_adr_i[21:2],2'b00};
        end else begin
            waitstate <= waitstate + 4'h1;
				    if(waitstate == 4'h3) begin
					     wb_dat_o[31:24] <= flash_dat_i;
					     flash_adr_o <= {10'b0000000000,wb_adr_i[21:2],2'b01};
						end else if(waitstate == 4'h6) begin
						   wb_dat_o[23:16] <= flash_dat_i;
						   flash_adr_o <= {10'b0000000000,wb_adr_i[21:2],2'b10};
						end else if(waitstate == 4'h9) begin
						   wb_dat_o[15:8] <= flash_dat_i;
						   flash_adr_o <= {10'b0000000000,wb_adr_i[21:2],2'b11};
						end else if(waitstate == 4'hc) begin
						   wb_dat_o[7:0] <= flash_dat_i;
               wb_ack_o <= 1'b1;
						end else if(waitstate == 4'hd) begin
               wb_ack_o <= 1'b0;
               waitstate <= 4'h0;
            end
         end
      end

    assign flash_ce = !wb_acc;
    assign flash_we = 1'b1;
    assign flash_oe = !wb_rd;


    assign flash_rst = !wb_rst_i;

endmodule
module sync_fifo (clk,
	          reset_n,
		  wr_en,
		  wr_data,
		  full,
		  empty,
		  rd_en,
		  rd_data);

   parameter W = 8;
   parameter D = 4;

   parameter AW = (D == 4)   ? 2 :
		  (D == 8)   ? 3 :
		  (D == 16)  ? 4 :
		  (D == 32)  ? 5 :
		  (D == 64)  ? 6 :
		  (D == 128) ? 7 :
		  (D == 256) ? 8 : 0;
   
   output [W-1 : 0]  rd_data;
   input [W-1 : 0]   wr_data;
   input 	     clk, reset_n, wr_en, rd_en;
   output 	     full, empty;

   // synopsys translate_off

   initial begin
      if (AW == 0) begin
	 $display ("%m : ERROR!!! Fifo depth %d not in range 4 to 256", D);
      end // if (AW == 0)
   end // initial begin

   // synopsys translate_on


   reg [W-1 : 0]    mem[D-1 : 0];
   reg [AW-1 : 0]   rd_ptr, wr_ptr;
   reg	 	    full, empty;

   wire [W-1 : 0]   rd_data;
   
   always @ (posedge clk or negedge reset_n) 
      if (reset_n == 1'b0) begin
         wr_ptr <= {AW{1'b0}} ;
      end
      else begin
         if (wr_en & !full) begin
            wr_ptr <= wr_ptr + 1'b1 ;
         end
      end

   always @ (posedge clk or negedge reset_n) 
      if (reset_n == 1'b0) begin
         rd_ptr <= {AW{1'b0}} ;
      end
      else begin
         if (rd_en & !empty) begin
            rd_ptr <= rd_ptr + 1'b1 ;
         end
      end


   always @ (posedge clk or negedge reset_n) 
      if (reset_n == 1'b0) begin
         empty <= 1'b1 ;
      end
      else begin
         empty <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b0}}, 1'b1}) & rd_en & ~wr_en) ? 1'b1 : 
                   ((wr_ptr == rd_ptr) & ~rd_en & wr_en) ? 1'b0 : empty ;
      end

   always @ (posedge clk or negedge reset_n) 
      if (reset_n == 1'b0) begin
         full <= 1'b0 ;
      end
      else begin
         full <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b1}}, 1'b0}) & ~rd_en & wr_en) ? 1'b1 : 
                 (((wr_ptr - rd_ptr) == {AW{1'b1}}) & rd_en & ~wr_en) ? 1'b0 : full ;
      end

   always @ (posedge clk) 
      if (wr_en)
	 mem[wr_ptr] <= wr_data;

assign  rd_data = mem[rd_ptr];


// synopsys translate_off
   always @(posedge clk) begin
      if (wr_en && full) begin
         $display("%m : Error! sfifo overflow!");
      end
   end

   always @(posedge clk) begin
      if (rd_en && empty) begin
         $display("%m : error! sfifo underflow!");
      end
   end

// synopsys translate_on
//---------------------------------------

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'h30000000;
		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 timer( //2 second timer
	input clk,rst_n,
	input timer_start,timer_tick,
	output timer_up
    );
	 
	 reg[6:0] timer_q=0,timer_d;
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) timer_q<=0;
		else timer_q<=timer_d;
	 end
	 
	 always @* begin
		timer_d=timer_q;
		if(timer_start) begin
			timer_d=7'b111_1111;
		end
		else if(timer_tick) begin //timer tick is 60Hz, thus 2 seconds will be after 120 ticks(or 7'b111_1111)
			timer_d=(timer_q==0)? 0:timer_q-1;
		end
	 end
	 assign timer_up= (timer_q==0);


endmodule
module vga_core(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		//650x480 parameters
	 localparam HD=640, //Horizontal Display
					HR=16, //Right Border
					HRet=96, //Horizontal Retrace
					HL=48, //Left Border
					
					VD=480, //Vertical Display
					VB=8, //Bottom Border
					VRet=2, //Vertical Retrace
					VT=35; //Top Border
	reg[11:0] vctr_q=0,vctr_d; //counter for vertical scan
	reg[11:0] hctr_q=0,hctr_d; //counter for vertical scan
	reg hsync_q=0,hsync_d;
	reg vsync_q=0,vsync_d;
	//vctr and hctr register operation
	always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			vctr_q<=0;
			hctr_q<=0;
			vsync_q<=0;
			hsync_q<=0;
		end
		else begin
			vctr_q<=vctr_d;
			hctr_q<=hctr_d;
			vsync_q<=vsync_d;
			hsync_q<=hsync_d;
		end
	end
	
	always @* begin
		vctr_d=vctr_q;
		hctr_d=hctr_q;
		video_on=0;
		hsync_d=1; 
		vsync_d=1; 
		
		if(hctr_q==HD+HR+HRet+HL-1) hctr_d=0; //horizontal counter
		else hctr_d=hctr_q+1'b1;
		
		if(vctr_q==VD+VB+VRet+VT-1) vctr_d=0; //vertical counter
		else if(hctr_q==HD+HR+HRet+HL-1) vctr_d=vctr_q+1'b1;
		
		if(hctr_q<HD && vctr_q<VD) video_on=1; //video_on 
		
		if( (hctr_d>=HD+HR) && (hctr_d<=HD+HR+HRet-1) ) hsync_d=0; //horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

endmodule
module LED_mux
	#(parameter N=19) //last 3 bits will be used as output. Frequency=50MHz/(2^(N-3)). So N=19 will have 763Hz
	(
	input clk,rst,
	input[4:0] in0,in1,in2,in3,in4,in5, //format: {dp,hex[3:0]}
	output reg[7:0] seg_out,
	output reg[5:0] sel_out
    );
	 
	 reg[N-1:0] r_reg=0;
	 reg[4:0] hex_out=0;
	 wire[N-1:0] r_nxt;
	 wire[2:0] out_counter; //last 3 bits to be used as output signal
	 
	 
	 //N-bit counter
	 always @(posedge clk,negedge rst)
	 if(!rst) r_reg<=0;
	 else r_reg<=r_nxt;
	 
	 assign r_nxt=(r_reg=={3'd5,{(N-3){1'b1}}})?19'd0:r_reg+1'b1; //last 3 bits counts from 0 to 5(6 turns) then wraps around
	 assign out_counter=r_reg[N-1:N-3];
	 
	 
	 //sel_out output logic
	 always @(out_counter) begin
		 sel_out=6'b111_111;    //active low
		 sel_out[out_counter]=1'b0;
	 end
	  
	 //hex_out output logic
	 always @* begin
		 hex_out=0;
			 casez(out_counter)
			 3'b000: hex_out=in0;
			 3'b001: hex_out=in1;
			 3'b010: hex_out=in2;
			 3'b011: hex_out=in3;
			 3'b100: hex_out=in4;
			 3'b101: hex_out=in5;
			 endcase
	 end
	 	 
	 //hex-to-seg decoder
	 always @* begin
		 seg_out=0;
			 case(hex_out[3:0])
			 4'h0: seg_out[6:0]=7'b0000_001;
			 4'h1: seg_out[6:0]=7'b1001_111;
			 4'h2: seg_out[6:0]=7'b0010_010;
			 4'h3: seg_out[6:0]=7'b0000_110;
			 4'h4: seg_out[6:0]=7'b1001_100;
			 4'h5: seg_out[6:0]=7'b0100_100;
			 4'h6: seg_out[6:0]=7'b0100_000;
			 4'h7: seg_out[6:0]=7'b0001_111;
			 4'h8: seg_out[6:0]=7'b0000_000;
			 4'h9: seg_out[6:0]=7'b0001_100;
			 4'ha: seg_out[6:0]=7'b0001_000;
			 4'hb: seg_out[6:0]=7'b1100_000;
			 4'hc: seg_out[6:0]=7'b0110_001;
			 4'hd: seg_out[6:0]=7'b1000_010;
			 4'he: seg_out[6:0]=7'b0110_000;
			 4'hf: seg_out[6:0]=7'b0111_000;
			 endcase
		 seg_out[7]=!hex_out[4]; //active high decimal
	 end

endmodule
module debouncing_TEST(
	input clk,rst_n,
	input sw, //active low
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 
	 reg[3:0] counter_db=0,counter_sw=0; //counts from 0-to-9 then wraps up
	 reg sw_reg=0,db_reg=0;
	 wire[3:0] counter_db_nxt,counter_sw_nxt;
	 wire db,tick_db,tick_sw;
	 wire sw_new;
	 assign sw_new=!sw;
	 
	 //debounce module instantiation
	debounce debounce_module
	(
	.clk(clk),
	.rst_n(rst_n),
	.signal(sw_new),
	.level(),
	.ready(),
	.r_edg(tick_db)
    );
	 
	 //rising-edge-detection and 10-mod-counter circuit
	 always@(posedge clk,negedge rst_n) begin
		if(!rst_n) begin 
			sw_reg<=0;
			counter_db<=0;
			counter_sw<=0;
			
		end
		else begin
			sw_reg<=sw;
			counter_db<=counter_db_nxt;
			counter_sw<=counter_sw_nxt;
		end
	 end

	 assign tick_sw=(!sw && sw_reg);
	 assign counter_db_nxt=tick_db?((counter_db==9)?0:counter_db+1):counter_db; //increment if tick is asserted(or when rising edge signal occurs)
	 assign counter_sw_nxt=tick_sw?((counter_sw==9)?0:counter_sw+1):counter_sw; //increment if tick is asserted(or when rising edge signal occurs)
	 
	 //Seven-segment-TIME-MUX Circuit
		LED_mux led_mux
		(
		.clk(clk),
		.rst(rst_n),
		.in0({1'b0,counter_db}),
		.in1({1'b1,counter_sw}),
		.in2(0),
		.in3(0),
		.in4(0),
		.in5(0),
		.seg_out(seg_out),
		.sel_out(sel_out)
		 );

endmodule
module debounce(
	input clk,rst_n,
	input signal,
	output reg level,
	output reg ready,r_edg	
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							one=2'd1,
							waiting=2'd2,
							zero=2'd3;
	 localparam N=5_000_000; //N/50MHz=100ms debounce delay
	 reg[1:0] state_reg,state_nxt;
	 reg[22:0] counter_reg,counter_nxt; //log_2(N) -> 20bits
	 //FSM register operations
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=0;
			counter_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			counter_reg<=counter_nxt;
		end
	 end
	 //FSM next-state logic
	 always @* begin
		state_nxt=state_reg;
		counter_nxt=counter_reg;
		ready=0;
		r_edg=0;
		level=0;
		case(state_reg) 
			   idle: begin
							ready=1;
							if(signal) begin
								counter_nxt=0;
								r_edg=1;
								state_nxt=one;
							end
						end
		       one: begin
							level=1;
							if(counter_reg==N-1) state_nxt=waiting;
							else counter_nxt=counter_reg+1;
						end
			waiting: begin
							level=1;
							if(!signal) begin
								counter_nxt=0;
								state_nxt=zero;
							end
						end
			   zero: begin
							if(counter_reg==N-1) state_nxt=idle;
							else counter_nxt=counter_reg+1;
						end
			default: state_nxt=idle;
		endcase
	 end
	 

endmodule
module debounce_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg signal;

	// Outputs
	wire level;
	wire ready;
	wire r_edg;

	// Instantiate the Unit Under Test (UUT)
	debounce uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.signal(signal), 
		.level(level), 
		.ready(ready), 
		.r_edg(r_edg)
	);
	always begin //100MHz-> 50ns debounce delay
	clk=0;
	#5;
	clk=1;
	#5;
	end

	initial begin
		rst_n = 1;
		signal = 0;
		repeat(5) @(negedge clk);
		signal=1;   
		#20; 
		signal=0;
		#20;
		signal=1; //will not turn off
		#150
		signal=0;
		repeat(5) @(negedge clk);
		$stop;

		

	end
      
endmodule
module fifo
	#(parameter W=4,B=8)
	(
	input clk,rst_n,
	input wr,rd,
	input[B-1:0] wr_data,
	output[B-1:0] rd_data,
	output reg full,empty,	
	output reg[W-1:0] rd_ptr,wr_ptr
    );
	 initial begin
		full=0;
		empty=1;
		rd_ptr=0;
		wr_ptr=0;
	 end
	 
	 reg[B-1:0] array_reg[2**W-1:0];

	 
	 //register file operation
	 always @(posedge clk) begin
		if(wr && !full && !(wr&&rd&&empty)) array_reg[wr_ptr]=wr_data;
	 end
	 assign rd_data=array_reg[rd_ptr];
	 
	 //fifo operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			rd_ptr=0;
			wr_ptr=0;
			full=0;
			empty=1;
		end
		else begin
			case({rd,wr})
				2'b01: if(!full) begin
							wr_ptr=wr_ptr+1;
							empty=0;
							full=(wr_ptr==rd_ptr);
						 end
				2'b10: if(!empty) begin
							rd_ptr=rd_ptr+1;
							full=0;
							empty=(rd_ptr==wr_ptr);
						 end
				2'b11: if(!empty && !full) begin
								rd_ptr=rd_ptr+1;
								wr_ptr=wr_ptr+1;
						 end
			endcase
		end
	 end

endmodule
module fifo_TB;

	//parameter for clock period
	localparam T=10;
	// Inputs
	reg clk;
	reg rst_n;
	reg wr;
	reg rd;
	reg [7:0] wr_data;

	// Outputs
	wire empty;
	wire full;
	wire [7:0] rd_data;
   wire [3:0] wr_ptr,rd_ptr;
	// Instantiate the Unit Under Test (UUT)
	fifo  #(.W(4),.B(8)) uut
	(
		.clk(clk), 
		.rst_n(rst_n), 
		.wr(wr), 
		.rd(rd), 
		.wr_data(wr_data), 
		.empty(empty), 
		.full(full), 
		.rd_data(rd_data),
		.wr_ptr(wr_ptr),
		.rd_ptr(rd_ptr)
	);

	always begin
		clk=1'b0;
		#(T/2);
		clk=1'b1;
		#(T/2);
	end
	integer i=0;

	initial begin
		// Initialize Inputs
		rst_n = 1;
		wr = 0;
		rd = 0;
		wr_data = 0;
		
		//reset
		@(negedge clk) rst_n=0;
		@(negedge clk) rst_n=1;
		
		//write
		$display("Write TEST");
		$display("wr rd ful emp read_data");
		wr=1;
		for(i=8'b1111_1111;i>(8'hff-20);i=i-1) begin
			wr_data=i;
			@(negedge clk);
		end
		
		//read and write while full
		$display("Read&Write while FULL TEST");
		$display("wr rd ful emp read_data");
		rd=1; 
		for(i=8'd1;i<10;i=i+1) begin
			wr_data=i;
			@(negedge clk);
		   end

		//read
		$display("Read TEST");
		$display("wr rd ful emp read_data");
		wr=0;
		repeat(20) @(negedge clk);
		
		//read and write while empty()
		$display("Read&Write while EMPTY TEST");
		$display("wr rd ful emp read_data");
		wr=1; 
		for(i=8'd1;i<20;i=i+1) begin
			wr_data=i;
			@(negedge clk);
		   end
			
			
		$display("Read and write but not full nor empty TEST");
		$display("wr rd ful emp read_data");
		wr=1;
		rd=0;
		for(i=8'b1111_0000;i>(8'b1111_0000-8);i=i-1) begin //fill half-way
			wr_data=i;
			@(negedge clk);
		end	
		rd=1;
		for(i=8'd1;i<20;i=i+1) begin
			wr_data=i;
			@(negedge clk);
		   end	
		$stop;	
	end
	
	initial begin
	$monitor("%d %d %d    %d   %d ",wr_ptr,rd_ptr,full,empty,rd_data);
	end
	
      
endmodule
module Stack
	#(parameter W=4,B=8)
	(
	input clk,rst,
	input [B-1:0] wr_data,
	input push,pop, //write,read
	output reg empty,full,
	output[B-1:0] rd_data,
	output[W-1:0] stack_ptr
    );
	 
	 initial begin
	 empty=1;
	 full=0;
	 end
	 
	 reg[B-1:0] array_reg[2**W-1:0];
	 reg[W-1:0] stack_pointer=0;
	 reg empty_nxt,full_nxt;
	 reg[W-1:0] stack_pointer_nxt=0;
	 
	 //register-file operation
	 always @(posedge clk) begin
	 if(!full && push) //synchronous write
		array_reg[stack_pointer]<=wr_data;
	 end
	 assign rd_data=array_reg[stack_pointer];  //asynchronous read
	 
	 //register operations
	 always @(posedge clk,posedge rst) begin
		if(rst) begin 
			stack_pointer<=0;
			empty<=1;
			full<=0;
		end
		else begin
			stack_pointer<=stack_pointer_nxt;
			empty<=empty_nxt;
			full<=full_nxt;
		end
	 end
	 
	 //next-state logics
	 always @* begin
	 stack_pointer_nxt=stack_pointer;
	 full_nxt=full;
	 empty_nxt=empty;
		 case({push,pop})
			//2'b00: do nothing
			2'b01: if(!empty) begin //read
						stack_pointer_nxt=stack_pointer-1;
						full_nxt=0;
						empty_nxt=(stack_pointer_nxt==0)?1:0;
					 end
			2'b10: if(!full) begin//write
						stack_pointer_nxt=stack_pointer+1;
						empty_nxt=0;
						full_nxt=(stack_pointer_nxt==0)?1:0;
					 end
			//2'b11: after writing,read it immediately, THUS STACK_POINTER WILL NOT MOVE		 
			
		 endcase
	 end
	 assign stack_ptr=stack_pointer;

	 


endmodule
module Stack_TB;

	//parameter for clock period
	localparam T=10;
	// Inputs
	reg clk;
	reg rst;
	reg push;
	reg pop;
	reg [7:0] wr_data;

	// Outputs
	wire empty;
	wire full;
	wire [7:0] rd_data;
   wire [3:0] stack_ptr;
	// Instantiate the Unit Under Test (UUT)
	Stack uut (
		.clk(clk), 
		.rst(rst), 
		.push(push), 
		.pop(pop), 
		.wr_data(wr_data), 
		.empty(empty), 
		.full(full), 
		.rd_data(rd_data),
		.stack_ptr(stack_ptr)
	);

	always begin
		clk=1'b0;
		#(T/2);
		clk=1'b1;
		#(T/2);
	end
	integer i=0;

	initial begin
		// Initialize Inputs
		rst = 0;
		push = 0;
		pop = 0;
		wr_data = 0;
		
		//reset
		@(negedge clk) rst=1;
		@(negedge clk) rst=0;
		
		//write
		$display("Write");
		$display("ptr full empty read_data");
		push=1;
		for(i=8'b1111_1111;i>(8'hff-20);i=i-1) begin //write from 255-to-240
			wr_data=i;
			@(negedge clk);
		end
		
		//read and write while full
		$display("Read&Write while FULL");
		$display("ptr full empty read_data");
		pop=1; 
		for(i=8'd1;i<10;i=i+1) begin //ptr does not move and read-data is still 255 since no write operation happens
			wr_data=i;
			@(negedge clk);
		   end

		//read
		$display("Read");
		$display("ptr full empty read_data");
		push=0;
		repeat(20) @(negedge clk); //read from 240-to-255
		
		//read and write while empty
		$display("Read&Write while EMPTY");
		$display("ptr full empty read_data");
		push=1; 
		for(i=8'd1;i<20;i=i+1) begin //replace 255 with 1,then2,then 3,until 19
			wr_data=i;
			@(negedge clk);
		   end
			
			
		$display("Read&Write But is Neither Full Nor Empty");
		$display("ptr full empty read_data");
		$display("Filling Half-Way");
		push=1; //since its empty last time,fill half of it first of values from 240-to-233
		pop=0;
		for(i=8'b1111_0000;i>(8'b1111_0000-8);i=i-1) begin //fill half-way
			wr_data=i;
			@(negedge clk);
		end	
		$display("Read&Write"); //it will just replace 233 of values from 1-to-19
		pop=1; //now read and write 
		for(i=8'd1;i<20;i=i+1) begin
			wr_data=i;
			@(negedge clk);
		   end	
			
			
		$display("Empty the Buffer");	
		push=0;
		repeat(20) @(negedge clk); //read from 233-to-240
	
		$stop;	
	end
	
	initial begin
	$monitor("%d   %b    %b     %d",stack_ptr,full,empty,rd_data);
	end
	
      
endmodule