`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////
// Company: Tair
// Engineer: Churbanov S.
// 
// Create Date:     
// Design Name: 
// Module Name:    TopSbtmsg
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//		Clk_i - is 24MHz.
//
//////////////////////////////////////////////////////////////////////////////////

module TopSbTmsg 
#(
    parameter DEVNUM = 8,
    parameter WORDWIDTH = 24,
    parameter SSPIWORDWIDTH = 24
) 
(
	input Clk_i,
	input Rst_i,
	
	input Sck_i,
	input Ss_i,
	
	input Mosi0_i,
	inout Mosi1_io,
	input Mosi2_i,
	input Mosi3_i,
	
	input MisoLdLmx_i,
	input MisoDds_i,
	input MisoLdMax2870_i,
	
	output I2cScl_o,
	inout I2cSda_io,
	
	output RfLd_o,
	output AnyFlag_o,

	//GPIO
	output RfSw1_o,
	output RfSw2_o,
	output CtrlAmSw3_o,
	output DdsSyncCtrlFpga_o,
	output DdsResetFpga_o,
	output DdsSyncFpga_o,
	output LrCtrlFpga_o,
	output AmAlcSw_o,
	output FpgaAlcDetSet_o,
	output SwCap2_o,
	output SwCap1_o,
	output AmAlc1Fix_o,
	output PllVtuneCtrl_o,
	output PllSyncCtrl_o,
	output PllSync_o,
	output PllLoopCtrl_o,
	output DdsX2Fpga_o,
	output DdsSaw2Fpga_o,
	output RefOffsetCtrlFpga_o,
	output GpioAdRfV1_o,
	output GpioAdRfV2_o,
	output DdsSaw1Fpga_o,
	output FpgaAmCtrl_o,
	output HrCtrlFpga_o,

	//Output SPI devices
	output reg CsLmx94_o,
	output reg ClkLmx94_o,
	output reg DataLmx94_o,

	output reg CsAd9912Fpga_o,
	output reg ClkAd9912Fpga_o,
	output reg MosiAd9912Fpga_o,

	output reg CsPot_o,
	output reg ClkPot_o,
	output reg MosiPot_o,

	output reg AmDac2Cs_o,
	output reg AmDac2Clk_o,
	output reg AmDac2_mosi_o,

	output reg FpgaCsAtt_o,
	output reg FpgaClkAtt_o,
	output reg FpgaMosiAtt_o,

	output reg CsRegRf2_o,
	output reg ClkRegRf2_o,
	output reg DataRegRf2_o,

	output reg CsMax2870MixRf2_o,
	output reg ClkMax2870MixRf2_o,
	output reg DataMax2870MixRf2_o,

	/* Led */
	output     FpgaLed_o


);

//================================================================================
//  LOCALPARAM

localparam [11:0] BOARD_VER 	= 12'h2;
localparam [11:0] FIRMWARE_VER	= 12'h1;

localparam LED_TICK_RATE = 48000000;//0.5Hz 24MHz

//================================================================================
//  REG/WIRE

	wire clk24;
	wire gclk100;
	wire clk5;
	wire clk20;
	wire clk50;
	wire clk26dot25;
	wire clk60;

	wire spiDataVal;
	wire spiDataValSync;
	wire [WORDWIDTH-1:0] spiData;
	wire [23:0] gpio1CtrlData;
	
	wire busyMosi1;
	wire busyMosi4;
	
	wire valLmxDataToFifo;		
	wire valDdsDataToFifo;		
	wire valPotDataToFifo;		
	wire valDacDataToFifo;		
	wire valAttDataToFifo;		
	wire valShRegDataToFifo;	
	wire valMaxDataToFifo;		
	wire valGpioDataToFifo;	
	
	wire flagDirectLmx;	
	wire flagDirectDds;	
	wire flagDirectPot;	
	wire flagDirectDac;	
	wire flagDirectAtt;	
	wire flagDirectShReg;	
	wire flagDirectMax;	
	wire flagDirectGpio1;
	wire flagDirectGpio2;	
	wire flagDirectTemp;
	wire flagDirectServInfo;

	wire misoTemp;
	wire misoGpio2;
	wire misoServInfo;
	wire anyFlag;

	//Output SpiM wires 
	wire lmxCsSpiM;
	wire lmxClkSpiM;
	wire lmxMosiSpiM;

	wire ddsCsSpiM;
	wire ddsClkSpiM;
	wire ddsMosiSpiM;

	wire potCsSpiM;
	wire potClkSpiM;
	wire potMosiSpiM;

	wire dacCsSpiM;
	wire dacClkSpiM;
	wire dacMosiSpiM;

	wire attCsSpiM;
	wire attClkSpiM;
	wire attMosiSpiM;

	wire shRegCsSpiM;
	wire shRegClkSpiM;
	wire shRegMosiSpiM;

	wire maxCsSpiM;
	wire maxClkSpiM;
	wire maxMosiSpiM;

	wire [3:0] lmxWordNum;
	wire [2:0] ddsWordNum;
	wire [2:0] ddsWordNumReg;
	wire valWordNum;

	wire testTrig;

	//InitRst
	wire initRst;

	/* Lock First PLL */
	wire lockFirstPll;

	reg misoReg;

	wire [23:0] servInfo;

	/* LedCnt*/
	reg [31:0] ledCnt;
	/* LedReg */
	reg ledReg;

//================================================================================
//  ASSIGNMENTS
//================================================================================
assign HrCtrlFpga_o			= gpio1CtrlData[23];
assign FpgaAmCtrl_o			= gpio1CtrlData[22];
assign DdsSaw1Fpga_o 		= gpio1CtrlData[21];
assign GpioAdRfV2_o 		= gpio1CtrlData[20];
assign GpioAdRfV1_o 		= gpio1CtrlData[19];
assign RefOffsetCtrlFpga_o	= gpio1CtrlData[18];
assign DdsSaw2Fpga_o 		= gpio1CtrlData[17];
assign DdsX2Fpga_o 			= gpio1CtrlData[16];
assign PllLoopCtrl_o 		= gpio1CtrlData[15];
assign PllSync_o 			= gpio1CtrlData[14];
assign PllSyncCtrl_o 		= gpio1CtrlData[13];
assign AmAlc1Fix_o 			= gpio1CtrlData[11];
assign SwCap1_o 			= gpio1CtrlData[10];
assign SwCap2_o 			= gpio1CtrlData[9];
assign FpgaAlcDetSet_o 		= gpio1CtrlData[8];
assign AmAlcSw_o 			= gpio1CtrlData[7];
assign LrCtrlFpga_o 		= gpio1CtrlData[6];
assign DdsResetFpga_o 		= gpio1CtrlData[4];
assign DdsSyncCtrlFpga_o 	= gpio1CtrlData[3];
assign CtrlAmSw3_o 			= gpio1CtrlData[2];
assign RfSw2_o 				= gpio1CtrlData[1];
assign RfSw1_o 				= gpio1CtrlData[0];

assign anyFlag = flagDirectTemp | flagDirectMax | flagDirectDds | flagDirectLmx | flagDirectGpio2;//Debug-only

assign RfLd_o = MisoLdLmx_i;
assign Mosi1_io = misoReg;
assign AnyFlag_o = anyFlag;//Debug-only

assign servInfo	= {BOARD_VER, FIRMWARE_VER};

assign FpgaLed_o = clk60;
// assign FpgaLed_o = 1'b1; //Golden-Image

//================================================================================
//  CODING
/* Blink Led */
always @(posedge Clk_i) begin
    if (initRst) begin
        ledCnt <= 0;
        ledReg <= 1'b1;
    end
    else begin
        if (ledCnt == LED_TICK_RATE) begin
            ledReg <= ~ledReg;
            ledCnt <= 0;
        end
        else begin
            ledCnt <= ledCnt + 1;
        end
    end
end

always @(*) begin 
	if (Rst_i) begin 
		misoReg = 1'b0;
	end
	else begin 
		if (flagDirectLmx) begin 
			misoReg = MisoLdLmx_i;
		end
		else if (flagDirectDds) begin 
			misoReg = MisoDds_i;
		end
		else if (flagDirectMax) begin 
			misoReg = MisoLdMax2870_i;
		end
		else if (flagDirectTemp) begin 
			misoReg = misoTemp;
		end
		else if (flagDirectGpio2) begin 
			misoReg = misoGpio2;
		end
		else if (flagDirectServInfo) begin 
			misoReg = misoServInfo;
		end
		else begin 
			misoReg = 1'bz;
		end
	end
end

//====================================
// MUX SpiM devices
//====================================
always @(*) begin
	if (flagDirectLmx) begin	//LMX
		CsLmx94_o 	= Ss_i;
		ClkLmx94_o 	= Sck_i;
		DataLmx94_o = Mosi0_i;
	end
	else begin
		CsLmx94_o 	= lmxCsSpiM;
		ClkLmx94_o 	= lmxClkSpiM;
		DataLmx94_o = lmxMosiSpiM;
	end
	if (flagDirectDds) begin	//DDS
		CsAd9912Fpga_o 		= Ss_i;
		ClkAd9912Fpga_o 	= Sck_i;
		MosiAd9912Fpga_o 	= Mosi0_i;
	end
	else begin
		CsAd9912Fpga_o 		= ddsCsSpiM;
		ClkAd9912Fpga_o 	= ddsClkSpiM;
		MosiAd9912Fpga_o 	= ddsMosiSpiM;
	end
	if (flagDirectPot) begin	//POT
		CsPot_o		= Ss_i;
		ClkPot_o	= Sck_i;
		MosiPot_o	= Mosi0_i;
	end
	else begin
		CsPot_o		= potCsSpiM;
		ClkPot_o	= potClkSpiM;
		MosiPot_o	= potMosiSpiM;
	end
	if (flagDirectDac) begin	//DAC
		AmDac2Cs_o 		= Ss_i;
		AmDac2Clk_o 	= Sck_i;
		AmDac2_mosi_o 	= Mosi0_i;
	end
	else begin
		AmDac2Cs_o 		= dacCsSpiM;
		AmDac2Clk_o 	= dacClkSpiM;
		AmDac2_mosi_o 	= dacMosiSpiM;
	end
	if (flagDirectAtt) begin	//ATT
		FpgaCsAtt_o		= Ss_i;
		FpgaClkAtt_o	= Sck_i;
		FpgaMosiAtt_o	= Mosi0_i;
	end
	else begin
		FpgaCsAtt_o		= attCsSpiM;
		FpgaClkAtt_o	= attClkSpiM;
		FpgaMosiAtt_o	= attMosiSpiM;
	end
	if (flagDirectShReg) begin	//ShReg
		CsRegRf2_o 		= Ss_i;
		ClkRegRf2_o 	= Sck_i;
		DataRegRf2_o 	= Mosi0_i;
	end
	else begin
		CsRegRf2_o 		= shRegCsSpiM;
		ClkRegRf2_o 	= shRegClkSpiM;
		DataRegRf2_o 	= shRegMosiSpiM;
	end
	if (flagDirectMax) begin	//MAX
		CsMax2870MixRf2_o	= Ss_i;
		ClkMax2870MixRf2_o	= Sck_i;
		DataMax2870MixRf2_o	= Mosi0_i;
	end
	else begin
		CsMax2870MixRf2_o	= maxCsSpiM;
		ClkMax2870MixRf2_o	= maxClkSpiM;
		DataMax2870MixRf2_o	= maxMosiSpiM;
	end
end

ClkGen ClkGen
(
	.Clk24Mhz_i			(Clk_i),
	
	.Clk24Mhz_o			(clk24),
	.Clk100Mhz_o		(gclk100),
	.Clk5Mhz_o			(clk5),
	.Clk20Mhz_o			(clk20),
	.Clk50Mhz_o			(clk50),
	.LockFirstPll_o		(lockFirstPll),
	.Clk26dot25Mhz_o	(clk26dot25),
	.Clk60Mhz_o			(clk60)
);

InitRst InitRst (
	.clk_i		(clk24),
	.signal_o	(initRst)
);

InterfaceArbiter 
#(	
	.OUTWORDWIDTH	(WORDWIDTH),
	.SSPIWORDWIDTH	(SSPIWORDWIDTH)
)
SpiSlaveArbiter
(
	.Rst_i		(Rst_i),
	.Clk_i		(clk60),
	
	.Sck_i		(Sck_i),
	.Ss_i		(Ss_i),
	
	.Mosi0_i	(Mosi0_i),
	.Mosi1_i	(Mosi1_io),
	.Mosi2_i	(Mosi2_i),
	.Mosi3_i	(Mosi3_i),
	
	.DataVal_o	(spiDataVal),
	.TestTrig_o	(testTrig),
	.Data_o		(spiData)
);

// Sync1bit SyncPulse(
// 	.ClkFast_i	(gclk100),
// 	.ClkSlow_i	(clk60),
// 	.Signal_i	(spiDataVal),
// 	.Ss_i		(Ss_i),
// 	.Rst_i		(initRst),
// 	.Signal_o	(spiDataValSync)	
// );

PacketAnalyzer4Mosi PacketAnalyzer4Mosi
(
	.Clk_i					(clk60),
	.Rst_i					(Rst_i),

	.DataFromSpi_i			(spiData),
	.ValDataFromSpi_i		(spiDataVal),

	.BusyMosi1_i			(busyMosi1),

	.LmxWordNum_o			(lmxWordNum),
	.DdsWordNum_o			(ddsWordNum),
	.ValWordNum_o			(valWordNum),

	.ValLmxDataToFifo_o		(valLmxDataToFifo),
	.ValDdsDataToFifo_o		(valDdsDataToFifo),
	.ValPotDataToFifo_o		(valPotDataToFifo),
	.ValDacDataToFifo_o		(valDacDataToFifo),
	.ValAttDataToFifo_o		(valAttDataToFifo),
	.ValShRegDataToFifo_o	(valShRegDataToFifo),
	.ValMaxDataToFifo_o		(valMaxDataToFifo),
	.ValGpioDataToFifo_o	(valGpioDataToFifo),

	.Busy_o					(busyMosi4)
);

PacketAnalyzer1Mosi	PacketAnalyzer1Mosi
(
	.Clk_i					(clk60),
	.Rst_i					(Rst_i),
	
	.DataFromSpi_i			(spiData),
	.ValDataFromSpi_i		(spiDataVal),
	
	.BusyMosi4_i			(busyMosi4),
	
	.FlagDirectLmx_o		(flagDirectLmx),
	.FlagDirectDds_o		(flagDirectDds),
	.FlagDirectPot_o		(flagDirectPot),
	.FlagDirectDac_o		(flagDirectDac),
	.FlagDirectAtt_o		(flagDirectAtt),
	.FlagDirectShReg_o		(flagDirectShReg),
	.FlagDirectMax_o		(flagDirectMax),
	.FlagDirectGpio1_o		(flagDirectGpio1),
	.FlagDirectTemp_o		(flagDirectTemp),
	.FlagDirectGpio2_o		(flagDirectGpio2),
	.FlagDirectServInfo_o	(flagDirectServInfo),
	
	.Busy_o					(busyMosi1)
);

LmxWrapper #(
	.IN_WIDTH			(24),
	.WR_NUM				(1),
	.OUT_WIDTH			(24),
	.DATA_WIDTH			(24)
) LmxWrapper(
	.WrClk_i			(clk60),
	.RdClk_i			(clk60),
	.Rst_i				(initRst),
	.Data_i				(spiData),
	.Val_i				(valLmxDataToFifo),
	.LmxWordNum_i		(lmxWordNum),
	.LmxWordNumVal_i	(valWordNum && (lmxWordNum != 0)),
	.DdsWordNumReg_i	(ddsWordNumReg),
	.DdsCs_i			(ddsCsSpiM),
	.LmxDirectFlag_i	(flagDirectLmx),	
	.PllVtuneCtrl_o		(PllVtuneCtrl_o),
	.Ss_o				(lmxCsSpiM),
	.Sck_o				(lmxClkSpiM),
	.Mosi_o				(lmxMosiSpiM)
);

DDSWrapper #(
	.IN_WIDTH			(24),
	.WR_NUM				(4),
	.OUT_WIDTH			(80),
	.DATA_WIDTH			(80)
) DDSWrapper(
	.WrClk_i			(clk60),
	.RdClk_i			(clk50),
	.Rst_i				(initRst),
	.DdsWordNum_i		(ddsWordNum),
	.DdsWordNumVal_i	( valWordNum && (ddsWordNum != 0)),
	.DdsDirectFlag_i	(flagDirectDds),
	.Data_i				(spiData),
	.Val_i				(valDdsDataToFifo),
	.DdsWordNumReg_o	(ddsWordNumReg),
	.DdsSyncFpga_o		(DdsSyncFpga_o),
	.Ss_o				(ddsCsSpiM),
	.Sck_o				(ddsClkSpiM),
	.Mosi_o				(ddsMosiSpiM)
);

PotWrapper #(
	.IN_WIDTH		(24),
	.WR_NUM			(1),
	.OUT_WIDTH		(16),
	.DATA_WIDTH		(16)
) PotWrapper(
	.WrClk_i		(clk60),
	.RdClk_i		(clk5),
	.Rst_i			(initRst),
	.Data_i			(spiData),
	.Val_i			(valPotDataToFifo),
	.Ss_o			(potCsSpiM),
	.Sck_o			(potClkSpiM),
	.Mosi_o			(potMosiSpiM)
);

DacWrapper #(
	.IN_WIDTH		(24),
	.WR_NUM			(1),
	.OUT_WIDTH		(16),
	.DATA_WIDTH		(16)
) DacWrapper(
	.WrClk_i		(clk60),
	.RdClk_i		(clk50),
	.Rst_i			(initRst),
	.Data_i			(spiData),
	.Val_i			(valDacDataToFifo),
	.Ss_o			(dacCsSpiM),
	.Sck_o			(dacClkSpiM),
	.Mosi_o			(dacMosiSpiM)
);

AttenuatorWrapper #(
	.IN_WIDTH		(24),
	.WR_NUM			(1),
	.OUT_WIDTH		(16),
	.DATA_WIDTH		(16)
) AttenuatorWrapper(
	.WrClk_i		(clk60),
	.RdClk_i		(clk50),
	.Rst_i			(initRst),
	.Data_i			(spiData),
	.Val_i			(valAttDataToFifo),
	.Ss_o			(attCsSpiM),
	.Sck_o			(attClkSpiM),
	.Mosi_o			(attMosiSpiM)
);

ShiftRegWrapper #(
	.IN_WIDTH		(24),
	.WR_NUM			(1),
	.OUT_WIDTH		(8),
	.DATA_WIDTH		(8)
) ShiftRegWrapper(
	.WrClk_i		(clk60),
	.RdClk_i		(clk26dot25),
	.Rst_i			(initRst),
	.Data_i			(spiData),
	.Val_i			(valShRegDataToFifo),
	.Ss_o			(shRegCsSpiM),
	.Sck_o			(shRegClkSpiM),
	.Mosi_o			(shRegMosiSpiM)
);

Max2870Wrapper #(
	.IN_WIDTH		(24),
	.WR_NUM			(2),
	.OUT_WIDTH		(32),
	.DATA_WIDTH		(32)
) Max2870Wrapper(
	.WrClk_i		(clk60),
	.RdClk_i		(clk20),
	.Rst_i			(initRst),
	.Data_i			(spiData),
	.Val_i			(valMaxDataToFifo),
	.Ss_o			(maxCsSpiM),
	.Sck_o			(maxClkSpiM),
	.Mosi_o			(maxMosiSpiM)
);

TempRead TempRead (
	.Clk24Mhz_i				(clk24),
	.Rst_i					(initRst),
	.ClkSpi_i				(Sck_i),
	.FlagDirectTempRead_i	(flagDirectTemp),
	.I2cScl_o				(I2cScl_o),
	.I2cSda_io				(I2cSda_io),
	.MisoTemp_o				(misoTemp)
);

Gpio1Ctrl Gpio1Ctrl
(
	.Clk_i					(clk60),
	.ValGpioDataToFifo_i	(valGpioDataToFifo),
	.ValDataFromSpi_i		(spiDataVal),
	.FlagDirectGpio1_i		(flagDirectGpio1),
	.Data_i					(spiData),
	.GpioReg_o				(gpio1CtrlData)
);

Gpio2Read Gpio2Read (
	.Clk_i				(clk60),
	.Rst_i				(initRst),
	.ClkSpi_i			(Sck_i),
	.LdMax_i			(MisoLdMax2870_i),
	.LdLmx_i			(MisoLdLmx_i),
	.FlagDirectGpio2_i	(flagDirectGpio2),
	.MisoGpio2_o		(misoGpio2)
);

SpiReadback ServInfoReadback (
	.ClkSpi_i		(Sck_i),
	.Rst_i			(initRst),
	.RegData_i		(servInfo),
	.FlagDirect_i	(flagDirectServInfo),
	.Miso_o			(misoServInfo)
);

endmodule
