`timescale 1ns / 1ps
(* keep_hierarchy = "yes" *)
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:		Churbanov S.
// 
// Create Date:    10:00:14 13/08/2019 
// Design Name: 
// Module Name:    DspPpiOut 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module DspPpiOut
#(	
	parameter	ODataWidth		=	16,	
	parameter	ResultWidth		=	40, 
	parameter	ChNum			=	8,
	localparam	DataBusWidth	=	((ChNum*2)+1)*ResultWidth,
	localparam	ServisePattern	=	32'hABCD
)
(
	input	Rst_i,
	input	Clk_i,	
	
	input	[ChNum-1:0]	ServiseRegData_i,
	input	[ResultWidth*(ChNum*2)-1:0]	MeasDataBus_i,
	
	input	LpOutStart_i,
	output	PpiBusy_o,
	
	output	LpOutClk_o,
	output	LpOutFs_o,
	output	[ODataWidth-1:0]	LpOutData_o
);
//================================================================================
//  REG/WIRE
//================================================================================
	reg	lpDataRst;
	reg	[5:0]	txCnt	=	6'd0;	
	reg	[DataBusWidth-1:0]	lpDataBuf;
	reg	dataShEn;
	reg	dataValid;
	
	reg	lpOutFs;
	reg	ppiBusy;
	
	wire	oddrCe = (txCnt	<=	6'd19 && dataValid)	?	1'b1:1'b0;
	
	wire	[7:0]	ampEnT1	=	{{7{1'b0}},ServiseRegData_i[0]};
	wire	[7:0]	ampEnR1	=	{{7{1'b0}},ServiseRegData_i[1]};
	wire	[7:0]	ampEnR2	=	{{7{1'b0}},ServiseRegData_i[2]};
	wire	[7:0]	ampEnT2	=	{{7{1'b0}},ServiseRegData_i[3]};
	
	wire	[31:0]	serviceData	=	{ampEnR2,ampEnT2,ampEnR1,ampEnT1};
	
	wire	outDataVal	=	(txCnt	<=	18	&&	txCnt	!=	0);
//================================================================================
//  ASSIGNMENTS
//================================================================================	
	assign	LpOutData_o	=	lpDataBuf[ODataWidth-1:0];
	assign	LpOutFs_o	=	lpOutFs;
	assign	PpiBusy_o	=	ppiBusy;
//================================================================================
//  CODING
//================================================================================	
always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(LpOutStart_i)	begin
			ppiBusy	<=	1'b1;
		end	else	if	(!dataValid)	begin
			ppiBusy	<=	1'b0;
		end
	end	else	begin
		ppiBusy	<=	1'b0;
	end
end

always	@(posedge Clk_i)	begin
	if	(!Rst_i)	begin
		if	(LpOutStart_i)	begin	
			txCnt	<=	6'd19;
		end	else	if	(dataValid)	begin
			txCnt	<=	txCnt	-	6'd1;
		end
	end	else	begin
		txCnt	<=	6'd0;
	end
end

always	@(*)	begin
	case (txCnt)
		6'd19:	begin
					dataShEn	=	1'b0;
					dataValid	=	1'b1;
					lpOutFs		=	1'b0;
				end
		6'd18:	begin 
					dataShEn	=	1'b1;
					dataValid	=	1'b1;
					lpOutFs		=	1'b1;
				end
		6'd17:	begin 
					dataShEn	=	1'b1;
					dataValid	=	1'b1;
					lpOutFs		=	1'b0;
				end
		6'd0:	begin	
					dataShEn	=	1'b0;
					dataValid	=	1'b0;
					lpOutFs		=	1'b0;
				end	
		default: 
			begin
				dataShEn	=	1'b1;
				dataValid	=	1'b1;
				lpOutFs		=	1'b0;
			end
	endcase
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(txCnt	==	6'd19)	begin
			lpDataBuf	<=	{serviceData,MeasDataBus_i};
		end	else	if	(dataShEn)	begin
			lpDataBuf	<=	{{ODataWidth{1'b0}},lpDataBuf[DataBusWidth-1:ODataWidth]};
		end
	end	else	begin
		lpDataBuf	<=	{DataBusWidth{1'b0}};
	end
end
//================================================================================
//  INSTANTIATIONS
//================================================================================		
ODDR2
#(
	.DDR_ALIGNMENT("NONE"),
	.INIT	(1'b0),
	.SRTYPE	("SYNC")
) clk_i10OutInst (
	.Q		(LpOutClk_o),
	.C0		(Clk_i),
	.C1		(~Clk_i),
	.CE		(1'b1),
	.D0		(1'b1),
	.D1		(1'b0),
	.R		(1'b0),
	.S		(1'b0)
);		

endmodule
