`timescale 1ns / 1ps

module ExtQSpiMEmul 
(
	input Rst_i,
	input Clk_i,
	
	input Start_i,
	output TxDone_o,
	
	output Sck_o,
	output reg Ss_o,
	output reg Mosi0_o,
	output reg Mosi1_o,
	output reg Mosi2_o,
	output reg Mosi3_o
);

//================================================================================
//  PARAMETERS
	localparam [1:0] IDLE = 0;
	localparam [1:0] CMD = 1;
	localparam [1:0] TX = 2;
	localparam [1:0] PAUSE = 3;

	parameter MODE = 1'h1;
	parameter [3:0] LMX = 4'h1;
	parameter [1:0] DDS = 2'h1;
	parameter POT = 1'h1;
	parameter DAC = 1'h1;
	parameter ATT = 1'h1;
	parameter [1:0] SHREG = 2'h1;
	parameter [2:0] MAX2870 = 3'h1;
	parameter [1:0] GPIO = 2'h1;
	parameter [5:0] RESERVED = 6'h0;
	parameter EOPBIT = 1'b0;
	
//================================================================================
//  REG/WIRE
	reg [1:0] currState;
	reg [1:0] nextState;
	
	reg	[6:0]	txCnt;
	reg	[6:0]	cmdCnt;
	reg	[3:0]	pauseCnt;

	
	
	wire	txStop	=	(cmdCnt	>=	LMX+DDS+POT+DAC+ATT+SHREG+MAX2870+GPIO+1);
	
	reg [23:0] headerCmd = {MODE,LMX,DDS,POT,DAC,ATT,SHREG,MAX2870,GPIO,RESERVED,EOPBIT};
	reg [23:0] spiData;
	
	reg	[23:0]	dspSpiData;
	
	reg sckFlag;
	
	wire [22:0] testWidre = headerCmd[22:0];
	
//================================================================================
//  ASSIGNMENTS

assign	Sck_o		=	(sckFlag)? ~Clk_i:1'b1;
assign	TxDone_o	=	(txStop & (currState== CMD));

//================================================================================
//  CODING

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(currState	==	CMD)	begin
			if	(!txStop)	begin
				cmdCnt	<=	cmdCnt+1;
			end else begin
				cmdCnt <= 0;
			end
		end
	end	else	begin
		cmdCnt	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(currState	==	TX)	begin
			txCnt	<=	txCnt+1;
		end	else	begin
			txCnt	<=	0;
		end
	end	else	begin
		txCnt	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(currState	==	PAUSE)	begin
			pauseCnt	<=	pauseCnt+1;
		end	else	begin
			pauseCnt	<=	0;
		end
	end	else	begin
		pauseCnt	<=	0;
	end
end
	
always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(currState	==	CMD)	begin
			spiData	<=	spiData+cmdCnt;
		end
	end	else	begin
		spiData	<=	24'hab;
	end
end

always	@(posedge	Clk_i)	begin
	if	(currState	==	CMD)	begin
		if	(cmdCnt	==	0)	begin
			dspSpiData		<=	headerCmd;
		end	else	begin
			dspSpiData		<=	spiData;
		end	
	end	else	if	(currState	==	TX)	begin
		dspSpiData	<=	dspSpiData<<1;
	end if	(currState	==	IDLE)	begin
		dspSpiData	<=	0;
	end
end

always	@(posedge Clk_i)	begin
	if	(currState	==	TX)	begin
		if	(txCnt	>=	7'd0)	begin
			Mosi0_o	<=	dspSpiData[23];
			Mosi1_o	<=	dspSpiData[17];
			Mosi2_o	<=	dspSpiData[11];
			Mosi3_o	<=	dspSpiData[5];
		end	else	begin
			Mosi0_o	<=	1'b1;
			Mosi1_o	<=	1'b1;
			Mosi2_o	<=	1'b1;
			Mosi3_o	<=	1'b1;
		end
	end	else	begin
		Mosi0_o	<=	1'b1;
		Mosi1_o	<=	1'b1;
		Mosi2_o	<=	1'b1;
		Mosi3_o	<=	1'b1;
	end
end

always	@(posedge	Clk_i)	begin
	if	(currState	==	TX)	begin
		Ss_o	<=	1'b0;
		sckFlag	<=	1'b1;
	end	else	begin
		Ss_o	<=	1'b1;
		sckFlag	<=	1'b0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(Rst_i)	begin
		currState	<=	IDLE;
	end	else	begin
		currState	<=	nextState;
	end
end


always	@(posedge	Clk_i)	begin
	if	(Rst_i)	begin
		currState	<=	IDLE;
	end	else	begin
		currState	<=	nextState;
	end
end


always @(*) begin
	nextState	=	IDLE;
	case(currState)
	IDLE	:	begin
					if (Start_i)	begin
						nextState = CMD;
					end	else begin
						nextState = IDLE;
					end
				end
				
	CMD	:		begin
					if (!txStop)	begin
						nextState = TX;
					end	else begin
						nextState = IDLE;
					end
				end

	TX		:	begin
					if (txCnt==6'd5) begin
						nextState  = PAUSE;
					end	else begin
						nextState  = TX;
					end
				end
        
	PAUSE	:	begin
					if (pauseCnt==4'd2) begin
						nextState  = CMD;
					end	else begin
						nextState  = PAUSE;
					end
				end
	endcase
end



endmodule



















