library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity top_level is
	port (
		sys_reset_n_ipad			: in	std_logic;
		clk_osc_mhz_14_ipad			: in	std_logic;
		clk_osc_khz_32_ipad			: in	std_logic;
		
		 -- Embedded Artists LPC3141 OEM Module Interface
		clk_lpc3141_clock_out_ipad	: in	std_logic;
		clk_lpc3141_sysclk_ipad		: in	std_logic;
		clk_lpc3141_256fs_ipad		: in	std_logic;
		lpc3141_b_n_stcs1_ipad		: in	std_logic;
		lpc3141_b_n_stcs0_ipad		: in	std_logic;
		lpc3141_bbls1_ipad			: in	std_logic;
		lpc3141_bbls0_ipad			: in	std_logic;	
		lpc3141_b_n_we_ipad			: in	std_logic;
		lpc3141_b_n_oe_ipad			: in	std_logic;
		lpc3141_ba_ipads			: in	std_logic_vector(15 downto 0);
		lpc3141_bd_iopads			: inout	std_logic_vector(15 downto 0);
		lpc3141_n_abuf_en_opad		: out	std_logic;
		lpc3141_n_dbuf_en_opad		: out	std_logic;
		
		 -- PC-104 Standard Control Signals
		pc104_std_iochk_n_ipad		: in	std_logic;
		pc104_std_iochrdy_ipad		: in	std_logic;
		pc104_std_endxfer_ipad		: in	std_logic;
		
		pc104_std_osc_opad			: out	std_logic;
		pc104_std_bclk_opad			: out	std_logic;
		pc104_std_aen_opad			: out	std_logic;	
		pc104_std_bale_opad			: out	std_logic;	
		pc104_std_smemr_n_opad		: out	std_logic;
		pc104_std_smemw_n_opad		: out	std_logic;
		pc104_std_ior_n_opad		: out	std_logic;	
		pc104_std_iow_n_opad		: out	std_logic;	
		pc104_std_reset_out_opad	: out	std_logic;
		pc104_std_refresh_n_opad	: out	std_logic;
		pc104_std_tc_opad			: out	std_logic;	
		
		 -- PC 104 Standard Address and Data Busses
		pc104_std_sa_opads			: out	std_logic_vector(19 downto 0);
		pc104_std_sd_iopads			: inout	std_logic_vector(7 downto 0);
		
		 -- PC-104 Standard Interrupt Requests
		pc104_std_irq9_ipad			: in	std_logic;
		pc104_std_irq7_ipad			: in	std_logic;
		pc104_std_irq6_ipad			: in	std_logic;
		pc104_std_irq5_ipad			: in	std_logic;
		pc104_std_irq4_ipad			: in	std_logic;
		pc104_std_irq3_ipad			: in	std_logic;
		
		 -- PC-104 Standard DMA Requests(unused)
		pc104_std_drq3_ipad			: in	std_logic;
		pc104_std_drq2_ipad			: in	std_logic;
		pc104_std_drq1_ipad			: in	std_logic;	

		 -- PC-104 Standard DMA Acknowledgements(unused)
		pc104_std_dack3_opad		: out	std_logic;
		pc104_std_dack2_opad		: out	std_logic;
		pc104_std_dack1_opad		: out	std_logic;	
		
		 -- PC-104 Extended Control Signals(unused)
		pc104_ext_master_n_ipad		: in	std_logic;
		pc104_ext_sbhe_n_opad		: out	std_logic;	
		pc104_ext_memcs16_n_opad	: out	std_logic;	
		pc104_ext_iocs16_n_opad		: out	std_logic;	
		pc104_ext_memr_n_opad		: out	std_logic;
		pc104_ext_memw_n_opad		: out	std_logic;
		
		 -- PC 104 Extended Address and Data Busses(unused)
		pc104_ext_la_opads			: out	std_logic_vector(23 downto 17);
		pc104_ext_sd_iopads			: inout	std_logic_vector(15 downto 8);
		
		 -- PC-104 Extended Interrupt Requests(unused)
		pc104_ext_irq15_ipad		: in	std_logic;
		pc104_ext_irq14_ipad		: in	std_logic;
		pc104_ext_irq12_ipad		: in	std_logic;
		pc104_ext_irq11_ipad		: in	std_logic;
		pc104_ext_irq10_ipad		: in	std_logic;

		 -- PC-104 Extended DMA Requests (unnused)
		pc104_ext_drq7_ipad			: in	std_logic;
		pc104_ext_drq6_ipad			: in	std_logic;
		pc104_ext_drq5_ipad			: in	std_logic;
		pc104_ext_drq0_ipad			: in	std_logic;
		
		 -- PC-104 Extended DMA Acknowledgements (unnused)
		pc104_ext_dack7_opad		: out	std_logic;
		pc104_ext_dack6_opad		: out	std_logic;
		pc104_ext_dack5_opad		: out	std_logic;
		pc104_ext_dack0_opad		: out	std_logic;
		
		 -- LPC3141 OEM Module GPIO (unnused)	
		lpc3141_gpio_20_opad		: out	std_logic;
		lpc3141_gpio_19_opad		: out	std_logic;
		lpc3141_gpio_18_opad		: out	std_logic;
		lpc3141_gpio_17_opad		: out	std_logic;
		lpc3141_gpio_16_opad		: out	std_logic;
		lpc3141_gpio_15_opad		: out	std_logic;
		lpc3141_gpio_14_opad		: out	std_logic;
		lpc3141_gpio_13_opad		: out	std_logic;
		lpc3141_gpio_12_opad		: out	std_logic;
		lpc3141_gpio_11_opad		: out	std_logic;
		lpc3141_gpio_4_opad			: out	std_logic;
		lpc3141_gpio_3_opad			: out	std_logic;
		
		 -- Ethernet Interface
		enet_intr_n_ipad			: in 	std_logic;
		enet_pme_ipad				: in 	std_logic;
		enet_reset_n_opad			: out	std_logic;
		enet_cs_n_opad				: out	std_logic;
		enet_rd_n_opad				: out	std_logic;
		enet_wr_n_opad				: out	std_logic;
		enet_cmd_opad				: out	std_logic;
		enet_io_iopads				: inout	std_logic_vector(15 downto 0);
		
		-- USB
		hs_usb_fault_ipad			: in	std_logic;
		hs_usb_on_opad				: out	std_logic;
		
		-- Real Time Clock
		rtc_interrupt_n_ipad		: in	std_logic;
		
		-- Miscellanous I/O		
		oscillator_enable			: out	std_logic;
		pwm_opad					: out	std_logic		
	);

	attribute loc : string;
	attribute io_type : string; 
	attribute level_mode : string; 	
	
	attribute loc of clk_lpc3141_256fs_ipad		: signal is "H14";
	attribute loc of clk_lpc3141_clock_out_ipad	: signal is "J1";
	attribute loc of clk_lpc3141_sysclk_ipad	: signal is "E1";
	attribute loc of clk_osc_khz_32_ipad		: signal is "T9";
	attribute loc of clk_osc_mhz_14_ipad		: signal is "T7";
	attribute loc of enet_cmd_opad				: signal is "B16";
	attribute loc of enet_cs_n_opad				: signal is "R5";
	attribute loc of enet_intr_n_ipad			: signal is "E15";
	attribute loc of enet_io_iopads				: signal is "J15,H16,T13,P12,M15,N14,G11,G12,K14,M16,K12,F14,E16,J16,J11,H12"; -- LSB to MSB order
	attribute loc of enet_pme_ipad				: signal is "B14";
	attribute loc of enet_rd_n_opad				: signal is "T3";
	attribute loc of enet_reset_n_opad			: signal is "T2";
	attribute loc of enet_wr_n_opad				: signal is "R4";
	attribute loc of hs_usb_fault_ipad			: signal is "F7";
	attribute loc of hs_usb_on_opad				: signal is "F9";
	attribute loc of lpc3141_b_n_oe_ipad		: signal is "R16";
	attribute loc of lpc3141_b_n_stcs0_ipad		: signal is "P16";
	attribute loc of lpc3141_b_n_stcs1_ipad		: signal is "R11";
	attribute loc of lpc3141_b_n_we_ipad		: signal is "P15";
	attribute loc of lpc3141_ba_ipads			: signal is "C7,N2,P10,P8,L7,M10,P9,R13,N1,R7,K5,D8,P2,C2,B10,A13";
	attribute loc of lpc3141_bbls0_ipad			: signal is "C13";
	attribute loc of lpc3141_bbls1_ipad			: signal is "E14";
	attribute loc of lpc3141_bd_iopads			: signal is "K16,H15,P13,R12,L13,M14,H13,F12,L16,L15,K13,G13,D15,J14,L12,G15";
	attribute loc of lpc3141_gpio_11_opad		: signal is "E11";
	attribute loc of lpc3141_gpio_12_opad		: signal is "A10";
	attribute loc of lpc3141_gpio_13_opad		: signal is "C11";
	attribute loc of lpc3141_gpio_14_opad		: signal is "D9";
	attribute loc of lpc3141_gpio_15_opad		: signal is "M9";
	attribute loc of lpc3141_gpio_16_opad		: signal is "K1";
	attribute loc of lpc3141_gpio_17_opad		: signal is "E2";
	attribute loc of lpc3141_gpio_18_opad		: signal is "M11";
	attribute loc of lpc3141_gpio_19_opad		: signal is "K6";
	attribute loc of lpc3141_gpio_20_opad		: signal is "R8";
	attribute loc of lpc3141_gpio_3_opad		: signal is "K3";
	attribute loc of lpc3141_gpio_4_opad		: signal is "N9";
	attribute loc of lpc3141_n_abuf_en_opad		: signal is "F1";
	attribute loc of lpc3141_n_dbuf_en_opad		: signal is "G3";
	attribute loc of pc104_ext_dack0_opad		: signal is "B6";
	attribute loc of pc104_ext_dack5_opad		: signal is "C8";
	attribute loc of pc104_ext_dack6_opad		: signal is "C5";
	attribute loc of pc104_ext_dack7_opad		: signal is "P4";
	attribute loc of pc104_ext_drq0_ipad		: signal is "A5";
	attribute loc of pc104_ext_drq5_ipad		: signal is "A8";
	attribute loc of pc104_ext_drq6_ipad		: signal is "A4";
	attribute loc of pc104_ext_drq7_ipad		: signal is "T4";
	attribute loc of pc104_ext_iocs16_n_opad	: signal is "G2";
	attribute loc of pc104_ext_irq10_ipad		: signal is "H5";
	attribute loc of pc104_ext_irq11_ipad		: signal is "C1";
	attribute loc of pc104_ext_irq12_ipad		: signal is "N10";
	attribute loc of pc104_ext_irq14_ipad		: signal is "J5";
	attribute loc of pc104_ext_irq15_ipad		: signal is "L8";
	attribute loc of pc104_ext_la_opads			: signal is "N7,L2,F8,R1,B1,D10,B12";
	attribute loc of pc104_ext_master_n_ipad	: signal is "C16";
	attribute loc of pc104_ext_memcs16_n_opad	: signal is "K2";
	attribute loc of pc104_ext_memr_n_opad		: signal is "H2";
	attribute loc of pc104_ext_memw_n_opad		: signal is "H1";
	attribute loc of pc104_ext_sbhe_n_opad		: signal is "J4";
	attribute loc of pc104_ext_sd_iopads		: signal is "K15,K11,L14,F16,F15,A15,H11,G14";
	attribute loc of pc104_std_aen_opad			: signal is "F2";
	attribute loc of pc104_std_bale_opad		: signal is "L3";
	attribute loc of pc104_std_bclk_opad		: signal is "G4";
	attribute loc of pc104_std_dack1_opad		: signal is "A12";
	attribute loc of pc104_std_dack2_opad		: signal is "T8";
	attribute loc of pc104_std_dack3_opad		: signal is "E8";
	attribute loc of pc104_std_drq1_ipad		: signal is "B11";
	attribute loc of pc104_std_drq2_ipad		: signal is "N8";
	attribute loc of pc104_std_drq3_ipad		: signal is "H3";
	attribute loc of pc104_std_endxfer_ipad		: signal is "C15";
	attribute loc of pc104_std_iochk_n_ipad		: signal is "D14";
	attribute loc of pc104_std_iochrdy_ipad		: signal is "D16";
	attribute loc of pc104_std_ior_n_opad		: signal is "G5";
	attribute loc of pc104_std_iow_n_opad		: signal is "J6";
	attribute loc of pc104_std_irq3_ipad		: signal is "M8";
	attribute loc of pc104_std_irq4_ipad		: signal is "E10";
	attribute loc of pc104_std_irq5_ipad		: signal is "B9";
	attribute loc of pc104_std_irq6_ipad		: signal is "A11";
	attribute loc of pc104_std_irq7_ipad		: signal is "C9";
	attribute loc of pc104_std_irq9_ipad		: signal is "R9";
	attribute loc of pc104_std_osc_opad			: signal is "H4";
	attribute loc of pc104_std_refresh_n_opad	: signal is "J3";
	attribute loc of pc104_std_reset_out_opad	: signal is "F5";
	attribute loc of pc104_std_sa_opads			: signal is "B7,P1,R10,L9,N6,P11,R3,T14,M3,P7,L4,A9,M2,D3,C10,C12,J2,G1,G6,L5";
	attribute loc of pc104_std_sd_iopads		: signal is "J13,J12,T15,R14,N15,N16,G16,F13";
	attribute loc of pc104_std_smemr_n_opad		: signal is "H6";
	attribute loc of pc104_std_smemw_n_opad		: signal is "K4";
	attribute loc of pc104_std_tc_opad			: signal is "F4";
	attribute loc of rtc_interrupt_n_ipad		: signal is "F10";
	attribute loc of pwm_opad					: signal is "T11";
	attribute loc of sys_reset_n_ipad			: signal is "B3";
	attribute loc of oscillator_enable			: signal is "M6";

end entity top_level;

architecture synthesis of top_level is

	component pll is
		port (
			clki					: in  std_logic; 
			clkop					: out  std_logic; 
			clkos					: out  std_logic; 
			clkos2					: out  std_logic; 
			lock					: out  std_logic
		);
	end component pll;

	signal	lpc3141_i			: std_logic_vector(15 downto 0);
	signal	lpc3141_o			: std_logic_vector(15 downto 0);
	signal	pc104_i				: std_logic_vector(15 downto 0);
	signal	enet_i				: std_logic_vector(15 downto 0);
	signal	enet_o				: std_logic_vector(15 downto 0);
	
	signal	tc_1				: std_logic;
	signal  tc_2				: std_logic;
	signal  tc_3				: std_logic;
	signal  tc_4				: std_logic;
	signal  tc_5				: std_logic;
	
	signal count_1				: std_logic_vector(1 downto 0);
	signal count_2				: std_logic_vector(2 downto 0);
	signal count_3				: std_logic_vector(3 downto 0);
	signal count_4				: std_logic_vector(4 downto 0);
	signal count_5				: std_logic_vector(5 downto 0);	
	
	signal pll_lock				: std_logic;
	signal pc104_std_bclk		: std_logic;
	signal pc104_std_bclk_2X	: std_logic;
	
begin
	clock_generator : pll
	port map (
		clki					=> clk_osc_mhz_14_ipad,
		clkop					=> pc104_std_osc_opad,
		clkos					=> pc104_std_bclk,
		clkos2					=> pc104_std_bclk_2X, 
		lock					=> pll_lock
	);
	
	lpc3141_o 					<= enet_i when (lpc3141_b_n_stcs0_ipad = '0') else pc104_i;
		
	lpc3141_bd_iopads			<= lpc3141_o when (lpc3141_b_n_stcs1_ipad = '0' and lpc3141_b_n_oe_ipad = '0')  else (others => 'Z');
	lpc3141_i 					<= lpc3141_bd_iopads;	
	pc104_std_sd_iopads			<= lpc3141_i( 7 downto 0) when (lpc3141_b_n_stcs1_ipad = '0' and lpc3141_b_n_we_ipad = '0') else (others => 'Z');
	pc104_ext_sd_iopads 		<= lpc3141_i(15 downto 8) when (lpc3141_b_n_stcs1_ipad = '0' and lpc3141_b_n_we_ipad = '0') else (others => 'Z');
	pc104_i 					<= pc104_ext_sd_iopads &  pc104_std_sd_iopads;		
	
	pc104_ext_la_opads			<= lpc3141_ba_ipads(15 downto 9);
	pc104_std_sa_opads			<= "0000" & lpc3141_ba_ipads;

	enet_io_iopads 				<= lpc3141_i when (lpc3141_b_n_stcs0_ipad = '0' and lpc3141_b_n_we_ipad = '0') else (others => 'Z');
	enet_i 						<= enet_io_iopads;	
	
	silly_1: process(pc104_std_bclk_2X, sys_reset_n_ipad)
	begin
		if (sys_reset_n_ipad = '0') then
			count_1 <= (others => '0');
		elsif rising_edge(clk_osc_mhz_14_ipad) then
			count_1 <= count_1 + 1;
		end if;
	end process silly_1;
	
	silly_2: process(clk_osc_khz_32_ipad, sys_reset_n_ipad)
	begin
		if (sys_reset_n_ipad = '0') then
			count_2 <= (others => '0');
		elsif rising_edge(clk_osc_khz_32_ipad) then
			count_2 <= count_2 + 1;
		end if;
	end process silly_2;
	
	silly_3: process(pc104_std_bclk_2X, sys_reset_n_ipad)
	begin
		if (sys_reset_n_ipad = '0') then
			count_3 <= (others => '0');
		elsif rising_edge(clk_lpc3141_clock_out_ipad) then			count_3 <= count_3 + 1;
		end if;
	end process silly_3;
	
	silly_4: process(pc104_std_bclk_2X, sys_reset_n_ipad)
	begin
		if (sys_reset_n_ipad = '0') then
			count_4 <= (others => '0');
		elsif rising_edge(clk_lpc3141_sysclk_ipad) then
			count_4 <= count_4 + 1;
		end if;
	end process silly_4;	
	
	silly_5: process(pc104_std_bclk_2X, sys_reset_n_ipad)
	begin
		if (sys_reset_n_ipad = '0') then
			count_5 <= (others => '0');
		elsif rising_edge(clk_lpc3141_256fs_ipad) then
			count_5 <= count_5 + 1;
		end if;
	end process silly_5;
	
	tc_1 <= '1' when count_1 = 3 else '0';
	tc_2 <= '1' when count_2 = 7 else '0';
	tc_3 <= '1' when count_3 = 15 else '0';
	tc_4 <= '1' when count_4 = 31 else '0';
	tc_5 <= '1' when count_5 = 63 else '0';

	pc104_ext_dack7_opad 		<= pc104_ext_drq7_ipad when tc_1 = '1' else '0';
	pc104_ext_dack6_opad 		<= pc104_ext_drq6_ipad when tc_2 = '1' else '0';
	pc104_ext_dack5_opad 		<= pc104_ext_drq5_ipad when tc_3 = '1' else '0';
	pc104_std_dack3_opad		<= pc104_std_drq3_ipad when tc_4 = '1' else '0';
	pc104_std_dack2_opad		<= pc104_std_drq2_ipad when tc_5 = '1' else '0';
	pc104_std_dack1_opad 		<= pc104_std_drq1_ipad;
	pc104_ext_dack0_opad 		<= pc104_ext_drq0_ipad;	
	
	 ---- LPC3141 OEM Module GPIO (unnused)	
	lpc3141_gpio_20_opad		<= pc104_ext_irq15_ipad;
	lpc3141_gpio_19_opad		<= pc104_ext_irq14_ipad;
	lpc3141_gpio_18_opad		<= pc104_ext_irq12_ipad;
	lpc3141_gpio_17_opad		<= pc104_ext_irq11_ipad;
	lpc3141_gpio_16_opad		<= pc104_ext_irq10_ipad;
	lpc3141_gpio_15_opad		<= pc104_std_irq9_ipad;
	lpc3141_gpio_14_opad		<= pc104_std_irq7_ipad;
	lpc3141_gpio_13_opad		<= pc104_std_irq6_ipad;
	lpc3141_gpio_12_opad		<= pc104_std_irq5_ipad;
	lpc3141_gpio_11_opad		<= pc104_std_irq4_ipad;
	lpc3141_gpio_4_opad			<= pc104_std_irq3_ipad;
	
	 ---- Junk logic for Ethernet interface
	enet_reset_n_opad			<= '1';
	enet_cs_n_opad				<= '1';
	enet_rd_n_opad				<= '1';
	enet_wr_n_opad				<= '1';
	enet_cmd_opad				<= 	(lpc3141_bbls1_ipad or lpc3141_bbls0_ipad or enet_pme_ipad or pc104_std_iochk_n_ipad or pc104_std_iochrdy_ipad or pc104_std_endxfer_ipad or pc104_ext_master_n_ipad) and enet_intr_n_ipad;
	
	hs_usb_on_opad              <= hs_usb_fault_ipad and rtc_interrupt_n_ipad and clk_lpc3141_clock_out_ipad and clk_lpc3141_sysclk_ipad and clk_lpc3141_256fs_ipad;
	
	pwm_opad					<= '1';
	oscillator_enable			<= '1';
	pc104_std_bclk_opad			<= pc104_std_bclk;
	
end architecture synthesis;
