module counter
	(
		input	wire			clock, frame, reset,

		input	wire	[15:0]	cfg_data,

		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;

	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(cfg_data[0]),
		.sclr(reset),
		.clock(clock),
		.data(reg_bits_wire),
//		.cnt_en(frame & cfg_data[1]),
		.cnt_en((frame) & (|cnt_bits_wire) & (cfg_data[1])),
		.q(cnt_bits_wire),
		.aclr(1'b0),
		.aload(1'b0),
		.aset(1'b0),
		.cin(1'b1),
		.clk_en(1'b1),
		.cout(),
		.eq(),
		.sset(1'b0),
		.updown(1'b1));

	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]),
				.aclr(),
				.aload(),
				.aset(),
				.sload(),
				.sset());
				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),
		.aclr(),
		.clken(),
		.clock(),
		.enable());

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

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

endmodule
