data/full_repos/permissive/172396252/WRAMPsys.srcs/sources_1/control_unit.v
[Errno 2] No such file or directory: 'preprocess.output'
1: b'%Error: data/full_repos/permissive/172396252/WRAMPsys.srcs/sources_1/control_unit.v:86: Cannot find include file: wramp.vh\n    `include "wramp.vh" \n             ^~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/172396252/WRAMPsys.srcs/sources_1,data/full_repos/permissive/172396252/wramp.vh\n             data/full_repos/permissive/172396252/WRAMPsys.srcs/sources_1,data/full_repos/permissive/172396252/wramp.vh.v\n             data/full_repos/permissive/172396252/WRAMPsys.srcs/sources_1,data/full_repos/permissive/172396252/wramp.vh.sv\n             wramp.vh\n             wramp.vh.v\n             wramp.vh.sv\n             obj_dir/wramp.vh\n             obj_dir/wramp.vh.v\n             obj_dir/wramp.vh.sv\n%Error: Exiting due to 1 error(s)\n'
module control_unit (
	input reset_n,
	input clk,


	input [31:0] instruction_reg,



	output reg mem_read,
	output reg mem_write,
	output reg check_mem,
	input memory_violation,


	output reg ir_in,
	output reg imm_16_out,
	output reg imm_20_out,
	output reg sign_extend,


	output reg pc_in,
	output reg pc_out,
	output reg pc_inc,


	output reg a_out,
	output reg b_out,
	output reg c_in,
	output reg [3:0] sel_a,
	output reg [3:0] sel_b,
	output reg [3:0] sel_c,


	output reg temp_in,
	output reg temp_out,


	output reg alu_out,
	output reg alu_start,
	output reg [4:0] alu_func,
	input alu_done,
	input zero,
	input div_zero,
	input overflow,


	output reg special_reg_in,
	output reg special_reg_out,
	output reg special_reg_save_state,
	output reg special_reg_restore_state,
	output reg inc_icount,
	output reg [3:0] special_reg_sel,
	output reg [3:0] exception_status,

	input interrupts_enabled,
	input kernel_mode,
	input [7:0] interrupts,
	input [7:0] int_mask
	);
    

    `include "wramp.vh"
	

	parameter check_exceptions 		=  0;
	parameter fetch_memcheck 		=  1;
	parameter insn_fetch 			=  2;
    parameter insn_fetch_2          =  3;
	parameter insn_decode 			=  4;
	parameter uncond_jump 			=  5;
	parameter jump_and_link 		=  6;
	parameter single_cycle_alu 		=  7;
	parameter setup_multi_cycle_alu =  8;
	parameter wait_multi_cycle_alu 	=  9;
	parameter special_move 			= 10;
	parameter eff_add_comp 			= 11;
	parameter do_memory_op 			= 12;
    parameter do_memory_op_load     = 13;
	parameter cond_branch 			= 14;
	parameter branch_taken 			= 15;
	parameter load_immed 			= 16;
	parameter error_state 			= 17;
	parameter memop_memcheck 		= 18;
	parameter arithmetic_exception 	= 19;
	parameter syscall_exception 	= 20;
	parameter break_exception 		= 21;
	parameter gpf_exception 		= 22;
	parameter exception_save_reg13 	= 23;
	parameter exception_load_reg13 	= 24;
	parameter interrupt_save_PC 	= 25;
	parameter interrupt_take_vector = 26;
	parameter return_from_exception = 27;
	parameter halt 					= 31;
	parameter fetch_memcheck_post   = 32;
	parameter memop_memcheck_post   = 33;


	wire [ 3:0] opcode 	   = instruction_reg[31:28];
	wire [ 3:0] reg_d 	   = instruction_reg[27:24];
	wire [ 3:0] reg_s 	   = instruction_reg[23:20];
	wire [ 3:0] reg_t      = instruction_reg[ 3: 0];
	wire [ 3:0] func       = instruction_reg[19:16];
	wire [15:0] immediate  = instruction_reg[15: 0];
	wire [19:0] address    = instruction_reg[19: 0];

	reg [5:0] current_state, next_state;



	always @(current_state, opcode, alu_done) begin
		

		temp_in <= 0;
		temp_out <= 0;


		special_reg_in <= 0;
		special_reg_out <= 0;
		special_reg_sel <= 0;
		inc_icount <= 0;
		special_reg_save_state <= 0;
		special_reg_restore_state <= 0;
		exception_status <= 0;
		

		a_out <= 0;
		b_out <= 0;
		c_in <= 0;
		sel_a <= 0000;
		sel_b <= 0000;
		sel_c <= 0000;
		

		pc_in <= 0;
		pc_out <= 0;
		pc_inc <= 0;
		

		ir_in <= 0;
		imm_16_out <= 0;
		imm_20_out <= 0;
		sign_extend <= 0;
		

		alu_out <= 0;
		alu_func <= 0;
		alu_start <= 0;
		

		mem_read <= 0;
		mem_write <= 0;
		check_mem <= 0;

		case (current_state)
			check_exceptions : begin

		    	if (((interrupts & int_mask) != 8'h00) && interrupts_enabled == 1'b1) begin
		      		special_reg_save_state <= 1;
		    	end
			end		    

		  	fetch_memcheck : begin

				mem_read <= 1;

				pc_out <= 1;


			end
			
			fetch_memcheck_post : begin

                mem_read <= 1;

                pc_out <= 1;

                check_mem <= 1;
            end
			
	
			insn_fetch : begin			    


				mem_read <= 1;
				pc_out <= 1;

				inc_icount <= 1;
			end		  
			
			insn_fetch_2 : begin

                mem_read <= 1;


                pc_out <= 1;

                ir_in <= 1;
			end  

			insn_decode : begin

				pc_inc <= 1;
			end

			uncond_jump : begin


				if (opcode == OPCODE_J || opcode == OPCODE_JAL) begin
					imm_20_out <= 1;
				end else begin

					a_out <= 1;
					sel_a <= reg_s;
				end


				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				pc_in <= 1;
			end


			jump_and_link : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				c_in <= 1;
				sel_c <= 15;
			end

			load_immed : begin

				imm_20_out <= 1;

				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				if (opcode == OPCODE_LA) begin
					alu_func <= FUNC_ADD;
				end else begin
					alu_func <= ALU_LHI;
				end

				c_in <= 1;
				sel_c <= reg_d;
			end


			cond_branch : begin

				a_out <= 1;
				sel_a <= reg_s;

				b_out <= 1;
				sel_b <= 0;

				alu_func <= FUNC_ADD;
			end

			branch_taken : begin

				imm_20_out <= 1;
				sign_extend <= 1;

				pc_out <= 1;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				pc_in <= 1;
			end

			eff_add_comp : begin


				imm_20_out <= 1;
				sign_extend <= 1;

				b_out <= 1;
				sel_b <= reg_s;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				temp_in <= 1;
			end
			
			memop_memcheck_post : begin

                temp_out <= 1;

                mem_read <= 1;

                check_mem <= 1;
            end

			memop_memcheck : begin

				temp_out <= 1;

				mem_read <= 1;

                check_mem <= 1;
			end
			
			

			do_memory_op : begin

				temp_out <= 1;

				if (opcode == OPCODE_LW) begin


				end 
				if (opcode == OPCODE_SW) begin

					mem_write <= 1;

					a_out <= 1;

					sel_a <= reg_d;
				end
			end
			
			do_memory_op_load : begin

			    temp_out <= 1;

			    mem_read <= 1;

			    c_in <= 1;

			    sel_c <= reg_d;
			end

			single_cycle_alu : begin

				b_out <= 1;
				sel_b <= reg_s;

				case (opcode) 
					OPCODE_ARITHI, OPCODE_TESTI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH,OPCODE_TEST : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase

				alu_out <= 1;
				if (opcode == OPCODE_ARITHI || opcode == OPCODE_ARITH) begin
					alu_func <= {1'b0, func};
				end else begin
					alu_func <= {1'b1, func};
				end

				c_in <= 1;
				sel_c <= reg_d;
			end

			setup_multi_cycle_alu : begin

				b_out <= 1;
				sel_b <= reg_s;

				case (opcode)
					OPCODE_ARITHI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase
				alu_func <= {1'b0, func};
				alu_start <= 1;
			end

			wait_multi_cycle_alu : begin


				b_out <= 1;
				sel_b <= reg_s;

				case (opcode)
					OPCODE_ARITHI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase
				alu_func <= {1'b0, func};
				sel_c <= reg_d;
				if (alu_done == 1) begin
					alu_out <= 1;
					c_in <= 1;
				end
			end

			special_move : begin

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				if (func == FUNC_MOVGS) begin
					b_out <= 1;
					sel_b <= reg_s;
					special_reg_in <= 1;
					special_reg_sel <= reg_d;
				end else begin
					c_in <= 1;
					sel_c <= reg_d;
					special_reg_out <= 1;
					special_reg_sel <= reg_s;
				end
			end

			exception_save_reg13 : begin

				a_out <= 1;
				sel_a <= 13;

				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				special_reg_in <= 1;
				special_reg_sel <= ERS_REGNO;
			end

			exception_load_reg13 : begin

				special_reg_out <= 1;
				special_reg_sel <= ERS_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				c_in <= 1;
				sel_c <= 13;
			end

			interrupt_save_PC : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;
			end

			interrupt_take_vector : begin

				special_reg_out <= 1;
				special_reg_sel <= IVEC_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				pc_in <= 1;
			end

			return_from_exception : begin
				special_reg_out <= 1;
				special_reg_sel <= IAR_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				pc_in <= 1;


				special_reg_restore_state <= 1;
			end

			break_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 4;

				special_reg_save_state <= 1;
			end

			syscall_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 2;

				special_reg_save_state <= 1;
			end

			arithmetic_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 8;

				special_reg_save_state <= 1;
			end

			gpf_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 1;

				special_reg_save_state <= 1;
			end
		endcase
	end		




	always @(current_state, 
	         instruction_reg, 
	         zero, 
	         interrupts, 
	         int_mask, 
	         interrupts_enabled, 
	         alu_done, 
	         kernel_mode, 
	         overflow, 
	         div_zero, 
	         memory_violation) begin


		next_state <= error_state;

		case (current_state)

			check_exceptions : begin

				if (((interrupts & int_mask) != 0) && interrupts_enabled) begin
					next_state <= interrupt_save_PC;
				end else if (kernel_mode == 0) begin
					next_state <= fetch_memcheck;
				end else begin
					next_state <= insn_fetch;
				end
			end

			fetch_memcheck : begin
				if (memory_violation == 1 && kernel_mode == 0) begin
					next_state <= gpf_exception;
				end else begin
					next_state <= fetch_memcheck_post;
				end
			end
			
			fetch_memcheck_post : begin
			    next_state <= insn_fetch;
			end

			insn_fetch : begin
				next_state <= insn_fetch_2;
			end
			
			insn_fetch_2 : begin
			    next_state <= insn_decode;
			end

			insn_decode : begin

				case (opcode)

					OPCODE_J, OPCODE_JR : begin
						next_state <= uncond_jump;				
					end


					OPCODE_JAL, OPCODE_JALR : begin
						next_state <= jump_and_link;
					end


					OPCODE_LW, OPCODE_SW : begin
						next_state <= eff_add_comp;
					end
		

					OPCODE_BEQZ, OPCODE_BNEZ : begin
						next_state <= cond_branch;
					end


					OPCODE_LA : begin
						next_state <= load_immed;
					end
		

					OPCODE_ARITH, OPCODE_ARITHI : begin
						if (func == FUNC_MULT || func == FUNC_MULTU	|| func == FUNC_DIV || func == FUNC_DIVU || func == FUNC_REM || func == FUNC_REMU) begin
							next_state <= setup_multi_cycle_alu;
						end else begin
							next_state <= single_cycle_alu;
						end
					end


					OPCODE_TESTI, OPCODE_TEST : begin
						if (func == FUNC_SLT || func == FUNC_SLTU
								|| func == FUNC_SGT || func == FUNC_SGTU
								|| func == FUNC_SLE || func == FUNC_SLEU
								|| func == FUNC_SGE || func == FUNC_SGEU
								|| func == FUNC_SEQ || func == FUNC_SEQU
								|| func == FUNC_SNE || func == FUNC_SNEU) begin
				
							next_state <= single_cycle_alu;
						end else if (opcode == OPCODE_TESTI && func == FUNC_LHI) begin
							next_state <= load_immed;
						end else if (opcode == OPCODE_TESTI && (func == FUNC_MOVSG || func == FUNC_MOVGS)) begin


							if (kernel_mode == 0) begin
								next_state <= gpf_exception;
							end else begin
								next_state <= special_move;
							end
						end else if (opcode == OPCODE_TEST && func == FUNC_RFE) begin

							if (kernel_mode == 0) begin
								next_state <= gpf_exception;
							end else begin
								next_state <= return_from_exception;
							end
						end else if (opcode == OPCODE_TEST && func == FUNC_BREAK) begin
							next_state <= break_exception;
						end else if (opcode == OPCODE_TEST && func == FUNC_SYSCALL) begin
							next_state <= syscall_exception;
						end else begin

							next_state <= gpf_exception;
						end
					end

					default :

						next_state <= gpf_exception;
				endcase
			end


			special_move : begin
				next_state <= check_exceptions;
			end



			single_cycle_alu : begin
				next_state <= check_exceptions;

				if (func == FUNC_ADD || func == FUNC_ADDU || func == FUNC_SUB || func == FUNC_SUBU) begin
					if (overflow == 1) begin
						next_state <= arithmetic_exception;
					end
				end
			end

			setup_multi_cycle_alu : begin
				next_state <= wait_multi_cycle_alu;
			end

			wait_multi_cycle_alu : begin
				if (div_zero == 1 || overflow == 1) begin
					next_state <= arithmetic_exception;
				end else if (alu_done == 1) begin
					next_state <= check_exceptions;
				end else begin
					next_state <= wait_multi_cycle_alu;
				end
			end


			load_immed : begin
				next_state <= check_exceptions;
			end


			uncond_jump : begin
				next_state <= check_exceptions;
			end

			jump_and_link : begin
				next_state <= uncond_jump;
			end


			eff_add_comp : begin
				if (kernel_mode == 0) begin
					next_state <= memop_memcheck_post;
				end else begin
					next_state <= do_memory_op;
				end
			end
			
			memop_memcheck_post : begin
			    next_state <= memop_memcheck;
			end

			memop_memcheck : begin
				if (memory_violation == 1 && kernel_mode == 0) begin
					next_state <= gpf_exception;
				end else begin
					next_state <= do_memory_op;
				end
			end

			do_memory_op : begin

				if (opcode == OPCODE_LW) begin
                    next_state <= do_memory_op_load;
				end
				else next_state <= check_exceptions;
			end
			
			do_memory_op_load : begin
			    next_state <= check_exceptions;
			end


			cond_branch : begin
				if ((opcode == OPCODE_BEQZ && zero == 1) || (opcode == OPCODE_BNEZ && zero == 0)) begin
					next_state <= branch_taken;
				end else begin
					next_state <= check_exceptions;
				end
			end

			branch_taken : begin
				next_state <= check_exceptions;
			end

			interrupt_save_PC : begin
				next_state <= exception_save_reg13;
			end

			exception_save_reg13 : begin
				next_state <= interrupt_take_vector;
			end

			interrupt_take_vector : begin
				next_state <= insn_fetch;
			end

			return_from_exception : begin
				next_state <= exception_load_reg13;
			end

			exception_load_reg13 : begin
				next_state <= check_exceptions;
			end

			break_exception, syscall_exception, arithmetic_exception, gpf_exception : begin
				next_state <= interrupt_save_PC;
			end

			halt : begin
				next_state <= halt;
			end

		endcase
	end



	always @(posedge clk) begin
		if (reset_n == 0) begin
			current_state <= insn_fetch;
		end else begin
			current_state <= next_state;
		end
	end
endmodule
module control_unit (
	input reset_n,
	input clk,


	input [31:0] instruction_reg,



	output reg mem_read,
	output reg mem_write,
	output reg check_mem,
	input memory_violation,


	output reg ir_in,
	output reg imm_16_out,
	output reg imm_20_out,
	output reg sign_extend,


	output reg pc_in,
	output reg pc_out,
	output reg pc_inc,


	output reg a_out,
	output reg b_out,
	output reg c_in,
	output reg [3:0] sel_a,
	output reg [3:0] sel_b,
	output reg [3:0] sel_c,


	output reg temp_in,
	output reg temp_out,


	output reg alu_out,
	output reg alu_start,
	output reg [4:0] alu_func,
	input alu_done,
	input zero,
	input div_zero,
	input overflow,


	output reg special_reg_in,
	output reg special_reg_out,
	output reg special_reg_save_state,
	output reg special_reg_restore_state,
	output reg inc_icount,
	output reg [3:0] special_reg_sel,
	output reg [3:0] exception_status,

	input interrupts_enabled,
	input kernel_mode,
	input [7:0] interrupts,
	input [7:0] int_mask
	);

    

    `include "wramp.vh"
	

	parameter check_exceptions 		=  0;
	parameter fetch_memcheck 		=  1;
	parameter insn_fetch 			=  2;
    parameter insn_fetch_2          =  3;
	parameter insn_decode 			=  4;
	parameter uncond_jump 			=  5;
	parameter jump_and_link 		=  6;
	parameter single_cycle_alu 		=  7;
	parameter setup_multi_cycle_alu =  8;
	parameter wait_multi_cycle_alu 	=  9;
	parameter special_move 			= 10;
	parameter eff_add_comp 			= 11;
	parameter do_memory_op 			= 12;
    parameter do_memory_op_load     = 13;
	parameter cond_branch 			= 14;
	parameter branch_taken 			= 15;
	parameter load_immed 			= 16;
	parameter error_state 			= 17;
	parameter memop_memcheck 		= 18;
	parameter arithmetic_exception 	= 19;
	parameter syscall_exception 	= 20;
	parameter break_exception 		= 21;
	parameter gpf_exception 		= 22;
	parameter exception_save_reg13 	= 23;
	parameter exception_load_reg13 	= 24;
	parameter interrupt_save_PC 	= 25;
	parameter interrupt_take_vector = 26;
	parameter return_from_exception = 27;
	parameter halt 					= 31;
	parameter fetch_memcheck_post   = 32;
	parameter memop_memcheck_post   = 33;


	wire [ 3:0] opcode 	   = instruction_reg[31:28];
	wire [ 3:0] reg_d 	   = instruction_reg[27:24];
	wire [ 3:0] reg_s 	   = instruction_reg[23:20];
	wire [ 3:0] reg_t      = instruction_reg[ 3: 0];
	wire [ 3:0] func       = instruction_reg[19:16];
	wire [15:0] immediate  = instruction_reg[15: 0];
	wire [19:0] address    = instruction_reg[19: 0];

	reg [5:0] current_state, next_state;



	always @(current_state, opcode, alu_done) begin
		

		temp_in <= 0;
		temp_out <= 0;


		special_reg_in <= 0;
		special_reg_out <= 0;
		special_reg_sel <= 0;
		inc_icount <= 0;
		special_reg_save_state <= 0;
		special_reg_restore_state <= 0;
		exception_status <= 0;
		

		a_out <= 0;
		b_out <= 0;
		c_in <= 0;
		sel_a <= 0000;
		sel_b <= 0000;
		sel_c <= 0000;
		

		pc_in <= 0;
		pc_out <= 0;
		pc_inc <= 0;
		

		ir_in <= 0;
		imm_16_out <= 0;
		imm_20_out <= 0;
		sign_extend <= 0;
		

		alu_out <= 0;
		alu_func <= 0;
		alu_start <= 0;
		

		mem_read <= 0;
		mem_write <= 0;
		check_mem <= 0;

		case (current_state)
			check_exceptions : begin

		    	if (((interrupts & int_mask) != 8'h00) && interrupts_enabled == 1'b1) begin
		      		special_reg_save_state <= 1;
		    	end
			end		    

		  	fetch_memcheck : begin

				mem_read <= 1;

				pc_out <= 1;


			end
			
			fetch_memcheck_post : begin

                mem_read <= 1;

                pc_out <= 1;

                check_mem <= 1;
            end
			
	
			insn_fetch : begin			    


				mem_read <= 1;
				pc_out <= 1;

				inc_icount <= 1;
			end		  
			
			insn_fetch_2 : begin

                mem_read <= 1;


                pc_out <= 1;

                ir_in <= 1;
			end  

			insn_decode : begin

				pc_inc <= 1;
			end

			uncond_jump : begin


				if (opcode == OPCODE_J || opcode == OPCODE_JAL) begin
					imm_20_out <= 1;
				end else begin

					a_out <= 1;
					sel_a <= reg_s;
				end


				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				pc_in <= 1;
			end


			jump_and_link : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				c_in <= 1;
				sel_c <= 15;
			end

			load_immed : begin

				imm_20_out <= 1;

				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				if (opcode == OPCODE_LA) begin
					alu_func <= FUNC_ADD;
				end else begin
					alu_func <= ALU_LHI;
				end

				c_in <= 1;
				sel_c <= reg_d;
			end


			cond_branch : begin

				a_out <= 1;
				sel_a <= reg_s;

				b_out <= 1;
				sel_b <= 0;

				alu_func <= FUNC_ADD;
			end

			branch_taken : begin

				imm_20_out <= 1;
				sign_extend <= 1;

				pc_out <= 1;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				pc_in <= 1;
			end

			eff_add_comp : begin


				imm_20_out <= 1;
				sign_extend <= 1;

				b_out <= 1;
				sel_b <= reg_s;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				temp_in <= 1;
			end
			
			memop_memcheck_post : begin

                temp_out <= 1;

                mem_read <= 1;

                check_mem <= 1;
            end

			memop_memcheck : begin

				temp_out <= 1;

				mem_read <= 1;

                check_mem <= 1;
			end
			
			

			do_memory_op : begin

				temp_out <= 1;

				if (opcode == OPCODE_LW) begin


				end 
				if (opcode == OPCODE_SW) begin

					mem_write <= 1;

					a_out <= 1;

					sel_a <= reg_d;
				end
			end
			
			do_memory_op_load : begin

			    temp_out <= 1;

			    mem_read <= 1;

			    c_in <= 1;

			    sel_c <= reg_d;
			end

			single_cycle_alu : begin

				b_out <= 1;
				sel_b <= reg_s;

				case (opcode) 
					OPCODE_ARITHI, OPCODE_TESTI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH,OPCODE_TEST : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase

				alu_out <= 1;
				if (opcode == OPCODE_ARITHI || opcode == OPCODE_ARITH) begin
					alu_func <= {1'b0, func};
				end else begin
					alu_func <= {1'b1, func};
				end

				c_in <= 1;
				sel_c <= reg_d;
			end

			setup_multi_cycle_alu : begin

				b_out <= 1;
				sel_b <= reg_s;

				case (opcode)
					OPCODE_ARITHI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase
				alu_func <= {1'b0, func};
				alu_start <= 1;
			end

			wait_multi_cycle_alu : begin


				b_out <= 1;
				sel_b <= reg_s;

				case (opcode)
					OPCODE_ARITHI : begin
						imm_16_out <= 1;

						if (func[0] == 0) begin
							sign_extend <= 1;
						end
					end
					OPCODE_ARITH : begin
						a_out <= 1;
						sel_a <= reg_t;
					end
				endcase
				alu_func <= {1'b0, func};
				sel_c <= reg_d;
				if (alu_done == 1) begin
					alu_out <= 1;
					c_in <= 1;
				end
			end

			special_move : begin

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				if (func == FUNC_MOVGS) begin
					b_out <= 1;
					sel_b <= reg_s;
					special_reg_in <= 1;
					special_reg_sel <= reg_d;
				end else begin
					c_in <= 1;
					sel_c <= reg_d;
					special_reg_out <= 1;
					special_reg_sel <= reg_s;
				end
			end

			exception_save_reg13 : begin

				a_out <= 1;
				sel_a <= 13;

				b_out <= 1;
				sel_b <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				special_reg_in <= 1;
				special_reg_sel <= ERS_REGNO;
			end

			exception_load_reg13 : begin

				special_reg_out <= 1;
				special_reg_sel <= ERS_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;

				c_in <= 1;
				sel_c <= 13;
			end

			interrupt_save_PC : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;
			end

			interrupt_take_vector : begin

				special_reg_out <= 1;
				special_reg_sel <= IVEC_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				pc_in <= 1;
			end

			return_from_exception : begin
				special_reg_out <= 1;
				special_reg_sel <= IAR_REGNO;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				pc_in <= 1;


				special_reg_restore_state <= 1;
			end

			break_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 4;

				special_reg_save_state <= 1;
			end

			syscall_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 2;

				special_reg_save_state <= 1;
			end

			arithmetic_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 8;

				special_reg_save_state <= 1;
			end

			gpf_exception : begin

				pc_out <= 1;

				a_out <= 1;
				sel_a <= 0;

				alu_out <= 1;
				alu_func <= FUNC_ADD;


				special_reg_in <= 1;
				special_reg_sel <= IAR_REGNO;

				exception_status <= 1;

				special_reg_save_state <= 1;
			end
		endcase
	end		




	always @(current_state, 
	         instruction_reg, 
	         zero, 
	         interrupts, 
	         int_mask, 
	         interrupts_enabled, 
	         alu_done, 
	         kernel_mode, 
	         overflow, 
	         div_zero, 
	         memory_violation) begin


		next_state <= error_state;

		case (current_state)

			check_exceptions : begin

				if (((interrupts & int_mask) != 0) && interrupts_enabled) begin
					next_state <= interrupt_save_PC;
				end else if (kernel_mode == 0) begin
					next_state <= fetch_memcheck;
				end else begin
					next_state <= insn_fetch;
				end
			end

			fetch_memcheck : begin
				if (memory_violation == 1 && kernel_mode == 0) begin
					next_state <= gpf_exception;
				end else begin
					next_state <= fetch_memcheck_post;
				end
			end
			
			fetch_memcheck_post : begin
			    next_state <= insn_fetch;
			end

			insn_fetch : begin
				next_state <= insn_fetch_2;
			end
			
			insn_fetch_2 : begin
			    next_state <= insn_decode;
			end

			insn_decode : begin

				case (opcode)

					OPCODE_J, OPCODE_JR : begin
						next_state <= uncond_jump;				
					end


					OPCODE_JAL, OPCODE_JALR : begin
						next_state <= jump_and_link;
					end


					OPCODE_LW, OPCODE_SW : begin
						next_state <= eff_add_comp;
					end
		

					OPCODE_BEQZ, OPCODE_BNEZ : begin
						next_state <= cond_branch;
					end


					OPCODE_LA : begin
						next_state <= load_immed;
					end
		

					OPCODE_ARITH, OPCODE_ARITHI : begin
						if (func == FUNC_MULT || func == FUNC_MULTU	|| func == FUNC_DIV || func == FUNC_DIVU || func == FUNC_REM || func == FUNC_REMU) begin
							next_state <= setup_multi_cycle_alu;
						end else begin
							next_state <= single_cycle_alu;
						end
					end


					OPCODE_TESTI, OPCODE_TEST : begin
						if (func == FUNC_SLT || func == FUNC_SLTU
								|| func == FUNC_SGT || func == FUNC_SGTU
								|| func == FUNC_SLE || func == FUNC_SLEU
								|| func == FUNC_SGE || func == FUNC_SGEU
								|| func == FUNC_SEQ || func == FUNC_SEQU
								|| func == FUNC_SNE || func == FUNC_SNEU) begin
				
							next_state <= single_cycle_alu;
						end else if (opcode == OPCODE_TESTI && func == FUNC_LHI) begin
							next_state <= load_immed;
						end else if (opcode == OPCODE_TESTI && (func == FUNC_MOVSG || func == FUNC_MOVGS)) begin


							if (kernel_mode == 0) begin
								next_state <= gpf_exception;
							end else begin
								next_state <= special_move;
							end
						end else if (opcode == OPCODE_TEST && func == FUNC_RFE) begin

							if (kernel_mode == 0) begin
								next_state <= gpf_exception;
							end else begin
								next_state <= return_from_exception;
							end
						end else if (opcode == OPCODE_TEST && func == FUNC_BREAK) begin
							next_state <= break_exception;
						end else if (opcode == OPCODE_TEST && func == FUNC_SYSCALL) begin
							next_state <= syscall_exception;
						end else begin

							next_state <= gpf_exception;
						end
					end

					default :

						next_state <= gpf_exception;
				endcase
			end


			special_move : begin
				next_state <= check_exceptions;
			end



			single_cycle_alu : begin
				next_state <= check_exceptions;

				if (func == FUNC_ADD || func == FUNC_ADDU || func == FUNC_SUB || func == FUNC_SUBU) begin
					if (overflow == 1) begin
						next_state <= arithmetic_exception;
					end
				end
			end

			setup_multi_cycle_alu : begin
				next_state <= wait_multi_cycle_alu;
			end

			wait_multi_cycle_alu : begin
				if (div_zero == 1 || overflow == 1) begin
					next_state <= arithmetic_exception;
				end else if (alu_done == 1) begin
					next_state <= check_exceptions;
				end else begin
					next_state <= wait_multi_cycle_alu;
				end
			end


			load_immed : begin
				next_state <= check_exceptions;
			end


			uncond_jump : begin
				next_state <= check_exceptions;
			end

			jump_and_link : begin
				next_state <= uncond_jump;
			end


			eff_add_comp : begin
				if (kernel_mode == 0) begin
					next_state <= memop_memcheck_post;
				end else begin
					next_state <= do_memory_op;
				end
			end
			
			memop_memcheck_post : begin
			    next_state <= memop_memcheck;
			end

			memop_memcheck : begin
				if (memory_violation == 1 && kernel_mode == 0) begin
					next_state <= gpf_exception;
				end else begin
					next_state <= do_memory_op;
				end
			end

			do_memory_op : begin

				if (opcode == OPCODE_LW) begin
                    next_state <= do_memory_op_load;
				end
				else next_state <= check_exceptions;
			end
			
			do_memory_op_load : begin
			    next_state <= check_exceptions;
			end


			cond_branch : begin
				if ((opcode == OPCODE_BEQZ && zero == 1) || (opcode == OPCODE_BNEZ && zero == 0)) begin
					next_state <= branch_taken;
				end else begin
					next_state <= check_exceptions;
				end
			end

			branch_taken : begin
				next_state <= check_exceptions;
			end

			interrupt_save_PC : begin
				next_state <= exception_save_reg13;
			end

			exception_save_reg13 : begin
				next_state <= interrupt_take_vector;
			end

			interrupt_take_vector : begin
				next_state <= insn_fetch;
			end

			return_from_exception : begin
				next_state <= exception_load_reg13;
			end

			exception_load_reg13 : begin
				next_state <= check_exceptions;
			end

			break_exception, syscall_exception, arithmetic_exception, gpf_exception : begin
				next_state <= interrupt_save_PC;
			end

			halt : begin
				next_state <= halt;
			end

		endcase
	end



	always @(posedge clk) begin
		if (reset_n == 0) begin
			current_state <= insn_fetch;
		end else begin
			current_state <= next_state;
		end
	end
endmodule