//+FHDR--------------------------------------------------------------------------------------------------------
//  Company: 
//-----------------------------------------------------------------------------------------------------------------
//  File Name             :    TailCorr_top.v
//  Department            :    
//  Author                :    thfu
//  Author's Tel          :     
//-----------------------------------------------------------------------------------------------------------------
//  Relese History
//  Version     Date            Author          Description
//  0.3        2024-05-15      thfu
//-----------------------------------------------------------------------------------------------------------------
//  Keywords            :       
//
//-----------------------------------------------------------------------------------------------------------------
//  Parameter
//
//-----------------------------------------------------------------------------------------------------------------
//  Purpose                 :
//                      
//-----------------------------------------------------------------------------------------------------------------
//  Target Device:        
//  Tool versions:        
//-----------------------------------------------------------------------------------------------------------------
//  Reuse Issues
//  Reset Strategy: 
//  Clock Domains: 
//  Critical Timing:
//  Asynchronous I/F:
//  Synthesizable (y/n): 
//  Other:
//-FHDR--------------------------------------------------------------------------------------------------------

module 	TailCorr_top	 	

(
		 	clk,
		 	rstn,
		 	en, 	
		 	vldi, 	
		 	tc_bypass, 		
		 	din,	
			a0_re,
			a0_im,
			ab0_re,
			ab0_im,
			bb0_re,
			bb0_im,
			a1_re,
			a1_im,
			ab1_re,
			ab1_im,
			bb1_re,
			bb1_im,
			a2_re,
			a2_im,
			ab2_re,
			ab2_im,
			bb2_re,
			bb2_im,
			a3_re,
			a3_im,
			ab3_re,
			ab3_im,
			bb3_re,
			bb3_im,
			a4_re,
			a4_im,
			ab4_re,
			ab4_im,
			bb4_re,
			bb4_im,
			a5_re,
			a5_im,
			ab5_re,
			ab5_im,
			bb5_re,
			bb5_im,
			dout
		 	);		

input rstn;
input clk;
input  en;
input  vldi;
input  tc_bypass;
input  signed [15:0] din;
input  signed [31:0] a0_re;
input  signed [31:0] a0_im;
input  signed [31:0] ab0_re;
input  signed [31:0] ab0_im;
input  signed [31:0] bb0_re;
input  signed [31:0] bb0_im;
input  signed [31:0] a1_re;
input  signed [31:0] a1_im;
input  signed [31:0] ab1_re;
input  signed [31:0] ab1_im;
input  signed [31:0] bb1_re;
input  signed [31:0] bb1_im;
input  signed [31:0] a2_re;
input  signed [31:0] a2_im;
input  signed [31:0] ab2_re;
input  signed [31:0] ab2_im;
input  signed [31:0] bb2_re;
input  signed [31:0] bb2_im;
input  signed [31:0] a3_re;
input  signed [31:0] a3_im;
input  signed [31:0] ab3_re;
input  signed [31:0] ab3_im;
input  signed [31:0] bb3_re;
input  signed [31:0] bb3_im;
input  signed [31:0] a4_re;
input  signed [31:0] a4_im;
input  signed [31:0] ab4_re;
input  signed [31:0] ab4_im;
input  signed [31:0] bb4_re;
input  signed [31:0] bb4_im;
input  signed [31:0] a5_re;
input  signed [31:0] a5_im;
input  signed [31:0] ab5_re;
input  signed [31:0] ab5_im;
input  signed [31:0] bb5_re;
input  signed [31:0] bb5_im;
output signed [15:0] dout;


wire signed	[15:0] IIRin;
wire signed	[15:0] dout_0;
wire signed	[15:0] dout_1;
wire signed	[15:0] dout_2;
wire signed	[15:0] dout_3;
wire signed	[15:0] dout_4;
wire signed	[15:0] dout_5;
wire signed	[18:0] Ysum;

reg signed [15:0] dout_r;

reg [15:0]  din_p0;
reg [15:0]  din_p1;
s2p_2 inst_s2p_2 (
        .clk    (clk),
        .rst_n  (rstn),
        .din    (din),
        .en   (vldi),
        .dout0 (din_p0),
        .dout1 (din_p1)
    );

reg  signed [15:0]		    din_p0_r1;
reg  signed [15:0]		    din_p0_r2;
reg  signed [15:0]		    din_p0_r3;
reg  signed [15:0]		    din_p0_r4;
reg  signed [15:0]		    din_p0_r5;
reg  signed [15:0]		    din_p0_r6;

always @(posedge clk or negedge rstn) 
  	if (!rstn)
		 begin
		    din_p0_r1  <= 'h0;
		    din_p0_r2  <= 'h0;
		    din_p0_r3  <= 'h0;
		    din_p0_r4  <= 'h0;
		    din_p0_r5  <= 'h0;
		    din_p0_r6  <= 'h0;
		 end 
	 else if(en)
		 begin
		    din_p0_r1  <= din_p0;
		    din_p0_r2  <= din_p0_r1;
		    din_p0_r3  <= din_p0_r2;
		    din_p0_r4  <= din_p0_r3;
		    din_p0_r5  <= din_p0_r4;
		    din_p0_r6  <= din_p0_r5;
		  end
	 else
		 begin
		    din_p0_r1  <= din_p0_r1;
		    din_p0_r2  <= din_p0_r2;
		    din_p0_r3  <= din_p0_r3;
		    din_p0_r4  <= din_p0_r4;
		    din_p0_r5  <= din_p0_r5;
		    din_p0_r6  <= din_p0_r6;
		  end

reg  signed [15:0]		    din_p1_r1;
reg  signed [15:0]		    din_p1_r2;
reg  signed [15:0]		    din_p1_r3;
reg  signed [15:0]		    din_p1_r4;
reg  signed [15:0]		    din_p1_r5;
reg  signed [15:0]		    din_p1_r6;

always @(posedge clk or negedge rstn) 
  	if (!rstn)
		 begin
		    din_p1_r1  <= 'h0;
		    din_p1_r2  <= 'h0;
		    din_p1_r3  <= 'h0;
		    din_p1_r4  <= 'h0;
		    din_p1_r5  <= 'h0;
		    din_p1_r6  <= 'h0;
		 end 
	 else if(en)
		 begin
		    din_p1_r1  <= din_p1;
		    din_p1_r2  <= din_p1_r1;
		    din_p1_r3  <= din_p1_r2;
		    din_p1_r4  <= din_p1_r3;
		    din_p1_r5  <= din_p1_r4;
		    din_p1_r6  <= din_p1_r5;
		  end
	 else
		 begin
		    din_p1_r1  <= din_p1_r1;
		    din_p1_r2  <= din_p1_r2;
		    din_p1_r3  <= din_p1_r3;
		    din_p1_r4  <= din_p1_r4;
		    din_p1_r5  <= din_p1_r5;
		    din_p1_r6  <= din_p1_r6;
		  end

wire  signed [15:0] IIRin_p0;
wire  signed [15:0] IIRin_p1;
assign  IIRin_p0 = din_p0 - din_p1_r1;
assign  IIRin_p1 = din_p1 - din_p0;

reg [15:0] IIRin_p0_r1;
reg [15:0] IIRin_p0_r2;
always  @(posedge clk or negedge rstn)begin
if(rstn==1'b0)begin
    IIRin_p0_r1 <= 0;
    IIRin_p0_r2 <= 0;
end
else if(en)begin
    IIRin_p0_r1 <= IIRin_p0;
    IIRin_p0_r2 <= IIRin_p0_r1;
end
else begin
    IIRin_p0_r1 <= IIRin_p0_r1;
    IIRin_p0_r2 <= IIRin_p0_r2;
end
end

reg [15:0] IIRin_p1_r1;
reg [15:0] IIRin_p1_r2;
always  @(posedge clk or negedge rstn)begin
if(rstn==1'b0)begin
    IIRin_p1_r1 <= 0;
    IIRin_p1_r2 <= 0;
end
else if(en)begin
    IIRin_p1_r1 <= IIRin_p1;
    IIRin_p1_r2 <= IIRin_p1_r1;
end
else begin
    IIRin_p1_r1 <= IIRin_p1_r1;
    IIRin_p1_r2 <= IIRin_p1_r2;
end
end

wire signed	[15:0] IIRout0_p0;
wire signed	[15:0] IIRout0_p1;
wire signed	[15:0] IIRout1_p0;
wire signed	[15:0] IIRout1_p1;
wire signed	[15:0] IIRout2_p0;
wire signed	[15:0] IIRout2_p1;
wire signed	[15:0] IIRout3_p0;
wire signed	[15:0] IIRout3_p1;
wire signed	[15:0] IIRout4_p0;
wire signed	[15:0] IIRout4_p1;
wire signed	[15:0] IIRout5_p0;
wire signed	[15:0] IIRout5_p1;

IIR_Filter_p2	inst_iir_0_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a0_re			),
					.a_im			(a0_im			),
					.ab_re			(ab0_re			),
					.ab_im			(ab0_im			),
					.bb_re			(bb0_re			),
					.bb_im			(bb0_im			),
					.dout                   (IIRout0_p0                 )
			   );

IIR_Filter_p2	inst_iir_0_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a0_re			),
					.a_im			(a0_im			),
					.ab_re			(ab0_re			),
					.ab_im			(ab0_im			),
					.bb_re			(bb0_re			),
					.bb_im			(bb0_im			),
					.dout                   (IIRout0_p1                 )
			   );
IIR_Filter_p2	inst_iir_1_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a1_re			),
					.a_im			(a1_im			),
					.ab_re			(ab1_re			),
					.ab_im			(ab1_im			),
					.bb_re			(bb1_re			),
					.bb_im			(bb1_im			),
					.dout                   (IIRout1_p0                 )
			   );

IIR_Filter_p2	inst_iir_1_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a1_re			),
					.a_im			(a1_im			),
					.ab_re			(ab1_re			),
					.ab_im			(ab1_im			),
					.bb_re			(bb1_re			),
					.bb_im			(bb1_im			),
					.dout                   (IIRout1_p1                 )
			   );
IIR_Filter_p2	inst_iir_2_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a2_re			),
					.a_im			(a2_im			),
					.ab_re			(ab2_re			),
					.ab_im			(ab2_im			),
					.bb_re			(bb2_re			),
					.bb_im			(bb2_im			),
					.dout                   (IIRout2_p0                 )
			   );

IIR_Filter_p2	inst_iir_2_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a2_re			),
					.a_im			(a2_im			),
					.ab_re			(ab2_re			),
					.ab_im			(ab2_im			),
					.bb_re			(bb2_re			),
					.bb_im			(bb2_im			),
					.dout                   (IIRout2_p1                 )
			   );
IIR_Filter_p2	inst_iir_3_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a3_re			),
					.a_im			(a3_im			),
					.ab_re			(ab3_re			),
					.ab_im			(ab3_im			),
					.bb_re			(bb3_re			),
					.bb_im			(bb3_im			),
					.dout                   (IIRout3_p0                 )
			   );

IIR_Filter_p2	inst_iir_3_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a3_re			),
					.a_im			(a3_im			),
					.ab_re			(ab3_re			),
					.ab_im			(ab3_im			),
					.bb_re			(bb3_re			),
					.bb_im			(bb3_im			),
					.dout                   (IIRout3_p1                 )
			   );
IIR_Filter_p2	inst_iir_4_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a4_re			),
					.a_im			(a4_im			),
					.ab_re			(ab4_re			),
					.ab_im			(ab4_im			),
					.bb_re			(bb4_re			),
					.bb_im			(bb4_im			),
					.dout                   (IIRout4_p0                 )
			   );

IIR_Filter_p2	inst_iir_4_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a4_re			),
					.a_im			(a4_im			),
					.ab_re			(ab4_re			),
					.ab_im			(ab4_im			),
					.bb_re			(bb4_re			),
					.bb_im			(bb4_im			),
					.dout                   (IIRout4_p1                 )
			   );
IIR_Filter_p2	inst_iir_5_p0 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p0		),
				 	.din_r1			(IIRin_p1_r2		),
					.a_re			(a5_re			),
					.a_im			(a5_im			),
					.ab_re			(ab5_re			),
					.ab_im			(ab5_im			),
					.bb_re			(bb5_re			),
					.bb_im			(bb5_im			),
					.dout                   (IIRout5_p0                 )
			   );

IIR_Filter_p2	inst_iir_5_p1 (
					.clk			(clk	                ),
					.rstn			(rstn			),
					.en			(en			),
				 	.din			(IIRin_p1		),
				 	.din_r1			(IIRin_p0		),
					.a_re			(a5_re			),
					.a_im			(a5_im			),
					.ab_re			(ab5_re			),
					.ab_im			(ab5_im			),
					.bb_re			(bb5_re			),
					.bb_im			(bb5_im			),
					.dout                   (IIRout5_p1                 )
			   );

wire signed [15:0] dout_p0;
wire signed [15:0] dout_p1;
assign  dout_p0  =  din_p0_r5 + IIRout0_p0+ IIRout1_p0+ IIRout2_p0+ IIRout3_p0+ IIRout4_p0+ IIRout5_p0;
assign  dout_p1  =  din_p1_r5 + IIRout0_p1+ IIRout1_p1+ IIRout2_p1+ IIRout3_p1+ IIRout4_p1+ IIRout5_p1;

always @(posedge clk or negedge rstn) 
  	if (!rstn)
		 begin
		    din_p0_r1  <= 'h0;
		    din_p0_r2  <= 'h0;
		    din_p0_r3  <= 'h0;
		    din_p0_r4  <= 'h0;
		    din_p0_r5  <= 'h0;
		    din_p0_r6  <= 'h0;
		 end 
	 else if(en)
		 begin
		    din_p0_r1  <= din_p0;
		    din_p0_r2  <= din_p0_r1;
		    din_p0_r3  <= din_p0_r2;
		    din_p0_r4  <= din_p0_r3;
		    din_p0_r5  <= din_p0_r4;
		    din_p0_r6  <= din_p0_r5;
		  end
	 else
		 begin
		    din_p0_r1  <= din_p0;
		    din_p0_r2  <= din_p0_r2;
		    din_p0_r3  <= din_p0_r3;
		    din_p0_r4  <= din_p0_r4;
		    din_p0_r5  <= din_p0_r5;
		    din_p0_r6  <= din_p0_r6;
		  end

always@(posedge clk or negedge rstn) 
    if (!rstn)begin
        dout_r     <= 'h0;
    end 
    else if(tc_bypass)begin
        dout_r     <= din;
    end
    else begin 
        if(en)  begin
            if(Ysum[16:15]==2'b01)
                dout_r	<=	16'd32767;
            else if(Ysum[16:15]==2'b10)
                dout_r	<=	-16'd32768;
            else
                dout_r	<=	Ysum[15:0];
            end
        else begin
            dout_r  <= dout_r;
        end
    end

assign	dout = dout_r;

endmodule

