//`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:02:35 04/20/2020 
// Design Name: 
// Module Name:    PulseGen 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module	PulseGen	
#(	
	parameter	CmdRegWidth	=	32
)
(
	input	Rst_i,
	input	Clk_i,
	input	EnPulse_i,
	
	input	PulsePol_i,
	input	EnEdge_i,
	input	[CmdRegWidth-29:0]	Mode_i,
	input	[CmdRegWidth-1:0]	P1Del_i,
	input	[CmdRegWidth-1:0]	P2Del_i,
	input	[CmdRegWidth-1:0]	P3Del_i,
	input	[CmdRegWidth-1:0]	P1Width_i,
	input	[CmdRegWidth-1:0]	P2Width_i,
	input	[CmdRegWidth-1:0]	P3Width_i,
	
	output	Pulse_o
);	

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

	localparam	IDLE	=	2'h0;
	localparam	DELAY	=	2'h1;
	localparam	PULSE	=	2'h2;
	
	localparam	DISABLED	=	8'd0;
	localparam	SINGLE		=	8'd1;
	localparam	DOUBLE		=	8'd2;
	localparam	TRIPPLE		=	8'd3;
	localparam	BURST		=	8'd4;
	localparam	CONTINIOUS	=	8'd5;
	
//================================================================================
	reg		pulse;
	wire	[31:0]	delArray	[2:0];
	wire	[31:0]	widthArray	[2:0];
	
	reg	[31:0]	pulseCnt;
	reg	[31:0]	delayCnt;
	reg	[31:0]	widthCnt;
	
	reg	[31:0]	currWidthValue;
	reg	[31:0]	currDelValue;

	reg	[1:0]	currState;
	reg	[1:0]	nextState;
	
	reg		pulseDone;	
	wire	delayDone	=	(currState	==	DELAY)?	delayCnt==currDelValue-1:1'b0;	
	
	wire	zeroDelay	=	(P1Del_i==0);
	
	reg	patternDone;

	reg	enPulseR;
	
	wire	enPulsePos	=	(!enPulseR&EnPulse_i);
	wire	enPulseNeg	=	(enPulseR&!EnPulse_i);
	
	wire	enPulse		=	(EnEdge_i)?	enPulseNeg:enPulsePos;
	wire	enPulseEn	=	(Mode_i	!=	0)?	enPulse:1'b0;
//================================================================================
//  ASSIGNMENTS
	assign	delArray	[0]	=	P1Del_i;
	assign	delArray	[1]	=	P2Del_i;
	assign	delArray	[2]	=	P3Del_i;
	
	assign	widthArray	[0]	=	P1Width_i;
	assign	widthArray	[1]	=	P2Width_i;
	assign	widthArray	[2]	=	P3Width_i;
	
	assign	Pulse_o	=	(PulsePol_i)?	~pulse:pulse;

//================================================================================
//  CODING

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		enPulseR	<=	EnPulse_i;
	end	else	begin
		enPulseR	<=	1'b0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(Mode_i	>=1 & Mode_i<=3)	begin	
			if	(currState	!=	IDLE)	begin
				delayCnt	<=	delayCnt+1;
			end	else	begin
				delayCnt	<=	0;
			end
		end	else	begin
			if	(currState	==	DELAY)	begin
				delayCnt	<=	delayCnt+1;
			end	else	begin
				delayCnt	<=	0;
			end
		end
	end	else	begin
		delayCnt	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(currState	==	PULSE)	begin
			widthCnt	<=	widthCnt+1;
		end	else	begin
			widthCnt	<=	0;
		end
	end	else	begin
		widthCnt	<=	0;
	end
end

always	@(*)	begin
	if	(!Rst_i)	begin
		if	(currState	==	PULSE)	begin
			if	(widthCnt==currWidthValue-1)	begin
				pulseDone	=	1'b1;
			end	else	begin
				pulseDone	=	1'b0;
			end
		end	else	begin
			pulseDone	=	1'b0;
		end
	end	else	begin
		pulseDone	=	1'b0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(pulseDone)	begin
			if	(!patternDone)	begin
				pulseCnt	<=	pulseCnt+1;
			end	else	begin
				pulseCnt	<=	0;
			end
		end
	end	else	begin
		pulseCnt	<=	0;
	end
end

always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		if	(Mode_i	==	0)	begin
				currDelValue	<=	0;
				currWidthValue	<=	0;
		end	else	begin
			if	(Mode_i	>=1 & Mode_i<=3)	begin
				currDelValue	<=	delArray[pulseCnt];
				currWidthValue	<=	widthArray[pulseCnt];
			end	else	begin
				if	(Mode_i	==	4|Mode_i	==	5)	begin
					if	(currState	==	IDLE)	begin
						currDelValue	<=	delArray[0];
						currWidthValue	<=	widthArray[0];
					end	else	if	(currState	==	PULSE	&	pulseDone)	begin
						currDelValue	<=	delArray[1];
						currWidthValue	<=	widthArray[0];
					end	
				end
			end
		end
	end	else	begin
		currDelValue	<=	0;
		currWidthValue	<=	0;
	end
end

always	@(*)	begin
	if	(!Rst_i)	begin
		if	(currState	!=	IDLE)	begin
			case(Mode_i)
				8'd0:	begin
							patternDone	=	0;
						end
				8'd1:	begin
							patternDone	=	((pulseCnt==Mode_i-1)&pulseDone);
						end
				8'd2:	begin
							patternDone	=	((pulseCnt==Mode_i-1)&pulseDone);
						end
				8'd3:	begin
							patternDone	=	((pulseCnt==Mode_i-1)&pulseDone);
						end
				8'd4:	begin
							patternDone	=	((pulseCnt==P2Width_i-1)&pulseDone);
						end
				8'd5:	begin
							patternDone	=	0;
						end
				default	:begin
							patternDone	=	0;
						end
			endcase
		end	else	begin
			patternDone	=	0;
		end
	end	else	begin
		patternDone	=	0;
	end
end

	
always	@(posedge	Clk_i)	begin
	if	(!Rst_i)	begin
		currState	<=	nextState;
	end	else	begin
		currState	<=	IDLE;
	end
end

always	@(*)	begin
	nextState	=	IDLE;
	case(currState)
	IDLE	:	begin
					if (enPulseEn)	begin
						if	(zeroDelay)	begin
							nextState = PULSE;
						end	else begin
							nextState = DELAY;
						end
					end	else	begin
						nextState = IDLE;
					end
				end
				
	DELAY	:	begin
					if	(delayDone)	begin
						nextState = PULSE;
					end	else begin
						nextState = DELAY;
					end
				end

	PULSE	:	begin
					if	(pulseDone)	begin
						if	(!patternDone)	begin
							nextState  = DELAY;
						end	else begin
							nextState  = IDLE;
						end
					end	else	begin
						nextState  = PULSE;
					end
				end
	endcase
end

always	@(*)	begin
	if	(!Rst_i)	begin
		if	(Mode_i	!=	0)	begin
			case(currState)
				IDLE:	begin
							pulse	=	1'b0;
						end
				DELAY:	begin
							pulse	=	1'b0;
						end
				PULSE:	begin
							pulse	=	1'b1;
						end
				default:begin
							pulse	=	1'b0;
						end
			endcase
		end	else	begin
			pulse	=	1'b0;
		end	
	end	else	begin
		pulse	=	1'b0;
	end
end

endmodule











