`timescale 1ns / 1ps
(* keep_hierarchy = "yes" *)	
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 		Churbanov S.
// 
// Create Date:		15:22:20 12/08/2019 
// Design Name: 
// Module Name:		Win_parameters
// Project Name:	Compact_main
// Target Devices: 
// Tool versions: 
// Description: 	
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Win_calc	(
	input			clk_i,
	input			wind_clk,
	input	[7:0]	filterCmd_i,
	input			reset_i,
	input			WinCtrl_i,
	input			MeasWind_i,
	input	[1:0]	TukeyCtrl_i,
	input	[31:0]	win_value_i,
	input	[2:0]	win_type_i,	
	output	signed [17:0]	win_o
);
//================================================================================
//  REG/WIRE
//================================================================================
	
	reg			[3:0]	calc_cycle;
	reg	signed	[17:0]	a1;		
	reg signed	[17:0]	b; 	
	reg signed	[17:0]	c1;
	reg signed	[17:0]	c2;	
	wire 		[47:0]	p2;
	wire 		[47:0]	p1;	
	
	reg			signed	[17:0]	sinWind;
	reg			signed	[17:0]	tukeyWind;	
		
	reg	[1:0]	tukeyCtrlR;
	reg	[1:0]	tukeyCtrlRR;
	
	reg	[35:0]	sinWindPow2;
	
	wire	sinFilterFlag	=	(filterCmd_i>=8'h54	&	filterCmd_i<=8'h62);
	// wire	rectFilterFlag	=	(filterCmd_i>=8'h63	&	filterCmd_i!=8'h70)|filterCmd_i==8'h30;
	wire	rectFilterFlag	=	(filterCmd_i>=8'h63	&	filterCmd_i!=8'h70);
	
	wire	[17:0]	bSin	=	win_value_i[31]	?	18'h3FFFF	-	win_value_i[31:14]	:	win_value_i	[31:14];
	wire	[17:0]	bTukey	=	win_value_i[31]	?	18'h3FFFF	-	win_value_i[31:14]	:	win_value_i	[31:14];
	
	wire	[17:0]	bCurr	=	sinFilterFlag	?	bSin:bTukey;
	
	wire	signed	[17:0]	constOne	=	18'b011111111111111111;
	
	reg		signed	[18:0]	tukeyCorr;
	
	reg		[17:0]	tukeyWindOut;
	
	wire	signed [17:0]	windMux1;
	wire	signed [17:0]	windMux2;
//================================================================================
//  PARAMETERS
//================================================================================
	localparam	signed	A3_1	=	18'h15584;
// ????????? ??? ?????????? SIN
	localparam signed	[17:0]	A1	=	18'h12400;			// a-1
	localparam signed	[17:0]	A2	=	18'h002C0;			// b
	localparam signed	[17:0]	A3	=	~A3_1	+	1'b1;	// c
	localparam signed	[17:0]	A4	=	18'h0126C;			// d
	localparam signed	[17:0]	A5	=	18'h01C5C;			// e
	
//================================================================================
//  ASSIGNMENTS
// ================================================================================	

	// assign	win_o	=	(sinFilterFlag)	?	sinWindPow2[34-:18]:tukeyWindOut;
	
	assign	win_o		=	windMux2;
	
	assign	windMux1	=	(sinFilterFlag)	?	sinWindPow2[34-:18]:tukeyWindOut;
	assign	windMux2	=	(rectFilterFlag)?	18'h1ffff:windMux1;

// ================================================================================
//  CODING
//================================================================================	


always	@(posedge	clk_i)	begin
	if	(!reset_i)	begin
		tukeyCtrlR	<=	TukeyCtrl_i;
		tukeyCtrlRR	<=	tukeyCtrlR;
	end	else	begin
		tukeyCtrlR	<=	0;
		tukeyCtrlRR	<=	0;
	end
end

always	@(posedge	clk_i)	begin
	if	(!reset_i)	begin
		tukeyCorr	<=	(tukeyWind+constOne);
		sinWindPow2	<=	sinWind**2;
	end	else	begin
		tukeyCorr	<=	18'h0;
		sinWindPow2	<=	18'h0;
	end
end

always	@(*)	begin
	if	(!reset_i)	begin
		case(tukeyCtrlRR)
			2'h0:		begin
							tukeyWindOut	=	0;
						end
			2'h1:		begin
							tukeyWindOut	=	18'h1ffff;
						end
			2'h2:		begin
							tukeyWindOut	=	tukeyCorr[18-:18];
						end
			default:	begin
							tukeyWindOut	=	0;
						end
		endcase
	end	else	begin
		tukeyWindOut	=	18'h0;
	end
end

always	@(negedge	wind_clk)	begin
	if	(!reset_i)	begin
		// if	(MeasWind_i)	begin
			case	(calc_cycle)
				4'd1: 	
						begin
							a1	<=	A5;
							c1	<=	A4;
							c2	<=	A3;
							b	<=	bCurr;
						end
						
				4'd2:	
						begin
							a1	<=	p2[34:17];
							c1	<=	A2;
							c2	<=	A1;
						end
				4'd3:	
						begin
							a1	<=	p2[34:17];
							c1	<=	b;
						end
			endcase
		// end	else	begin
			// a1	<=	18'b0;
			// c1	<=	18'b0;
			// c2	<=	18'b0;
			// b	<=	18'b0;
		// end
	end	else	begin
		a1	<=	18'b0;
		c1	<=	18'b0;
		c2	<=	18'b0;
		b	<=	18'b0;
	end
end

// always	@(*)	begin
	// if	(!reset_i)	begin
		// if	(MeasWind_i)	begin
			// case	(calc_cycle)
				// 3'd1: 	
						// begin
							// a1	=	A5;
							// c1	=	A4;
							// c2	=	A3;
							// b	=	bCurr;
						// end
			// endcase
		// end	else	begin
			// a1	=	18'b0;
			// c1	=	18'b0;
			// c2	=	18'b0;
			// b	=	18'b0;
		// end
	// end	else	begin
		// a1	=	18'b0;
		// c1	=	18'b0;
		// c2	=	18'b0;
		// b	=	18'b0;
	// end
// end

		
always	@(posedge	wind_clk)	begin
	if	(!reset_i)	begin
		if	(!win_type_i)	begin 
			if (calc_cycle	==	3'd0) begin
				if	(p1[47:34]	==	0)	begin
					sinWind	<=	p1[34-:18];//1.0.17	
				end	else	begin
					sinWind	<=	18'h1FFFF;
				end
				
			end 
		end	else	begin
			sinWind		<=	18'h0;
		end
	end	else	begin
		sinWind		<=	18'h0;
	end
end

always	@(posedge	wind_clk)	begin
	if	(!reset_i)	begin
		if	(!win_type_i)	begin 
			if (calc_cycle	==	3'd0) begin
				if	(!WinCtrl_i)	begin
					tukeyWind	<=	p1[34-:18];
				end	else	begin
					tukeyWind	<=	0-p1[34-:18];
				end
			end 
		end	else	begin
			tukeyWind	<=	18'h0;
		end
	end	else	begin
		tukeyWind	<=	18'h0;
	end
end

//??????? "????? ??????? ????????". ????????  [(b*A5+A4) = p1 ? ????????????? ?????? (b*p1+A3)=p2] == 1 ????.

always	@(posedge	wind_clk)	begin
	if	(!reset_i)	begin
		if	(MeasWind_i)	begin
			if	(calc_cycle	!=	4'd3)	begin
				calc_cycle	<=	calc_cycle	+	4'd1;
			end	else	begin
				calc_cycle	<=	4'd0;
			end
		end	else	begin
			calc_cycle	<=	4'd0;
		end
	end	else	begin
		calc_cycle	<=	4'd0;
	end
end

DSP48E1 #(
      // Feature Control Attributes: Data Path Selection
      .A_INPUT("DIRECT"),               // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
      .B_INPUT("DIRECT"),               // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
      .USE_DPORT("FALSE"),              // Select D port usage (TRUE or FALSE)
      .USE_MULT("MULTIPLY"),            // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
      .USE_SIMD("ONE48"),               // SIMD selection ("ONE48", "TWO24", "FOUR12")
      // Pattern Detector Attributes: Pattern Detection Configuration
      .AUTORESET_PATDET("NO_RESET"),    // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH" 
      .MASK(48'h3fffffffffff),          // 48-bit mask value for pattern detect (1=ignore)
      .PATTERN(48'h000000000000),       // 48-bit pattern match for pattern detect
      .SEL_MASK("MASK"),                // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2" 
      .SEL_PATTERN("PATTERN"),          // Select pattern value ("PATTERN" or "C")
      .USE_PATTERN_DETECT("NO_PATDET"), // Enable pattern detect ("PATDET" or "NO_PATDET")
      // Register Control Attributes: Pipeline Register Configuration
      .ACASCREG(0),                     // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
      .ADREG(0),                        // Number of pipeline stages for pre-adder (0 or 1)
      .ALUMODEREG(0),                   // Number of pipeline stages for ALUMODE (0 or 1)
      .AREG(0),                         // Number of pipeline stages for A (0, 1 or 2)
      .BCASCREG(0),                     // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
      .BREG(0),                         // Number of pipeline stages for B (0, 1 or 2)
      .CARRYINREG(0),                   // Number of pipeline stages for CARRYIN (0 or 1)
      .CARRYINSELREG(0),                // Number of pipeline stages for CARRYINSEL (0 or 1)
      .CREG(0),                         // Number of pipeline stages for C (0 or 1)
      .DREG(0),                         // Number of pipeline stages for D (0 or 1)
      .INMODEREG(0),                    // Number of pipeline stages for INMODE (0 or 1)
      .MREG(0),                         // Number of multiplier pipeline stages (0 or 1)
      .OPMODEREG(0),                    // Number of pipeline stages for OPMODE (0 or 1)
      .PREG(1)                          // Number of pipeline stages for P (0 or 1)
   )
FirstStage (
      // Cascade: 30-bit (each) output: Cascade Ports
      .ACOUT(),                   // 30-bit output: A port cascade output
      .BCOUT(),                   // 18-bit output: B port cascade output
      .CARRYCASCOUT(),     // 1-bit output: Cascade carry output
      .MULTSIGNOUT(),       // 1-bit output: Multiplier sign cascade output
      .PCOUT(),                   // 48-bit output: Cascade output
      // Control: 1-bit (each) output: Control Inputs/Status Bits
      .OVERFLOW(),             // 1-bit output: Overflow in add/acc output
      .PATTERNBDETECT(), // 1-bit output: Pattern bar detect output
      .PATTERNDETECT(),   // 1-bit output: Pattern detect output
      .UNDERFLOW(),           // 1-bit output: Underflow in add/acc output
      // Data: 4-bit (each) output: Data Ports
      .CARRYOUT(),             // 4-bit output: Carry output
      .P(p1),                           // 48-bit output: Primary data output
      // Cascade: 30-bit (each) input: Cascade Ports
      .ACIN(),                     // 30-bit input: A cascade data input
      .BCIN(),                     // 18-bit input: B cascade input
      .CARRYCASCIN(),       // 1-bit input: Cascade carry input
      .MULTSIGNIN(),         // 1-bit input: Multiplier sign input
      .PCIN(48'b0),                     // 48-bit input: P cascade input
      // Control: 4-bit (each) input: Control Inputs/Status Bits
      .ALUMODE(4'b0000),               // 4-bit input: ALU control input
      .CARRYINSEL(3'b000),         // 3-bit input: Carry select input
      // .CLK(1'b0),                       // 1-bit input: Clock input
      .CLK(wind_clk),                       // 1-bit input: Clock input
      .INMODE(5'b00000),                 // 5-bit input: INMODE control input
      .OPMODE(7'b0110101),                 // 7-bit input: Operation mode input
      // Data: 30-bit (each) input: Data Ports
      .A({{12{a1[17]}},a1}),                           // 30-bit input: A data input
      .B(b),                           // 18-bit input: B data input
      .C({ {13{c1[17]}}, c1[17:0],17'b0 }),                           // 48-bit input: C data input
      .CARRYIN(1'b0),               // 1-bit input: Carry input signal
      .D(25'b0),                           // 25-bit input: D data input
      // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
      .CEA1(1'b1),                     // 1-bit input: Clock enable input for 1st stage AREG
      .CEA2(1'b1),                     // 1-bit input: Clock enable input for 2nd stage AREG
      .CEAD(1'b1),                     // 1-bit input: Clock enable input for ADREG
      .CEALUMODE(1'b1),           // 1-bit input: Clock enable input for ALUMODE
      .CEB1(1'b1),                     // 1-bit input: Clock enable input for 1st stage BREG
      .CEB2(1'b1),                     // 1-bit input: Clock enable input for 2nd stage BREG
      .CEC(1'b1),                       // 1-bit input: Clock enable input for CREG
      .CECARRYIN(1'b1),           // 1-bit input: Clock enable input for CARRYINREG
      .CECTRL(1'b1),                 // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
      .CED(1'b1),                       // 1-bit input: Clock enable input for DREG
      .CEINMODE(1'b1),             // 1-bit input: Clock enable input for INMODEREG
      .CEM(1'b0),                       // 1-bit input: Clock enable input for MREG
      .CEP(1'b1),                       // 1-bit input: Clock enable input for PREG
      .RSTA(1'b0),                     // 1-bit input: Reset input for AREG
      .RSTALLCARRYIN(1'b0),   // 1-bit input: Reset input for CARRYINREG
      .RSTALUMODE(1'b0),         // 1-bit input: Reset input for ALUMODEREG
      .RSTB(1'b0),                     // 1-bit input: Reset input for BREG
      .RSTC(1'b0),                     // 1-bit input: Reset input for CREG
      .RSTCTRL(1'b0),               // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
      .RSTD(1'b0),                     // 1-bit input: Reset input for DREG and ADREG
      .RSTINMODE(1'b0),           // 1-bit input: Reset input for INMODEREG
      .RSTM(reset_i),                     // 1-bit input: Reset input for MREG
      .RSTP(reset_i)                      // 1-bit input: Reset input for PREG
);
   
DSP48E1 #(
      // Feature Control Attributes: Data Path Selection
      .A_INPUT("DIRECT"),               // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
      .B_INPUT("DIRECT"),               // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
      .USE_DPORT("FALSE"),              // Select D port usage (TRUE or FALSE)
      .USE_MULT("MULTIPLY"),            // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
      .USE_SIMD("ONE48"),               // SIMD selection ("ONE48", "TWO24", "FOUR12")
      // Pattern Detector Attributes: Pattern Detection Configuration
      .AUTORESET_PATDET("NO_RESET"),    // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH" 
      .MASK(48'h1),          // 48-bit mask value for pattern detect (1=ignore)
      .PATTERN(48'h000000000000),       // 48-bit pattern match for pattern detect
      .SEL_MASK("MASK"),                // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2" 
      .SEL_PATTERN("PATTERN"),          // Select pattern value ("PATTERN" or "C")
      .USE_PATTERN_DETECT("NO_PATDET"), // Enable pattern detect ("PATDET" or "NO_PATDET")
      // Register Control Attributes: Pipeline Register Configuration
      .ACASCREG(0),                     // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
      .ADREG(0),                        // Number of pipeline stages for pre-adder (0 or 1)
      .ALUMODEREG(0),                   // Number of pipeline stages for ALUMODE (0 or 1)
      .AREG(0),                         // Number of pipeline stages for A (0, 1 or 2)
      .BCASCREG(0),                     // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
      .BREG(0),                         // Number of pipeline stages for B (0, 1 or 2)
      .CARRYINREG(0),                   // Number of pipeline stages for CARRYIN (0 or 1)
      .CARRYINSELREG(0),                // Number of pipeline stages for CARRYINSEL (0 or 1)
      .CREG(0),                         // Number of pipeline stages for C (0 or 1)
      .DREG(0),                         // Number of pipeline stages for D (0 or 1)
      .INMODEREG(0),                    // Number of pipeline stages for INMODE (0 or 1)
      .MREG(0),                         // Number of multiplier pipeline stages (0 or 1)
      .OPMODEREG(0),                    // Number of pipeline stages for OPMODE (0 or 1)
      .PREG(0)                          // Number of pipeline stages for P (0 or 1)
   )
SecondStage (
      // Cascade: 30-bit (each) output: Cascade Ports
      .ACOUT(),                   // 30-bit output: A port cascade output
      .BCOUT(),                   // 18-bit output: B port cascade output
      .CARRYCASCOUT(),     // 1-bit output: Cascade carry output
      .MULTSIGNOUT(),       // 1-bit output: Multiplier sign cascade output
      .PCOUT(),                   // 48-bit output: Cascade output
      // Control: 1-bit (each) output: Control Inputs/Status Bits
      .OVERFLOW(),             // 1-bit output: Overflow in add/acc output
      .PATTERNBDETECT(), // 1-bit output: Pattern bar detect output
      .PATTERNDETECT(),   // 1-bit output: Pattern detect output
      .UNDERFLOW(),           // 1-bit output: Underflow in add/acc output
      // Data: 4-bit (each) output: Data Ports
      .CARRYOUT(),             // 4-bit output: Carry output
      .P(p2),                           // 48-bit output: Primary data output
      // Cascade: 30-bit (each) input: Cascade Ports
      .ACIN(),                     // 30-bit input: A cascade data input
      .BCIN(),                     // 18-bit input: B cascade input
      .CARRYCASCIN(),       // 1-bit input: Cascade carry input
      .MULTSIGNIN(),         // 1-bit input: Multiplier sign input
      .PCIN(48'b0),                     // 48-bit input: P cascade input
      // Control: 4-bit (each) input: Control Inputs/Status Bits
      .ALUMODE(4'b0000),               // 4-bit input: ALU control input
      .CARRYINSEL(3'b000),         // 3-bit input: Carry select input
      .CLK(1'b0),                       // 1-bit input: Clock input
      // .CLK(wind_clk),                       // 1-bit input: Clock input
      .INMODE(5'b00000),                 // 5-bit input: INMODE control input
      .OPMODE(7'b0110101),                 // 7-bit input: Operation mode input
      // Data: 30-bit (each) input: Data Ports
      .A({{12{p1[47]}},p1[34:17]}),                           // 30-bit input: A data input
      .B(b),                           // 18-bit input: B data input
      .C({ {13{c2[17]}}, c2[17:0],17'b0 }),                           // 48-bit input: C data input
      .CARRYIN(1'b0),               // 1-bit input: Carry input signal
      .D(25'b0),                           // 25-bit input: D data input
      // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
      .CEA1(1'b1),                     // 1-bit input: Clock enable input for 1st stage AREG
      .CEA2(1'b1),                     // 1-bit input: Clock enable input for 2nd stage AREG
      .CEAD(1'b1),                     // 1-bit input: Clock enable input for ADREG
      .CEALUMODE(1'b1),           // 1-bit input: Clock enable input for ALUMODE
      .CEB1(1'b1),                     // 1-bit input: Clock enable input for 1st stage BREG
      .CEB2(1'b1),                     // 1-bit input: Clock enable input for 2nd stage BREG
      .CEC(1'b1),                       // 1-bit input: Clock enable input for CREG
      .CECARRYIN(1'b1),           // 1-bit input: Clock enable input for CARRYINREG
      .CECTRL(1'b1),                 // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
      .CED(1'b1),                       // 1-bit input: Clock enable input for DREG
      .CEINMODE(1'b1),             // 1-bit input: Clock enable input for INMODEREG
      .CEM(1'b0),                       // 1-bit input: Clock enable input for MREG
      .CEP(1'b0),                       // 1-bit input: Clock enable input for PREG
      .RSTA(1'b0),                     // 1-bit input: Reset input for AREG
      .RSTALLCARRYIN(1'b0),   // 1-bit input: Reset input for CARRYINREG
      .RSTALUMODE(1'b0),         // 1-bit input: Reset input for ALUMODEREG
      .RSTB(1'b0),                     // 1-bit input: Reset input for BREG
      .RSTC(1'b0),                     // 1-bit input: Reset input for CREG
      .RSTCTRL(1'b0),               // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
      .RSTD(1'b0),                     // 1-bit input: Reset input for DREG and ADREG
      .RSTINMODE(1'b0),           // 1-bit input: Reset input for INMODEREG
      .RSTM(reset_i),                     // 1-bit input: Reset input for MREG
      .RSTP(reset_i)                      // 1-bit input: Reset input for PREG
);

endmodule
