module amplitude
	#(
		parameter	width	=	12 // bit width of the input data
	)
	(
		input	wire				clock, frame, reset,
		input	wire	[width-1:0]	min_data,
		input	wire	[width-1:0]	max_data,
		input	wire	[width-1:0]	inp_data,
		output	wire	[width-1:0]	out_data,
		output	wire	[1:0]		out_flag
	);

	reg					int_case_reg, int_case_next;
	reg					out_flag_reg, out_flag_next;
	reg					int_flag_reg, int_flag_next;
	reg		[width-1:0]	int_mini_reg, int_mini_next;
	reg		[width-1:0]	out_data_reg, out_data_next;
	reg		[width-1:0]	inp_data_reg [1:0], inp_data_next [1:0];

	wire				int_comp_wire;
	reg					int_comp_reg, int_comp_next;

	reg		[5:0]		int_cntr_reg, int_cntr_next;

	assign int_comp_wire = (inp_data_reg[1] < inp_data);

	always @(posedge clock)
	begin
		if (reset)
		begin
			int_case_reg <= 1'b0;
			int_mini_reg <= {(width){1'b0}};
			inp_data_reg[0] <= {(width){1'b0}};
			inp_data_reg[1] <= {(width){1'b0}};
			out_data_reg <= {(width){1'b0}};
			out_flag_reg <= 1'b0;
			int_flag_reg <= 1'b0;
			int_comp_reg <= 1'b0;
			int_cntr_reg <= 6'd0;
		end
		else
		begin
			int_case_reg <= int_case_next;
			int_mini_reg <= int_mini_next;
			inp_data_reg[0] <= inp_data_next[0];
			inp_data_reg[1] <= inp_data_next[1];
			out_data_reg <= out_data_next;
			out_flag_reg <= out_flag_next;
			int_flag_reg <= int_flag_next;
			int_comp_reg <= int_comp_next;
			int_cntr_reg <= int_cntr_next;
		end
	end
	
	always @*
	begin
		int_case_next = int_case_reg;
		int_mini_next = int_mini_reg;
		inp_data_next[0] = inp_data_reg[0];
		inp_data_next[1] = inp_data_reg[1];
		out_data_next = out_data_reg;
		out_flag_next = out_flag_reg;
		int_flag_next = int_flag_reg;
		int_comp_next = int_comp_reg;
		int_cntr_next = int_cntr_reg;
		
		case (int_case_reg)
			0:
			begin
				if (frame)
				begin
					inp_data_next[0] = inp_data;
					inp_data_next[1] = inp_data_reg[0];
					int_comp_next = int_comp_wire;
					out_data_next = {(width){1'b0}};
					out_flag_next = 1'b0;
					// minimum
					if ((~int_comp_reg) & (int_comp_wire) & int_cntr_reg[5])
					begin
						int_mini_next = inp_data_reg[0];
						int_flag_next = 1'b1;
					end
					// maximum after minimum
					else if ((int_comp_reg) & (~int_comp_wire) & (int_flag_reg))
					begin
						out_data_next = inp_data_reg[0] - int_mini_reg;
						int_flag_next = 1'b0;
						int_case_next = 1'b1;
					end
					else if (~int_cntr_reg[5])
					begin
						int_cntr_next = int_cntr_reg + 6'd1;
					end
                end
 			end
			
			1:
			begin
				if (out_data_reg > min_data)
				begin
					int_cntr_next = 6'b0;
//					out_flag_next = 1'b1;
					out_flag_next = (inp_data_reg[1] < max_data);
				end
				int_case_next = 1'b0;
 			end

		endcase
	end

	assign out_data = out_data_reg;
	assign out_flag = {~int_cntr_reg[5], out_flag_reg};

endmodule
