module cicFilter 
#(
	parameter N = 2,	//filter order
	parameter M = 1,	//comb delay
	// parameter R = 4,	//decim fartor
	parameter	filteredDataWidth	=	28,
	parameter	inOutDataWidth	=	16,
	parameter	decimCntWidth	=	7
)
(
	input Clk_i,
	input Rst_i,
	input [2:0]	DecimFactor_i,
	input [inOutDataWidth-1:0] Data_i,
	input DataNd_i,
	output [filteredDataWidth-1:0] Data_o,
	output DataValid_o
);
	
wire	[filteredDataWidth-1:0]	inData	[N-1:0];

wire	[filteredDataWidth-1:0]	intFilteredData	[N-1:0];
wire	intFilteredDataValid	[N-1:0];
wire	intDataVal	[N-1:0];

wire	[filteredDataWidth-1:0]	decimIntData;
wire	decimIntDataValid;

wire	[filteredDataWidth-1:0]	combFilteredData	[N-1:0];
wire	[filteredDataWidth-1:0]	combInData	[N-1:0];
wire	combDataVal	[N-1:0];
wire	combFilteredDataVal	[N-1:0];

genvar i,j;
generate 
	for (i=0; i<N; i=i+1)	begin: IntFilterGen
	
		// assign	inData	[i]		=	(i==0)?{{filteredDataWidth-inOutDataWidth{Data_i[inOutDataWidth-1]}},Data_i}:intFilteredData[i-1][filteredDataWidth-1-:filteredDataWidth];
		assign	inData	[i]		=	(i==0)?Data_i:intFilteredData[i-1];
		assign	intDataVal[i]	=	(i==0)?DataNd_i:intFilteredDataValid[i-1];
		
		intFilterWrapper
		#(
			.filteredDataWidth	(filteredDataWidth),
			.inOutDataWidth		(filteredDataWidth)
		)
		intFilterWrapperInst
		(
			.Clk_i		(Clk_i),
			.Data_i		(inData[i]),
			.DataNd_i	(intDataVal[i]),
			.Data_o		(intFilteredData[i]),
			.DataValid_o(intFilteredDataValid[i])
		);
	end
	
		decimBlock
		#(	
			// .R	(R),
			.inOutDataWidth	(filteredDataWidth),
			.decimCntWidth	(decimCntWidth)
		)
		decimBlockInst
		(
			.Clk_i			(Clk_i),
			.Rst_i			(Rst_i),
			.DecimFactor_i	(DecimFactor_i),
			.Data_i			(intFilteredData[N-1]),
			.DataNd_i		(intFilteredDataValid[N-1]),
			.Data_o			(decimIntData),
			.DataValid_o	(decimIntDataValid)
		);	

	
	for (j=0; j<N; j=j+1)	begin: CombFilterGen
	
		assign	combInData	[j]	=	(j==0)?decimIntData:combFilteredData[j-1];
		assign	combDataVal	[j]	=	(j==0)?decimIntDataValid:combFilteredDataVal[j-1];
		
		combFilterWrapper
		#(
			.M (M),
			.filteredDataWidth	(filteredDataWidth),
			.inOutDataWidth		(filteredDataWidth)
		)
		combFilterWrapperInst
		(
			.Clk_i		(Clk_i),
			.Rst_i		(Rst_i),
			.Data_i		(combInData[j]),
			.DataNd_i	(combDataVal[j]),
			.Data_o		(combFilteredData[j]),
			.DataValid_o(combFilteredDataVal[j])
		);
	end
endgenerate

assign	Data_o	=	combFilteredData[N-1];
assign	DataValid_o	=	combFilteredDataVal[N-1];
endmodule