`timescale 1ns / 1ps
(* keep_hierarchy = "yes" *)
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:00:25 07/10/2019 
// Design Name: 
// Module Name:    internal_dsp 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module InternalDsp	
#(	
	parameter	AdcDataWidth		=	14,	
	parameter	WindWidth			=	18,
	parameter	WindNcoPhIncWidth	=	32,
	parameter	NcoWidth			=	18,
	parameter	ChNum				=	4,
	parameter	ResultWidth			=	32,
	parameter	WinTypeWidth		=	3,
	parameter	BandCmdWidth		=	8,
	parameter	WindPNumWidth		=	32,
	parameter	WindNormCoefWidth	=	32,
	parameter	WindCorrCoefWidth	=	32,
	parameter	CmdDataRegWith		=	24,
	parameter	IntermediateWidth	=	18,
	parameter	CorrAdcDataWidth	=	20,
	parameter	AccWidth			=	80,
	parameter	[8:0]	MaxAddr		=	9'h190
)
(
	input	wire	Clk_i,
	input	wire	WindCalcClk_i,
	input	wire	Rst_i,
	input	wire	NcoRst_i,
	output	wire	OscWind_o,
	
	input	wire	[AdcDataWidth-1:0]	Adc1ChT1Data_i,	//A
	input	wire	[AdcDataWidth-1:0]	Adc1ChR1Data_i,	//R1
	input	wire	[AdcDataWidth-1:0]	Adc2ChR2Data_i,	//R2
	input	wire	[AdcDataWidth-1:0]	Adc2ChT2Data_i,	//B	
	
	input	wire	GatingPulse_i,
	
	input	wire	StartMeas_i,
	input	wire	StartMeasDsp_i,
	input	wire	OscDataRdFlag_i,
	
	input	wire	[32-1:0]	MeasNum_i,
	
	input	wire	[CmdDataRegWith-1:0]	MeasCtrl_i,
	input	wire	[CmdDataRegWith-1:0]	FilterCorrCoefL_i,
	input	wire	[CmdDataRegWith-1:0]	FilterCorrCoefH_i,
	
	output	wire	EndMeas_o,
	
	input	wire	CalModeEn_i,
	output	wire	CalModeDone_o,

	input	wire	[CmdDataRegWith-1:0]	IfFtwL_i,
	input	wire	[CmdDataRegWith-1:0]	IfFtwH_i,
	
	output	wire	[ResultWidth-1:0]	Adc1ImT1Data_o,
	output	wire	[ResultWidth-1:0]	Adc1ReT1Data_o,
	output	wire	[ResultWidth-1:0]	Adc1ImR1Data_o,
	output	wire	[ResultWidth-1:0]	Adc1ReR1Data_o,
	//adc2                 
	output	wire	[ResultWidth-1:0]	Adc2ImR2Data_o,
	output	wire	[ResultWidth-1:0]	Adc2ReR2Data_o,
	output	wire	[ResultWidth-1:0]	Adc2ImT2Data_o,
	output	wire	[ResultWidth-1:0]	Adc2ReT2Data_o,
	
	output	wire	[NcoWidth-1:0]	NcoSin_o,
	output	wire	[NcoWidth-1:0]	NcoCos_o,
	
	output	wire	MeasDataRdy_o,
	output	wire	MeasWind_o,
	output	wire	MeasEnd_o,
	output	wire	SampleStrobeGenRst_o
);

//================================================================================
//  REG/WIRE
	wire	[WindNormCoefWidth-1:0]	windNormCoef;
	wire	[WindPNumWidth-1:0]		windPointsNum;
	wire	[WindPNumWidth-1:0]		averageNoizeLvl;
	wire	[WindNcoPhIncWidth-1:0]	windPhInc;
	wire	[WindNcoPhIncWidth-1:0]	winPhIncStart;
	
	wire	[WindWidth-1:0]	wind;			

	wire	[NcoWidth-1:0]	ncoCosFirstTone;
	wire	[NcoWidth-1:0]	ncoSinFirstTone;
	
	wire	[NcoWidth-1:0]	ncoCosSecondTone;
	wire	[NcoWidth-1:0]	ncoSinSecondTone;
	
	wire	[CorrAdcDataWidth-1:0]	adcDataBus	[ChNum-1:0];
	wire	[CorrAdcDataWidth-1:0]	adcDataBusExt	[ChNum-1:0];
	wire	[CorrAdcDataWidth-1:0]	gatedAdcDataBus	[ChNum-1:0];
	wire	[CorrAdcDataWidth-1:0]	calAdcData		[ChNum-1:0];
	wire	[CorrAdcDataWidth-1:0]	prngData;
	reg		[CorrAdcDataWidth-1:0]	prngDataBus		[ChNum-1:0];
	wire	[ChNum-1:0]	calDone;
	
	genvar g;
	integer i;
	
	wire	[ResultWidth-1:0]	resultImBus		[ChNum-1:0];
	wire	[ResultWidth-1:0]	resultReBus		[ChNum-1:0];
	wire	[ChNum-1:0]	resultValBus;
	
	wire	measWind;
	wire	measWindDelayed;
	wire	stopMeas;
	wire	[1:0]	tukeyCtrl;
	
	reg		[CmdDataRegWith-1:0]	measCtrlReg;
	reg		[32-1:0]	windPointsNumReg;
	reg		[32-1:0]	measNumReg;
	reg		[WindCorrCoefWidth-1:0]	filterCorrCoeffReg;
	reg		[CmdDataRegWith-1:0]	ifFtwLReg;
	reg		[CmdDataRegWith-1:0]	ifFtwHReg;
	reg		[CmdDataRegWith-1:0]	filterCorrCoefLReg;
	reg		[CmdDataRegWith-1:0]	filterCorrCoefHReg;
	
	wire	[31:0]	windArg;
	
	wire	[CorrAdcDataWidth-1:0]	adc1ChT1DataGated	=	(GatingPulse_i)?	adcDataBusExt[ChNum-4]:{CorrAdcDataWidth{1'b0}};
	wire	[CorrAdcDataWidth-1:0]	adc1ChR1DataGated	=	(GatingPulse_i)?	adcDataBusExt[ChNum-3]:{CorrAdcDataWidth{1'b0}};
	wire	[CorrAdcDataWidth-1:0]	adc2ChR2DataGated	=	(GatingPulse_i)?	adcDataBusExt[ChNum-2]:{CorrAdcDataWidth{1'b0}};
	wire	[CorrAdcDataWidth-1:0]	adc2ChT2DataGated	=	(GatingPulse_i)?	adcDataBusExt[ChNum-1]:{CorrAdcDataWidth{1'b0}};	
	
	wire	[WindNcoPhIncWidth-1:0]	ncoPhInc = {ifFtwHReg[0+:WindNcoPhIncWidth-CmdDataRegWith],ifFtwLReg};
	
	reg		[8:0]	memAddrFirstTone;
	wire	[8:0]	memAddrNextFirstTone;
	wire	[8:0]	memAddrNext_pFirstTone;									//аргументы для расчета следующего значения
	wire	[9:0]	memAddrNext_mFirstTone;									//аргументы для расчета следующего значения
	
	reg		[8:0]	memAddrSecondTone;
	wire	[8:0]	memAddrNextSecondTone;
	wire	[8:0]	memAddrNext_pSecondTone;									//аргументы для расчета следующего значения
	wire	[9:0]	memAddrNext_mSecondTone;									//аргументы для расчета следующего значения
	
	wire	[8:0]	addrStepFirstTone	=	9'h50;
	wire	[8:0]	addrStepSecondTone	=	9'h64;
	
	wire	[35:0]	firstToneSinCosValues;
	wire	[35:0]	secondToneSinCosValues;
	
	wire	[17:0]	sinFirstTone	=	firstToneSinCosValues [35:18];			//выделяем из вычитаных данных, значение Cos
	wire	[17:0]	cosFirstTone	=	firstToneSinCosValues [17:0];			//выделяем из вычитаных данных, значение Sin
	
	wire	[17:0]	sinSecondTone	=	secondToneSinCosValues [35:18];			//выделяем из вычитаных данных, значение Cos
	wire	[17:0]	cosSecondTone	=	secondToneSinCosValues [17:0];			//выделяем из вычитаных данных, значение Sin
//================================================================================
//  ASSIGNMENTS

	// assign	adcDataBus	[ChNum-1]	=	18'h0;
	// assign	adcDataBus	[ChNum-2]	=	18'h0;
	// assign	adcDataBus	[ChNum-3]	=	18'h0;
	// assign	adcDataBus	[ChNum-4]	=	{{2{Adc1ChT1Data_i[AdcDataWidth-1]}},Adc1ChT1Data_i,4'b0};	//T2
		
	assign	adcDataBus	[ChNum-1]	=	{{2{Adc1ChR1Data_i[AdcDataWidth-1]}},Adc1ChR1Data_i,4'b0};
	assign	adcDataBus	[ChNum-2]	=	{{2{Adc2ChR2Data_i[AdcDataWidth-1]}},Adc2ChR2Data_i,4'b0};
	assign	adcDataBus	[ChNum-3]	=	{{2{Adc2ChT2Data_i[AdcDataWidth-1]}},Adc2ChT2Data_i,4'b0};
	assign	adcDataBus	[ChNum-4]	=	{{2{Adc1ChT1Data_i[AdcDataWidth-1]}},Adc1ChT1Data_i,4'b0};
	
	assign	adcDataBusExt	[ChNum-1]	=	calAdcData	[ChNum-1]+prngDataBus[ChNum-1];
	assign	adcDataBusExt	[ChNum-2]	=	calAdcData	[ChNum-2]+prngDataBus[ChNum-2];
	assign	adcDataBusExt	[ChNum-3]	=	calAdcData	[ChNum-3]+prngDataBus[ChNum-3];
	assign	adcDataBusExt	[ChNum-4]	=	calAdcData	[ChNum-4]+prngDataBus[ChNum-4];
	
	assign	gatedAdcDataBus	[ChNum-1]	=	adc2ChT2DataGated;
	assign	gatedAdcDataBus	[ChNum-2]	=	adc2ChR2DataGated;
	assign	gatedAdcDataBus	[ChNum-3]	=	adc1ChR1DataGated;
	assign	gatedAdcDataBus	[ChNum-4]	=	adc1ChT1DataGated;
	
	assign	Adc1ImT1Data_o	=	resultImBus	[ChNum-4];	//T1->T2_F_I
	assign	Adc1ReT1Data_o	=	resultReBus	[ChNum-4];	//T1->T2_F_Q
	assign	Adc1ImR1Data_o	=	resultImBus	[ChNum-3];	
	assign	Adc1ReR1Data_o	=	resultReBus	[ChNum-3];	
	//adc2                 
	assign	Adc2ImR2Data_o	=	resultImBus	[ChNum-1];	
	assign	Adc2ReR2Data_o	=	resultReBus	[ChNum-1];	
	assign	Adc2ImT2Data_o	=	resultImBus	[ChNum-2];	//T1->R2_S_I
	assign	Adc2ReT2Data_o	=	resultReBus	[ChNum-2];	//T1->R2_S_Q
	
	
	assign	MeasDataRdy_o	=	&resultValBus;
	assign	EndMeas_o		=	stopMeas;
	
	assign	NcoCos_o	=	ncoCosFirstTone;
	assign	NcoSin_o	=	ncoSinSecondTone;
	assign	MeasWind_o	=	measWind;
	
	assign	CalModeDone_o	=	&calDone;
	
	assign	memAddrNextFirstTone		=	!memAddrNext_mFirstTone[9]	?	memAddrNext_mFirstTone	:	memAddrNext_pFirstTone;
	assign	memAddrNext_pFirstTone	=	memAddrFirstTone	+ addrStepFirstTone;
	assign	memAddrNext_mFirstTone	=	memAddrFirstTone	+ addrStepFirstTone - MaxAddr;
	
	assign	memAddrNextSecondTone		=	!memAddrNext_mSecondTone[9]	?	memAddrNext_mSecondTone	:	memAddrNext_pSecondTone;
	assign	memAddrNext_pSecondTone	=	memAddrSecondTone	+ addrStepSecondTone;
	assign	memAddrNext_mSecondTone	=	memAddrSecondTone	+ addrStepSecondTone - MaxAddr;
//================================================================================
//  INSTANTIATIONS

//----------------------------------------------
//Module generates event signals for measurement

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(!StartMeas_i)	begin
			measCtrlReg			<=	MeasCtrl_i;
			ifFtwLReg			<=	IfFtwL_i;
			ifFtwHReg			<=	IfFtwH_i;
			filterCorrCoefLReg	<=	FilterCorrCoefL_i;
			filterCorrCoefHReg	<=	FilterCorrCoefH_i;
			measNumReg			<=	MeasNum_i;
			windPointsNumReg	<=	windPointsNum;
		end 
	end	else	begin
		measCtrlReg			<=	0;
		ifFtwLReg			<=	0;
		ifFtwHReg			<=	0;
		filterCorrCoefLReg	<=	0;
		filterCorrCoefHReg	<=	0;
		measNumReg			<=	0;
		windPointsNumReg	<=	0;
	end 
end

MeasCtrlModule	
#(	
	.WindPNumWidth	(WindPNumWidth)
)
MeasCtrlModule	
(
	.Clk_i					(Clk_i),
	.Rst_i					(Rst_i),
	.OscWind_o				(OscWind_o),
	.FilterCmd_i			(measCtrlReg[15-:8]),
		
	.MeasNum_i				(measNumReg),
	.StartMeas_i			(StartMeas_i),
	.StartMeasDsp_i			(StartMeasDsp_i),
	.Mode_i					(measCtrlReg[0]),
	.OscDataRdFlag_i		(OscDataRdFlag_i),
		
	.WindPointsNum_i		(windPointsNumReg),
		
	.WindPhInc_i			(windPhInc),
	.WindPhIncStart_i		(winPhIncStart),
	.WindArg_o				(windArg),
		
	.StartFpConv_o			(StartFpConv),
	.MeasWind_o				(measWind),
	.MeasWindDel_o			(measWindDelayed),
	.StopMeas_o				(stopMeas),
	.MeasEnd_o				(MeasEnd_o),
	.WinCtrl_o				(winCtrl),
	.TukeyCtrl_o			(tukeyCtrl),
	.SampleStrobeGenRst_o	(SampleStrobeGenRst_o)
);	

//----------------------------------------------
//Module selects settings for current window
WinParameters 
#(	
	.WindPhIncWidth		(WindNcoPhIncWidth),
	.WindNormCoefWidth	(WindNormCoefWidth),
	.WindPNumWidth		(WindPNumWidth),
	.BandCmdWidth		(BandCmdWidth)
)
WinParameters
(	
	.Clk_i				(Clk_i),
	.Rst_i				(Rst_i),
	.FilterCmd_i		(measCtrlReg[15-:8]),
	.WinPhInc_o			(windPhInc),
	.WinPhIncStart_o	(winPhIncStart),
	.WinNormCoef_o		(windNormCoef),
	.WinPointsNum_o		(windPointsNum),
	.AverageNoiseLvl_o	(averageNoizeLvl)
);

//----------------------------------------------
//Module generates win samples
Win_calc	WinCalcInst
(
	.clk_i			(Clk_i),
	.wind_clk		(WindCalcClk_i),
	.filterCmd_i	(measCtrlReg[15-:8]),
	.reset_i		(Rst_i),
	.WinCtrl_i		(winCtrl),
	.TukeyCtrl_i	(tukeyCtrl),
	.MeasWind_i		(measWind),
	.win_value_i	(windArg),
	.win_type_i		(measCtrlReg[2:0]),
	.win_o			(wind)
);


//----------------------------------------------
//Module generates Sin and Cos for measurement

CordicNco		
#(	
	.ODatWidth	(NcoWidth),
	.PhIncWidth	(WindNcoPhIncWidth),
	.IterNum	(15),
	.EnSinN		(0)
)
ncoFirstTone
(
	.Clk_i		(Clk_i),
	// .Rst_i		(Rst_i|NcoRst_i),
	.Rst_i		(Rst_i),
	.Val_i		(1'b1),
	// .PhaseInc_i	({ifFtwHReg[0+:WindNcoPhIncWidth-CmdDataRegWith],ifFtwLReg}),
	// .PhaseInc_i	(32'h40000000),
	.PhaseInc_i	(32'h33333333),
	.WindVal_i	(1'b1),
	.WinType_i	(),
	.Wind_o		(),
	.Sin_o		(ncoSinFirstTone),
	.Cos_o		(ncoCosFirstTone),	
	.Val_o		()
);

CordicNco		
#(	
	.ODatWidth	(NcoWidth),
	.PhIncWidth	(WindNcoPhIncWidth),
	.IterNum	(15),
	.EnSinN		(0)
)
ncoSecondTone
(
	.Clk_i		(Clk_i),
	// .Rst_i		(Rst_i|NcoRst_i),
	.Rst_i		(Rst_i),
	.Val_i		(1'b1),
	// .PhaseInc_i	({ifFtwHReg[0+:WindNcoPhIncWidth-CmdDataRegWith],ifFtwLReg}),
	// .PhaseInc_i	(32'h31eb851e),
	// .PhaseInc_i	(32'h33333333),
	.PhaseInc_i	(32'h40000000),
	.WindVal_i	(1'b1),
	.WinType_i	(),
	.Wind_o		(),
	.Sin_o		(ncoSinSecondTone),
	.Cos_o		(ncoCosSecondTone),	
	.Val_o		()
);

always 	@(posedge Clk_i) begin
	if	(!Rst_i)	begin
		memAddrFirstTone	<=	memAddrNextFirstTone;
	end	else	begin
		memAddrFirstTone	<=	9'b0;
	end
end

always 	@(posedge Clk_i) begin
	if	(!Rst_i)	begin
		memAddrSecondTone	<=	memAddrNextSecondTone;
	end	else	begin
		memAddrSecondTone	<=	9'b0;
	end
end
	
blk_mem_gen_0 sinCosMemFirstTone
(
	.clka	(Clk_i),    // input wire clka
	.addra	(memAddrFirstTone),  // input wire [8 : 0] addra
	.douta	(firstToneSinCosValues)  // output wire [35 : 0] douta
);

blk_mem_gen_0 sinCosMemSecondTone
(
	.clka	(Clk_i),    // input wire clka
	.addra	(memAddrSecondTone),  // input wire [8 : 0] addra
	.douta	(secondToneSinCosValues)  // output wire [35 : 0] douta
);

ComplPrng
#(
	.DataPrngWidth	(8),
	.InDataWidth 	(CorrAdcDataWidth),
	.OutDataWidth	(CorrAdcDataWidth)
)
ComplPrngAdderInst
(
	.Clk_i	(Clk_i),
	.Rst_i	(Rst_i),

	.PrngData_o		(prngData)
);

always @(posedge Clk_i) begin
	prngDataBus[0]  <= prngData;
	for(i=1; i<4; i=i+1) begin
		prngDataBus	[i]<=prngDataBus[i-1];
	end
end
//------------------------------------------------
//Generating needed amount of calculating channels
generate
	for	(g=0;	g<ChNum-2;	g=g+1)	begin	:DspChannel
	
		AdcCalibration 
		#(	
			.AccNum			(2097152),
			.AdcDataWidth	(CorrAdcDataWidth)
		)
		AdcCalibrationInst
		(	
			.Clk_i					(Clk_i),
			.Rst_i					(Rst_i),
			.CalModeEn_i			(CalModeEn_i),
			.AdcData_i				(adcDataBus[g]),
			
			.CalDone_o				(calDone[g]),
			.CalibratedAdcData_o	(calAdcData[g])
		);
		
		DspPipeline	
		#(	
			.AdcDataWidth		(AdcDataWidth),
			.AccWidth			(AccWidth),
			.WindWidth			(WindWidth),
			.NcoWidth			(NcoWidth),
			.ResultWidth		(ResultWidth),
			.WindCorrCoefWidth	(WindCorrCoefWidth),
			.WindNormCoefWidth	(WindNormCoefWidth),
			.IntermediateWidth	(IntermediateWidth)
		)
		DspFirstTone
		(
			.Clk_i				(Clk_i),
			.Rst_i				(Rst_i),
			.Val_i				(measWind),
			.StartFpConv_i		(StartFpConv),
			
			.FilterCorrCoef_i	({filterCorrCoefHReg[0+:WindNcoPhIncWidth-CmdDataRegWith],filterCorrCoefLReg}),
			.AverageNoizeLvl_i	(averageNoizeLvl),
			.AdcData_i			(gatedAdcDataBus[g]),
			.Wind_i				(wind),
			// .NcoSin_i			(ncoSinFirstTone),
			// .NcoCos_i			(ncoCosFirstTone),
			
			.NcoSin_i			(sinFirstTone),
			.NcoCos_i			(cosFirstTone),	
			.NormCoef_i			(windNormCoef),

			.CorrResultIm_o		(resultImBus[g]),
			.CorrResultRe_o		(resultReBus[g]),
			.CorrResultVal_o	(resultValBus[g])
		);
		
		DspPipeline	
		#(	
			.AdcDataWidth		(AdcDataWidth),
			.AccWidth			(AccWidth),
			.WindWidth			(WindWidth),
			.NcoWidth			(NcoWidth),
			.ResultWidth		(ResultWidth),
			.WindCorrCoefWidth	(WindCorrCoefWidth),
			.WindNormCoefWidth	(WindNormCoefWidth),
			.IntermediateWidth	(IntermediateWidth)
		)
		DspSecondTone
		(
			.Clk_i				(Clk_i),
			.Rst_i				(Rst_i),
			.Val_i				(measWind),
			.StartFpConv_i		(StartFpConv),
			
			.FilterCorrCoef_i	({filterCorrCoefHReg[0+:WindNcoPhIncWidth-CmdDataRegWith],filterCorrCoefLReg}),
			.AverageNoizeLvl_i	(averageNoizeLvl),
			.AdcData_i			(gatedAdcDataBus[g]),
			.Wind_i				(wind),
			// .NcoSin_i			(ncoSinSecondTone),
			// .NcoCos_i			(ncoCosSecondTone),	
			
			.NcoSin_i			(sinSecondTone),
			.NcoCos_i			(cosSecondTone),	
			.NormCoef_i			(windNormCoef),

			.CorrResultIm_o		(resultImBus[g+2]),
			.CorrResultRe_o		(resultReBus[g+2]),
			.CorrResultVal_o	(resultValBus[g+2])
		);
		
	end
endgenerate

endmodule

















