`timescale 1ns / 1ps
module S5443TopTb;
	
	//=================================================================================================================================================================================================================
	//COMMANDS	FOR REG_MAP
	parameter	[31:0]	SensAutoPattern		= 32'h1;
	parameter	[31:0]	SensLowThreshT1		= {8'h01,24'h3BD080};
	parameter	[31:0]	SensHighThreshT1	= {8'h02,24'h401640};
	parameter	[31:0]	SensLowThreshR1 	= {8'h03,24'h3BD080};
	parameter	[31:0]	SensHighThreshR1 	= {8'h04,24'h401640};
	parameter	[31:0]	SensLowThreshT2 	= {8'h05,24'h3BD080};
	parameter	[31:0]	SensHighThreshT2 	= {8'h06,24'h401640};
	parameter	[31:0]	SensLowThreshR2 	= {8'h07,24'h3BD080};
	parameter	[31:0]	SensHighThreshR2 	= {8'h08,24'h401640};
	parameter	[31:0]	OverloadCtrlCmd 	= {8'h89,24'h000000};
	parameter	[31:0]	OverloadThresh 		= {8'h0A,24'h000400};
	parameter	[31:0]	DitherCmd 			= {8'h0E,24'h100192};
	parameter	[31:0]	MeasCmd 			= {8'h11,8'h0,8'h62,8'h0};
	parameter	[31:0]	AdcCtrl 			= {8'h12,24'h0};
	//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	parameter	[31:0]	DirectWrite0Cmd 	= {8'h13,24'h5};
	parameter	[31:0]	DirectWrite1Cmd 	= {8'h14,24'h5};
	parameter	[31:0]	NotDirectWriteCmd 	= {1'b0,7'h9,24'h5};
	parameter	[31:0]	DirectReadCmd 		= {1'b1,7'h11,24'h0};
	parameter	[31:0]	NotDirectReadCmd 	= {1'b1,7'h0,24'b1};
	parameter	[31:0]	DirectReadAns 		= {1'b0,7'h1b,24'h5};
	//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	parameter	[31:0]	IfFtwH 				= {8'h15,16'h0,8'h23};
	parameter	[31:0]	IfFtwL 				= {8'h16,24'h51eb85};
	parameter	[31:0]	FilterCorrCmdH 		= {8'h17,24'hD70A3D};
	parameter	[31:0]	FilterCorrCmdL 		= {8'h18,24'hD70A3D};
	parameter	[31:0]	ExtPosTrig0Cmd 		= {8'h19,16'h32,8'h7};	//триггер приходит положительной полярности от внешнего устройства к DSP. Триггер к DSP всегда выдаётся как импульс положительной полярности.
	parameter	[31:0]	ExtPosTrig1Cmd 		= {8'h1a,16'h32,8'h6};	//триггер приходит положительной полярности от внешнего устройства к DSP. Триггер к DSP всегда выдаётся как импульс положительной полярности.
	parameter	[31:0]	ExtNegTrig0Cmd 		= {8'h19,16'h32,8'h5};	//триггер приходит отрицательной полярности от внешнего устройства к DSP. Триггер к DSP всегда выдаётся как импульс положительной полярности.
	parameter	[31:0]	ExtNegTrig1Cmd 		= {8'h1a,16'h32,8'h4};	//триггер приходит отрицательной полярности от внешнего устройства к DSP. Триггер к DSP всегда выдаётся как импульс положительной полярности.
	parameter	[31:0]	IntPosTrig0Cmd 		= {8'h19,16'h32,8'h3};	//триггер приходит от DSP к внешнему устройству
	parameter	[31:0]	IntPosTrig1Cmd 		= {8'h1a,16'h32,8'h3};	//триггер приходит от DSP к внешнему устройству
	parameter	[31:0]	IntNegTrig0Cmd 		= {8'h19,16'h32,8'h1};	//триггер приходит от DSP к внешнему устройству
	parameter	[31:0]	IntNegTrig1Cmd 		= {8'h1a,16'h32,8'h0};	//триггер приходит от DSP к внешнему устройству
	//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	parameter	[31:0]	PulseMeasCtrlCmd 	= {8'h1b,16'h0,8'h11};	
	
	parameter	[31:0]	Pg1Mode				= {8'h1c,16'h0,8'h0};	
	
	parameter	[31:0]	Pg1P123DelH			= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg1P1DelL			= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg2P1DelL			= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg3P1DelL			= {8'h1c,16'h0,8'h0};
	
	parameter	[31:0]	Pg1P123WidthH		= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg1P1WidthL			= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg1P2WidthL			= {8'h1c,16'h0,8'h0};
	parameter	[31:0]	Pg1P3WidthL			= {8'h1c,16'h0,8'h0};

	//=================================================================================================================================================================================================================
	
	reg		Clk41;
	reg		Clk82;
	reg		Clk50;
	reg		Fclk25;
	reg		Dclk175;
	reg		Clk350;
	reg		Clk125;
	
	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	startCalcCmdRegO;
						
	wire	[13:0]	cos_value;	
	wire	[13: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		=	(tb_cnt	<=	150)?	ExtDspTrigPos0:ExtDspTrigNeg0;
	wire	ExtTrigger0		=	ExtDspTrigNeg0;
	
	wire	TrigFromDsp		=	(tb_cnt	>=	1100	&&	tb_cnt	<=	1101)?	1'b1:1'b0;
//==========================================================================================
//clocks gen
	always	#10 Clk50	=	~Clk50;
	always	#8 Clk125	=	~Clk125;
	always	#20 Fclk25	=	~Fclk25;
	always	#10 clk_i	=	~clk_i;
	always	#(24.390243902439/2)	Clk41	=	~Clk41;
	
	reg	Dclk175Reg;
	wire	sck_i;	
//==========================================================================================
initial begin
	Clk50	=	1'b1;
	Fclk25	=	1'b1;
	Clk125	=	1'b1;
	rst		=	1'b1;
	Clk41	=	1'b0;
	startCalcCmdReg	=	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	Clk41)	begin
	if	(tb_cnt	==	1700)	begin
		startCalcCmdReg	<=	1'b1;
	end	else	if	(endMeasNeg)	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

reg	startMeasSync;
always	@(posedge	Clk41)	begin
	startMeasSync	<=	startCalcCmdRegO;
end

wire	Adc1DataDa0P;
wire	Adc1DataDa1P;

wire	[31:0]	test	=	32'h2351eb85;
CordicNco		
#(	.ODatWidth	(14),
	.PhIncWidth	(32),
	.IterNum	(10),
	.EnSinN		(0))
ncoInst
(
	.Clk_i				(Clk50),
	.Rst_i				(rst),
	.Val_i				(1'b1),
	.PhaseInc_i			(test>>1),
	.WindVal_i			(1'b1),
	.WinType_i			(),
	.Wind_o				(),
	.Sin_o				(sin_value),
	.Cos_o				(cos_value),
	.Val_o				()
);

wire	[13:0]	TPSK1		=	14'h1;
wire	[13:0]	TPSKN1		=	14'b11111111111111;
wire	[13:0]	I			=	(tb_cnt	>=	300	&&	tb_cnt	<=	500)?	TPSK1:TPSKN1;
wire	[13:0]	Q			=	(tb_cnt	>=	200	&&	tb_cnt	<=	500)?	TPSKN1:TPSK1;

// ExtMult	
// #(	
	// .FactorAWidth	(14),
	// .FactorBWidth	(14),
	// .OutputWidth	(17)
// )
// Mixer	
// (
	// .Rst_i		(rst),
	// .Clk_i		(Clk50),
	// .Val_i		(1'b1),
	// .FactorC_i	(sin_value),
	// .FactorD_i	(cos_value),
	// .FactorA_i	(I),
	// .FactorB_i	(Q),
	// .Result_o	(),
	// .ResultVal_o()
// );

// IQModulatorWrapper	IQModulatorInst
// (
	// .Rst_i		(rst),
	// .Clk_i		(Clk125),
	// .Val_i		(1'b1),
	
	// .Result_o	()
// );

S5443Top uut (
	.Clk_i				(Clk50),
	.Led_o				(),
//------------------------------------------	
    .Adc1FclkP_i		(Fclk25),		
    .Adc1FclkN_i		(~Fclk25),		
		
    .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		(Fclk25),		
    .Adc2FclkN_i		(~Fclk25),		
			
    .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),
//------------------------------------------
	.AdcInitMosi_o		(),
	.AdcInitClk_o		(),			
	.Adc1InitCs_o		(),
	.Adc2InitCs_o		(),
	.AdcInitRst_o		(),
//------------------------------------------	
	
	.Mosi_i				(mosi_i),
	.Sck_i				(~sck_i),
	.Ss_i				(ss_i),
		
	.LpOutClk_o			(),
	.LpOutFs_o			(),			
	.LpOutData_o		(),
	
	//fpga-dsp signals
	.StartMeas_i		(startCalcCmdReg),
	.StartMeas_o		(),
	.EndMeas_o			(endMeas),
	.TimersClk_o		(),
	
	//trigger's 
	.TrigExtDev0_io		(),
	.TrigExtDev0Dir_o	(),
	
	.TrigExtDev1_io		(),
	.TrigExtDev1Dir_o	(),
	
	.TrigFromDsp_i		(TrigFromDsp),			//Trig from DSP
	.TrigToDsp_o		(),						//Trig To DSP
	
	//overload lines
	.OverloadS_i		(1'b0),
	.Overload_o			(),
	
	//gain lines
	.SensEnS_i			(1'b0),
	.AmpEn_o			(),	//	0-adc1ChA 1-adc1ChB 2-adc2ChA 3-adc2ChB
	.AdcData_i			(sin_value)
	);

localparam	IDLE	=	2'h0;
localparam	CMD		=	2'h1;
localparam	TX		=	2'h2;
localparam	PAUSE	=	2'h3;

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

wire	txWork	=	tb_cnt	>=	23;
wire	txStop	=	cmdCnt	>=	23;

reg	[8:0]	cmdCnt;
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		<=	SensAutoPattern;
		end	else	if	(cmdCnt	==	1)	begin
			DspSpiData		<=	SensLowThreshT1;
		end	else	if	(cmdCnt	==	2)	begin
			DspSpiData		<=	SensHighThreshT1;
		end	else	if	(cmdCnt	==	3)	begin
			DspSpiData		<=	SensLowThreshR1;
		end	else	if	(cmdCnt	==	4)	begin
			DspSpiData		<=	SensHighThreshR1;
		end	else	if	(cmdCnt	==	5)	begin
			DspSpiData		<=	SensLowThreshT2;
		end	else	if	(cmdCnt	==	6)	begin
			DspSpiData		<=	SensHighThreshT2;	
		end	else	if	(cmdCnt	==	7)	begin
			DspSpiData		<=	SensLowThreshR2;
		end	else	if	(cmdCnt	==	8)	begin
			DspSpiData		<=	SensHighThreshR2;
		end	else	if	(cmdCnt	==	9)	begin
			DspSpiData		<=	SensLowThreshR2;
		end	else	if	(cmdCnt	==	10)	begin
			DspSpiData		<=	OverloadCtrlCmd;
		end	else	if	(cmdCnt	==	11)	begin
			DspSpiData		<=	OverloadThresh;
		end	else	if	(cmdCnt	==	12)	begin
			DspSpiData		<=	DitherCmd;
		end	else	if	(cmdCnt	==	13)	begin
			DspSpiData		<=	MeasCmd;
		end	else	if	(cmdCnt	==	14)	begin
			DspSpiData		<=	AdcCtrl;
		end	else	if	(cmdCnt	==	15)	begin
			DspSpiData		<=	DirectWrite0Cmd;
		end	else	if	(cmdCnt	==	16)	begin
			DspSpiData		<=	DirectWrite1Cmd;
		end	else	if	(cmdCnt	==	17)	begin
			DspSpiData		<=	IfFtwH;	
		end	else	if	(cmdCnt	==	18)	begin
			DspSpiData		<=	IfFtwL;
		end	else	if	(cmdCnt	==	19)	begin
			DspSpiData		<=	FilterCorrCmdH;
		end	else	if	(cmdCnt	==	20)	begin
			DspSpiData		<=	FilterCorrCmdL;
		end	else	if	(cmdCnt	==	21)	begin
			DspSpiData		<=	IntPosTrig0Cmd;
		end	else	if	(cmdCnt	==	22)	begin
			DspSpiData		<=	IntPosTrig1Cmd;
		end	else	if	(cmdCnt	==	23)	begin
			DspSpiData		<=	PulseMeasCtrlCmd;
		end	else	if	(cmdCnt	==	24)	begin
			DspSpiData		<=	PNumHCmd;
		end	else	if	(cmdCnt	==	25)	begin
			DspSpiData		<=	PNumLCmd;
		end	else	if	(cmdCnt	==	26)	begin
			DspSpiData		<=	ModDelHCmd;
		end	else	if	(cmdCnt	==	27)	begin
			DspSpiData		<=	ModDelLCmd;
		end	else	if	(cmdCnt	==	28)	begin
			DspSpiData		<=	ModWidthHCmd;
		end	else	if	(cmdCnt	==	29)	begin
			DspSpiData		<=	ModWidthLCmd;
		end	else	if	(cmdCnt	==	30)	begin
			DspSpiData		<=	PGenDelHCmd;
		end	else	if	(cmdCnt	==	31)	begin
			DspSpiData		<=	PGenDelLCmd;
		end	else	if	(cmdCnt	==	32)	begin
			DspSpiData		<=	Trig0Timing1Cmd;
		end	else	if	(cmdCnt	==	33)	begin
			DspSpiData		<=	Trig0Timing2Cmd;
		end	else	if	(cmdCnt	==	34)	begin
			DspSpiData		<=	Trig1Timing1Cmd;
		end	else	if	(cmdCnt	==	35)	begin
			DspSpiData		<=	Trig1Timing2Cmd;
		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






























