`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////
// Company: Tair
// Engineer: Zaytsev M.
// 
// Create Date:     
// Design Name: 
// Module Name:    Gpio2ReadTb
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module Gpio2ReadTb();

//================================================================================
//  REG/WIRE
	
	parameter OutWordWith = 24;
	parameter SingleSpiWordWith = 24;
	parameter QuadSpiWordWith = 6;
	
	localparam [1:0] IDLE = 0;
	localparam [1:0] SINGLE = 1;
	localparam [1:0] DELAY = 2;
	localparam [1:0] QUAD = 3;
	
	reg SPIMODE = 1'b0; //0 - single 1- quad
	
	reg [31:0] tbCnt;
	reg [31:0] delCnt;
	reg stateCnt;
	
	reg Clk100;
	reg Clk10;

	reg Clk24;
	
	reg [1:0] currState;
	reg [1:0] nextState;
	
	reg rst;
	
	wire txStart = (tbCnt == 100 | tbCnt == 3000);
	wire txDoneS;
	wire txDoneQ;
	
	
	wire sckS;
	wire sckQ;
	wire ssS;
	wire ssQ;
	
	wire ss;
	wire sck;
	
	wire mosi0S;
	wire mosi0Q;
	wire mosi1Q;
	wire mosi2Q;
	wire mosi3Q;
	
	wire delDone = (delCnt == 500);
//================================================================================
//  ASSIGNMENTS
	
	assign sck = (currState==SINGLE) ? sckS:sckQ;
	assign ss = (currState==SINGLE) ? ssS:ssQ;
	assign mosi0 = (currState==SINGLE) ? mosi0S:mosi0Q;
	assign mosi1 = (currState==SINGLE) ? 1'b1:mosi1Q;
	assign mosi2 = (currState==SINGLE) ? 1'b1:mosi2Q;
	assign mosi3 = (currState==SINGLE) ? 1'b1:mosi3Q;
//================================================================================
//clocks gen
	always	#5 Clk100	=	~Clk100;	
	always	#50 Clk10	=	~Clk10;	

	always	#21 Clk24	=	~Clk24;
	
//================================================================================
//  CODING

initial begin
	Clk100	=	1'b1;
	Clk10	=	1'b1;
	Clk24	= 	1'b1;
	rst		=	1'b1;
#100;
	rst		=	1'b0;
end	
	
always	@(negedge	Clk100)	begin
	if	(!rst)		begin
		tbCnt	<=	tbCnt+1;
	end	else	begin
		tbCnt	<=	0;
	end
end

always	@(posedge	Clk100)	begin
	if	(!rst)		begin
		if (currState == DELAY) begin
			delCnt	<=	delCnt+1;
		end	else	begin
			delCnt	<=	0;
		end
	end else	begin
		delCnt	<=	0;
	end
end

always	@(negedge	Clk10)	begin
	if	(!rst)		begin
		if (txDoneS|txDoneQ) begin
			stateCnt	<=	stateCnt+1;
		end	
	end else begin
		stateCnt <= 0;
	end
end

always	@(posedge	Clk100)	begin
	if	(!rst)		begin
		case (stateCnt)
			0:	begin
					SPIMODE <= 1'b0;
				end
			1:	begin
					SPIMODE <= 1'b1;
				end
			default:begin
						SPIMODE <= 1'b0;
					end
		endcase
	end else begin
		SPIMODE <= 1'b0;
	end
end

always	@(posedge	Clk100)	begin
	if	(rst)	begin
		currState	<=	IDLE;
	end	else	begin
		currState	<=	nextState;
	end
end


always @(*) begin
	nextState	=	IDLE;
	case(currState)
	IDLE	:	begin
					if (txStart)	begin
						case (SPIMODE)
							1'b0:	begin
											nextState = SINGLE;
										end
							1'b1:		begin
											nextState = QUAD;
										end
						endcase
					end	else begin
						nextState = IDLE;
					end
				end
				
	SINGLE	:	begin
					if (txDoneS)	begin
						nextState = DELAY;
					end	else begin
						nextState = SINGLE;
					end
				end
				
	DELAY	:	begin
					if (delDone)	begin
						nextState = SINGLE;
					end	else begin
						nextState = DELAY;
					end
				end
				
	QUAD		:	begin
					if (txDoneQ) begin
						nextState  = IDLE;
					end	else begin
						nextState  = QUAD;
					end
				end
	endcase
end

ExtSpiMEmulGpio2Read SingleSpiSm
(
	.Rst_i		(rst),
	.Clk_i		(Clk10),
	
	.Start_i	((currState==SINGLE)),
	.TxDone_o	(txDoneS),
	
	.Sck_o		(sckS),
	.Ss_o		(ssS),
	.Mosi_o		(mosi0S)
	
);

wire dataValIntArb;
wire [23:0] dataFromIntArb;
wire flagDirectGpio2;

InterfaceArbiter InterfaceArbiter
(
	.Rst_i		(rst),
	.Clk_i		(Clk100),
	
	.Sck_i		(sck),
	.Ss_i		(ss),
	
	.Mosi0_i	(mosi0),
	.Mosi1_i	(mosi1),
	.Mosi2_i	(mosi2),
	.Mosi3_i	(mosi3),
	
	
	.DataVal_o	(dataValIntArb),
	.Data_o		(dataFromIntArb)
);

PacketAnalyzer1Mosi PacketAnalyzer1Mosi_inst (
	.Clk_i					(Clk100),	
	.Rst_i					(rst),	
	
	.DataFromSpi_i 			(dataFromIntArb),
	.ValDataFromSpi_i 		(dataValIntArb),
	
	.BusyMosi4_i			(0),

	.FlagDirectLmx_o		(),
	.FlagDirectDds_o		(),
	.FlagDirectPot_o		(),
	.FlagDirectDac_o		(),
	.FlagDirectAtt_o		(),
	.FlagDirectShReg_o		(),
	.FlagDirectMax_o		(),
	.FlagDirectGpio1_o		(),
	.FlagDirectTemp_o		(),
	.FlagDirectGpio2_o		(flagDirectGpio2),

	.Busy_o					()
);

Gpio2Read DUT(
	.Clk_i					(Clk100),
	.Rst_i					(rst),
	.ClkSpi_i				(sckS),
	.LdLmx_i				(0),
	.LdMax_i				(1),
	.FlagDirectGpio2_i		(flagDirectGpio2),
	.MisoGpio2_o			()
);

endmodule
