// Company:         TAIR
// Engineer:        Chigrinskiy A.  
// 
// Create Date:     18/04/2024 
// Design Name: 
// Module Name:     DDSWrapper
// Project Name:    SB_TMSG44V1_FPGA
// Target Devices:  Board: SB_TMSG44v1. FPGA: GW1N-LV9PG256C6/I5
// Tool versions:
// Description:    This module is a wrapper for the Fifo, Fifo Controller and SPI Master modules.
//
// Dependencies:  
// Revision: 
// Revision 1.0 - File Created
// Additional Comments: 
//
////////////////////////////////////////////////////////////////////////////////////////////
module DDSWrapper #(
    parameter IN_WIDTH = 24,
    parameter WR_NUM = 3,
    parameter OUT_WIDTH = 64,
    parameter DATA_WIDTH = 64
)(
    input WrClk_i,
    input RdClk_i,
    input Rst_i,
	input [2:0] DdsWordNum_i,
	input DdsWordNumVal_i,
	input DdsDirectFlag_i,
    input [IN_WIDTH-1:0] Data_i,
    input Val_i,

	output reg DdsSyncFpga_o,
	output [2:0] DdsWordNumReg_o,

    output Ss_o,
    output Sck_o,
    output Mosi_o

);
//==========================================================================//
//									LOCALPARAMS									//
//==========================================================================//
localparam STAGES = 2;
localparam WIDTH = 1;
//================================================================================
//	                                REG/WIRE
//================================================================================    
wire [OUT_WIDTH-1:0] dataFromDdsFifoCtrl;
wire [OUT_WIDTH-1:0] dataFromDdsFifo;
wire readEnDds;
wire writeEnDds;
wire valRdDataDDS;
wire busySpiMDds;
wire ddsFifoFull;
wire ddsFifoEmpty;

reg ssR;
reg ssReg;
reg ddsDirectFlagR;
reg [2:0] ddsWordNumReg;
reg [2:0] ddsWordNumRegSync;
reg [2:0] ddsSyncCnt;

reg plsToggle;
reg plsToggleSyncA;
reg plsToggleSyncB;
reg ssPosEdge;
wire ssPosEdgeSync;
wire [63:0] dataFromDdsFifoCut;
//================================================================================
//	                                ASSIGNMENTS
//================================================================================ 
assign DdsWordNumReg_o = ddsWordNumReg;
assign ssPosEdgeSync = plsToggleSyncB^plsToggleSyncA;
assign dataFromDdsFifoCut = dataFromDdsFifo[63:0];
//==========================================================================//
//									CODING									//
//==========================================================================//
always @(posedge WrClk_i) begin
	if (Rst_i) begin 
		ssR <= 1'b0;
	end
	else begin 
		ssR <= Ss_o;
	end
end

always @(posedge RdClk_i) begin 
	if (Rst_i) begin 
		ddsDirectFlagR <= 1'b0;
	end
	else begin 
		ddsDirectFlagR <= DdsDirectFlag_i;
	end
end

always @(posedge RdClk_i) begin 
	ssReg <= Ss_o;
end

always @(posedge RdClk_i) begin 
	if (Rst_i) begin 
		ssPosEdge <= 1'b0;
	end
	else begin 
		ssPosEdge <= (Ss_o && !ssReg);
	end
end

always @(posedge RdClk_i) begin 
	if (Rst_i) begin 
		plsToggle <= 1'b0;
	end
	else if (ssPosEdge) begin 
		plsToggle <= ~plsToggle;
	end
	else begin 
		plsToggle <= plsToggle;
	end
end

always @(posedge WrClk_i) begin 
	if (Rst_i) begin 
		plsToggleSyncA <= 1'b0;
		plsToggleSyncB <= 1'b0;
	end
	else begin 
		plsToggleSyncA <= plsToggle;
		plsToggleSyncB <= plsToggleSyncA;
	end
end

always @(posedge WrClk_i) begin
	if (Rst_i) begin 
		ddsWordNumReg <= 3'h0;
	end
	else begin 
		if (DdsWordNumVal_i) begin 
			ddsWordNumReg <= DdsWordNum_i>>2;
		end
		else begin 
			if (ssPosEdgeSync && (ddsWordNumReg > 0)) begin 
				ddsWordNumReg <= ddsWordNumReg-1;
			end
		end
	end
end

always @(posedge RdClk_i) begin 
	if (Rst_i) begin 
		ddsWordNumRegSync <= 3'h0;
	end
	else begin 
		ddsWordNumRegSync <= ddsWordNumReg;
	end
end

always @(posedge RdClk_i) begin 
	if (Rst_i) begin 
		DdsSyncFpga_o <= 1'b0;
	end
	else begin
		if (ddsDirectFlagR && !DdsDirectFlag_i) begin 
				DdsSyncFpga_o <= 1'b1;
		end 
		else if ((!Ss_o && ssReg) && (ddsWordNumRegSync != 0)) begin 
			DdsSyncFpga_o <= 1'b0;
		end
		else begin 
			if (ddsWordNumRegSync == 3'h1 && (Ss_o && !ssReg)) begin 
				DdsSyncFpga_o <= 1'b1;
			end
			else begin 
				DdsSyncFpga_o <= 1'b0;
			end
		end
	end
end


FifoCtrl #(
	.PARITY_CHECK	(1),
	.IN_WIDTH		(IN_WIDTH),
	.WR_NUM			(WR_NUM),
	.OUT_WIDTH		(OUT_WIDTH)
) FifoCtrlDDS
(
	.WrClk_i		(WrClk_i),
	.RdClk_i		(RdClk_i),
	.Rst_i			(Rst_i),
	.Data_i			(Data_i),
	.Val_i			(Val_i),
	.BusySpiM_i		(busySpiMDds),
	.FifoFull_i		(ddsFifoFull),
	.FifoEmpty_i	(ddsFifoEmpty),
	.Data_o			(dataFromDdsFifoCtrl),
	.ReadEn_o		(readEnDds),
	.WriteEn_o		(writeEnDds),
	.ValRdData_o	(valRdDataDDS)
);

FifoDDS FifoDDS_inst (
	.Data	(dataFromDdsFifoCtrl),
	.WrClk	(WrClk_i),
	.RdClk	(RdClk_i),
	.Reset	(Rst_i),
	.WrEn	(writeEnDds),
	.RdEn	(readEnDds),
	.Full	(ddsFifoFull),
	.Empty	(ddsFifoEmpty),
	.Q		(dataFromDdsFifo)
);

SpiM #(
	.DATA_WIDTH	(DATA_WIDTH)
)SpiMDDS(
	.Clk_i		(RdClk_i),
	.Rst_i		(Rst_i),
	.Val_i		(valRdDataDDS),
	.SpiData_i	(dataFromDdsFifo),
	.Busy_o	    (busySpiMDds),
	.Ss_o		(Ss_o),
	.Mosi_o		(Mosi_o),
	.Sck_o		(Sck_o)
);

endmodule