module counter
	(
		input	wire			clock, frame,

		input	wire			reset, setup, count,

		input	wire			bus_ssel, bus_wren,
		input	wire	[1:0]	bus_addr,
		input	wire	[15:0]	bus_mosi,

		output	wire	[15:0]	bus_miso,
		output	wire			bus_busy,
		
		output  wire			cnt_good
	);

	wire 	[3:0]	int_ssel_wire;
	wire	[15:0]	int_miso_wire;

	reg				cnt_good_reg;
	reg		[15:0]	int_miso_reg;

	wire 	[63:0]	reg_bits_wire;
	wire 	[63:0]	cnt_bits_wire;
	
	reg				int_load_reg;

	integer i;
	genvar j;

	lpm_counter	#(
		.lpm_direction("DOWN"),
		.lpm_port_updown("PORT_UNUSED"),
		.lpm_type("LPM_COUNTER"),
		.lpm_width(64)) lpm_counter_component (
		.sload(int_load_reg | setup),
		.sclr(reset),
		.clock(clock),
		.data(reg_bits_wire),
		.cnt_en((frame) & (count) & (|cnt_bits_wire)),
		.q(cnt_bits_wire));

	generate
		for (j = 0; j < 4; j = j + 1)
		begin : BUS_OUTPUT
			lpm_ff #(
				.lpm_fftype("DFF"),
				.lpm_type("LPM_FF"),
				.lpm_width(16)) cfg_reg_unit (
				.enable(int_ssel_wire[j] & bus_ssel & bus_wren),
				.sclr(reset),
				.clock(clock),
				.data(bus_mosi),
				.q(reg_bits_wire[j*16+15:j*16]));
				end
	endgenerate

	lpm_mux #(
		.lpm_size(4),
		.lpm_type("LPM_MUX"),
		.lpm_width(16),
		.lpm_widths(2)) bus_miso_mux_unit (
		.sel(bus_addr),
		.data(cnt_bits_wire),
		.result(int_miso_wire));


	lpm_decode #(
		.lpm_decodes(4),
		.lpm_type("LPM_DECODE"),
		.lpm_width(2)) lpm_decode_unit (
		.data(bus_addr),
		.eq(int_ssel_wire));

	always @(posedge clock)
	begin
		if (reset)
		begin
			int_miso_reg <= 16'd0;
			cnt_good_reg <= 1'b0;
			int_load_reg <= 1'b0;
		end
		else
		begin
			int_miso_reg <= int_miso_wire;
			cnt_good_reg <= |cnt_bits_wire;
			int_load_reg <= bus_ssel & bus_wren;
		end
	end

	// output logic
	assign	bus_miso = int_miso_reg;
	assign	bus_busy = 1'b0;
	assign	cnt_good = cnt_good_reg;

endmodule
