module CicFilterNewWrapperNoIntDiff #(
    parameter InDataWidth       = 14,
    parameter N                 = 4, // Number of stages
    parameter M                 = 1, // Differential delay
    parameter DECIM_WIDTH       = 4, // Decimation factor width
    parameter MAX_DECIM_FACTOR  = 16,
    parameter integer INTER_DATA_WIDTH  = $ceil(N*$clog2(M*MAX_DECIM_FACTOR)) + InDataWidth
)
(
    input logic 								    Clk_i,
    input logic 			[DECIM_WIDTH-1:0]       DecimFactor_i, // Decimation factor (1, 2, 4, 8)
	input logic                     			    Rst_i,

    input logic                     			    DataVal_i,
    input logic 	signed	[InDataWidth-1:0]       Data_i,

    output logic 								    DataVal_o,
    output logic 	signed	[15:0] 	                Data_o
);
//======================================================================================
//								REG/WIRE
//======================================================================================
/* Integrator Block */
logic signed					[INTER_DATA_WIDTH-1:0] 	integratedDataIn 	    [N-1:0];
logic 										            integratedDataValIn     [N-1:0];
logic signed					[INTER_DATA_WIDTH-1:0] 	integratedDataOut 	    [N-1:0];
logic 											        integratedValOut 	    [N-1:0];
/* Decim Block */
logic signed 				    [INTER_DATA_WIDTH-1:0] 	decimDataOut;
logic 											        decimDataValOut;
/* Comb Filter Block */
logic signed					[INTER_DATA_WIDTH-1:0] 	combDataIn			    [N-1:0];
logic 											        combDataValIn		    [N-1:0];
logic signed					[INTER_DATA_WIDTH-1:0] 	combDataOut			    [N-1:0];
logic 											        combDataValOut		    [N-1:0];

/* ShTest */
logic signed					[InDataWidth-1:0] 	shTest;
/* Current MSB_POS */
logic                           [31:0]              currentMsbPos; 

//======================================================================================
//								ASSIGNMENTS
//======================================================================================
assign Data_o 		= combDataOut[N-1][currentMsbPos-1-:16];
assign DataVal_o 	= combDataValOut[N-1];

//======================================================================================
//								CODING
//======================================================================================
genvar i;
/* Integrators */
generate
    for (i = 0; i < N; i++) begin : gen_integrators
    
        assign integratedDataIn[i] = (i == 0) ? Data_i : integratedDataOut[i-1];
        assign integratedDataValIn[i] = (i == 0) ? DataVal_i : integratedValOut[i-1];

        CicIntegrator #(
            .InDataWidth    (INTER_DATA_WIDTH),
            .OutDataWidth   (INTER_DATA_WIDTH)
        ) integrator_inst (
            .Clk_i          (Clk_i),
            .Rst_i          (Rst_i),
            .Data_i         (integratedDataIn[i]),
            .DataVal_i      (integratedDataValIn[i]),
            .Data_o         (integratedDataOut[i]),
            .DataVal_o      (integratedValOut[i])
        );
    end
endgenerate

/* Decimation */
CicDecimator #(
    .InDataWidth			(INTER_DATA_WIDTH),
    .DECIM_WIDTH			(DECIM_WIDTH)
) decimator_inst (
    .Clk_i          		(Clk_i),
    .Rst_i          		(Rst_i),
    .DecimFactor_i  		(DecimFactor_i),
    .DataVal_i      		(integratedValOut[N-1]),
    .Data_i         		(integratedDataOut[N-1]),
    .DataVal_o      		(decimDataValOut),
    .Data_o         		(decimDataOut)
);

genvar j;
/* Comb Filters */
generate
    for (j = 0; j < N; j++) begin : gen_comb_filters

        assign combDataIn[j] = (j == 0) ? decimDataOut : combDataOut[j-1];
        assign combDataValIn[j] = (j == 0) ? decimDataValOut : combDataValOut[j-1];

        CicCombFilter #(
            .InOutDataWidth (INTER_DATA_WIDTH),
            .M              (M)
        ) comb_filter_inst (
            .Clk_i          (Clk_i),
            .Rst_i          (Rst_i),
            .DataVal_i      (combDataValIn[j]),
            .Data_i         (combDataIn[j]),
            .DataVal_o      (combDataValOut[j]),
            .Data_o         (combDataOut[j])
        );
    end
endgenerate

always_comb begin 
    case (DecimFactor_i)
    2: currentMsbPos = CoeffsR2pkg::MSB_POS;
    4: currentMsbPos = CoeffsR4pkg::MSB_POS;
    8: currentMsbPos = CoeffsR8pkg::MSB_POS;
    default : currentMsbPos = 16;
    endcase
end

endmodule