//////////////////////////////////////////////////////////////////////////////////
// Company:			TAIR
// Engineer:		
// 
// Create Date:		10/30/2023 11:24:31 AM
// Design Name:
// Module Name:		SpiSubSystem
// Project Name:	S5443_V3_FPGA3
// Target Devices:	BOARD: BY5443v3. FPGA: xc7s25csga225-2
// Tool Versions:
// Description: 	This is wrapper that encapsulates FIFO's, Spi modules and 
//					modules that multiplex Spi output lines 
// 
// Dependencies: 
// 
// Revision:
// Revision 1.0 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module SpiSubSystem #(
	parameter STAGES = 3,
	parameter CMD_REG_WIDTH = 32,
	parameter ADDR_REG_WIDTH = 12,
	parameter WIDTH  = 1,
    parameter FIFO_NUM = 7
) 
(
	input Clk123_i,
	input SpiClk_i,

	input TxEn_i,

	input FifoRxRst_i,
	input FifoTxRst_i,
	input FifoRxRstRdPtr_i,
	input FifoTxRstWrPtr_i,
	input SmcAre_i,
	input SmcAwe_i,
	input [ADDR_REG_WIDTH-1:0] SmcAddr_i,
	input ToFifoVal_i,
	input [CMD_REG_WIDTH-1:0] ToFifoData_i,

	input [1:0] WidthSel_i,
	input PulsePol_i,
	input ClockPhase_i,
	input EndianSel_i,
	input Lag_i,
	input Lead_i,
	input SelSt_i,
	input [5:0] Stop_i,
	input Assel_i,

	input ChipSelFpga_i,
	input ChipSelFlash_i,

	input SpiMode_i,
	input SpiEn_i,

	output [CMD_REG_WIDTH-1:0] TxFifoCtrlReg_o,
	output [CMD_REG_WIDTH-1:0] RxFifoCtrlReg_o,
	output [CMD_REG_WIDTH-1:0] DataFromRxFifo_o,

	output Sck_o,
	output Ss_o,
	output SsFlash_o,
	output Mosi0_o,
	inout Mosi1_io,
	output Mosi2_o,
	output Mosi3_o
);

//================================================================================
//	REG/WIRE
//================================================================================
wire [CMD_REG_WIDTH-1:0] toSpiData;
wire emptyFlagTx;
wire initRst;

wire sckR;
wire ssR;
wire mosi0R;
wire valToTxR;
wire valToRxR;

wire sckQ;
wire ssQ;
wire mosi0Q;
wire valToTxQ;

wire valToTxFifoRead;
wire valToRxFifoWrite;
wire [CMD_REG_WIDTH-1:0] dataToRxFifo;

//================================================================================
//  ASSIGNMENTS
//================================================================================
assign valToTxFifoRead  = (SpiMode_i) ? valToTxQ : valToTxR;

assign Mosi1_io = (SpiMode_i) ? mosi1_o : 1'bz;

//================================================================================
//	CODING
//================================================================================
InitRst InitRst_inst
(
	.clk_i		(SpiClk_i),
	.signal_o	(initRst)
);

Sync1bit #(
	.WIDTH		(1),
	.STAGES		(STAGES)
) Sync1bit_inst 
(
	.ClkFast_i	(Clk123_i),
	.ClkSlow_i	(SpiClk_i),
	.TxEn_i		(TxEn_i),
	.TxEn_o		(spiTxEnSync)
);

DataFifoWrapper #(
	.CMD_REG_WIDTH		(CMD_REG_WIDTH),
	.ADDR_REG_WIDTH		(ADDR_REG_WIDTH),
	.STAGES				(STAGES),
	.FIFO_NUM			(FIFO_NUM)
) DataFifoWrapper
(
	.WrClk_i			(Clk123_i),
	.RdClk_i			(SpiClk_i),

	.FifoRxRst_i		(FifoRxRst_i),
	.FifoTxRst_i		(FifoTxRst_i),
	.FifoRxRstRdPtr_i	(FifoRxRstRdPtr_i),
	.FifoTxRstWrPtr_i	(FifoTxRstWrPtr_i),

	.SmcAre_i			(SmcAre_i),
	.SmcAwe_i			(SmcAwe_i),
	.SmcAddr_i			(SmcAddr_i),
	.ToFifoVal_i		(ToFifoVal_i),
	.ToFifoRxData_i		(dataToRxFifo),
	.ToFifoRxWriteVal_i	(valToRxR),
	.ToFifoTxReadVal_i	(valToTxFifoRead),
	.ToFifoData_i		(ToFifoData_i),

	.TxFifoCtrlReg_o	(TxFifoCtrlReg_o),
	.RxFifoCtrlReg_o	(RxFifoCtrlReg_o),
	.EmptyFlagTx_o		(emptyFlagTx),
	.DataFromRxFifo_o	(DataFromRxFifo_o),
	.ToSpiData_o		(toSpiData)
);

SPIm SPIm_inst (
	.Clk_i			(SpiClk_i),
	.Start_i		(spiTxEnSync),
	.Rst_i			(initRst | SpiMode_i | !SpiEn_i),
	.EmptyFlag_i	(emptyFlagTx),
	.SpiData_i		(toSpiData),
	.WidthSel_i		(WidthSel_i),
	.PulsePol_i		(PulsePol_i),
	.ClockPhase_i	(ClockPhase_i),
	.EndianSel_i	(EndianSel_i),
	.Lag_i			(Lag_i),
	.Lead_i			(Lead_i),
	.Stop_i			(Stop_i),
	.SelSt_i		(SelSt_i),
	.Sck_o			(sckR),
	.Ss_o			(ssR),
	.Mosi0_o		(mosi0R),
	.Val_o			(valToTxR)
);

SPIs SPIs_inst (
	.Clk_i			(SpiClk_i),
	.Rst_i			(initRst | SpiMode_i),
	.Sck_i			(sckR),
	.Ss_i			(ssR),
	.Mosi0_i		(Mosi1_io),
	.WidthSel_i		(WidthSel_i),
	.EndianSel_i	(EndianSel_i),
	.SelSt_i		(SelSt_i),
	.DataToRxFifo_o	(dataToRxFifo),
	.Val_o			(valToRxR)
);

QuadSPIm QuadSPIm_inst (
	.Clk_i			(SpiClk_i),
	.Start_i		(spiTxEnSync),
	.Rst_i			(initRst | !SpiMode_i | !SpiEn_i),
	.EmptyFlag_i	(emptyFlagTx),
	.SpiData_i		(toSpiData),
	.WidthSel_i		(WidthSel_i),
	.PulsePol_i		(PulsePol_i),
	.ClockPhase_i	(ClockPhase_i),
	.EndianSel_i	(EndianSel_i),
	.Lag_i			(Lag_i),
	.Lead_i			(Lead_i),
	.Stop_i			(Stop_i),
	.SelSt_i		(SelSt_i),
	.Sck_o			(sckQ),
	.Ss_o			(ssQ),
	.Mosi0_o		(mosi0Q),
	.Mosi1_o		(mosi1_o),
	.Mosi2_o		(Mosi2_o),
	.Mosi3_o		(Mosi3_o),
	.Val_o			(valToTxQ)
);

SpiLinesMuxer SpiLinesMuxer (
	.SsR_i			(ssR),
	.SsQ_i			(ssQ),
	.SckR_i			(sckR),
	.SckQ_i			(sckQ),
	.Mosi0R_i		(mosi0R),
	.Mosi0Q_i		(mosi0Q),
	.ChipSelFpga_i	(ChipSelFpga_i),
	.ChipSelFlash_i	(ChipSelFlash_i),
	.Assel_i		(Assel_i),
	.SpiMode_i		(SpiMode_i),
	.Ss_o			(Ss_o),
	.SsFlash_o		(SsFlash_o),
	.Sck_o			(Sck_o),
	.Mosi0_o		(Mosi0_o)
);

endmodule