module histogram
	(
		input	wire			clk, reset,
		input	wire			data_ready,
		input	wire	[11:0]  data, address,
		output	wire	[31:0]  q,
		output	wire	[3:0]	led
	);
	
	// signal declaration
	reg		[3:0]	state_reg, state_next;

	reg		[31:0]	led_data_reg [3:0];
	reg		[31:0]  led_data_next [3:0];

	reg				wren_reg, wren_next;
	reg		[11:0]	addr_reg, addr_next;
	reg		[31:0]	data_reg, data_next;

	wire	[31:0]	q_a_wire, q_b_wire;

	ram4096x32 ram4096x32_unit (
		.address_a(addr_reg),
		.address_b(address),
		.clock(~clk),
		.data_a(data_reg),
		.data_b(),
		.wren_a(wren_reg),
		.wren_b(1'b0),
		.q_a(q_a_wire),
		.q_b(q_b_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;
			led_data_reg[0] <= led_data_next[0];
			led_data_reg[1] <= led_data_next[1];
			led_data_reg[2] <= led_data_next[2];
			led_data_reg[3] <= led_data_next[3];
		end
	end

	always @*
	begin
		state_next = state_reg;
		wren_next = wren_reg;
		addr_next = addr_reg;
		data_next = data_reg;
		led_data_next[0] = led_data_reg[0];
		led_data_next[1] = led_data_reg[1];
		led_data_next[2] = led_data_reg[2];
		led_data_next[3] = led_data_reg[3];
		case (state_reg)
			0: ; // nothing to do
			1: 
			begin
				// start reset
				wren_next = 1'b1;
				addr_next = 0;
				data_next = 0;
				led_data_next[0] = 0;
				led_data_next[1] = 0;
				led_data_next[2] = 0;
				led_data_next[3] = 0;
				state_next = 4'd2;
			end
			
			2:
			begin
				// write zeros
				if (&addr_reg)
				begin
					state_next = 4'd3;
				end
				else
				begin
					addr_next = addr_reg + 12'd1;
				end
			end
	
			3:
			begin
				// read
				wren_next = 1'b0;
				if (&data_reg)
				begin
					state_next = 4'd0;
				end
				else if (data_ready)
				begin
					// set addr
					addr_next = data;
					state_next = 4'd4;
				end
			end

			4:
			begin
				// increment and write
				wren_next = 1'b1;
				data_next = q_a_wire + 32'd1;
				led_data_next[addr_reg>>10] = q_a_wire;
				state_next = 4'd3;
			end

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

	// output logic
	assign	q			=	q_b_wire;
	assign	led[0]		=	led_data_reg[0][23];
	assign	led[1]		=	led_data_reg[1][23];
	assign	led[2]		=	led_data_reg[2][23];
	assign	led[3]		=	led_data_reg[3][23];

endmodule
