
(* ALTERA_ATTRIBUTE = {"{-to int_data_p} DDIO_INPUT_REGISTER=HIGH; {-to int_data_n} DDIO_INPUT_REGISTER=LOW"} *)

module adc_lvds
	#(
		parameter	size	=	3, // number of channels
		parameter	width	=	12 // channel resolution
	)
	(
		input	wire						clock,

		input	wire						lvds_dco,
		input	wire						lvds_fco,
 		input	wire	[size-1:0]			lvds_d,

 		input	wire	[1:0]				trig,

		output	wire						adc_frame,
		output	wire	[size*width-1+2:0]	adc_data

	);
	localparam	width2	=	width + 2;
		

	reg							state, int_rdreq, adc_frame_reg;
	wire						int_wrfull, int_rdempty;

	reg		[size-1:0]			int_data_p, int_data_n;

	reg 	[2:0]				int_edge_reg;

	reg 	[size*width-1:0]	int_fifo_reg;
	wire	[size*width-1:0]	int_fifo_wire;

	reg 	[size*width2-1:0]	int_data_reg;
	wire	[size*width2-1:0]	int_data_wire;

	wire	[size*width-1+2:0]	int_q_wire;
	reg		[size*width-1+2:0]	adc_data_reg;
	


	genvar j;

	generate
		for (j = 0; j < size; j = j + 1)
		begin : INT_DATA
// MSB first
//			assign int_data_wire[j*width+width-1:j*width] = {int_data_reg[j*width+width-3:j*width], int_data_p[j], int_data_n[j]};
// LSB first
//			assign int_data_wire[j*width+width-1:j*width] = {int_data_n[j], int_data_p[j], int_data_reg[j*width+width-1:j*width+2]};

			assign int_data_wire[j*width2+width2-1:j*width2] = {int_data_reg[j*width2+width2-3:j*width2], int_data_p[j], int_data_n[j]};
			assign int_fifo_wire[j*width+width-1:j*width] = int_data_reg[j*width2+width2-1:j*width2+2];
//			assign int_data_wire[j*width2+width2-1:j*width2] = {int_data_n[j], int_data_p[j], int_data_reg[j*width2+width2-1:j*width2+2]};
//			assign int_fifo_wire[j*width+width-1:j*width] = int_data_reg[j*width2+width2-3:j*width2];
		end
	endgenerate


	dcfifo #(
		.intended_device_family("Cyclone III"),
		.lpm_numwords(16),
		.lpm_showahead("ON"),
		.lpm_type("dcfifo"),
		.lpm_width(size*width+2),
		.lpm_widthu(4),
		.rdsync_delaypipe(4),
		.wrsync_delaypipe(4),
		.overflow_checking("ON"),
		.underflow_checking("ON"),
		.use_eab("ON")) fifo_unit (
//		.data(int_data_wire),
		.data({trig, int_fifo_reg}),
		.rdclk(clock),
		.rdreq((~int_rdempty) & int_rdreq),
		.wrclk(lvds_fco),
		.wrreq(~int_wrfull),
		.q(int_q_wire),
		.rdempty(int_rdempty),
		.wrfull(int_wrfull),
		.aclr(),
		.rdfull(),
		.rdusedw(),
		.wrempty(),
		.wrusedw());

	always @ (posedge clock)
	begin
		case (state)
			1'b0:
			begin
				int_rdreq <= 1'b1;
				adc_frame_reg <= 1'b0;
				state <= 1'b1;
			end

			1'b1: 
			begin
				if (~int_rdempty)
				begin
					int_rdreq <= 1'b0;
					adc_frame_reg <= 1'b1;
					adc_data_reg <= int_q_wire;
					state <= 1'b0;
				end
			end
		endcase
	end
	
	always @ (negedge lvds_dco)
	begin
		int_data_n <= lvds_d;
	end

	always @ (posedge lvds_dco)
	begin
		int_data_p <= lvds_d;
		int_data_reg <= int_data_wire;
		int_edge_reg <= {(~int_edge_reg[1]), int_edge_reg[0], lvds_fco};
		if (int_edge_reg[1] & int_edge_reg[2])
		begin
			int_fifo_reg <= int_fifo_wire;
		end
	end

	assign	adc_frame = adc_frame_reg;
	assign	adc_data = adc_data_reg;

endmodule
