`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// company: 
// engineer: 
// 
// create date:    16:37:06 07/11/2019 
// design name: 
// module name:    dsp_linkport_interface 
// project name: 
// target devices: 
// tool versions: 
// description: 					
//
// dependencies: 
//
// revision: 
// revision 0.01 - file created
// additional comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module	DspInterface
#(	
	parameter	AdcDataWidth	=	14,	
	parameter	ExtAdcDataWidth	=	16,	
	parameter	ODataWidth		=	16,	
	parameter	ResultWidth		=	40,
	parameter	ChNum			=	16,
	parameter	CmdRegWidth		=	32,
	parameter	CmdDataRegWith	=	24,
	parameter	HeaderWidth		=	7,
	parameter	DataCntWidth	=	5,
	parameter	CmdWidth		=	3
)
(
	input	Clk_i,
	input	Rst_i,
	input	OscWind_i,
	input	StartMeasDsp_i,
	input	DspReadyForRx_i,
	input	[31:0]	MeasNum_i,
	
	input	Mosi_i,
	input	Sck_i,
	input	Ss_i,
	
	input	Mode_i,
	input	[CmdWidth-2:0]		PortSel_i,
	input	[CmdWidth-1:0]		DecimFactor_i,
	
	input	[CmdRegWidth-1:0]	IfFtwL_i,
	input	[CmdRegWidth-1:0]   IfFtwH_i,
	
	output	OscDataRdFlag_o,
	input	[AdcDataWidth-1:0]	Adc1ChT1Data_i,	
	input	[AdcDataWidth-1:0]	Adc1ChR1Data_i,	
	input	[AdcDataWidth-1:0]	Adc2ChR2Data_i,	
	input	[AdcDataWidth-1:0]	Adc2ChT2Data_i,	
	
	output	Mosi_o,
	output	Sck_o,
	output	Ss0_o,
	output	Ss1_o,
	input	Miso_i,
	output	Miso_o,

	
	output	[CmdRegWidth-1:0]	CmdDataReg_o,
	output	CmdDataVal_o,
	
	input	[CmdDataRegWith-1:0]	AnsReg_i,
	output	[HeaderWidth-1:0]		AnsAddr_o,	

	output	LpOutFs_o,
	output	LpOutClk_o,
	output	[ODataWidth-1:0]	LpOutData_o,
	
	input	[ResultWidth-1:0]	Adc1T1ImResult_i,
	input	[ResultWidth-1:0]	Adc1T1ReResult_i,
	input	[ResultWidth-1:0]	Adc1R1ImResult_i,
	input	[ResultWidth-1:0]	Adc1R1ReResult_i,	
	
	input	[ResultWidth-1:0]	Adc2R2ImResult_i,
	input	[ResultWidth-1:0]	Adc2R2ReResult_i,
	input	[ResultWidth-1:0]	Adc2T2ImResult_i,
	input	[ResultWidth-1:0]	Adc2T2ReResult_i,
	input	[ChNum-1:0]			ServiseRegData_i,

	input	LpOutStart_i
);
//================================================================================
//	REG/WIRE
//================================================================================
	wire	[ResultWidth*(ChNum*2)-1:0]	measDataBus;
	wire	[ResultWidth*(ChNum*2)-1:0]	fftDataBus;
	wire	[ResultWidth*(ChNum*2)-1:0]	decimDataBus;
	
	reg		[ResultWidth*(ChNum*2)-1:0]	dataForFifo;
	reg		dataForFifoVal;
	
	wire	fftDataBusVal;
	wire	decimDataBusVal;
	
	wire	[ResultWidth*(ChNum*2)-1:0]	measDataBusTx;
	wire	measDataValTx;
	
	wire	ppiBusy;
	
	reg	signed	[15:0]	adc1ChT1DataExt;	
	reg	signed	[15:0]	adc1ChR1DataExt;	
	reg	signed	[15:0]	adc2ChR2DataExt;	
	reg	signed	[15:0]	adc2ChT2DataExt;
	
	reg		signed	[AdcDataWidth-1:0]	currDataChannel;
	reg		signed	[AdcDataWidth-1:0]	testDataChannel;
	wire	signed	[AdcDataWidth-1:0]	currDataChannelDecim;
	wire	currDataChannelDecimVal;
	
	wire	signed	[31:0]	filteredDecimData;
	wire	signed	[31:0]	filteredDecimDataQ;
	wire	filteredDecimDataVal;
//================================================================================
//	ASSIGNMENTS
//================================================================================

	assign	measDataBus	[(ResultWidth*(ChNum*2-7))-1-:ResultWidth]	=	Adc1T1ImResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-6))-1-:ResultWidth]	=	Adc1T1ReResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-5))-1-:ResultWidth]	=	Adc1R1ImResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-4))-1-:ResultWidth]	=	Adc1R1ReResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-3))-1-:ResultWidth]	=	Adc2T2ImResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-2))-1-:ResultWidth]	=	Adc2T2ReResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-1))-1-:ResultWidth]	=	Adc2R2ImResult_i;
	assign	measDataBus	[(ResultWidth*(ChNum*2-0))-1-:ResultWidth]	=	Adc2R2ReResult_i;
	
	assign	OscDataRdFlag_o	=	measDataValTx;
	
//================================================================================
//	CODING
//================================================================================

reg	oscWindR;
reg	[15:0]	testPatternData;

wire	oscWindNeg	=	(!OscWind_i&oscWindR);

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		oscWindR	<=	OscWind_i;
	end	else	begin
		oscWindR	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(oscWindNeg)	begin
			testPatternData	<=	~testPatternData;
		end
	end	else	begin
		testPatternData	<=	16'h1fff;
	end
end


always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(OscWind_i)	begin
			if	(testDataChannel	!=	(16'd511*16))	begin
				testDataChannel	<=	testDataChannel+16'd511;
			end	else	begin
				testDataChannel	<=	16'd0;
			end
		end	else	begin
			testDataChannel	<=	16'd0;
		end
	end	else	begin
		testDataChannel	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		case(PortSel_i)
			0:	begin
					// currDataChannel	<=	testDataChannel;
					currDataChannel	<=	Adc2ChT2Data_i;		//Device T3
				end
			1:	begin
					currDataChannel	<=	Adc2ChR2Data_i;		//Device R3
				end
			2:	begin
					currDataChannel	<=	Adc1ChT1Data_i;		//Device T4
				end
			3:	begin
					currDataChannel	<=	Adc1ChR1Data_i;		//Device R4
				end
		endcase
	end	else	begin
		currDataChannel	<=	0;
	end
end
	
SlaveSpi
#(	
	.CmdRegWidth	(CmdRegWidth),
	.DataCntWidth	(DataCntWidth),
	.HeaderWidth	(HeaderWidth)
)
DspSlaveSpi
(
	.Clk_i		(Clk_i),
	.Rst_i		(Rst_i),

	.Data_o		(CmdDataReg_o),
	.Val_o		(CmdDataVal_o),
	
	.Mosi_i		(Mosi_i),
	.Sck_i		(Sck_i),
	.Ss_i		(Ss_i),
	
	.Mosi_o		(Mosi_o),
	.Sck_o		(Sck_o),
	.Ss0_o		(Ss0_o),
	.Ss1_o		(Ss1_o),
	
	.AnsAddr_o	(AnsAddr_o),
	.AnsReg_i	(AnsReg_i),
	
	.Miso_i		(Miso_i),
	.Miso_o		(Miso_o)
);

// DecimFilterWrapperTest	DecimFilter
// (
	// .Clk_i			(Clk_i),
	// .Rst_i			(Rst_i),
	// .DataVal_i		(OscWind_i),
	// .DecimFactor_i	(DecimFactor_i),
	
	
	// .Data_i		(currDataChannel),
	// .TestData_o		(testData),
	
	// .Data_o	(filteredDecimData),
	// .DataVal_o	(filteredDecimDataVal)
// );

reg [15:0] currDecimFactor;
reg [15:0] currDecimFactorR;

reg changeFlag;
reg decimChangeVal;

reg [15:0] s_axis_config_tdata; 
reg s_axis_config_tvalid;
wire s_axis_config_tready;

reg [15:0] s_axis_data_tdata;
reg s_axis_data_tvalid;
wire s_axis_data_tready;
wire [31:0] m_axis_data_tdata;
wire m_axis_data_tvalid;

reg [2:0] corrDecimFactor;

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if (DecimFactor_i <= 3'd4) begin
			corrDecimFactor <= 3'd4;
		end else begin
			corrDecimFactor <= DecimFactor_i;
		end
	end else begin
		corrDecimFactor <= 0;
	end
end

always @(posedge Clk_i) begin
	if (Rst_i) begin
		currDecimFactor <= 0;
		currDecimFactorR <= 0;
	end else begin
		currDecimFactor <= {12'd0,corrDecimFactor};
		currDecimFactorR <= currDecimFactor;
	end
end

always @(posedge Clk_i) begin
	if (Rst_i) begin
		changeFlag <= 0;
	end else begin
		changeFlag <= (currDecimFactor!=currDecimFactorR);
	end
end

always @(posedge Clk_i) begin
	if (!Rst_i) begin
		if (changeFlag) begin
			decimChangeVal <= 1'b1;
		end
		if (s_axis_config_tvalid) begin
			decimChangeVal <= 1'b0;
		end
	end else begin
		decimChangeVal <= 1'b0;
	end
end

always @(posedge Clk_i) begin
	if (!Rst_i) begin
		if (decimChangeVal) begin
			if (s_axis_config_tready) begin
				s_axis_config_tdata <= currDecimFactor;
				s_axis_config_tvalid <= 1'b1;
			end else begin
				s_axis_config_tvalid <= 1'b0;
			end
		end else begin
			s_axis_config_tdata <= s_axis_config_tdata;
			s_axis_config_tvalid <= 1'b0;
		end
	end else begin
		s_axis_config_tdata <= 0;
		s_axis_config_tvalid <= 1'b0;
	end	
end

always @(posedge Clk_i) begin
	if (!Rst_i) begin
		if (OscWind_i) begin
			if (s_axis_data_tready) begin
				s_axis_data_tdata <={{2{currDataChannel[AdcDataWidth-1]}},currDataChannel};
				s_axis_data_tvalid <= 1'b1;
			end else begin
				s_axis_data_tvalid <= 1'b0;
			end
		end else begin
			s_axis_data_tdata <= s_axis_data_tdata;
			s_axis_data_tvalid <= 1'b0;
		end
	end else begin
		s_axis_data_tdata <= 0;
		s_axis_data_tvalid <= 1'b0;
	end	
end

CicTest CicCompilerTest (
  .aclk(Clk_i),                                  // input wire aclk
  .s_axis_config_tdata(s_axis_config_tdata),    // input wire [15 : 0] s_axis_config_tdata
  .s_axis_config_tvalid(s_axis_config_tvalid),  // input wire s_axis_config_tvalid
  .s_axis_config_tready(s_axis_config_tready),  // output wire s_axis_config_tready
  
  .s_axis_data_tdata(s_axis_data_tdata),        // input wire [15 : 0] s_axis_data_tdata
  .s_axis_data_tvalid(s_axis_data_tvalid),      // input wire s_axis_data_tvalid
  .s_axis_data_tready(s_axis_data_tready),      // output wire s_axis_data_tready
  
  .m_axis_data_tdata(filteredDecimData),        // output wire [31 : 0] m_axis_data_tdata
  .m_axis_data_tvalid(filteredDecimDataVal)      // output wire m_axis_data_tvalid
);

OscDataFormer	DecimDataFormer
(
	.Clk_i				(Clk_i), 
	.Rst_i				(Rst_i),	
	.OscWind_i			(s_axis_data_tvalid),
	// .OscWind_i			(OscWind_i),
	.MeasNum_i			(MeasNum_i),

	.AdcDataVal_i		(filteredDecimDataVal),
	.AdcData_i			(filteredDecimData),	
	
	.OscDataBus_o		(decimDataBus),
	.OscDataBusVal_o	(decimDataBusVal)
);

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(Mode_i)	begin
			dataForFifo		<=	decimDataBus;
			dataForFifoVal	<=	decimDataBusVal;
		end	else	begin
			dataForFifo		<=	measDataBus;
			dataForFifoVal	<=	LpOutStart_i;
		end
	end	else	begin
		dataForFifo		<=	0;
		dataForFifoVal	<=	0;
	end
end

MeasDataFifoWrapper		
#(	
	.DataWidth	(ResultWidth),
	.ChNum		(ChNum)
)
MeasDataFifoInst
(
	.Clk_i			(Clk_i), 
	.Rst_i			(Rst_i),	
	.PpiBusy_i		(ppiBusy),	
	.MeasNum_i		(MeasNum_i),	
	.StartMeasDsp_i	(StartMeasDsp_i),	
	.DspReadyForRx_i(DspReadyForRx_i),	
	// .MeasDataBus_i	(measDataBus),
	.MeasDataBus_i	(dataForFifo),
	// .MeasDataVal_i	(LpOutStart_i),	
	.MeasDataVal_i	(dataForFifoVal),	
	
	.MeasDataBus_o	(measDataBusTx),
	.MeasDataVal_o	(measDataValTx)
);

DspPpiOut	
#(	
	.ODataWidth		(ODataWidth),	
	.ResultWidth	(ResultWidth), 
	.ChNum			(ChNum)
)
MeasDataPpiOut
(
	.Rst_i				(Rst_i),	
	.Clk_i				(Clk_i),		
	
	.MeasDataBus_i		(measDataBusTx),
	.ServiseRegData_i	(ServiseRegData_i),
	
	.PpiBusy_o			(ppiBusy),
	.LpOutStart_i		(measDataValTx),
	
	.LpOutClk_o			(LpOutClk_o),
	.LpOutFs_o			(LpOutFs_o),
	.LpOutData_o		(LpOutData_o)
);

endmodule







