// ********************************************************************/
// Actel Corporation Proprietary and Confidential
// Copyright 2010 Actel Corporation.  All rights reserved.
//
// ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
// ACCORDANCE WITH THE ACTEL LICENSE AGREEMENT AND MUST BE APPROVED
// IN ADVANCE IN WRITING.
//
// Description:	CoreAPB3 - Actel-enhanced version of AMBA APB3 Fabric
//				instantiates the following modules:
//				COREAPB3_MUXPTOB3
//
// Revision Information:
// Date			Description
// ----			-----------------------------------------
// 05Feb10		Production Release Version 3.0
//
// SVN Revision Information:
// SVN $Revision: 12344 $
// SVN $Date: 2010-02-27 21:59:30 -0800 (Sat, 27 Feb 2010) $
//
// Resolved SARs
// SAR      Date     Who   Description
//
// Notes:
// 1. best viewed with tabstops set to "4" (tabs used throughout file)
//
// *********************************************************************/
`timescale 1ns/1ps
module CoreAPB3 #(
parameter [5:0]APB_DWIDTH		= 32,
parameter [20:0]RANGESIZE		= 256,
parameter [0:0]IADDR_ENABLE		= 0,
parameter [0:0]APBSLOT0ENABLE	= 1,
parameter [0:0]APBSLOT1ENABLE	= 1,
parameter [0:0]APBSLOT2ENABLE	= 1,
parameter [0:0]APBSLOT3ENABLE	= 1,
parameter [0:0]APBSLOT4ENABLE	= 1,
parameter [0:0]APBSLOT5ENABLE	= 1,
parameter [0:0]APBSLOT6ENABLE	= 1,
parameter [0:0]APBSLOT7ENABLE	= 1,
parameter [0:0]APBSLOT8ENABLE	= 1,
parameter [0:0]APBSLOT9ENABLE	= 1,
parameter [0:0]APBSLOT10ENABLE	= 1,
parameter [0:0]APBSLOT11ENABLE	= 1,
parameter [0:0]APBSLOT12ENABLE	= 1,
parameter [0:0]APBSLOT13ENABLE	= 1,
parameter [0:0]APBSLOT14ENABLE	= 1,
parameter [0:0]APBSLOT15ENABLE	= 1
)
(
input								PRESETN,
input								PCLK,
input			[23:0]				PADDR,
input								PWRITE,
input								PENABLE,
input								PSEL,
input			[31:0]				PWDATA,
output wire		[31:0]				PRDATA,
output	wire						PREADY,
output	wire						PSLVERR,
output	wire	[23:0]				PADDRS,
output	wire	[(((1-IADDR_ENABLE)*24)+((IADDR_ENABLE)*32))-1:0] PADDRS0,
output	wire						PWRITES,
output	wire						PENABLES,
output	wire	[31:0]				PWDATAS,
output	wire						PSELS0,
output	wire						PSELS1,
output	wire						PSELS2,
output	wire						PSELS3,
output	wire						PSELS4,
output	wire						PSELS5,
output	wire						PSELS6,
output	wire						PSELS7,
output	wire						PSELS8,
output	wire						PSELS9,
output	wire						PSELS10,
output	wire						PSELS11,
output	wire						PSELS12,
output	wire						PSELS13,
output	wire						PSELS14,
output	wire						PSELS15,
input			[31:0]				PRDATAS0,
input			[31:0]				PRDATAS1,
input			[31:0]				PRDATAS2,
input			[31:0]				PRDATAS3,
input			[31:0]				PRDATAS4,
input			[31:0]				PRDATAS5,
input			[31:0]				PRDATAS6,
input			[31:0]				PRDATAS7,
input			[31:0]				PRDATAS8,
input			[31:0]				PRDATAS9,
input			[31:0]				PRDATAS10,
input			[31:0]				PRDATAS11,
input			[31:0]				PRDATAS12,
input			[31:0]				PRDATAS13,
input			[31:0]				PRDATAS14,
input			[31:0]				PRDATAS15,
input								PREADYS0,
input								PREADYS1,
input								PREADYS2,
input								PREADYS3,
input								PREADYS4,
input								PREADYS5,
input								PREADYS6,
input								PREADYS7,
input								PREADYS8,
input								PREADYS9,
input								PREADYS10,
input								PREADYS11,
input								PREADYS12,
input								PREADYS13,
input								PREADYS14,
input								PREADYS15,
input								PSLVERRS0,
input								PSLVERRS1,
input								PSLVERRS2,
input								PSLVERRS3,
input								PSLVERRS4,
input								PSLVERRS5,
input								PSLVERRS6,
input								PSLVERRS7,
input								PSLVERRS8,
input								PSLVERRS9,
input								PSLVERRS10,
input								PSLVERRS11,
input								PSLVERRS12,
input								PSLVERRS13,
input								PSLVERRS14,
input								PSLVERRS15
);
function integer ezlog2;
input [31:0] val;
begin
	ezlog2 = 0;
	while (val>1)
	begin
		val		= val>>1;
		ezlog2	= ezlog2 + 1;
	end
end
endfunction
localparam RANGEBITS		= ezlog2(RANGESIZE);
localparam RANGEBITS_LT16	= (RANGEBITS * (RANGESIZE<65536)) +
								(15 * (RANGESIZE>=65536));
localparam [RANGEBITS-1:0] IADDR_31_24_8B_A		= 'hc;
localparam [RANGEBITS-1:0] IADDR_23_16_8B_A		= 'h8;
localparam [RANGEBITS-1:0] IADDR_15_8_8B_A		= 'h4;
localparam [RANGEBITS-1:0] IADDR_7_0_8B_A		= 'h0;
localparam [RANGEBITS-1:0] IADDR_31_16_16B_A	= 'h4;
localparam [RANGEBITS-1:0] IADDR_15_0_16B_A		= 'h0;
localparam [RANGEBITS-1:0] IADDR_31_0_32B_A		= 'h0;
localparam [15:0] SL0  = APBSLOT0ENABLE  * (2**0);
localparam [15:0] SL1  = APBSLOT1ENABLE  * (2**1);
localparam [15:0] SL2  = APBSLOT2ENABLE  * (2**2);
localparam [15:0] SL3  = APBSLOT3ENABLE  * (2**3);
localparam [15:0] SL4  = APBSLOT4ENABLE  * (2**4);
localparam [15:0] SL5  = APBSLOT5ENABLE  * (2**5);
localparam [15:0] SL6  = APBSLOT6ENABLE  * (2**6);
localparam [15:0] SL7  = APBSLOT7ENABLE  * (2**7);
localparam [15:0] SL8  = APBSLOT8ENABLE  * (2**8);
localparam [15:0] SL9  = APBSLOT9ENABLE  * (2**9);
localparam [15:0] SL10 = APBSLOT10ENABLE * (2**10);
localparam [15:0] SL11 = APBSLOT11ENABLE * (2**11);
localparam [15:0] SL12 = APBSLOT12ENABLE * (2**12);
localparam [15:0] SL13 = APBSLOT13ENABLE * (2**13);
localparam [15:0] SL14 = APBSLOT14ENABLE * (2**14);
localparam [15:0] SL15 = APBSLOT15ENABLE * (2**15);
wire	[31:0] iPADDR;
wire	[31:0] iPRDATA;
wire	[31:0] iPRDATAS0;
wire	[31:0] iPRDATAS1;
wire	[31:0] iPRDATAS2;
wire	[31:0] iPRDATAS3;
wire	[31:0] iPRDATAS4;
wire	[31:0] iPRDATAS5;
wire	[31:0] iPRDATAS6;
wire	[31:0] iPRDATAS7;
wire	[31:0] iPRDATAS8;
wire	[31:0] iPRDATAS9;
wire	[31:0] iPRDATAS10;
wire	[31:0] iPRDATAS11;
wire	[31:0] iPRDATAS12;
wire	[31:0] iPRDATAS13;
wire	[31:0] iPRDATAS14;
wire	[31:0] iPRDATAS15;
wire	[31:0] IA_PRDATAS1;
wire	[15:0]	iPREADYS;
wire	[15:0]	iPSLVERRS;
reg		[15:0]	iPSELS;
wire	[3:0]	slotSel;
wire	[31:0]	TieOffLo32;	
wire			TieOffHi;	
wire			TieOffLo;	
assign TieOffLo32	= 32'b0;
assign TieOffHi		= 1'b1;
assign TieOffLo		= 1'b0;
assign PADDRS	= iPADDR[23:0];
assign PADDRS0	= iPADDR[(((1-IADDR_ENABLE)*24)+((IADDR_ENABLE)*32))-1:0];
assign PWRITES	= PWRITE;
assign PENABLES	= PENABLE;
assign PWDATAS	= PWDATA[31:0];
generate
begin: g_rangesel
	assign slotSel = PADDR[(RANGEBITS+3):(RANGEBITS+0)];
end
endgenerate
generate
begin: g_iaddr
	if (IADDR_ENABLE==0)
	begin: g_ia0
		assign iPADDR[31:0] = {
								TieOffLo32[31:RANGEBITS+4],
								PADDR[(RANGEBITS+3):0]
							};
		assign IA_PRDATAS1[31:0] = TieOffLo32[31:0];
	end
	else if (IADDR_ENABLE==1)
	begin: g_ia1
		reg [31:0] IADDR;
		if (APB_DWIDTH==8)
		begin
			always @ (posedge PCLK or negedge PRESETN)
			begin
				if (PRESETN==1'b0)
					IADDR[31:0] <= 32'b0;
				else
				begin
					if (RANGESIZE<65536)
					begin
						if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
							PADDR[(RANGEBITS-1):0]==IADDR_15_8_8B_A[(RANGEBITS-1):0])
							IADDR[15:RANGEBITS_LT16] <= PWDATA[7:(RANGEBITS_LT16-8)];
					end
					if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
						PADDR[(RANGEBITS-1):0]==IADDR_23_16_8B_A[(RANGEBITS-1):0])
						IADDR[23:16] <= PWDATA[7:0];
					if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
						PADDR[(RANGEBITS-1):0]==IADDR_31_24_8B_A[(RANGEBITS-1):0])
						IADDR[31:24] <= PWDATA[7:0];
				end
			end
			assign IA_PRDATAS1[7:0]	=
					(PADDR[(RANGEBITS-1):0]==IADDR_7_0_8B_A[(RANGEBITS-1):0])		?	IADDR[7:0]:
					(PADDR[(RANGEBITS-1):0]==IADDR_15_8_8B_A[(RANGEBITS-1):0])		?	IADDR[15:8]:
					(PADDR[(RANGEBITS-1):0]==IADDR_23_16_8B_A[(RANGEBITS-1):0])		?	IADDR[23:16]:
					(PADDR[(RANGEBITS-1):0]==IADDR_31_24_8B_A[(RANGEBITS-1):0])		?	IADDR[31:24]:
																						8'b0;
		end
		else if (APB_DWIDTH==16)
		begin
			always @ (posedge PCLK or negedge PRESETN)
			begin
				if (PRESETN==1'b0)
					IADDR[31:0] <= 32'b0;
				else
				begin
					if (RANGESIZE<65536)
					begin
						if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
							PADDR[(RANGEBITS-1):0]==IADDR_15_0_16B_A[(RANGEBITS-1):0])
							IADDR[15:RANGEBITS_LT16] <= PWDATA[15:RANGEBITS_LT16];
					end
					if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
						PADDR[(RANGEBITS-1):0]==IADDR_31_16_16B_A[(RANGEBITS-1):0])
						IADDR[31:16] <= PWDATA[15:0];
				end
			end
			assign IA_PRDATAS1[15:0]	=
					(PADDR[(RANGEBITS-1):0]==IADDR_15_0_16B_A[(RANGEBITS-1):0])		?	IADDR[15:0]:
					(PADDR[(RANGEBITS-1):0]==IADDR_31_16_16B_A[(RANGEBITS-1):0])	?	IADDR[31:16]:
																						16'b0;
		end
		else
		begin
			always @ (posedge PCLK or negedge PRESETN)
			begin
				if (PRESETN==1'b0)
					IADDR[31:0] <= 32'b0;
				else
				begin
					if (iPSELS[1]==1'b1 && PWRITE==1'b1 && PENABLE==1'b1 &&
						PADDR[(RANGEBITS-1):0]==IADDR_31_0_32B_A[(RANGEBITS-1):0])
						IADDR[31:RANGEBITS] <= PWDATA[31:RANGEBITS];
				end
			end
			assign IA_PRDATAS1[31:0]	=
					(PADDR[(RANGEBITS-1):0]==IADDR_31_0_32B_A[(RANGEBITS-1):0])	?	IADDR[31:0]:
																					32'b0;
		end
		assign iPADDR[31:RANGEBITS] = (iPSELS[0]==1'b1) ?
												IADDR[31:RANGEBITS] : {
													TieOffLo32[31:RANGEBITS+4],
													PADDR[(RANGEBITS+3):(RANGEBITS+0)]
												};
		assign iPADDR[(RANGEBITS-1):0] = PADDR[(RANGEBITS-1):0];
	end
end
endgenerate
always @ (*)
begin
	if (PSEL == 1'b1)
	begin
		case (slotSel)
			4'b0000: iPSELS = SL0;
			4'b0001: iPSELS = SL1;
			4'b0010: iPSELS = SL2;
			4'b0011: iPSELS = SL3;
			4'b0100: iPSELS = SL4;
			4'b0101: iPSELS = SL5;
			4'b0110: iPSELS = SL6;
			4'b0111: iPSELS = SL7;
			4'b1000: iPSELS = SL8;
			4'b1001: iPSELS = SL9;
			4'b1010: iPSELS = SL10;
			4'b1011: iPSELS = SL11;
			4'b1100: iPSELS = SL12;
			4'b1101: iPSELS = SL13;
			4'b1110: iPSELS = SL14;
			4'b1111: iPSELS = SL15;
			default: iPSELS = 16'b0000000000000000;
		endcase
	end
	else
	begin
		iPSELS = 16'b0000000000000000;
	end
end
generate
begin: g_tieoffs
    if (APBSLOT0ENABLE)  assign iPRDATAS0[31:0]  = PRDATAS0[31:0];  else assign iPRDATAS0[31:0]  = TieOffLo32[31:0];
    if (IADDR_ENABLE)         assign iPRDATAS1[31:0]  = IA_PRDATAS1[31:0];
    else if (APBSLOT1ENABLE)  assign iPRDATAS1[31:0]  = PRDATAS1[31:0]; else assign iPRDATAS1[31:0]  = TieOffLo32[31:0];
    if (APBSLOT2ENABLE)  assign iPRDATAS2[31:0]  = PRDATAS2[31:0];  else assign iPRDATAS2[31:0]  = TieOffLo32[31:0];
    if (APBSLOT3ENABLE)  assign iPRDATAS3[31:0]  = PRDATAS3[31:0];  else assign iPRDATAS3[31:0]  = TieOffLo32[31:0];
    if (APBSLOT4ENABLE)  assign iPRDATAS4[31:0]  = PRDATAS4[31:0];  else assign iPRDATAS4[31:0]  = TieOffLo32[31:0];
    if (APBSLOT5ENABLE)  assign iPRDATAS5[31:0]  = PRDATAS5[31:0];  else assign iPRDATAS5[31:0]  = TieOffLo32[31:0];
    if (APBSLOT6ENABLE)  assign iPRDATAS6[31:0]  = PRDATAS6[31:0];  else assign iPRDATAS6[31:0]  = TieOffLo32[31:0];
    if (APBSLOT7ENABLE)  assign iPRDATAS7[31:0]  = PRDATAS7[31:0];  else assign iPRDATAS7[31:0]  = TieOffLo32[31:0];
    if (APBSLOT8ENABLE)  assign iPRDATAS8[31:0]  = PRDATAS8[31:0];  else assign iPRDATAS8[31:0]  = TieOffLo32[31:0];
    if (APBSLOT9ENABLE)  assign iPRDATAS9[31:0]  = PRDATAS9[31:0];  else assign iPRDATAS9[31:0]  = TieOffLo32[31:0];
    if (APBSLOT10ENABLE) assign iPRDATAS10[31:0] = PRDATAS10[31:0]; else assign iPRDATAS10[31:0] = TieOffLo32[31:0];
    if (APBSLOT11ENABLE) assign iPRDATAS11[31:0] = PRDATAS11[31:0]; else assign iPRDATAS11[31:0] = TieOffLo32[31:0];
    if (APBSLOT12ENABLE) assign iPRDATAS12[31:0] = PRDATAS12[31:0]; else assign iPRDATAS12[31:0] = TieOffLo32[31:0];
    if (APBSLOT13ENABLE) assign iPRDATAS13[31:0] = PRDATAS13[31:0]; else assign iPRDATAS13[31:0] = TieOffLo32[31:0];
    if (APBSLOT14ENABLE) assign iPRDATAS14[31:0] = PRDATAS14[31:0]; else assign iPRDATAS14[31:0] = TieOffLo32[31:0];
    if (APBSLOT15ENABLE) assign iPRDATAS15[31:0] = PRDATAS15[31:0]; else assign iPRDATAS15[31:0] = TieOffLo32[31:0];
    if (APBSLOT0ENABLE)  assign iPREADYS[0]  = PREADYS0;  else assign iPREADYS[0]  = TieOffHi;
    if (IADDR_ENABLE)         assign iPREADYS[1]  = TieOffHi;
    else if (APBSLOT1ENABLE)  assign iPREADYS[1]  = PREADYS1;  else assign iPREADYS[1]  = TieOffHi;
    if (APBSLOT2ENABLE)  assign iPREADYS[2]  = PREADYS2;  else assign iPREADYS[2]  = TieOffHi;
    if (APBSLOT3ENABLE)  assign iPREADYS[3]  = PREADYS3;  else assign iPREADYS[3]  = TieOffHi;
    if (APBSLOT4ENABLE)  assign iPREADYS[4]  = PREADYS4;  else assign iPREADYS[4]  = TieOffHi;
    if (APBSLOT5ENABLE)  assign iPREADYS[5]  = PREADYS5;  else assign iPREADYS[5]  = TieOffHi;
    if (APBSLOT6ENABLE)  assign iPREADYS[6]  = PREADYS6;  else assign iPREADYS[6]  = TieOffHi;
    if (APBSLOT7ENABLE)  assign iPREADYS[7]  = PREADYS7;  else assign iPREADYS[7]  = TieOffHi;
    if (APBSLOT8ENABLE)  assign iPREADYS[8]  = PREADYS8;  else assign iPREADYS[8]  = TieOffHi;
    if (APBSLOT9ENABLE)  assign iPREADYS[9]  = PREADYS9;  else assign iPREADYS[9]  = TieOffHi;
    if (APBSLOT10ENABLE) assign iPREADYS[10] = PREADYS10; else assign iPREADYS[10] = TieOffHi;
    if (APBSLOT11ENABLE) assign iPREADYS[11] = PREADYS11; else assign iPREADYS[11] = TieOffHi;
    if (APBSLOT12ENABLE) assign iPREADYS[12] = PREADYS12; else assign iPREADYS[12] = TieOffHi;
    if (APBSLOT13ENABLE) assign iPREADYS[13] = PREADYS13; else assign iPREADYS[13] = TieOffHi;
    if (APBSLOT14ENABLE) assign iPREADYS[14] = PREADYS14; else assign iPREADYS[14] = TieOffHi;
    if (APBSLOT15ENABLE) assign iPREADYS[15] = PREADYS15; else assign iPREADYS[15] = TieOffHi;
    if (APBSLOT0ENABLE)  assign iPSLVERRS[0]  = PSLVERRS0;  else assign iPSLVERRS[0]  = TieOffLo;
    if (IADDR_ENABLE)         assign iPSLVERRS[1]  = TieOffLo;
    else if (APBSLOT1ENABLE)  assign iPSLVERRS[1]  = PSLVERRS1;  else assign iPSLVERRS[1]  = TieOffLo;
    if (APBSLOT2ENABLE)  assign iPSLVERRS[2]  = PSLVERRS2;  else assign iPSLVERRS[2]  = TieOffLo;
    if (APBSLOT3ENABLE)  assign iPSLVERRS[3]  = PSLVERRS3;  else assign iPSLVERRS[3]  = TieOffLo;
    if (APBSLOT4ENABLE)  assign iPSLVERRS[4]  = PSLVERRS4;  else assign iPSLVERRS[4]  = TieOffLo;
    if (APBSLOT5ENABLE)  assign iPSLVERRS[5]  = PSLVERRS5;  else assign iPSLVERRS[5]  = TieOffLo;
    if (APBSLOT6ENABLE)  assign iPSLVERRS[6]  = PSLVERRS6;  else assign iPSLVERRS[6]  = TieOffLo;
    if (APBSLOT7ENABLE)  assign iPSLVERRS[7]  = PSLVERRS7;  else assign iPSLVERRS[7]  = TieOffLo;
    if (APBSLOT8ENABLE)  assign iPSLVERRS[8]  = PSLVERRS8;  else assign iPSLVERRS[8]  = TieOffLo;
    if (APBSLOT9ENABLE)  assign iPSLVERRS[9]  = PSLVERRS9;  else assign iPSLVERRS[9]  = TieOffLo;
    if (APBSLOT10ENABLE) assign iPSLVERRS[10] = PSLVERRS10; else assign iPSLVERRS[10] = TieOffLo;
    if (APBSLOT11ENABLE) assign iPSLVERRS[11] = PSLVERRS11; else assign iPSLVERRS[11] = TieOffLo;
    if (APBSLOT12ENABLE) assign iPSLVERRS[12] = PSLVERRS12; else assign iPSLVERRS[12] = TieOffLo;
    if (APBSLOT13ENABLE) assign iPSLVERRS[13] = PSLVERRS13; else assign iPSLVERRS[13] = TieOffLo;
    if (APBSLOT14ENABLE) assign iPSLVERRS[14] = PSLVERRS14; else assign iPSLVERRS[14] = TieOffLo;
    if (APBSLOT15ENABLE) assign iPSLVERRS[15] = PSLVERRS15; else assign iPSLVERRS[15] = TieOffLo;
end
endgenerate
COREAPB3_MUXPTOB3 u_mux_p_to_b3 (
	.PSELS		(iPSELS[15:0]),
	.PRDATAS0	(iPRDATAS0[31:0]),    
	.PRDATAS1	(iPRDATAS1[31:0]),
	.PRDATAS2	(iPRDATAS2[31:0]),
	.PRDATAS3	(iPRDATAS3[31:0]),
	.PRDATAS4	(iPRDATAS4[31:0]),
	.PRDATAS5	(iPRDATAS5[31:0]),
	.PRDATAS6	(iPRDATAS6[31:0]),
	.PRDATAS7	(iPRDATAS7[31:0]),
	.PRDATAS8	(iPRDATAS8[31:0]),
	.PRDATAS9	(iPRDATAS9[31:0]),
	.PRDATAS10	(iPRDATAS10[31:0]),
	.PRDATAS11	(iPRDATAS11[31:0]),
	.PRDATAS12	(iPRDATAS12[31:0]),
	.PRDATAS13	(iPRDATAS13[31:0]),
	.PRDATAS14	(iPRDATAS14[31:0]),
	.PRDATAS15	(iPRDATAS15[31:0]),
	.PREADYS	(iPREADYS[15:0]),    
	.PSLVERRS	(iPSLVERRS[15:0]),    
	.PREADY		(PREADY),
	.PSLVERR	(PSLVERR),
	.PRDATA		(iPRDATA[31:0])
);
assign PRDATA[31:0] = iPRDATA[31:0];
assign PSELS0	= iPSELS[0];
generate
begin: g_psels1
    if (IADDR_ENABLE) assign PSELS1=1'b0; else assign PSELS1=iPSELS[1];
end
endgenerate
assign PSELS2	= iPSELS[2];
assign PSELS3	= iPSELS[3];
assign PSELS4	= iPSELS[4];
assign PSELS5	= iPSELS[5];
assign PSELS6	= iPSELS[6];
assign PSELS7	= iPSELS[7];
assign PSELS8	= iPSELS[8];
assign PSELS9	= iPSELS[9];
assign PSELS10	= iPSELS[10];
assign PSELS11	= iPSELS[11];
assign PSELS12	= iPSELS[12];
assign PSELS13	= iPSELS[13];
assign PSELS14	= iPSELS[14];
assign PSELS15	= iPSELS[15];
endmodule
