--------------------------------------------------------------------
--
--	LPM_SHIFTREG Parameterized Megafunction
--
--  Copyright 1991-2009 Corporation  
--  Your use of Altera Corporation's design tools, logic functions  
--  and other software and tools, and its AMPP partner logic  
--  functions, and any output files from any of the foregoing  
--  (including device programming or simulation files), and any  
--  associated documentation or information are expressly subject  
--  to the terms and conditions of the Altera Program License  
--  Subscription Agreement, Altera MegaCore Function License  
--  Agreement, or other applicable license agreement, including,  
--  without limitation, that your use is for the sole purpose of  
--  programming logic devices manufactured by Altera and sold by  
--  Altera or its authorized distributors.  Please refer to the  
--  applicable agreement for further details. 
--  
--  9.0 Build 132  02/25/2009   
--
--	Version 1.0
--
--------------------------------------------------------------------

INCLUDE "lpm_constant.inc";
INCLUDE "dffeea.inc";

PARAMETERS
(
	LPM_WIDTH,
	LPM_DIRECTION = "LEFT",
	LPM_AVALUE = "UNUSED",
	LPM_SVALUE = "UNUSED",
	DEVICE_FAMILY
);

INCLUDE "aglobal90.inc";

SUBDESIGN lpm_shiftreg
(
	data[LPM_WIDTH-1..0]		: INPUT = GND;
	clock						: INPUT;
	enable						: INPUT = VCC;
	shiftin						: INPUT = VCC;
	load						: INPUT = GND;
	aclr, aset					: INPUT = GND;
	sclr, sset					: INPUT = GND;
	q[LPM_WIDTH-1..0]			: OUTPUT;
	shiftout					: OUTPUT;
)

VARIABLE
	IF (FAMILY_HAS_PRESET() == 0 & USED(aclr) & USED(aset)) GENERATE
		dffs[LPM_WIDTH-1..0]		: dffeea;
	ELSE GENERATE
		dffs[LPM_WIDTH-1..0]		: DFFE;
	END GENERATE;

	shift_node[LPM_WIDTH-1..0]	: NODE;
	IF (USED(LPM_AVALUE)) GENERATE
		ac	: lpm_constant with (LPM_WIDTH=LPM_WIDTH, LPM_CVALUE=LPM_AVALUE);
	END GENERATE;
	IF (USED(LPM_SVALUE)) GENERATE
		sc	: lpm_constant with (LPM_WIDTH=LPM_WIDTH, LPM_CVALUE=LPM_SVALUE);
	END GENERATE;

BEGIN

	ASSERT (LPM_WIDTH > 0)
			REPORT "Value of LPM_WIDTH parameter must be greater than 0"
			SEVERITY ERROR
			HELP_ID LPM_SHIFTREG_WIDTH;

	ASSERT (USED(aset) # USED(LPM_AVALUE) == 0)
			REPORT "Ignored LPM_AVALUE parameter because the aset port is not used"
			SEVERITY WARNING
			HELP_ID LPM_SHIFTREG_AVALUE;

	ASSERT (USED(sset) # USED(LPM_SVALUE) == 0)
			REPORT "Ignored LPM_SVALUE parameter because the sset port is not used"
			SEVERITY WARNING
			HELP_ID LPM_SHIFTREG_SVALUE;

	ASSERT (LPM_DIRECTION == "LEFT" # LPM_DIRECTION == "RIGHT")
			REPORT "Illegal value for LPM_DIRECTION parameter (%) -- value must be LEFT or RIGHT"
				LPM_DIRECTION
			SEVERITY ERROR
			HELP_ID LPM_SHIFTREG_DIRECTION;

	ASSERT (FAMILY_IS_KNOWN() == 1)
			REPORT "Megafunction lpm_shiftreg does not recognize the current device family (%) -- ensure that you are using the newest version of the megafunction"
				DEVICE_FAMILY
			SEVERITY WARNING
			HELP_ID LPM_SHIFTREG_FAMILY_UNKNOWN;

	% common ports %
	dffs[].ena = enable;
	dffs[].clk = clock;

	% Asynchronous control logic %
	IF (USED(LPM_AVALUE)) GENERATE
		dffs[].clrn = !aclr & (!aset # ac.result[]);
		dffs[].prn  = aclr # !aset # !ac.result[];
	ELSE GENERATE
		IF (USED(aclr)) GENERATE
			dffs[].clrn = !aclr;
		END GENERATE;
		IF (USED(aset)) GENERATE
			dffs[].prn = aclr # !aset;
		END GENERATE;
	END GENERATE;

	% Shift direction nodes %
	if (LPM_WIDTH > 1) GENERATE
		IF (LPM_DIRECTION == "LEFT") GENERATE
			shift_node[] = (dffs[LPM_WIDTH-2..0].q, shiftin);
			shiftout = dffs[LPM_WIDTH-1].q;
		ELSE GENERATE
			shift_node[] = (shiftin, dffs[LPM_WIDTH-1..1].q);
			shiftout = dffs[0].q;
		END GENERATE;
	ELSE GENERATE
		shift_node[] = shiftin;
		shiftout = dffs[0].q;
	END GENERATE;

	% Synchronous input logic %
	IF (USED(LPM_SVALUE)) GENERATE
		dffs[].d = !sclr & (  sset & sc.result[]
							# !sset & ( !load & shift_node[]
									  # load & data[]));
	ELSE GENERATE
		dffs[].d = !sclr & (sset # ( !load & shift_node[]
									# load & data[]));
	END GENERATE;

	% Connect outputs %
	q[] = dffs[].q;
	IF !USED(q) GENERATE
		q[] = GND;
	END GENERATE;
	IF !USED(shiftout) GENERATE
		shiftout = GND;
	END GENERATE;
END;
