`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 10/30/2023 11:24:31 AM
// Design Name: 
// Module Name: S5443_3Top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module S5443_3Top 
#(
	parameter CMD_REG_WIDTH = 32,
	parameter ADDR_REG_WIDTH = 12,
	parameter STAGES = 3,
	parameter SPI_NUM = 7
)
(
	input Clk123_i,
	input [ADDR_REG_WIDTH-2:0] SmcAddr_i,
	inout [CMD_REG_WIDTH/2-1:0] SmcData_io,
	
	input SmcAwe_i,
	input SmcAmsN_i,
	
	input SmcAre_i,
	input [1:0] SmcBe_i,
	input SmcAoe_i,
	input [SPI_NUM-1:0] Ld_i,

	output Led_o,

	output [SPI_NUM-1:0] Mosi0_o, 
	inout  [SPI_NUM-1:0] Mosi1_io,	//inout: when RSPI mode, input; when QSPI mode output; 
	output [SPI_NUM-1:0] Mosi2_o,
	output [SPI_NUM-2:0] Mosi3_o,
	output [SPI_NUM-1:0] Ss_o,
	output [SPI_NUM-1:0] SsFlash_o,
	output [SPI_NUM-1:0] Sck_o,
	output [SPI_NUM-1:0] SpiRst_o,
	output [SPI_NUM-1:0] SpiDir_o,
	output LoCsReg_o,
	output LD_o
);

//================================================================================
//  REG/WIRE
//================================================================================
	wire clk80;
	wire [ADDR_REG_WIDTH-1:0] addrExt;

	wire [SPI_NUM-1:0] mosi3;
	wire [SPI_NUM-1:0] txEn;

	wire initRst;
	wire gclk;

	wire [0:7] baudRate [SPI_NUM-1:0];
	
	wire [0:31] txFifoCtrlReg [SPI_NUM-1:0];
	wire [0:31] rxFifoCtrlReg [SPI_NUM-1:0];
	
	//InitRst
	wire rst80;

	//SPI0
	wire [CMD_REG_WIDTH-1:0] spi0Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi0Clk;
	wire [CMD_REG_WIDTH-1:0] spi0CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi0CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi0TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi0RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi0TxFifo;
	wire [CMD_REG_WIDTH-1:0] spi0RxFifo;
	wire [CMD_REG_WIDTH-1:0] spi0TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi0RxFifoCtrlReg;
	
	wire [CMD_REG_WIDTH-1:0] spi0CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi0ClkRR;
	wire [CMD_REG_WIDTH-1:0] spi0CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi0CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi0TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi0RxFifoCtrlRR;
	
	//SPI1
	wire [CMD_REG_WIDTH-1:0] spi1Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi1Clk;
	wire [CMD_REG_WIDTH-1:0] spi1CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi1CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi1TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi1RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi1TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi1RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi1CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi1CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi1CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi1TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi1RxFifoCtrlRR;

	//SPI2
	wire [CMD_REG_WIDTH-1:0] spi2Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi2Clk;
	wire [CMD_REG_WIDTH-1:0] spi2CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi2CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi2TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi2RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi2TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi2RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi2CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi2CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi2CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi2TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi2RxFifoCtrlRR;

	//SPI3
	wire [CMD_REG_WIDTH-1:0] spi3Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi3Clk;
	wire [CMD_REG_WIDTH-1:0] spi3CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi3CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi3TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi3RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi3TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi3RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi3CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi3ClkRR;
	wire [CMD_REG_WIDTH-1:0] spi3CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi3CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi3TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi3RxFifoCtrlRR;

	//SPI4
	wire [CMD_REG_WIDTH-1:0] spi4Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi4Clk;
	wire [CMD_REG_WIDTH-1:0] spi4CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi4CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi4TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi4RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi4TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi4RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi4CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi4ClkRR;
	wire [CMD_REG_WIDTH-1:0] spi4CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi4CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi4TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi4RxFifoCtrlRR;
	
	//SPI5
	wire [CMD_REG_WIDTH-1:0] spi5Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi5Clk;
	wire [CMD_REG_WIDTH-1:0] spi5CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi5CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi5TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi5RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi5TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi5RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi5CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi5ClkRR;
	wire [CMD_REG_WIDTH-1:0] spi5CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi5CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi5TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi5RxFifoCtrlRR;

	//SPI6
	wire [CMD_REG_WIDTH-1:0] spi6Ctrl;
	wire [CMD_REG_WIDTH-1:0] spi6Clk;
	wire [CMD_REG_WIDTH-1:0] spi6CsDelay;
	wire [CMD_REG_WIDTH-1:0] spi6CsCtrl;
	wire [CMD_REG_WIDTH-1:0] spi6TxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi6RxFifoCtrl;
	wire [CMD_REG_WIDTH-1:0] spi6TxFifoCtrlReg;
	wire [CMD_REG_WIDTH-1:0] spi6RxFifoCtrlReg;

	wire [CMD_REG_WIDTH-1:0] spi6CtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi6ClkRR;
	wire [CMD_REG_WIDTH-1:0] spi6CsDelayRR;
	wire [CMD_REG_WIDTH-1:0] spi6CsCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi6TxFifoCtrlRR;
	wire [CMD_REG_WIDTH-1:0] spi6RxFifoCtrlRR;
	
	wire [CMD_REG_WIDTH-1:0] spiTxRxEn;
	wire [CMD_REG_WIDTH-1:0] Gpio;
	
	wire [ADDR_REG_WIDTH-1:0]	toRegMapAddr;
	wire [CMD_REG_WIDTH/2-1:0]	toRegMapData;
	wire toRegMapVal;
	
	wire [SPI_NUM-1:0]	toFifoVal;
	wire [CMD_REG_WIDTH*SPI_NUM-1:0] toFifoData;
	
	wire [SPI_NUM-1:0]	toSpiVal;
	wire [0:31]	toSpiData [SPI_NUM-1:0];
	
	wire [0:1] widthSel [SPI_NUM-1:0];
	wire [SPI_NUM-1:0] clockPol;
	wire [SPI_NUM-1:0] clockPhase;
	wire [SPI_NUM-1:0] endianSel;
	wire [SPI_NUM-1:0] selSt;
	wire [SPI_NUM-1:0] spiMode;
	
	wire [0:5] stopDelay [SPI_NUM-1:0];
	wire [SPI_NUM-1:0] leadx;
	wire [SPI_NUM-1:0] lag; 
	wire [SPI_NUM-1:0] fifoRxRst;
	wire [SPI_NUM-1:0] fifoTxRst;
	wire [SPI_NUM-1:0] fifoRxRstRdPtr;
	wire [SPI_NUM-1:0] fifoTxRstWrPtr;
	wire [0:7]  wordCntTx [SPI_NUM-1:0];
	wire [0:7]  wordCntRx [SPI_NUM-1:0];
	
	wire [SPI_NUM-1:0] chipSelFpga;
	wire [SPI_NUM-1:0] chipSelFlash;
	
	wire [SPI_NUM-1:0] assel;
	
	wire	[SPI_NUM-1:0]	spiClkBus;

	//RxFifo 
	wire [0:31] dataFromRxFifo [SPI_NUM-1:0];
	
	wire [CMD_REG_WIDTH/2-1:0] muxedData;
	
	wire smcValComb; 
	wire [CMD_REG_WIDTH/2-1:0]	ansData;

	wire requestToFifo;

	wire [SPI_NUM-1:0] spiEn;

	wire [SPI_NUM-1:0] ldReg;

	wire [SPI_NUM-1:0] ssW;

//================================================================================
//  ASSIGNMENTS
//================================================================================
	assign addrExt = {SmcAddr_i, 1'b0};
	assign smcValComb = (!SmcAmsN_i && !SmcAwe_i) ? 1'b1 : 1'b0;
	assign txEn = spiTxRxEn[6:0];

	assign Mosi3_o[0] = mosi3[0];
	assign Mosi3_o[1] = mosi3[1];
	assign Mosi3_o[2] = mosi3[2];
	assign Mosi3_o[3] = mosi3[3];
	assign Mosi3_o[4] = mosi3[4];
	// assign Mosi3_o[5] = mosi3[5];
	assign Mosi3_o[5] = mosi3[6];// Mosi6 

	assign Ss_o		 = ssW;
	assign LoCsReg_o = ssW[5];
	
	assign widthSel[0] = spi0CtrlRR[6:5];
	assign widthSel[1] = spi1CtrlRR[6:5];
	assign widthSel[2] = spi2CtrlRR[6:5];
	assign widthSel[3] = spi3CtrlRR[6:5];
	assign widthSel[4] = spi4CtrlRR[6:5];
	assign widthSel[5] = spi5CtrlRR[6:5];
	assign widthSel[6] = spi6CtrlRR[6:5];

	assign spiEn[0] = spi0CtrlRR[0];
	assign spiEn[1] = spi1CtrlRR[0];
	assign spiEn[2] = spi2CtrlRR[0];
	assign spiEn[3] = spi3CtrlRR[0];
	assign spiEn[4] = spi4CtrlRR[0];
	assign spiEn[5] = spi5CtrlRR[0];
	assign spiEn[6] = spi6CtrlRR[0];
	
	assign spiMode[0] = spi0CtrlRR[7];
	assign spiMode[1] = spi1CtrlRR[7];
	assign spiMode[2] = spi2CtrlRR[7];
	assign spiMode[3] = spi3CtrlRR[7];
	assign spiMode[4] = spi4CtrlRR[7];
	assign spiMode[5] = spi5CtrlRR[7];
	assign spiMode[6] = spi6CtrlRR[7];
	
	assign clockPol[0] = spi0CtrlRR[2];
	assign clockPol[1] = spi1CtrlRR[2];
	assign clockPol[2] = spi2CtrlRR[2];
	assign clockPol[3] = spi3CtrlRR[2];
	assign clockPol[4] = spi4CtrlRR[2];
	assign clockPol[5] = spi5CtrlRR[2];
	assign clockPol[6] = spi6CtrlRR[2];
	
	assign clockPhase[0] = spi0CtrlRR[1];
	assign clockPhase[1] = spi1CtrlRR[1];
	assign clockPhase[2] = spi2CtrlRR[1];
	assign clockPhase[3] = spi3CtrlRR[1];
	assign clockPhase[4] = spi4CtrlRR[1];
	assign clockPhase[5] = spi5CtrlRR[1];
	assign clockPhase[6] = spi6CtrlRR[1];
	
	assign endianSel[0] = spi0CtrlRR[8];
	assign endianSel[1] = spi1CtrlRR[8];
	assign endianSel[2] = spi2CtrlRR[8];
	assign endianSel[3] = spi3CtrlRR[8];
	assign endianSel[4] = spi4CtrlRR[8];
	assign endianSel[5] = spi5CtrlRR[8];
	assign endianSel[6] = spi6CtrlRR[8];
	
	assign selSt[0] = spi0CtrlRR[4];
	assign selSt[1] = spi1CtrlRR[4];
	assign selSt[2] = spi2CtrlRR[4];
	assign selSt[3] = spi3CtrlRR[4];
	assign selSt[4] = spi4CtrlRR[4];
	assign selSt[5] = spi5CtrlRR[4];
	assign selSt[6] = spi6CtrlRR[4];
	
	assign assel[0] = spi0CtrlRR[3];
	assign assel[1] = spi1CtrlRR[3];
	assign assel[2] = spi2CtrlRR[3];
	assign assel[3] = spi3CtrlRR[3];
	assign assel[4] = spi4CtrlRR[3];
	assign assel[5] = spi5CtrlRR[3];
	assign assel[6] = spi6CtrlRR[3];
	
	assign stopDelay[0] = spi0CsDelayRR[7:2];
	assign stopDelay[1] = spi1CsDelayRR[7:2];
	assign stopDelay[2] = spi2CsDelayRR[7:2];
	assign stopDelay[3] = spi3CsDelayRR[7:2];
	assign stopDelay[4] = spi4CsDelayRR[7:2];
	assign stopDelay[5] = spi5CsDelayRR[7:2];
	assign stopDelay[6] = spi6CsDelayRR[7:2];
	
	assign leadx[0] = spi0CsDelayRR[1];
	assign leadx[1] = spi1CsDelayRR[1];
	assign leadx[2] = spi2CsDelayRR[1];
	assign leadx[3] = spi3CsDelayRR[1];
	assign leadx[4] = spi4CsDelayRR[1];
	assign leadx[5] = spi5CsDelayRR[1];
	assign leadx[6] = spi6CsDelayRR[1];
	
	assign lag[0] = spi0CsDelayRR[0];
	assign lag[1] = spi1CsDelayRR[0];
	assign lag[2] = spi2CsDelayRR[0];
	assign lag[3] = spi3CsDelayRR[0];
	assign lag[4] = spi4CsDelayRR[0];
	assign lag[5] = spi5CsDelayRR[0];
	assign lag[6] = spi6CsDelayRR[0];
	
	assign baudRate[0] = spi0Clk[7:0];
	assign baudRate[1] = spi1Clk[7:0];
	assign baudRate[2] = spi2Clk[7:0];
	assign baudRate[3] = spi3Clk[7:0];
	assign baudRate[4] = spi4Clk[7:0];
	assign baudRate[5] = spi5Clk[7:0];
	assign baudRate[6] = spi6Clk[7:0];
	
	assign SpiRst_o[0] = Gpio[0];
	assign SpiRst_o[1] = Gpio[1];
	assign SpiRst_o[2] = Gpio[2];
	assign SpiRst_o[3] = Gpio[3];
	assign SpiRst_o[4] = Gpio[4];
	assign SpiRst_o[5] = Gpio[5];
	assign SpiRst_o[6] = Gpio[6];
	
	assign fifoRxRstRdPtr[0] = spi0RxFifoCtrl[0];
	assign fifoRxRstRdPtr[1] = spi1RxFifoCtrl[0];
	assign fifoRxRstRdPtr[2] = spi2RxFifoCtrl[0];
	assign fifoRxRstRdPtr[3] = spi3RxFifoCtrl[0];
	assign fifoRxRstRdPtr[4] = spi4RxFifoCtrl[0];
	assign fifoRxRstRdPtr[5] = spi5RxFifoCtrl[0];
	assign fifoRxRstRdPtr[6] = spi6RxFifoCtrl[0];
	
	assign fifoRxRst[0] = spi0RxFifoCtrlRR[0];
	assign fifoRxRst[1] = spi1RxFifoCtrlRR[0];
	assign fifoRxRst[2] = spi2RxFifoCtrlRR[0];
	assign fifoRxRst[3] = spi3RxFifoCtrlRR[0];
	assign fifoRxRst[4] = spi4RxFifoCtrlRR[0];
	assign fifoRxRst[5] = spi5RxFifoCtrlRR[0];
	assign fifoRxRst[6] = spi6RxFifoCtrlRR[0];
	
	assign fifoTxRstWrPtr[0] = spi0TxFifoCtrl[0];
	assign fifoTxRstWrPtr[1] = spi1TxFifoCtrl[0];
	assign fifoTxRstWrPtr[2] = spi2TxFifoCtrl[0];
	assign fifoTxRstWrPtr[3] = spi3TxFifoCtrl[0];
	assign fifoTxRstWrPtr[4] = spi4TxFifoCtrl[0];
	assign fifoTxRstWrPtr[5] = spi5TxFifoCtrl[0];
	assign fifoTxRstWrPtr[6] = spi6TxFifoCtrl[0];
	
	assign fifoTxRst[0] = spi0TxFifoCtrlRR[0];
	assign fifoTxRst[1] = spi1TxFifoCtrlRR[0];
	assign fifoTxRst[2] = spi2TxFifoCtrlRR[0];
	assign fifoTxRst[3] = spi3TxFifoCtrlRR[0];
	assign fifoTxRst[4] = spi4TxFifoCtrlRR[0];
	assign fifoTxRst[5] = spi5TxFifoCtrlRR[0];
	assign fifoTxRst[6] = spi6TxFifoCtrlRR[0];
	
	assign LD_o = ldReg[0]&ldReg[1]&ldReg[2]&ldReg[3]&ldReg[4]&ldReg[5]&ldReg[6];
	
	assign wordCntRx[0] = spi0RxFifoCtrlRR[15:8];
	assign wordCntRx[1] = spi1RxFifoCtrlRR[15:8];
	assign wordCntRx[2] = spi2RxFifoCtrlRR[15:8];
	assign wordCntRx[3] = spi3RxFifoCtrlRR[15:8];
	assign wordCntRx[4] = spi4RxFifoCtrlRR[15:8];
	assign wordCntRx[5] = spi5RxFifoCtrlRR[15:8];
	assign wordCntRx[6] = spi6RxFifoCtrlRR[15:8];
	
	assign wordCntTx[0] = spi0TxFifoCtrlRR[15:8];
	assign wordCntTx[1] = spi1TxFifoCtrlRR[15:8];
	assign wordCntTx[2] = spi2TxFifoCtrlRR[15:8];
	assign wordCntTx[3] = spi3TxFifoCtrlRR[15:8];
	assign wordCntTx[4] = spi4TxFifoCtrlRR[15:8];
	assign wordCntTx[5] = spi5TxFifoCtrlRR[15:8];
	assign wordCntTx[6] = spi6TxFifoCtrlRR[15:8];
	
	assign chipSelFpga[0] = spi0CsCtrlRR[0];
	assign chipSelFpga[1] = spi1CsCtrlRR[0];
	assign chipSelFpga[2] = spi2CsCtrlRR[0];
	assign chipSelFpga[3] = spi3CsCtrlRR[0];
	assign chipSelFpga[4] = spi4CsCtrlRR[0];
	assign chipSelFpga[5] = spi5CsCtrlRR[0];
	assign chipSelFpga[6] = spi6CsCtrlRR[0];
	
	assign chipSelFlash[0] = spi0CsCtrlRR[1];
	assign chipSelFlash[1] = spi1CsCtrlRR[1];
	assign chipSelFlash[2] = spi2CsCtrlRR[1];
	assign chipSelFlash[3] = spi3CsCtrlRR[1];
	assign chipSelFlash[4] = spi4CsCtrlRR[1];
	assign chipSelFlash[5] = spi5CsCtrlRR[1];
	assign chipSelFlash[6] = spi6CsCtrlRR[1];
	
	assign SpiDir_o[0] = (spiMode[0]) ? 1'b1 : 1'b0 ;
	assign SpiDir_o[1] = (spiMode[1]) ? 1'b1 : 1'b0 ;
	assign SpiDir_o[2] = (spiMode[2]) ? 1'b1 : 1'b0 ;
	assign SpiDir_o[3] = (spiMode[3]) ? 1'b1 : 1'b0 ;
	assign SpiDir_o[4] = (spiMode[4]) ? 1'b1 : 1'b0 ;
	assign SpiDir_o[5] = 1'b1;
	assign SpiDir_o[6] = (spiMode[6]) ? 1'b1 : 1'b0 ;
	
	assign spi0TxFifoCtrlReg = txFifoCtrlReg[0];
	assign spi1TxFifoCtrlReg = txFifoCtrlReg[1];
	assign spi2TxFifoCtrlReg = txFifoCtrlReg[2];
	assign spi3TxFifoCtrlReg = txFifoCtrlReg[3];
	assign spi4TxFifoCtrlReg = txFifoCtrlReg[4];
	assign spi5TxFifoCtrlReg = txFifoCtrlReg[5];
	assign spi6TxFifoCtrlReg = txFifoCtrlReg[6];
	
	assign spi0RxFifoCtrlReg = rxFifoCtrlReg[0];
	assign spi1RxFifoCtrlReg = rxFifoCtrlReg[1];
	assign spi2RxFifoCtrlReg = rxFifoCtrlReg[2];
	assign spi3RxFifoCtrlReg = rxFifoCtrlReg[3];
	assign spi4RxFifoCtrlReg = rxFifoCtrlReg[4];
	assign spi5RxFifoCtrlReg = rxFifoCtrlReg[5];
	assign spi6RxFifoCtrlReg = rxFifoCtrlReg[6];
	
	assign	SmcData_io	=	(!SmcAre_i && !SmcAoe_i) ? muxedData : 16'bz;
	
//================================================================================
//  CODING
//================================================================================	
	SmcAnsMux SmcAnsMux
	(
		.Clk_i				(gclk),
		.Addr_i				(addrExt),
		.ToRegMapAddr_i		(toRegMapAddr),
		.RequestToFifo_i	(requestToFifo),
		.FifoRxRst_i		(fifoRxRstRdPtr[0]),
		.SmcAre_i			(SmcAre_i),

		.DataFromRegMap_i	(ansData),

		.DataFromRxFifo1_i	(dataFromRxFifo[0]),
		.DataFromRxFifo2_i	(dataFromRxFifo[1]),
		.DataFromRxFifo3_i	(dataFromRxFifo[2]),
		.DataFromRxFifo4_i	(dataFromRxFifo[3]),
		.DataFromRxFifo5_i	(dataFromRxFifo[4]),
		.DataFromRxFifo6_i	(dataFromRxFifo[5]),
		.DataFromRxFifo7_i	(dataFromRxFifo[6]),

		.AnsData_o 			(muxedData)
	);
	
	BUFG BUFG_inst (
		.O	(gclk),		// 1-bit output: Clock output
		.I	(Clk123_i)	// 1-bit input: Clock input
	);
	
	SmcInDataMux SmcInDataMux
	(
		.Clk_i				(gclk),
		.Rst_i				(initRst),
	
		.SmcVal_i			(smcValComb),
		.SmcData_i			(SmcData_io),
		.SmcAddr_i			(addrExt),

		.RequestToFifo_o	(requestToFifo),

		.ToRegMapVal_o		(toRegMapVal),
		.ToRegMapData_o		(toRegMapData),
		.ToRegMapAddr_o		(toRegMapAddr),
	
		.ToFifoVal_o		(toFifoVal),
		.ToFifoData_o		(toFifoData)
	);
	
	CDC #(
		.WIDTH				(CMD_REG_WIDTH),
		.STAGES				(STAGES),
		.SPI_NUM			(SPI_NUM)

	) synchronizer(
		.ClkFast_i			(gclk),
		.ClkSlow_i			(spiClkBus),

		.Spi0Ctrl_i			(spi0Ctrl),
		.Spi0CsCtrl_i		(spi0CsCtrl),
		.Spi0CsDelay_i		(spi0CsDelay),
		.Spi0TxFifoCtrl_i	(spi0TxFifoCtrl),
		.Spi0RxFifoCtrl_i	(spi0RxFifoCtrl),

		.Spi1Ctrl_i			(spi1Ctrl),
		.Spi1CsCtrl_i		(spi1CsCtrl),
		.Spi1CsDelay_i		(spi1CsDelay),
		.Spi1TxFifoCtrl_i	(spi1TxFifoCtrl),
		.Spi1RxFifoCtrl_i	(spi1RxFifoCtrl),

		.Spi2Ctrl_i			(spi2Ctrl),
		.Spi2CsCtrl_i		(spi2CsCtrl),
		.Spi2CsDelay_i		(spi2CsDelay),
		.Spi2TxFifoCtrl_i	(spi2TxFifoCtrl),
		.Spi2RxFifoCtrl_i	(spi2RxFifoCtrl),

		.Spi3Ctrl_i			(spi3Ctrl),
		.Spi3CsCtrl_i		(spi3CsCtrl),
		.Spi3CsDelay_i		(spi3CsDelay),
		.Spi3TxFifoCtrl_i	(spi3TxFifoCtrl),
		.Spi3RxFifoCtrl_i	(spi3RxFifoCtrl),

		.Spi4Ctrl_i			(spi4Ctrl),
		.Spi4CsCtrl_i		(spi4CsCtrl),
		.Spi4CsDelay_i		(spi4CsDelay),
		.Spi4TxFifoCtrl_i	(spi4TxFifoCtrl),
		.Spi4RxFifoCtrl_i	(spi4RxFifoCtrl),

		.Spi5Ctrl_i			(spi5Ctrl),
		.Spi5CsCtrl_i		(spi5CsCtrl),
		.Spi5CsDelay_i		(spi5CsDelay),
		.Spi5TxFifoCtrl_i	(spi5TxFifoCtrl),
		.Spi5RxFifoCtrl_i	(spi5RxFifoCtrl),

		.Spi6Ctrl_i			(spi6Ctrl),
		.Spi6CsCtrl_i		(spi6CsCtrl),
		.Spi6CsDelay_i		(spi6CsDelay),
		.Spi6TxFifoCtrl_i	(spi6TxFifoCtrl),
		.Spi6RxFifoCtrl_i	(spi6RxFifoCtrl),

		.Spi0Ctrl_o			(spi0CtrlRR),
		.Spi0CsCtrl_o		(spi0CsCtrlRR),
		.Spi0CsDelay_o		(spi0CsDelayRR),
		.Spi0TxFifoCtrl_o	(spi0TxFifoCtrlRR),
		.Spi0RxFifoCtrl_o	(spi0RxFifoCtrlRR),

		.Spi1Ctrl_o			(spi1CtrlRR),
		.Spi1CsCtrl_o		(spi1CsCtrlRR),
		.Spi1CsDelay_o		(spi1CsDelayRR),
		.Spi1TxFifoCtrl_o	(spi1TxFifoCtrlRR),
		.Spi1RxFifoCtrl_o	(spi1RxFifoCtrlRR),

		.Spi2Ctrl_o			(spi2CtrlRR),
		.Spi2CsCtrl_o		(spi2CsCtrlRR),
		.Spi2CsDelay_o		(spi2CsDelayRR),
		.Spi2TxFifoCtrl_o	(spi2TxFifoCtrlRR),
		.Spi2RxFifoCtrl_o	(spi2RxFifoCtrlRR),

		.Spi3Ctrl_o			(spi3CtrlRR),
		.Spi3CsCtrl_o		(spi3CsCtrlRR),
		.Spi3CsDelay_o		(spi3CsDelayRR),
		.Spi3TxFifoCtrl_o	(spi3TxFifoCtrlRR),
		.Spi3RxFifoCtrl_o	(spi3RxFifoCtrlRR),

		.Spi4Ctrl_o			(spi4CtrlRR),
		.Spi4CsCtrl_o		(spi4CsCtrlRR),
		.Spi4CsDelay_o		(spi4CsDelayRR),
		.Spi4TxFifoCtrl_o	(spi4TxFifoCtrlRR),
		.Spi4RxFifoCtrl_o	(spi4RxFifoCtrlRR),

		.Spi5Ctrl_o			(spi5CtrlRR),
		.Spi5CsCtrl_o		(spi5CsCtrlRR),
		.Spi5CsDelay_o		(spi5CsDelayRR),
		.Spi5TxFifoCtrl_o	(spi5TxFifoCtrlRR),
		.Spi5RxFifoCtrl_o	(spi5RxFifoCtrlRR),

		.Spi6Ctrl_o			(spi6CtrlRR),
		.Spi6CsCtrl_o		(spi6CsCtrlRR),
		.Spi6CsDelay_o		(spi6CsDelayRR),
		.Spi6TxFifoCtrl_o	(spi6TxFifoCtrlRR),
		.Spi6RxFifoCtrl_o	(spi6RxFifoCtrlRR)
	);

	RegMap 
	#(
		.CMD_REG_WIDTH(32),
		.ADDR_REG_WIDTH(12)
	)
	RegMap_inst 
	(
		.Clk_i					(gclk),
		.Rst_i					(initRst),
		.SmcBe_i				(SmcBe_i),

		.Data_i					(toRegMapData),
		.Addr_i					(toRegMapAddr),
		.Val_i					(toRegMapVal),

		.TxFifoCtrlReg0_i		(spi0TxFifoCtrlReg),
		.TxFifoCtrlReg1_i		(spi1TxFifoCtrlReg),
		.TxFifoCtrlReg2_i		(spi2TxFifoCtrlReg),
		.TxFifoCtrlReg3_i		(spi3TxFifoCtrlReg),
		.TxFifoCtrlReg4_i		(spi4TxFifoCtrlReg),
		.TxFifoCtrlReg5_i		(spi5TxFifoCtrlReg),
		.TxFifoCtrlReg6_i		(spi6TxFifoCtrlReg),
		.RxFifoCtrlReg0_i		(spi0RxFifoCtrlReg),
		.RxFifoCtrlReg1_i		(spi1RxFifoCtrlReg),
		.RxFifoCtrlReg2_i		(spi2RxFifoCtrlReg),
		.RxFifoCtrlReg3_i		(spi3RxFifoCtrlReg),
		.RxFifoCtrlReg4_i		(spi4RxFifoCtrlReg),
		.RxFifoCtrlReg5_i		(spi5RxFifoCtrlReg),
		.RxFifoCtrlReg6_i		(spi6RxFifoCtrlReg),

		.LdReg_i				(ldReg),

		//Spi0
		.Spi0CtrlReg_o			(spi0Ctrl),
		.Spi0ClkReg_o			(spi0Clk),
		.Spi0CsDelayReg_o		(spi0CsDelay),
		.Spi0CsCtrlReg_o		(spi0CsCtrl),
		.Spi0TxFifoCtrlReg_o	(spi0TxFifoCtrl),
		.Spi0RxFifoCtrlReg_o	(spi0RxFifoCtrl),
		//Spi1
		.Spi1CtrlReg_o			(spi1Ctrl),
		.Spi1ClkReg_o			(spi1Clk),
		.Spi1CsDelayReg_o		(spi1CsDelay),
		.Spi1CsCtrlReg_o		(spi1CsCtrl),
		.Spi1TxFifoCtrlReg_o	(spi1TxFifoCtrl),
		.Spi1RxFifoCtrlReg_o	(spi1RxFifoCtrl),
		//Spi2
		.Spi2CtrlReg_o			(spi2Ctrl),
		.Spi2ClkReg_o			(spi2Clk),
		.Spi2CsDelayReg_o		(spi2CsDelay),
		.Spi2CsCtrlReg_o		(spi2CsCtrl),
		.Spi2TxFifoCtrlReg_o	(spi2TxFifoCtrl),
		.Spi2RxFifoCtrlReg_o	(spi2RxFifoCtrl),
		//Spi3
		.Spi3CtrlReg_o			(spi3Ctrl),
		.Spi3ClkReg_o			(spi3Clk),
		.Spi3CsDelayReg_o		(spi3CsDelay),
		.Spi3CsCtrlReg_o		(spi3CsCtrl),
		.Spi3TxFifoCtrlReg_o	(spi3TxFifoCtrl),
		.Spi3RxFifoCtrlReg_o	(spi3RxFifoCtrl),
		//Spi4
		.Spi4CtrlReg_o			(spi4Ctrl),
		.Spi4ClkReg_o			(spi4Clk),
		.Spi4CsDelayReg_o		(spi4CsDelay),
		.Spi4CsCtrlReg_o		(spi4CsCtrl),
		.Spi4TxFifoCtrlReg_o	(spi4TxFifoCtrl),
		.Spi4RxFifoCtrlReg_o	(spi4RxFifoCtrl),
		//Spi5
		.Spi5CtrlReg_o			(spi5Ctrl),
		.Spi5ClkReg_o			(spi5Clk),
		.Spi5CsDelayReg_o		(spi5CsDelay),
		.Spi5CsCtrlReg_o		(spi5CsCtrl),
		.Spi5TxFifoCtrlReg_o	(spi5TxFifoCtrl),
		.Spi5RxFifoCtrlReg_o	(spi5RxFifoCtrl),
		//Spi6
		.Spi6CtrlReg_o			(spi6Ctrl),
		.Spi6ClkReg_o			(spi6Clk),
		.Spi6CsDelayReg_o		(spi6CsDelay),
		.Spi6CsCtrlReg_o		(spi6CsCtrl),
		.Spi6TxFifoCtrlReg_o	(spi6TxFifoCtrl),
		.Spi6RxFifoCtrlReg_o	(spi6RxFifoCtrl),
		
		.SpiTxRxEnReg_o			(spiTxRxEn),
		.GPIOAReg_o				(Gpio),

		.AnsDataReg_o			(ansData),
		.Led_o					(Led_o)
	);
	
	ClkManager #(
		.SPI_NUM(SPI_NUM),
		.STAGES(STAGES) 
	) ClkManager
	(
		.Clk_i			(gclk),
		.Rst_i			(initRst),
		.Rst80_i		(rst80),
		.BaudRate0_i	(baudRate[0]),
		.BaudRate1_i	(baudRate[1]),
		.BaudRate2_i	(baudRate[2]),
		.BaudRate3_i	(baudRate[3]),
		.BaudRate4_i	(baudRate[4]),
		.BaudRate5_i	(baudRate[5]),
		.BaudRate6_i	(baudRate[6]),
		.Clk80_o		(clk80),
		.SpiClk_o		(spiClkBus)
	);
	 
	genvar i;
	generate 
		for (i = 0; i < SPI_NUM; i = i + 1) begin : SpiSubSystem

			SpiSubSystem #(
				.STAGES				(STAGES),
				.CMD_REG_WIDTH		(CMD_REG_WIDTH),
				.ADDR_REG_WIDTH		(ADDR_REG_WIDTH),
				.WIDTH				(1),
				.FIFO_NUM			(SPI_NUM)
			) SpiSubSystem(
				.Clk123_i			(gclk),
				.SpiClk_i			(spiClkBus[i]),

				.TxEn_i				(txEn[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			(addrExt),
				.ToFifoVal_i		(toFifoVal[i]),
				.ToFifoData_i		(toFifoData[32*i+:32]),
				.WidthSel_i			(widthSel[i]),
				.PulsePol_i			(clockPol[i]),
				.ClockPhase_i		(clockPhase[i]),
				.EndianSel_i		(endianSel[i]),
				.ChipSelFlash_i		(chipSelFlash[i]),
				.ChipSelFpga_i		(chipSelFpga[i]),
				.Assel_i			(assel[i]),
				.Lag_i				(lag[i]),
				.Lead_i				(leadx[i]),
				.SelSt_i			(selSt[i]),
				.Stop_i				(stopDelay[i]),
				.SpiMode_i			(spiMode[i]),
				.SpiEn_i			(spiEn[i]),
				
				.TxFifoCtrlReg_o	(txFifoCtrlReg[i]),
				.RxFifoCtrlReg_o	(rxFifoCtrlReg[i]),
				.DataFromRxFifo_o	(dataFromRxFifo[i]),

				.Sck_o				(Sck_o[i]),
				.Ss_o				(ssW[i]),
				.SsFlash_o			(SsFlash_o[i]),
				.Mosi0_o			(Mosi0_o[i]),
				.Mosi1_io			(Mosi1_io[i]),
				.Mosi2_o			(Mosi2_o[i]),
				.Mosi3_o			(mosi3[i])
			);
			
			xpm_cdc_single #(
				.DEST_SYNC_FF		(3),
				.INIT_SYNC_FF		(0),
				.SIM_ASSERT_CHK		(0),
				.SRC_INPUT_REG		(1)
			)
			xpm_cdc_single_inst(
				.dest_out	(ldReg[i]),

				.dest_clk	(gclk),
				.src_clk	(spiClkBus[i]),
				.src_in		(Ld_i[i])
			);
		end
	endgenerate
	
	/////////////FOR DEBUG///////////// 
	/* QuadSPIs QuadSPIs (
		.Clk_i(spiClkBus[0]),
		.Rst_i(initRstGen[0] | !spiMode[0]),
		.Sck_i(sckQ[0]),
		.Ss_i(ssQ[0]),
		.Mosi0_i(mosi0Q[0]),
		.Mosi1_i(mosi1[0]),
		.Mosi2_i(mosi2[0]),
		.Mosi3_i(mosi3[0]),
		.WidthSel_i(widthSel[0]),
		.SELST_i(selSt[0]),
		.EndianSel_i(endianSel[0])
	);*/
	
	InitRst InitRst_inst
	(
		.clk_i(gclk),
		.signal_o(initRst)
	);

	InitRst Rst80_inst
	(
		.clk_i(clk80),
		.signal_o(rst80)
	);
	
endmodule