`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 17.09.2020 14:18:14
// Design Name: 
// Module Name: SlaveSpi
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module	SlaveSpi
#(	
	parameter	CmdRegWidth			=	32,
	parameter	DataCntWidth		=	6,
	parameter	HeaderWidth			=	7,
	parameter	CmdDataRegWith		=	24,
	parameter	Adc0DirAccessAddr	=	7'h13,
	parameter	Adc1DirAccessAddr	=	7'h14
)
(
	input	Clk_i,
	input	Rst_i,

	output	reg	[CmdRegWidth-1:0]	Data_o,
	output	reg	Val_o,
	
	//-----------------------------------
	//input Spi lines from ext. Dsp
	input	Mosi_i,
	input	Sck_i,
	input	Ss_i,
	//-----------------------------------
	
	//-----------------------------------
	output	Mosi_o,
	output	Sck_o,
	output	Ss0_o,
	output	Ss1_o,
	//-----------------------------------
	
	output	[HeaderWidth-1:0]		AnsAddr_o,
	input	[CmdDataRegWith-1:0]	AnsReg_i,
	
	input	Miso_i,
	output	Miso_o
);
//================================================================================
//	REG/WIRE
//================================================================================
	reg	[CmdRegWidth-1:0]		dataCaptReg;
	reg	[DataCntWidth-1:0]		dataCnt;
	reg	[HeaderWidth-1:0]		ansAddr;
	reg	spiMode;
	wire	directTransit	=	(ansAddr	==	Adc0DirAccessAddr)|(ansAddr	==	Adc1DirAccessAddr);
	reg	txWind;
	reg	[4:0]	txCnt;
//================================================================================
//	ASSIGNMENTS
//================================================================================
	assign	Mosi_o		=	(!spiMode&directTransit)?	Mosi_i:1'b1;
	assign	Sck_o		=	(directTransit)?	Sck_i:1'b0;
	assign	Ss0_o		=	(directTransit&&(ansAddr==Adc0DirAccessAddr))?	Ss_i:1'b1;
	assign	Ss1_o		=	(directTransit&&(ansAddr==Adc1DirAccessAddr))?	Ss_i:1'b1;
	assign	AnsAddr_o	=	ansAddr;
	assign	Miso_o		=	txWind?	AnsReg_i[txCnt]:1'b0;
//================================================================================
//	CODING
//================================================================================
always	@(posedge	Sck_i)	begin
	if	(~Ss_i)	begin
		dataCaptReg	<=	{dataCaptReg[CmdRegWidth-2:0],Mosi_i};
	end	else	begin
		dataCaptReg	<=	dataCaptReg;
	end
end

always	@(posedge	Sck_i)	begin
	if	(~Rst_i)	begin
		if	(~Ss_i)	begin
			dataCnt	<=	dataCnt	+	5'd1;
		end
	end	else	begin
		dataCnt	<=	0;
	end
end

always	@(posedge	Sck_i)	begin
	if	(~Rst_i)	begin
		if	(dataCnt	==	5'd1)	begin
			if	(dataCaptReg[CmdRegWidth-CmdRegWidth])	begin
				spiMode	<=	1'b1;
			end	else	begin
				spiMode	<=	1'b0;
			end
		end
	end	else	begin
		spiMode	<=	1'b0;
	end
end

always	@(negedge Sck_i)	begin
	if	(~Rst_i)	begin
		if	(~Ss_i)	begin
			if	(dataCnt	==	5'd8)	begin
				ansAddr	<=	dataCaptReg[CmdRegWidth-26-:HeaderWidth];
			end	else	if	(dataCnt	==	5'd0)	begin
				ansAddr	<=	7'h7F;
			end
		end	else	begin
			ansAddr	<=	7'h7F;	
		end
	end	else	begin
		ansAddr	<=	7'h7F;	
	end
end

//================================================================================
//	Generating output signals
//================================================================================
reg	ssReg;
reg	ssRegR;

always	@(posedge	Clk_i)	begin
	ssReg	<=	Ss_i;
	ssRegR	<=	ssReg;
end

reg	ssPos;

always	@(posedge	Clk_i)	begin
	ssPos	<=	ssReg&!ssRegR;
end

always	@(posedge	Clk_i)	begin
	if	(!directTransit&!spiMode)	begin
		if	(ssReg&!ssRegR)	begin
			Val_o	<=	1'b1;
		end	else	begin
			Val_o	<=	0;
		end
	end
end

always	@(posedge	Clk_i)	begin
	if	(((ansAddr	!=	Adc0DirAccessAddr)|(ansAddr	!=	Adc1DirAccessAddr))&!spiMode)	begin
		if	(ssReg&!ssRegR)	begin
			Data_o	<=	dataCaptReg;
		end	
	end
end

always	@(*)	begin
	if	(spiMode	&	!Ss_i)	begin
		if	(dataCnt	>=5'd8|dataCnt	==	0)	begin
			txWind	=	1'b1;
		end	else	begin
			txWind	=	1'b0;
		end
	end	else	begin
		txWind	=	1'b0;
	end
end

always	@(negedge	Sck_i)	begin
	if	(txWind)	begin
		if	(~Ss_i	&	txWind	&	txCnt!=	0)	begin
			txCnt	<=	txCnt	-	5'd1;
		end	else	begin
			txCnt	<=	5'd24;
		end
	end	else	begin
		txCnt	<=	5'd24;
	end
end


endmodule
























