////////////////////////////////////////////////////////////////////////////////////////////
// Company:			TAIR
// Engineer:		Zaytsev Mikhail
// 
// Create Date:		18/04/2024 
// Design Name: 
// Module Name:		PacketAnalyzer4Mosi 
// Project Name:	SB_TMSG44V1_FPGA
// Target Devices:	Board: SB_TMSG44v1. FPGA: GW1N-LV9PG256C6/I5
// Tool versions:
// Description:		The module analyzes the input data bus DataFromSpi_i[23:0] by the 
//					validity signal ValDataFromSpi_i. When a configuration packet is 
//					received, it is captured into the internal register. Further, each 
//					incoming data packet decrements the internal configuration register 
//					until the internal configuration register is zero, which means that 
//					the module is ready to receive the next configuration packet. Each 
//					decrement sets the data validity bit for the specific end device. 
//					The module also has an output signal Busy_o, which signals that 
//					the module is in the state of processing the data received in 
//					4MOSI mode for writing to the FIFO.
//
// Dependencies:	
// Revision: 
// Revision 1.0 - File Created
// Additional Comments: 
//
////////////////////////////////////////////////////////////////////////////////////////////
module PacketAnalyzer4Mosi (
	input Clk_i,
	input Rst_i,

	input [23:0] DataFromSpi_i,
	input ValDataFromSpi_i,

	input BusyMosi1_i,

	output reg ValLmxDataToFifo_o,
	output reg ValDdsDataToFifo_o,
	output reg ValPotDataToFifo_o,
	output reg ValDacDataToFifo_o,
	output reg ValAttDataToFifo_o,
	output reg ValShRegDataToFifo_o,
	output reg ValMaxDataToFifo_o,
	output reg ValGpioDataToFifo_o,

	output reg Busy_o
);

//==========================================
// Registers
//==========================================
reg [22:0] dataSpiReg;

//==========================================
// Wires
//==========================================
wire lmxOr;
wire ddsOr;
wire potOr;
wire dacOr;
wire attOr;
wire shRegOr;
wire maxOr;
wire gpioOr;

wire [7:0] selector;

//==========================================
// Parameters
//==========================================
localparam [22:0] DECREMENT_LMX 	= 23'h80000;	//23'b000 1000 0000 0000 0000 0000
localparam [22:0] DECREMENT_DDS 	= 23'h20000;	//23'b000 0010 0000 0000 0000 0000
localparam [22:0] DECREMENT_POT 	= 23'h10000;	//23'b000 0001 0000 0000 0000 0000
localparam [22:0] DECREMENT_DAC 	= 23'h8000;		//23'b000 0000 1000 0000 0000 0000
localparam [22:0] DECREMENT_ATT 	= 23'h4000;		//23'b000 0000 0100 0000 0000 0000
localparam [22:0] DECREMENT_SH_REG 	= 23'h1000;		//23'b000 0000 0001 0000 0000 0000
localparam [22:0] DECREMENT_MAX 	= 23'h200;		//23'b000 0000 0000 0010 0000 0000
localparam [22:0] DECREMENT_GPIO 	= 23'h80;		//23'b000 0000 0000 0000 1000 0000

//==========================================
// Assignments
//==========================================
assign lmxOr 	= 	|dataSpiReg[22:19];
assign ddsOr 	= 	|dataSpiReg[18:17];
assign potOr 	= 	 dataSpiReg[16];
assign dacOr 	= 	 dataSpiReg[15];
assign attOr 	= 	 dataSpiReg[14];
assign shRegOr 	= 	|dataSpiReg[13:12];
assign maxOr 	= 	|dataSpiReg[11:9];
assign gpioOr 	= 	|dataSpiReg[8:7];

assign selector = {lmxOr, ddsOr, potOr, dacOr, attOr, shRegOr, maxOr, gpioOr};

//==========================================================================//
//									CODING									//
//==========================================================================//
always @(posedge Clk_i) begin
	if (Rst_i) begin
		Busy_o <= 1'b0;
	end
	else if (dataSpiReg != 0) begin
		Busy_o <= 1'b1;
	end
	else begin
		Busy_o <= 1'b0;
	end
end

always @(posedge Clk_i) begin
	if (Rst_i || BusyMosi1_i) begin
		dataSpiReg <= 23'b0;
		ValLmxDataToFifo_o <= 1'b0;
		ValDdsDataToFifo_o <= 1'b0;
		ValPotDataToFifo_o <= 1'b0;
		ValDacDataToFifo_o <= 1'b0;
		ValAttDataToFifo_o <= 1'b0;
		ValShRegDataToFifo_o <= 1'b0;
		ValMaxDataToFifo_o <= 1'b0;
		ValGpioDataToFifo_o <= 1'b0;
	end
	else if (ValDataFromSpi_i) begin
		if ((dataSpiReg == 0) && (DataFromSpi_i[23] == 1'b1)) begin
			dataSpiReg <= DataFromSpi_i[22:0];
		end
		else begin
			casez(selector)
			8'b1???????: begin //LMX
				dataSpiReg <= dataSpiReg - DECREMENT_LMX;
				ValLmxDataToFifo_o <= 1'b1;
			end
			8'b01??????: begin //DDS
				dataSpiReg <= dataSpiReg - DECREMENT_DDS;
				ValDdsDataToFifo_o <= 1'b1;
			end
			8'b001?????: begin //POT
				dataSpiReg <= dataSpiReg - DECREMENT_POT;
				ValPotDataToFifo_o <= 1'b1;
			end
			8'b0001????: begin //DAC
				dataSpiReg <= dataSpiReg - DECREMENT_DAC;
				ValDacDataToFifo_o <= 1'b1;
			end
			8'b00001???: begin //ATT
				dataSpiReg <= dataSpiReg - DECREMENT_ATT;
				ValAttDataToFifo_o <= 1'b1;
			end
			8'b000001??: begin //ShReg
				dataSpiReg <= dataSpiReg - DECREMENT_SH_REG;
				ValShRegDataToFifo_o <= 1'b1;
			end
			8'b0000001?: begin //MAX2870
				dataSpiReg <= dataSpiReg - DECREMENT_MAX;
				ValMaxDataToFifo_o <= 1'b1;
			end
			8'b00000001: begin //GPIO
				dataSpiReg <= dataSpiReg - DECREMENT_GPIO;
				ValGpioDataToFifo_o <= 1'b1;
			end
			default: begin
				ValLmxDataToFifo_o <= 1'b0;
				ValDdsDataToFifo_o <= 1'b0;
				ValPotDataToFifo_o <= 1'b0;
				ValDacDataToFifo_o <= 1'b0;
				ValAttDataToFifo_o <= 1'b0;
				ValShRegDataToFifo_o <= 1'b0;
				ValMaxDataToFifo_o <= 1'b0;
				ValGpioDataToFifo_o <= 1'b0;
			end
		endcase
//=========================DELETE AFTER HARDWARE TEST===========================
			/*if (lmxOr) begin //LMX
				dataSpiReg <= dataSpiReg - DECREMENT_LMX;
				ValLmxDataToFifo_o 		<= 1'b1;
			end
			else if (ddsOr) begin //DDS
				dataSpiReg <= dataSpiReg - DECREMENT_DDS;
				ValDdsDataToFifo_o 		<= 1'b1;
			end
			else if (potOr) begin //POT
				dataSpiReg <= dataSpiReg - DECREMENT_POT;
				ValPotDataToFifo_o 		<= 1'b1;
			end
			else if (dacOr) begin //DAC
				dataSpiReg <= dataSpiReg - DECREMENT_DAC;
				ValDacDataToFifo_o 		<= 1'b1;
			end
			else if (attOr) begin
				dataSpiReg <= dataSpiReg - DECREMENT_ATT;
				ValAttDataToFifo_o 		<= 1'b1;
			end
			else if (shRegOr) begin
				dataSpiReg <= dataSpiReg - DECREMENT_SH_REG;
				ValShRegDataToFifo_o 	<= 1'b1;
			end
			else if (maxOr) begin
				dataSpiReg <= dataSpiReg - DECREMENT_MAX;
				ValMaxDataToFifo_o 		<= 1'b1;
			end
			else if (gpioOr) begin
				dataSpiReg <= dataSpiReg - DECREMENT_GPIO;
				ValGpioDataToFifo_o 	<= 1'b1;
			end
			else begin
				ValLmxDataToFifo_o 		<= 1'b0;
				ValDdsDataToFifo_o 		<= 1'b0;
				ValPotDataToFifo_o 		<= 1'b0;
				ValDacDataToFifo_o 		<= 1'b0;
				ValAttDataToFifo_o 		<= 1'b0;
				ValShRegDataToFifo_o 	<= 1'b0;
				ValMaxDataToFifo_o 		<= 1'b0;
				ValGpioDataToFifo_o 	<= 1'b0;
			end*/
//=========================DELETE AFTER HARDWARE TEST===========================
		end
	end
	else begin
		ValLmxDataToFifo_o 		<= 1'b0;
		ValDdsDataToFifo_o 		<= 1'b0;
		ValPotDataToFifo_o 		<= 1'b0;
		ValDacDataToFifo_o 		<= 1'b0;
		ValAttDataToFifo_o 		<= 1'b0;
		ValShRegDataToFifo_o 	<= 1'b0;
		ValMaxDataToFifo_o 		<= 1'b0;
		ValGpioDataToFifo_o 	<= 1'b0;
	end
end

endmodule