`timescale 1ns / 1ps

//=============================================================================================================

//	Тестовая конфигурация:
//
//	Режим измерения "Точка в импульсе".
//	Количество измерений = 1.
//	Выбраный фильтр = 2МГц.
//
//	PG1	->	Reference Sequense Generator.	|	Шаблон 1 имп.
//	PG2	->	модулятор.						|	Шаблон 1 имп.
//	PG3	->	Sample Strobe Generator.		|	Шаблон 1 имп.
//	PG4	->	Gating Generator.				|	Шаблон 1 имп.
//	
//	Настройки мультиплексоров генераторов:
//	PG1MUX_OUT	->	INT_TRIG.
//	PG2MUX_OUT	->	PG1. Для всех генераторов кроме PG1 сигналом начала работы является выход PG1.
//	PG3MUX_OUT	->	PG1.
//	PG4MUX_OUT	->	PG1.
//	PG5MUX_OUT	->	PG1.
//	PG6MUX_OUT	->	PG1.
//	PG7MUX_OUT	->	PG1.
//	
//	Настройки остальных мультиплексоров:
//	MODMUX_OUT			->	PG2.
//	GATINGMUX_OUT		->	PG4.
//	SAMPLSTROBEMUX_OUT	->	PG3.
//	EXTSTARTMUX			->	DSPSTART.

//=============================================================================================================
module S5243TopSpectrumTb;

	localparam	[4:0]	EXTTRIGMUXCMD	=	5'd15;
	localparam	[4:0]	DSPTRIGINCMD	=	5'h8;
	localparam	[4:0]	MUXSLOWMODCMD	=	5'd1;
	localparam	[4:0]	MUXFASTMODCMD	=	5'd1;
	localparam	[4:0]	GATINGMUXCMD	=	5'd2;
	localparam	[4:0]	SMPLSTRBMUXCMD	=	5'd3;
	localparam	[6:0]	DECIMFACTOR		=	7'd2;
	
	localparam	[1:0]	CURRADCCHANNEL	=	2'h3;
	//COMMANDS	FOR REG_MAP
	// parameter	[31:0]	MeasCmdBypass	=	{8'h11,8'h0,8'h63,7'h1,1'h1};
	parameter	[31:0]	MeasCmdFft 		=	{8'h11,8'h0,8'h63,DECIMFACTOR,1'b1};
	parameter	[31:0]	AdcCtrl =	{8'h12,24'h2};
	parameter	[31:0]	SensCtrlCmd =	{1'b0,21'h0,CURRADCCHANNEL,4'h0,4'h1};
	parameter	[31:0]	DitherCmd 	= {8'h0E,8'd9,4'h0,4'h1,4'd11,4'h3};
	parameter	[31:0]	IfFtwH 	=	{8'h15,16'h0,8'h40};
	parameter	[31:0]	IfFtwL 	=	{8'h16,24'h000000};
	parameter	[31:0]	FilterCorrCmdH 		=	{8'h17,24'hD70A3D};
	parameter	[31:0]	FilterCorrCmdL 		=	{8'h18,24'hD70A3D};
	parameter	[31:0]	MeasNum0RegCmd		=	{8'h58,24'd100};
	parameter	[31:0]	MeasNum1RegCmd		=	{8'h59,MUXSLOWMODCMD,MUXFASTMODCMD,DSPTRIGINCMD,25'd0};
	//===========================================================================================
	
	reg		Clk41;
	reg		Clk50;
	reg		Clk70;
	
	reg	[31:0]	tb_cnt=4'd0;
	reg	rst;
	reg	mosi_i	=	1'b0;
	reg	Miso_i	=	1'b0;
	reg	ss_i;
	reg	clk_i	=	1'b0;
	
	
	reg	[31:0]	DspSpiData;
	reg		startCalcCmdReg;
						
	wire	[17:0]	cos_value;	
	wire	[17:0]	sin_value;				

	wire	ExtDspTrigPos0	=	(tb_cnt	>=	180	&&	tb_cnt	<=	181)?	1'b1:1'b0;
	wire	ExtDspTrigNeg0	=	(tb_cnt	>=	180	&&	tb_cnt	<=	181)?	1'b0:1'b1;
	
	wire	ExtTrigger0		=	ExtDspTrigNeg0;
	
	wire	TrigFromDsp		=	(tb_cnt	>=	1100	&&	tb_cnt	<=	1101)?	1'b1:1'b0;
	wire	endMeas;
	reg	[31:0]	cmdCnt;
	
	reg	trig0;
	reg	trig1;
	
	wire	trig0R;
    wire	trig1R;
	
	// wire	[13:0]	DelpaPulse	=	(tb_cnt>=4508	&	tb_cnt	<=	4518)	?	14'h1fff:14'h0;
	wire	[13:0]	DelpaPulse	=	(tb_cnt==4508)	?	14'h1fff:14'h0;
		
	assign	trig0R	=	trig0;
    assign	trig1R	=	trig1;
	
	wire	signed	[13:0]	ncoSin1;
	wire	signed	[13:0]	ncoCos1;
	wire	signed	[13:0]	ncoSin2;
	wire	signed	[13:0]	ncoCos2;
	
	wire	signed	[13:0]	sinAdd	=	(ncoSin1>>>1)+(ncoSin2>>>1);
	
//==========================================================================================
//clocks gen
	always	#10 Clk50	=	~Clk50;
	always	#(14.285714285714/2) Clk70	=	~Clk70;
	always	#10 clk_i	=	~clk_i;
	always	#(24.390243902439/2)	Clk41	=	~Clk41;

	
	wire	sck_i;	
//==========================================================================================
initial begin
	Clk50	=	1'b1;
	Clk70	=	1'b1;
	rst		=	1'b1;
	Clk41	=	1'b0;
	trig0	=	1'b0;
	trig1	=	1'b0;
#100;
	rst		=	1'b0;
#400;
	Clk41	=	1'b0;
end		
	
reg	endMeasReg;
always	@(posedge	Clk41)	begin
	endMeasReg	<=	endMeas;
end

wire	endMeasNeg	=	!endMeas&endMeasReg;

always	@(posedge	Clk70)	begin
	if	(!rst)	begin
		if	(!endMeas)	begin
			if	(tb_cnt	==	4505)	begin
				startCalcCmdReg	<=	1'b1;
			end	
		end	else	begin
			startCalcCmdReg	<=	1'b0;
		end
	end	else	begin
		startCalcCmdReg	<=	1'b0;
	end
end

always	@(negedge	Clk41)	begin
	if	(!rst)		begin
		tb_cnt	<=	tb_cnt+1;
	end	else	begin
		tb_cnt	<=	0;
	end
end

wire	Adc1DataDa0P;
wire	Adc1DataDa1P;

reg [13:0] Data_i;
real pi = 3.14159265358;
real phase = 0;
real phaseInc = 0.001;
real signal;
always @ (posedge Clk50)
	begin
		if (tb_cnt >= 4505)
			begin
				phase = phase + phaseInc;
				phaseInc <= phaseInc + 0.0005;
				signal = $sin(2*pi*phase);
				Data_i = 2**12 * signal;
			end
		else
			Data_i = 0;
	end
		
wire	[31:0]	test	=	32'h2351eb85;
// wire	[31:0]	test	=	32'h40000000;

CordicNco		
#(	
	.ODatWidth	(14),
	.PhIncWidth	(32),
	.IterNum	(10),
	.EnSinN		(1)
)
ncoInst1
(
	.Clk_i		(Clk50),
	.Rst_i		(rst),
	.Val_i		(1'b1),
	.PhaseInc_i	(32'h51eb851),
	.WindVal_i	(1'b1),
	.WinType_i	(),
	.Wind_o		(),
	.Sin_o		(ncoSin1),
	.Cos_o		(ncoCos1),
	.Val_o		()
);

CordicNco		
#(	
	.ODatWidth	(14),
	.PhIncWidth	(32),
	.IterNum	(10),
	.EnSinN		(1)
)
ncoInst2
(
	.Clk_i		(Clk50),
	.Rst_i		(rst),
	.Val_i		(1'b1),
	// .PhaseInc_i	(32'h33333333),
	// .PhaseInc_i	(32'h4ccccccc),
	.PhaseInc_i	(32'h40000000),
	.WindVal_i	(1'b1),
	.WinType_i	(),
	.Wind_o		(),
	.Sin_o		(ncoSin2),
	.Cos_o		(ncoCos2),
	.Val_o		()
);

CordicNco		
#(	.ODatWidth	(18),
	.PhIncWidth	(32),
	.IterNum	(10),
	.EnSinN		(0))
ncoInst
(
	.Clk_i				(Clk50),
	.Rst_i				(rst),
	.Val_i				(1'b1),
	.PhaseInc_i			(test),
	.WindVal_i			(1'b1),
	.WinType_i			(),
	.Wind_o				(),
	.Sin_o				(sin_value),
	.Cos_o				(cos_value),
	.Val_o				()
);

S5243Top MasterFpga 
(
	.ClkP_i				(Clk50),
	.ClkN_i				(~Clk50),
	.Led_o				(),
//------------------------------------------	
    .Adc1FclkP_i		(),		
    .Adc1FclkN_i		(),		

    .Adc1DataDa0P_i		(Adc1DataDa0P),
	.Adc1DataDa0N_i		(~Adc1DataDa0P),		
    .Adc1DataDa1P_i		(Adc1DataDa1P),
    .Adc1DataDa1N_i		(~Adc1DataDa1P),

	.Adc1DataDb0P_i		(Adc1DataDa0P),
    .Adc1DataDb0N_i		(~Adc1DataDa0P),		
    .Adc1DataDb1P_i		(Adc1DataDa1P),
    .Adc1DataDb1N_i		(~Adc1DataDa1P),
//------------------------------------------	
    .Adc2FclkP_i		(),		
    .Adc2FclkN_i		(),		

    .Adc2DataDa0P_i		(1'b1),
    .Adc2DataDa0N_i		(1'b0),		
    .Adc2DataDa1P_i		(1'b1),
    .Adc2DataDa1N_i		(1'b0),
  
	.Adc2DataDb0P_i		(1'b1),
    .Adc2DataDb0N_i		(1'b0),		
    .Adc2DataDb1P_i		(1'b1),
    .Adc2DataDb1N_i		(1'b0),
//------------------------------------------
	.Adc1InitMosi_o		(),
	.Adc2InitMosi_o		(),
	
	.Adc1InitClk_o		(),
	.Adc2InitClk_o		(),
	
	.Adc1InitCs_o		(),
	.Adc2InitCs_o		(),
	
	.Adc1InitRst_o		(),
	.Adc2InitRst_o		(),
	
	
	.DitherCtrlCh1_o	(),
	.DitherCtrlCh2_o	(),
//------------------------------------------	
	
	.Mosi_i				(mosi_i),
	.Sck_i				(~sck_i),
	.Ss_i				(ss_i),
	.Miso_i				(),
	.Miso_o				(),
	
	.LpOutClk_o			(),
	.LpOutFs_o			(),			
	.LpOutData_o		(),
	
	//fpga-dsp signals
	.StartMeas_i		(startCalcCmdReg),
	.EndMeas_o			(endMeas),
	
	.TimersClk_o		(),
	
	.Trig6to1_io		(),	
	.Trig6to1Dir_o		(),	
	
	.DspTrigOut_i		(),				//Trig from DSP
	.DspTrigIn_o		(),				//Trig To DSP
	
	.Overload_o			(),
	
	.PortSel_o			(),
	
	//mod out line
	
	.Mod_o				(),	
	
	//gain lines
	.DspReadyForRx_i		(1'b0),
	.AmpEn_o				(),	//	0-adc1ChA 1-adc1ChB 2-adc2ChA 3-adc2ChB
	// .AdcData_i				(sin_value[17-:14])
	// .AdcData_i			(DelpaPulse)
	.AdcData_i			(sinAdd)
	// .AdcData_i			(Data_i)
);
parameter	IDLE	=	2'h0;
parameter	CMD		=	2'h1;
parameter	TX		=	2'h2;
parameter	PAUSE	=	2'h3;

reg	[1:0]	txCurrState;
reg	[1:0]	txNextState;

wire	txWork	=	tb_cnt	>=	23;
// wire	txStop	=	(cmdCnt	>=	90)	&	(cmdCnt	>=	70)	&	(cmdCnt	>=	71);
wire	txStop	=	(cmdCnt	>=	251);



reg	[6:0]	txCnt;
reg	[3:0]	pauseCnt;

always	@(posedge	Clk41)	begin
	if	(!rst)	begin
		if	(txCurrState	==	CMD)	begin
			if	(!txStop)	begin
				cmdCnt	<=	cmdCnt+1;
			end
		end
	end	else	begin
		cmdCnt	<=	0;
	end
end

always	@(posedge	Clk41)	begin
	if	(!rst)	begin
		if	(txCurrState	==	TX)	begin
			txCnt	<=	txCnt+1;
		end	else	begin
			txCnt	<=	0;
		end
	end	else	begin
		txCnt	<=	0;
	end
end

always	@(posedge	Clk41)	begin
	if	(!rst)	begin
		if	(txCurrState	==	PAUSE)	begin
			pauseCnt	<=	pauseCnt+1;
		end	else	begin
			pauseCnt	<=	0;
		end
	end	else	begin
		pauseCnt	<=	0;
	end
end
	
always	@(posedge	Clk41)	begin
	if	(txCurrState	==	CMD)	begin
		if	(cmdCnt	==	0)	begin
			DspSpiData		<=	MeasCmdFft;
		end	else	if	(cmdCnt	==	1)	begin
			DspSpiData		<=	MeasNum0RegCmd;
		end	else	if	(cmdCnt	==	2)	begin
			DspSpiData		<=	MeasNum1RegCmd;
		end else	if	(cmdCnt	==	3)	begin
			DspSpiData		<=	SensCtrlCmd;
		end
	end	else	if	(txCurrState	==	TX)	begin
		DspSpiData	<=	DspSpiData<<1;
	end
end

always	@(posedge Clk41)	begin
	if	(txCurrState	==	TX)	begin
		if	(txCnt	>=	7'd0)	begin
			mosi_i	<=	DspSpiData[31];
		end	else	begin
			mosi_i	<=	1'b1;
		end
	end	else	begin
		mosi_i	<=	1'b1;
	end
end

always	@(posedge	Clk41)	begin
	if	(txCurrState	==	TX)	begin
		ss_i	<=	1'b0;
	end	else	begin
		ss_i	<=	1'b1;
	end
end

assign	sck_i	=	Clk41;

always	@(posedge	Clk41)	begin
	if	(rst)	begin
		txCurrState	<=	IDLE;
	end	else	begin
		txCurrState	<=	txNextState;
	end
end


always @(*) begin
	txNextState	=	IDLE;
	case(txCurrState)
	IDLE	:	begin
					if (txWork)	begin
						txNextState = CMD;
					end	else begin
						txNextState = IDLE;
					end
				end
				
	CMD	:		begin
					if (!txStop)	begin
						txNextState = TX;
					end	else begin
						txNextState = IDLE;
					end
				end

	TX		:	begin
					if (txCnt==6'd31) begin
						txNextState  = PAUSE;
					end	else begin
						txNextState  = TX;
					end
				end
        
	PAUSE	:	begin
					if (pauseCnt==4'd10) begin
						txNextState  = CMD;
					end	else begin
						txNextState  = PAUSE;
					end
				end
	endcase
end


		
endmodule






























