module oscilloscope
	(
		input	wire			clk, reset,
		input	wire			data_ready,
		input	wire	[15:0]  raw_data, uwt_data, threshold,
		input	wire	[9:0]	address,
		output	wire	[9:0]	start_address,
		output	wire	[15:0]  q
	);
	
	// signal declaration
	reg		[3:0]	state_reg, state_next;

	reg				wren_reg, wren_next;
	reg		[9:0]	addr_reg, addr_next;
	reg		[15:0]	data_reg, data_next;

	reg				trig_reg, trig_next;
	reg		[9:0]	trig_addr_reg, trig_addr_next;
	reg		[9:0]	counter_reg, counter_next;

	wire	[15:0]	q_wire;

	ram1024x16 ram1024x16_unit (
		.clock(~clk),
		.data(data_reg),
		.rdaddress(address),
		.wraddress(addr_reg),
		.wren(wren_reg),
		.q(q_wire));

	// body
	always @(posedge clk)
	begin
		if (reset)
        begin
			state_reg <= 4'b1;
		end
		else
		begin
			state_reg <= state_next;
			wren_reg <= wren_next;
			addr_reg <= addr_next;
			data_reg <= data_next;
			trig_reg <= trig_next;
			trig_addr_reg <= trig_addr_next;
			counter_reg <= counter_next;
		end
	end

	always @*
	begin
		state_next = state_reg;
		wren_next = wren_reg;
		addr_next = addr_reg;
		data_next = data_reg;
		trig_next = trig_reg;
		trig_addr_next = trig_addr_reg;
		counter_next = counter_reg;

		case (state_reg)
			0: ; // nothing to do  
			1: 
			begin
				// start reset
				wren_next = 1'b1;
				addr_next = 0;
				data_next = 0;
				trig_next = 0;
				trig_addr_next = 0;
				counter_next = 0;
				state_next = 4'd2;
			end
			
			2:
			begin
				// write zeros
				if (&addr_reg)
				begin
					wren_next = 1'b0;
					state_next = 4'd3;
				end
				else
				begin
					addr_next = addr_reg + 10'd1;
				end
			end
	
			3:
			begin
				if (&counter_reg)
				begin
					state_next = 4'd0;
				end
				else if (data_ready)
				begin
					// start write
					wren_next = 1'b1;
					data_next = raw_data;
					if ((~trig_reg)
						& (counter_reg == 10'd512)
						& (uwt_data >= threshold))
					begin
						// trigger
						trig_next = 1'b1;
						trig_addr_next = addr_reg;
					end
					state_next <= 4'd4;
				end
			end

			4:
			begin
				// stop write
				wren_next <= 1'b0;
				addr_next = addr_reg + 10'd1;
				if (trig_reg | (counter_reg < 10'd512))
				begin
					counter_next = counter_reg + 10'd1;
				end
				state_next = 4'd3;
			end

			default:
			begin
				state_next = 4'd0;
			end
		endcase
	end

	// output logic
	assign	q				=	q_wire;
	assign	start_address	=	trig_reg ? trig_addr_reg ^ 10'h200 : addr_reg + 10'd1;

endmodule
