`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//	Tony Kim
//	6.111 Lab2
//
// Module name: AntiTheftFSM
// Description: Implementation of the AntiTheft finite state machine. See documentation
//					 for more details.
//
//////////////////////////////////////////////////////////////////////////////////

module AntiTheftFSM(clk_27mhz, driver_door, passenger_door, ignition, reprogram, interval, 
						  start_timer, expired, status_indicator, siren, state);
    input clk_27mhz;
    input driver_door;
    input passenger_door;
    input ignition;
    input reprogram;
    output [1:0] interval;
    output start_timer;
    input expired;
    output [1:0] status_indicator;
    output siren;
	 output [2:0] state;
	
	//----------------------------------------------------------------------
	// The states of our AntiTheftFSM
	//----------------------------------------------------------------------
	parameter S_DISARMED 					= 3'd0;
	parameter S_DOOROPEN_IGNITIONOFF 	= 3'd1;
	parameter S_WAIT_T_ARM_DELAY 			= 3'd2;
	parameter S_ARMED 						= 3'd3;
	parameter S_WAIT_T_PASSENGER_DELAY 	= 3'd4;
	parameter S_WAIT_T_DRIVER_DELAY    	= 3'd5;
	parameter S_ALARM_ON 					= 3'd6;
	parameter S_WAIT_T_ALARM_ON 			= 3'd7;

	//----------------------------------------------------------------------
	// Timing parameters
	//----------------------------------------------------------------------
	parameter T_ARM_DELAY       = 2'b00;
	parameter T_DRIVER_DELAY    = 2'b01;
	parameter T_PASSENGER_DELAY = 2'b10;
	parameter T_ALARM_ON        = 2'b11; 

	//----------------------------------------------------------------------
	// Status indicator modes
	//----------------------------------------------------------------------
	parameter I_OFF   = 2'b00;
	parameter I_BLINK = 2'b01;
	parameter I_ON    = 2'b10;

	reg [2:0] state = S_ARMED;
	reg [2:0] next_state;
	
	reg [1:0] interval = T_ARM_DELAY;
	reg start_timer;
	reg [1:0] status_indicator;
	reg siren;

	always @ (posedge clk_27mhz) 
	begin
		if(reprogram) next_state <= S_ARMED;
		else 
		begin
			//----------------------------------------------------------------------
			// By default, we will stay at our current state. Transitions are
			// explicitly coded in.
			//----------------------------------------------------------------------
			next_state <= state;
			case(state)
				S_DISARMED:
				begin
					// Current outputs
					start_timer <= 1'b0;
					status_indicator <= I_OFF;
					siren <= 1'b0;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					if(driver_door && ~ignition) next_state <= S_DOOROPEN_IGNITIONOFF;
				end
				
				S_DOOROPEN_IGNITIONOFF:
				begin
					// Current outputs
					start_timer <= 1'b0;
					status_indicator <= I_OFF;
					siren <= 1'b0;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					if(~driver_door) next_state <= S_WAIT_T_ARM_DELAY;
				end
				
				S_WAIT_T_ARM_DELAY:
				begin
					// Current outputs
					interval         <= T_ARM_DELAY;
					start_timer      <= 1'b1;
					status_indicator <= I_OFF;
					siren            <= 1'b0;
					
					// Next states
					if(ignition)    next_state <= S_DISARMED;
					if(driver_door) next_state <= S_DOOROPEN_IGNITIONOFF;
					if(expired)     next_state <= S_ARMED;
				end
				
				S_ARMED:
				begin
					// Current outputs
					start_timer      <= 1'b0;
					status_indicator <= I_BLINK;
					siren            <= 1'b0;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					if(passenger_door) next_state <= S_WAIT_T_PASSENGER_DELAY;
					if(driver_door) next_state <= S_WAIT_T_DRIVER_DELAY;
				end
				
				S_WAIT_T_PASSENGER_DELAY:
				begin
					// Current outputs
					interval         <= T_PASSENGER_DELAY;
					start_timer      <= 1'b1;
					status_indicator <= I_ON;
					siren            <= 1'b0;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					else if(expired)  next_state <= S_ALARM_ON;
				end
				
				S_WAIT_T_DRIVER_DELAY:
				begin
					// Current outputs
					interval         <= T_DRIVER_DELAY;
					start_timer      <= 1'b1;
					status_indicator <= I_ON;
					siren            <= 1'b0;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					else if(expired)  next_state <= S_ALARM_ON;
				end
				
				S_ALARM_ON:
				begin
					// Current outputs
					start_timer      <= 1'b0;
					status_indicator <= I_ON;
					siren            <= 1'b1;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					else if( expired ) next_state <= S_ALARM_ON;
					else if( ~passenger_door && ~driver_door ) next_state <= S_WAIT_T_ALARM_ON;
				end
				
				S_WAIT_T_ALARM_ON:
				begin
					// Current outputs;
					interval         <= T_ALARM_ON;
					start_timer      <= 1'b1;
					status_indicator <= I_ON;
					siren            <= 1'b1;
					
					// Next states
					if(ignition) next_state <= S_DISARMED;
					if(expired)  next_state <= S_ARMED;
				end
			endcase
		end
		
		//----------------------------------------------------------------------
		// Move to our new state
		//----------------------------------------------------------------------
		state <= next_state;
	end

endmodule
