module C_SHIFT_FD_V5_0 (LSB_2_MSB, SDIN, D, P_LOAD, CLK, CE, ACLR, ASET, AINIT, SCLR, SSET, SINIT, SDOUT, Q);

	parameter C_AINIT_VAL 		= "";
	parameter C_ENABLE_RLOCS	= 1;
	parameter C_FILL_DATA		= `c_sdin;
	parameter C_HAS_ACLR 		= 0;
	parameter C_HAS_AINIT 		= 0;
	parameter C_HAS_ASET 		= 0;
	parameter C_HAS_CE 			= 0;
	parameter C_HAS_D			= 0;
	parameter C_HAS_LSB_2_MSB	= 0;
	parameter C_HAS_Q			= 1;
	parameter C_HAS_SCLR 		= 0;
	parameter C_HAS_SDIN 		= 1;
	parameter C_HAS_SDOUT 		= 0;
	parameter C_HAS_SINIT 		= 0;
	parameter C_HAS_SSET 		= 0;
	parameter C_SHIFT_TYPE 		= `c_lsb_to_msb;
	parameter C_SINIT_VAL 		= "";
	parameter C_SYNC_ENABLE 	= `c_override;	
	parameter C_SYNC_PRIORITY 	= `c_clear;	
	parameter C_WIDTH		 	= 16;	
	
	//san 13/12/99
	parameter MUX_BUS_INIT_VAL     = {C_WIDTH-(C_WIDTH>2?2:0){"0"}};
	
	input LSB_2_MSB;
	input SDIN;
	input [C_WIDTH-1 : 0] D;
	input P_LOAD;
	input CLK;
	input CE;
	input ACLR;
	input ASET;
	input AINIT;
	input SCLR;
	input SSET;
	input SINIT;
	output SDOUT;
	output [C_WIDTH-1 : 0] Q;
	 
	// Internal values to drive signals when input is missing
	wire intLSB_2_MSB;
	wire intSDIN;
	wire [C_WIDTH-1 : 0] intD;
	wire intP_LOAD;
	wire intCE;
	wire intACLR;
	wire intASET;
	wire intAINIT;
	wire intSCLR;
	wire intSSET;
	wire intSINIT;
	wire intSDOUT;
	wire [C_WIDTH-1 : 0] intQ;
	 
	wire [C_WIDTH-1 : 0] Q = (C_HAS_Q == 1 ? intQ : `allXs);
	wire SDOUT = (C_HAS_SDOUT == 1 ? intSDOUT : 1'bx);

	wire [C_WIDTH-1 : 0] regsin;
	wire [C_WIDTH-1 : 0] regsout;
	wire [3 : 0] MSBmuxi;
	wire [3 : 0] LSBmuxi;
	wire [1 : 0] muxc;
	
	wire MSBmuxo;
	wire LSBmuxo;
	wire [C_WIDTH-(C_WIDTH>2?2:0) : 1] shmuxo;

	wire [C_WIDTH-(C_WIDTH>2?2:0) : 1] shmuxi0;
	wire [C_WIDTH-(C_WIDTH>2?2:0) : 1] shmuxi1;
	wire [C_WIDTH-(C_WIDTH>2?2:0) : 1] shmuxi2;
	wire [C_WIDTH-(C_WIDTH>2?2:0) : 1] shmuxi3;
	// Sort out default values for missing ports
	
	assign intLSB_2_MSB = (C_SHIFT_TYPE == `c_bidirectional ? (C_HAS_LSB_2_MSB == 1 ? (C_WIDTH == 1 ? 1'b1 : LSB_2_MSB) : 1'bx) : (C_SHIFT_TYPE == `c_lsb_to_msb ? 1'b1 : (C_WIDTH == 1 ? 1'b1 :1'b0)));
	assign intSDIN = (C_HAS_SDIN == 1 ? SDIN : (C_FILL_DATA == `c_zeros ? 1'b0 : (C_FILL_DATA == `c_ones ? 1'b1 : (C_FILL_DATA == `c_lsb ? regsout[0] : (C_FILL_DATA == `c_msb ? regsout[C_WIDTH-1] : (C_FILL_DATA == `c_wrap ? (intLSB_2_MSB === 1'b0 ? regsout[0] : regsout[C_WIDTH-1]) : 1'bx))))));
	assign intD = (C_HAS_D == 1 ? D : `allXs);
	assign intP_LOAD = (C_HAS_D == 1 ? P_LOAD : 1'b0);
	assign intCE = defval(CE, C_HAS_CE, 1);
	assign intACLR = defval(ACLR, C_HAS_ACLR, 0);
	assign intASET = defval(ASET, C_HAS_ASET, 0);
	assign intAINIT = defval(AINIT, C_HAS_AINIT, 0);
	assign intSCLR = defval(SCLR, C_HAS_SCLR, 0);
	assign intSSET = defval(SSET, C_HAS_SSET, 0);
	assign intSINIT = defval(SINIT, C_HAS_SINIT, 0);

	assign intSDOUT = (C_SHIFT_TYPE == `c_lsb_to_msb || C_SHIFT_TYPE == `c_bidirectional ? regsout[C_WIDTH-1] : regsout[0]);
	assign intQ = (C_HAS_Q == 1 ? regsout : `allXs);

	assign LSBmuxi[0] = regsout[(C_WIDTH>1?1:0)];
	assign LSBmuxi[1] = intSDIN;
	assign LSBmuxi[2] = intD[0];
	assign LSBmuxi[3] = intD[0];

	assign MSBmuxi[0] = intSDIN;
	assign MSBmuxi[1] = regsout[C_WIDTH-(C_WIDTH>1?2:1)];
	assign MSBmuxi[2] = intD[C_WIDTH-1];
	assign MSBmuxi[3] = intD[C_WIDTH-1];
	
	assign shmuxi0 = regsout[C_WIDTH-1 : (C_WIDTH>2?2:0)];
	assign shmuxi1 = regsout[C_WIDTH-(C_WIDTH>2?3:1) : 0];
	assign shmuxi2 = intD[C_WIDTH-(C_WIDTH>2?2:1) : (C_WIDTH>2?1:0)];
	assign shmuxi3 = intD[C_WIDTH-(C_WIDTH>2?2:1) : (C_WIDTH>2?1:0)];

	assign muxc[0] = intLSB_2_MSB;
	assign muxc[1] = intP_LOAD;
	
	assign regsin[0] = LSBmuxo;
	assign regsin[C_WIDTH-1] = (C_WIDTH == 1 ? LSBmuxo : MSBmuxo);
	assign regsin[C_WIDTH-(C_WIDTH>2?2:1) : (C_WIDTH>2?1:0)] = (C_WIDTH == 1 ? LSBmuxo : (C_WIDTH == 2 ? {MSBmuxo, LSBmuxo} : shmuxo));

	integer i, j, k;
	integer m, unknown;
	
	// Register implements SR
	C_REG_FD_V5_0 #(C_AINIT_VAL, C_ENABLE_RLOCS, C_HAS_ACLR, C_HAS_AINIT, C_HAS_ASET,
			   C_HAS_CE, C_HAS_SCLR, C_HAS_SINIT, C_HAS_SSET,
			   C_SINIT_VAL, C_SYNC_ENABLE, C_SYNC_PRIORITY, C_WIDTH)
		shreg (.D(regsin), .CLK(CLK), .CE(intCE), .ACLR(intACLR), .ASET(intASET),
			  .AINIT(intAINIT), .SCLR(intSCLR), .SSET(intSSET), .SINIT(intSINIT),
			  .Q(regsout)); 

	// Muxes to steer data
	C_MUX_BIT_V5_0 #("0000", 1, 0, 0, 0,
					 0, 1, 0, 0, 0, 0,
					 4, 0, 0, 2, "0000", 0, 0)
			MSBmux (.M(MSBmuxi), .S(muxc),
			        .CLK(), .CE(),
					.ACLR(), .ASET(), .AINIT(),
					.SCLR(), .SSET(), .SINIT(),
			        .O(MSBmuxo), .Q()); // Feeds regsin[C_WIDTH-1]

	C_MUX_BIT_V5_0 #("0000", 1, 0, 0, 0,
					 0, 1, 0, 0, 0, 0,
					 4, 0, 0, 2, "0000", 0, 0)
			LSBmux(.M(LSBmuxi), .S(muxc), 
			       .CLK(), .CE(),
 				   .ACLR(), .ASET(), .AINIT(),
				   .SCLR(), .SSET(), .SINIT(),
			       .O(LSBmuxo), .Q()); // Feeds regsin[0];
			
	//Edited SAN 13/12/99 //Added extra latency parameter, nritchie 15/9/00
	C_MUX_BUS_V5_0 #(MUX_BUS_INIT_VAL, 1, 0, 0, 0,
			   0, 0, 1, 0, 0, 0, 0,
			   4, 0, 0, 2, MUX_BUS_INIT_VAL, 0, 0, C_WIDTH-(C_WIDTH>2?2:0))
			shmux (.MA(shmuxi0), .MB(shmuxi1), .MC(shmuxi2), .MD(shmuxi3), .ME(), .MF(), .MG(), .MH(),
			       .MAA(), .MAB(), .MAC(), .MAD(), .MAE(), .MAF(), .MAG(), .MAH(),
 		           .MBA(), .MBB(), .MBC(), .MBD(), .MBE(), .MBF(), .MBG(), .MBH(),
                   .MCA(), .MCB(), .MCC(), .MCD(), .MCE(), .MCF(), .MCG(), .MCH(),
			       .S(muxc),
			       .CLK(), .CE(), .EN(),
				   .ACLR(), .ASET(), .AINIT(),
			       .SCLR(), .SSET(), .SINIT(), 
			       .O(shmuxo), .Q()); // Feeds regsin[C_WIDTH-2 : 1]

	
	function defval;
	input i;
	input hassig;
	input val;
		begin
			if(hassig == 1)
				defval = i;
			else
				defval = val;
		end
	endfunction

endmodule