`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//	Tony Kim
//	6.111 Lab2
//
// Module name: Timer 
// Description: This module when triggered by 'start_timer', will count down from
//					 the initial 'count_value' towards zero. The count occurs whenever 
//				    'clk_1hz' is high. When it has reached zero, will output a high
//					 'expired'. The 'current_count' output is used for HEX displays on
//					 the labkit.
//
//////////////////////////////////////////////////////////////////////////////////

module Timer(clk_27mhz, clk_1hz, count_value, start_timer, expired, current_count);
    input clk_27mhz;
    input clk_1hz;
    input [3:0] count_value;
    input start_timer;
    output expired;
	 output [3:0] current_count;

	reg expired = 0;
	reg [3:0] current_count;
	
	reg [3:0] count;

	parameter TIMER_SLEEP = 1'b0;
	parameter TIMER_COUNT = 1'b1;
	reg timer_mode = TIMER_SLEEP;

	always @ (posedge clk_27mhz)
	begin
		if(start_timer)
		begin
			case(timer_mode)
				// If we get the start_timer signal, and the timer is currently sleeping,
				// then we initialize the value of `count' and change our state.
				TIMER_SLEEP: 
				begin
					timer_mode <= TIMER_COUNT;
					expired    <= 0;
					count      <= count_value;
				end
				// We are already in the counting mode, then we see if the counter has 
				// reached zero. If so, we set the expired signal high, and change the timer
				// mode back into sleep.
				//
				// If the count is not zero, then we see if clock_1hz is high. (Recall that the
				// 1Hz signal is high for one period of the 27MHz clock.)
				TIMER_COUNT:
				begin
					current_count <= count;
					if(count == 0)
					begin
						expired    <= 1;
					end
					else
					begin
						if(clk_1hz)	count <= count - 1;
					end
				end
			endcase
		end
		else
		begin
			// The timer is now turned off.
			expired       <= 0;
			timer_mode    <= TIMER_SLEEP;
			current_count <= count;
		end
	end
endmodule
