-------------------------------------------------------------------------
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
-- This file: system test using Xilinx ML-402

-- Copyright (C) 2007 J. Ahrensfeld

-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.

-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-- Lesser General Public License for more details.

-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

-- For questions and ideas, please contact the author at jens@jayfield.org

-----------------------------------------------------------------------

LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
use std.textio.all; --  Imports the standard textio package.

Library UNISIM;
use UNISIM.vcomponents.all;

library work;
use work.mips_types.all;
use work.sdram_config.all;
use work.sdram_types.all;
use work.vga_types.all;
use work.async_types.all;
use work.async_defs.all;


ENTITY mips_sys IS
GENERIC
(
	sys_freq_in			: real		    	:= 100.0;
	cpu_freq			: real				:= 100.0;
	tsvga				: vga_timespec_t 	:= ts_vga_800_600_72

);
PORT
(
	sys_rst_n_in		: in std_logic;
	sys_clk_in			: in std_logic;

	-- Buttons and LEDs
	sys_btn				: in unsigned(4 downto 0);
	sys_dip				: in unsigned(7 downto 0);
	sys_led				: out unsigned(8 downto 0);

	-- UART
	sys_uart0_rx		: in std_logic;
	sys_uart0_tx		: out std_logic;
	sys_uart1_rx		: in std_logic;
	sys_uart1_tx		: out std_logic;
	sys_uart2_rx		: in std_logic;
	sys_uart2_tx		: out std_logic;

	-- LCD
	sys_lcd_d			: inout unsigned(3 downto 0);
	sys_lcd_e			: out std_logic;
	sys_lcd_rs			: out std_logic;
	sys_lcd_rw			: out std_logic;

	-- DDR SDRAM
	sys_sdr_clk_p		: out std_logic;    -- ddr_sdram_clock
	sys_sdr_clk_n		: out std_logic;    -- /ddr_sdram_clock
	sys_sdr_cke_q		: out std_logic;    -- clock enable
	sys_sdr_cs_qn		: out std_logic;    -- /chip select
	sys_sdr_ras_qn		: out std_logic;    -- /ras
	sys_sdr_cas_qn		: out std_logic;    -- /cas
	sys_sdr_we_qn		: out std_logic;    -- /write enable
	sys_sdr_dm_q		: out unsigned(PART_DM_WIDTH-1 downto 0);     -- data mask bits, set to "00"
	sys_sdr_dqs_q		: inout unsigned(PART_DQS_WIDTH-1 downto 0);    -- data strobe, only for write
	sys_sdr_ba_q		: out unsigned(PART_BANK_WIDTH-1 downto 0);   -- bank select
	sys_sdr_a_q			: out unsigned(PART_ADDR_WIDTH-1 downto 0);   -- address bus 
	sys_sdr_data		: inout unsigned(PART_DATA_WIDTH-1 downto 0); -- bidir data bus
	sys_sdr_clk_fb		: in std_logic;
	
	-- VGA
	sys_vga_clk			: out std_logic;
	sys_vga_red			: out unsigned(7 downto 0);
	sys_vga_green		: out unsigned(7 downto 0);
	sys_vga_blue		: out unsigned(7 downto 0);
	sys_vga_blank_n		: out std_logic;
	sys_vga_sync_n		: out std_logic;
	sys_vga_hsync		: out std_logic;
	sys_vga_vsync		: out std_logic;

	sys_usb_d			: inout unsigned(15 downto 0);
	sys_usb_a			: out unsigned(1 downto 0);
	sys_usb_csn			: out std_logic;
	sys_usb_wrn			: out std_logic;
	sys_usb_rdn			: out std_logic;
	sys_usb_rstn		: out std_logic;
	sys_usb_int			: in std_logic;

	sys_flash_ssram_d		: inout unsigned(31 downto 0);
	sys_flash_ssram_a		: out unsigned(24 downto 0);
	sys_flash_ce			: out std_logic;
	sys_flash_ssram_we_n	: out std_logic;
	sys_flash_ssram_oe_n	: out std_logic;
	sys_flash_ac97_rstn		: out std_logic;
	sys_flash_byten			: out std_logic;	
	
	sys_ssram_clk			: out std_logic;
	sys_ssram_clk_fb		: in std_logic;
	sys_ssram_cke_n			: out std_logic;
	sys_ssram_ce_n			: out std_logic;
	sys_ssram_bw_n			: out unsigned(3 downto 0);
	sys_ssram_dp			: inout unsigned(3 downto 0);
	sys_ssram_adv			: out std_logic;
	sys_ssram_mode			: out std_logic;
	sys_ssram_zz			: out std_logic;

	sys_ac97_sdata_in		: in  std_logic;
	sys_ac97_bit_clk		: in  std_logic;
	sys_ac97_sdata_out		: out std_logic;
	sys_ac97_ssync			: out std_logic;

	sys_ps2_clk				: inout std_logic;
	sys_ps2_data			: inout std_logic;

	sys_phy_rstn			: out std_logic;
	sys_phy_mdc				: out std_logic;
	sys_phy_mdio			: inout std_logic;
	sys_phy_int				: in  std_logic;

	sys_phy_rx_clk			: in  STD_LOGIC;
	sys_phy_rx_dv			: in  STD_LOGIC;
	sys_phy_rx_er			: in  STD_LOGIC;
	sys_phy_rx				: in unsigned(7 downto 0);
	sys_phy_tx_clk			: in  STD_LOGIC;
	sys_phy_tx_en			: out STD_LOGIC;
	sys_phy_tx_er			: out STD_LOGIC;
	sys_phy_tx				: out unsigned(7 downto 0);
	sys_phy_gtx_clk			: out STD_LOGIC;
	sys_phy_crs				: in  STD_LOGIC;
	sys_phy_col				: in  STD_LOGIC;

	sys_error				: out unsigned(1 downto 0) -- indicates Errors
	
);
--	attribute BUFFER_TYPE : string;
--	attribute BUFFER_TYPE of sys_clk_in			: signal is "BUFG";
--	attribute BUFFER_TYPE of sys_sdr_dcm_clk_fb	: signal is "BUFG";

END mips_sys;

ARCHITECTURE behavior OF mips_sys IS 

	signal nmi			: std_logic;
	signal eb			: std_logic;
	signal vga_clk		: std_logic;
	signal vga_rst		: std_logic;
	
	signal vga_ce		: std_logic;
	signal rst_in		: std_logic;
	signal int_timer	: std_logic;
	signal int_uart0	: std_logic;
	signal int_uart1	: std_logic;
	signal int_uart2	: std_logic;
	signal locked		: std_logic;
	signal ac97_rstn	: std_logic;
	signal flash_rstn	: std_logic;
	signal ADDR_I_usb 	: unsigned(31 downto 0);
	signal ADDR_I_ssram	: unsigned(31 downto 0);
	signal ssram_clk	: std_logic;
	signal ssram_a		: unsigned(24 downto 0);
	signal ssram_do		: unsigned(31 downto 0);
	signal ssram_oe_n	: std_logic;
	signal ssram_we_n	: std_logic;
	signal ssram_d_drv	: std_logic;
	signal ssram_bsy	: std_logic;
	signal flash_a		: unsigned(24 downto 0);
	signal flash_do		: unsigned(31 downto 0);
	signal flash_oe_n	: std_logic;
	signal flash_we_n	: std_logic;
	signal flash_d_drv	: std_logic;
	signal flash_bsy	: std_logic;
	signal flash_page_mode_en	: std_logic;

	signal ps2_clk_rx	: std_logic;
	signal ps2_data_rx	: std_logic;
	signal ps2_clk_tx	: std_logic;
	signal ps2_data_tx	: std_logic;
	
	-- Arbiter
	constant ARB_MAX_MASTER	: natural := 2;
	signal arb_idx		: natural range 0 to ARB_MAX_MASTER-1;
	signal arb_req		: unsigned (ARB_MAX_MASTER-1 downto 0);
	signal arb_gnt		: unsigned (ARB_MAX_MASTER-1 downto 0);
	
	-- J-Bus signals
	signal CLK_O		: std_logic;
	signal RST_O		: std_logic;
	signal INT	 		: unsigned(5 downto 0);
	signal MDAT_I		: word_t;
	signal MDAT_O 		: word_t;
	signal ADDR_O 		: word_t;
	signal SEL_O 		: unsigned(3 downto 0);
	signal WE_O 		: std_logic;
	signal CYC_O 		: std_logic;
	signal STB_O 		: std_logic;
	signal ACK_I		: std_logic;
	signal SRDY_I		: std_logic;
	signal MRDY_O		: std_logic;

	-- CPU Master
	signal MRDY_O_cpu	: std_logic;
	signal MDAT_O_cpu	: word_t;
	signal ADDR_O_cpu	: word_t;
	signal SEL_O_cpu	: unsigned(3 downto 0);
	signal WE_O_cpu		: std_logic;
	signal CYC_O_cpu	: std_logic;
	signal STB_O_cpu	: std_logic;
	signal SRDY_I_cpu	: std_logic;
	signal ACK_I_cpu	: std_logic;

	-- VGA Master
	signal MRDY_O_vga	: std_logic;
	signal ADDR_O_vga	: word_t;
	signal SEL_O_vga	: unsigned(7 downto 0);
	signal WE_O_vga		: std_logic;
	signal CYC_O_vga	: std_logic;
	signal STB_O_vga	: std_logic;
	signal SRDY_I_vga	: std_logic;
	signal ACK_I_vga	: std_logic;
	signal MDAT_I_vga	: unsigned(63 downto 0);
	signal MDAT_O_vga	: unsigned(63 downto 0);

	-- Slaves
	signal CYC_I_flash	: std_logic;
	signal ACK_O_flash	: std_logic;
	signal SRDY_O_flash	: std_logic;
	signal SDAT_O_flash	: unsigned(31 downto 0);

	signal CYC_I_usb	: std_logic;
	signal ACK_O_usb	: std_logic;
	signal SRDY_O_usb	: std_logic;
	signal SDAT_O_usb	: unsigned(31 downto 0);

	signal CYC_I_sdram	: std_logic;
	signal ACK_O_sdram	: std_logic;
	signal SRDY_O_sdram	: std_logic;
	signal SDAT_O_sdram	: unsigned(63 downto 0);
	signal SDAT_I_sdram	: unsigned(63 downto 0);
	signal SEL_I_sdram	: unsigned(7 downto 0);

	signal CYC_I_rom	: std_logic;
	signal ACK_O_rom	: std_logic;
	signal SRDY_O_rom	: std_logic;
	signal SDAT_O_rom	: unsigned(31 downto 0);

	signal CYC_I_gpio	: std_logic;
	signal ACK_O_gpio	: std_logic;
	signal SRDY_O_gpio	: std_logic;
	signal SDAT_O_gpio	: unsigned(31 downto 0);

	signal CYC_I_uart0	: std_logic;
	signal ACK_O_uart0	: std_logic;
	signal SRDY_O_uart0	: std_logic;
	signal SDAT_O_uart0	: unsigned(31 downto 0);
	signal CYC_I_uart1	: std_logic;
	signal ACK_O_uart1	: std_logic;
	signal SRDY_O_uart1	: std_logic;
	signal SDAT_O_uart1	: unsigned(31 downto 0);
	signal CYC_I_uart2	: std_logic;
	signal ACK_O_uart2	: std_logic;
	signal SRDY_O_uart2	: std_logic;
	signal SDAT_O_uart2	: unsigned(31 downto 0);

	signal CYC_I_vga	: std_logic;
	signal ACK_O_vga	: std_logic;
	signal SRDY_O_vga	: std_logic;
	signal SDAT_O_vga	: unsigned(31 downto 0);

	signal CYC_I_ssram	: std_logic;
	signal ACK_O_ssram	: std_logic;
	signal SRDY_O_ssram	: std_logic;
	signal SDAT_O_ssram	: unsigned(31 downto 0);

	signal INT_O_ac97	: std_logic;
	signal CYC_I_ac97	: std_logic;
	signal ACK_O_ac97	: std_logic;
	signal SRDY_O_ac97	: std_logic;
	signal SDAT_O_ac97	: unsigned(31 downto 0);

	signal INT_O_ps2	: std_logic;
	signal CYC_I_ps2	: std_logic;
	signal ACK_O_ps2	: std_logic;
	signal SRDY_O_ps2	: std_logic;
	signal SDAT_O_ps2	: unsigned(31 downto 0);

	signal INT_O_emac	: std_logic;
	signal CYC_I_emac	: std_logic;
	signal ACK_O_emac	: std_logic;
	signal SRDY_O_emac	: std_logic;
	signal SDAT_O_emac	: unsigned(31 downto 0);

	signal gpi_0		: unsigned(31 downto 0);
	signal gpo_0		: unsigned(31 downto 0);

	signal ac97_inten	: std_logic;
	signal usb_inten	: std_logic;
	signal phy_inten	: std_logic;

	signal debug		: unsigned(1 downto 0);

	constant topad		: time := 3 ns;
	constant vga_freq	: real := real(tsvga.f_pxl_clk)/1.0E6;
	
--	attribute rom_style: string;
--	attribute rom_style of cmd_fifo_dout: signal is "DISTRIBUTED";
--	attribute rom_style of cpu_cpu_write_fifo_dout: signal is "DISTRIBUTED";
--	attribute rom_style of cpu_read_fifo_dout: signal is "DISTRIBUTED";

	type mem_area_t is (mem_dead, mem_flash, mem_ssram, mem_usb, mem_rom, mem_gpio, mem_uart0, mem_uart1, mem_uart2, mem_uart, mem_sdram, mem_vga, mem_ac97, mem_emac);
	signal mem_area : mem_area_t;

BEGIN

	------------------------------------
	-- GPIO_0 bits used for
	--  8.. 0	= O: LED 8..0
	-- 11.. 9	= free    
	-- 12		= O: USB RST
	-- 13		= O: USB INTEN
	-- 14		= free
	-- 15		= O: AC97 INTEN
	-- 32..16	= I: DIP 7..0
	-- 28..24	= I: BTN 4..0
	-- 29		= O: PHY RESET
	-- 30		= O: PHY MDC
	-- 31		= IO: PHY MDIO
	------------------------------------
	gpi_0(28 downto 24)		<= sys_btn;
	gpi_0(23 downto 16)		<= sys_dip;
	gpi_0(31)				<= sys_phy_mdio;
	
	sys_led					<= gpo_0(8 downto 0);
	sys_usb_rstn			<= not gpo_0(12);
	usb_inten				<= gpo_0(13);
	phy_inten				<= gpo_0(14);
	ac97_inten				<= gpo_0(15);
	sys_phy_rstn			<= not gpo_0(29);
	sys_phy_mdc				<= gpo_0(30);
	sys_phy_mdio			<= gpo_0(31);

	eb						<= sys_dip(7);
	sys_error				<= debug;
	nmi						<= not sys_rst_n_in;
	rst_in 					<= not sys_rst_n_in and sys_btn(0) and sys_btn(2);
	sys_flash_byten			<= '1';
	ADDR_I_usb				<= X"0000000" & "00" & ADDR_O(3 downto 2);
	ADDR_I_ssram			<= ("0000000000000" & ADDR_O(19 downto 2)) & '0';

	SDAT_I_sdram			<= MDAT_O & MDAT_O;
	SEL_I_sdram				<= "0000" & SEL_O;

	sys_flash_ac97_rstn		<= ac97_rstn and flash_rstn;
	vga_ce					<= not vga_rst;
	
sys_flash_ssram_out:
	process(CLK_O)
	begin
		if rising_edge(CLK_O) then
			sys_flash_ssram_d		<= (others => 'Z') after topad;
			sys_flash_ssram_oe_n	<= '1';
			sys_flash_ssram_we_n	<= '1';
			if flash_bsy = '1' then
				sys_flash_ssram_oe_n	<= flash_oe_n;
				sys_flash_ssram_we_n	<= flash_we_n;
				sys_flash_ssram_a 		<= ('0' & flash_a(24 downto 2) & '0') after topad;
				if flash_d_drv = '1' then
					sys_flash_ssram_d	<= flash_do after topad;
				end if;
			elsif ssram_bsy = '1' then
				sys_flash_ssram_oe_n	<= ssram_oe_n;
				sys_flash_ssram_we_n	<= ssram_we_n;
				sys_flash_ssram_a 		<= ssram_a after topad;
				if ssram_d_drv = '1' then
					sys_flash_ssram_d	<= ssram_do after topad;
				end if;
			end if;	
		end if;
	end process;
	
	---------------------------------------------------------------
	-- Arbiter
	MRDY_O		<= MRDY_O_cpu when arb_gnt(0) = '1' else MRDY_O_vga when arb_gnt(1) = '1' else '0';
	MDAT_O		<= MDAT_O_cpu when arb_gnt(0) = '1' else MDAT_O_vga(31 downto 0) when arb_gnt(1) = '1' else (others => '0');
	ADDR_O		<= ADDR_O_cpu when arb_gnt(0) = '1' else ADDR_O_vga when arb_gnt(1) = '1' else (others => '0');
	SEL_O		<= SEL_O_cpu when arb_gnt(0) = '1' else SEL_O_vga(3 downto 0) when arb_gnt(1) = '1' else (others => '0');
	WE_O		<= WE_O_cpu when arb_gnt(0) = '1' else WE_O_vga when arb_gnt(1) = '1' else '0';
	CYC_O		<= CYC_O_cpu when arb_gnt(0) = '1' else CYC_O_vga when arb_gnt(1) = '1' else '0';
	STB_O		<= STB_O_cpu when arb_gnt(0) = '1' else STB_O_vga when arb_gnt(1) = '1' else '0';
	SRDY_I_cpu	<= SRDY_I and arb_gnt(0);
	SRDY_I_vga	<= SRDY_I and arb_gnt(1);
	ACK_I_cpu	<= ACK_I and arb_gnt(0);
	ACK_I_vga	<= ACK_I and arb_gnt(1);
	
	arb_req(0)	<= CYC_O_cpu;
	arb_req(1)	<= CYC_O_vga;
	
	MDAT_I_vga	<= SDAT_O_sdram(63 downto 32) & MDAT_I;
	
arbiter_proc:
	process(CLK_O)
	begin
		if rising_edge(CLK_O) then
			if RST_O = '1' then
				arb_gnt	<= (others => '0');
				arb_idx	<= 0;
			elsif arb_req(arb_idx) = '0' then
				if arb_idx /= ARB_MAX_MASTER-1 then
					arb_idx	<= arb_idx + 1;
				else
					arb_idx	<= 0;
				end if;
			else	
				arb_gnt	<= (others => '0');
				arb_gnt(arb_idx)	<= '1';
			end if;	
		end if;
	end process;
	
int_sample:
	process(CLK_O)
	begin
		if rising_edge(CLK_O) then
			INT <= int_timer & (INT_O_ps2 or INT_O_emac) & (ac97_inten and INT_O_ac97) & (usb_inten and sys_usb_int) & (int_uart0 or int_uart1 or int_uart2) & sys_btn(4);
		end if;
	end process;
	
mem_mux:
	process(ADDR_O)
	begin
		mem_area	<= mem_dead;
		flash_page_mode_en	<= '0';
		if ADDR_O(31 downto 28) = X"0" then
			mem_area	<= mem_flash;
			flash_page_mode_en	<= '1';
		elsif ADDR_O(31 downto 28) = X"1" then
			mem_area	<= mem_emac;
		elsif ADDR_O(31 downto 28) = X"A" then
			if ADDR_O(27 downto 26) = "00" then
				if ADDR_O(18 downto 16) = "000" then
					mem_area	<= mem_gpio;
				elsif ADDR_O(18 downto 16) = "001" then
					if ADDR_O(9 downto 8) = "00" then
						mem_area	<= mem_uart0;
					elsif ADDR_O(9 downto 8) = "01" then
						mem_area	<= mem_uart1;
					elsif ADDR_O(9 downto 8) = "10" then
						mem_area	<= mem_uart2;
					end if;						
				elsif ADDR_O(18 downto 16) = "010" then
					mem_area	<= mem_usb;
				elsif ADDR_O(18 downto 16) = "011" then
					mem_area	<= mem_vga;
				elsif ADDR_O(18 downto 16) = "100" then
					mem_area	<= mem_ac97;
				elsif ADDR_O(18 downto 16) = "101" then
					mem_area	<= mem_emac;
				end if;	
			elsif ADDR_O(27 downto 26) = "01" then
				mem_area	<= mem_flash;
			elsif ADDR_O(27 downto 26) = "10" then
				mem_area	<= mem_ssram;
			end if;	
		elsif (ADDR_O(31 downto 28) = X"B" and ADDR_O(15) = '0') then
			mem_area	<= mem_rom;
		elsif (ADDR_O(31 downto 28) = X"8" or ADDR_O(30) = '1') then
			mem_area	<= mem_sdram;
		end if;
	end process;	

signal_mux:
	process(mem_area, CYC_O)
	begin
	
		CYC_I_uart0		<= '0';
		CYC_I_uart1		<= '0';
		CYC_I_uart2		<= '0';
		CYC_I_gpio		<= '0';
		CYC_I_flash		<= '0';
		CYC_I_usb		<= '0';
		CYC_I_rom		<= '0';
		CYC_I_sdram		<= '0';
		CYC_I_vga		<= '0';
		CYC_I_ssram		<= '0';
		CYC_I_ac97		<= '0';
		CYC_I_emac		<= '0';
		
		case mem_area is

		when mem_gpio =>
			CYC_I_gpio		<= CYC_O;

		when mem_uart0 =>
			CYC_I_uart0		<= CYC_O;

		when mem_uart1 =>
			CYC_I_uart1		<= CYC_O;

		when mem_uart2 =>
			CYC_I_uart2		<= CYC_O;

		when mem_flash =>
			CYC_I_flash		<= CYC_O;

		when mem_usb =>
			CYC_I_usb		<= CYC_O;

		when mem_rom =>
			CYC_I_rom		<= CYC_O;

		when mem_sdram =>
			CYC_I_sdram		<= CYC_O;
		
		when mem_vga =>
			CYC_I_vga		<= CYC_O;

		when mem_ac97 =>
			CYC_I_ac97		<= CYC_O;

		when mem_emac =>
			CYC_I_emac		<= CYC_O;

		when mem_ssram =>
			CYC_I_ssram		<= CYC_O;

		when others => null;
		
		end case;
		
	end process;

------------------------------------------------------------------
 	SRDY_I		<=	SRDY_O_flash or SRDY_O_ssram or SRDY_O_usb or SRDY_O_sdram or SRDY_O_rom or SRDY_O_uart0 or SRDY_O_uart1 or SRDY_O_uart2 or SRDY_O_gpio or SRDY_O_vga or SRDY_O_ac97 or SRDY_O_emac;
 	ACK_I		<=	ACK_O_flash or ACK_O_usb or ACK_O_sdram or ACK_O_ssram or ACK_O_rom or ACK_O_uart0 or ACK_O_uart1 or ACK_O_uart2 or ACK_O_gpio or ACK_O_vga or ACK_O_ac97 or ACK_O_emac;
 	MDAT_I		<=	SDAT_O_ssram when CYC_I_ssram = '1' else
 					SDAT_O_sdram(31 downto 0) when CYC_I_sdram = '1' else
					SDAT_O_rom when CYC_I_rom = '1' else
					SDAT_O_flash when CYC_I_flash = '1' else
					SDAT_O_usb when CYC_I_usb = '1' else
					SDAT_O_uart0 when CYC_I_uart0 = '1' else
					SDAT_O_uart1 when CYC_I_uart1 = '1' else
					SDAT_O_uart2 when CYC_I_uart2 = '1' else
					SDAT_O_vga when CYC_I_vga = '1' else
					SDAT_O_ac97 when CYC_I_ac97 = '1' else
					SDAT_O_emac when CYC_I_emac = '1' else
					SDAT_O_gpio when CYC_I_gpio = '1' else X"DEADBEEF";

------------------------------------------------------------------
inst_mips_top: entity work.mips_top
	PORT MAP
	(
		debug			=> debug,
		eb				=> eb,
		nmi				=> nmi,
		cpu_clk			=> CLK_O,
		RST_I			=> RST_O,
		CLK_I			=> CLK_O,
		ACK_I			=> ACK_I_cpu,
		SRDY_I			=> SRDY_I_cpu,
		MRDY_O			=> MRDY_O_cpu,
		CYC_O			=> CYC_O_cpu,
		STB_O			=> STB_O_cpu,
		WE_O			=> WE_O_cpu,
		SEL_O			=> SEL_O_cpu,
		DAT_I			=> MDAT_I,
		DAT_O			=> MDAT_O_cpu,
		ADDR_O			=> ADDR_O_cpu,
		INT				=> INT
	);

inst_rom_wb : entity work.rom_wb
	PORT MAP
	(
		CLK_I	=> CLK_O,
		RST_I	=> RST_O,
		CYC_I	=> CYC_I_rom,
		STB_I	=> STB_O,
		WE_I	=> WE_O,
		ACK_O	=> ACK_O_rom,
		MRDY_I	=> MRDY_O,
		SRDY_O	=> SRDY_O_rom,
		ADDR_I	=> ADDR_O,
		DAT_O	=> SDAT_O_rom
	);


inst_lcd_port: entity work.lcd_port
	PORT MAP
	(
		clk => CLK_O,
		rst => RST_O,
		we => '0',
		din => X"00",
		dout => open,
		lcd_d => sys_lcd_d,
		lcd_e => sys_lcd_e,
		lcd_rs => sys_lcd_rs,
		lcd_rw => sys_lcd_rw
	);
	
inst_gpio_wb : entity work.gpio_wb
	GENERIC MAP
	(
		f_sysclk	=> sys_freq_in
	)
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_gpio,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_gpio,
		SRDY_O		=> SRDY_O_gpio,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_gpio,
		INT_TIM_O	=> int_timer,

		sys_gpi_0	=> gpi_0,
		sys_gpo_0	=> gpo_0
	);

inst_flash_port : entity work.flash_port_wb
	GENERIC MAP
	(
		f_sysclk		=> sys_freq_in,
		addr_width		=> 25,
		data_width		=> 32,
		async_timespec	=> ts_flash
	)
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_flash,
		STB_I		=> STB_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_flash,
		SRDY_O		=> SRDY_O_flash,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_flash,
		port_bsyo	=> flash_bsy,
		port_bsyi	=> ssram_bsy,
		port_a		=> flash_a,
		port_di		=> sys_flash_ssram_d,
		port_do		=> flash_do,
		port_d_drv	=> flash_d_drv,
		port_wr		=> flash_we_n,
		port_rd		=> flash_oe_n,
		flash_cs	=> sys_flash_ce,
		flash_rst	=> flash_rstn
	);

inst_usb_port : entity work.async_port_wb
	GENERIC MAP
	(
		f_sysclk		=> sys_freq_in,
		addr_width		=> 2,
		data_width		=> 16,
		byte_sel_width	=> 1,
		async_timespec	=> ts_usb
	)
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_usb,
		STB_I		=> STB_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_usb,
		SRDY_O		=> SRDY_O_usb,
		MRDY_I		=> MRDY_O,
		SEL_I		=> SEL_O,
		ADDR_I		=> ADDR_I_usb,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_usb,
		page_mode_en	=> '0',
		async_a		=> sys_usb_a,
		async_d		=> sys_usb_d,
		async_cs	=> sys_usb_csn,
		async_wr	=> sys_usb_wrn,
		async_rd	=> sys_usb_rdn,
		async_be	=> open,
		async_rst	=> open
	);

inst_uart_wb_0 : entity work.uart_wb
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_uart0,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_uart0,
		SRDY_O		=> SRDY_O_uart0,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_uart0,
		INT_O		=> int_uart0,
		ser_rx		=> sys_uart0_rx,
		ser_tx		=> sys_uart0_tx
	);

inst_uart_wb_1 : entity work.uart_wb
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_uart1,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_uart1,
		SRDY_O		=> SRDY_O_uart1,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_uart1,
		INT_O		=> int_uart1,
		ser_rx		=> sys_uart1_rx,
		ser_tx		=> sys_uart1_tx
	);

inst_uart_wb_2 : entity work.uart_wb
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_uart2,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_uart2,
		SRDY_O		=> SRDY_O_uart2,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_uart2,
		INT_O		=> int_uart2,
		ser_rx		=> sys_uart2_rx,
		ser_tx		=> sys_uart2_tx
	);
inst_ssram_port_wb : entity work.ssram_port_wb
	GENERIC MAP
	(
		addr_width		=> 25,
		data_width		=> 32,
		parity_width	=> 4
	)
	PORT MAP
	(
		-- J-Bus domain
		RST_I		=> RST_O,
		CLK_I		=> CLK_O,
		CYC_I		=> CYC_I_ssram,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_ssram,
		SRDY_O		=> SRDY_O_ssram,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_I_ssram,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_ssram,
		
		-- Sync SRAM domain
		ssram_clk_o		=> sys_ssram_clk,
		ssram_clk_fb	=> sys_ssram_clk_fb,
		ssram_cke_n		=> sys_ssram_cke_n,
		ssram_ce_n		=> sys_ssram_ce_n,
		port_bsyo		=> ssram_bsy,
		port_bsyi		=> flash_bsy,
		port_di			=> sys_flash_ssram_d,
		port_do			=> ssram_do,
		port_d_drv		=> ssram_d_drv,
		port_wr			=> ssram_we_n,
		port_rd			=> ssram_oe_n,
		port_a			=> ssram_a,
		ssram_adv		=> sys_ssram_adv,
		ssram_mode		=> sys_ssram_mode,
		ssram_zz		=> sys_ssram_zz,
		ssram_dp		=> sys_ssram_dp,
		ssram_bw_n		=> sys_ssram_bw_n
	);

inst_clockgen_cpu : entity work.clockgen
	GENERIC MAP
	(
		clk_in_freq			=> sys_freq_in,
		clk_out_freq		=> cpu_freq
	)
	PORT MAP 
	(
		-- Clocks and Reset
		rst_in				=> rst_in,
		clk_in				=> sys_clk_in,
		rst_out				=> RST_O,
		clk_out				=> CLK_O
	);

inst_clocken_vga : entity work.clockgen
	GENERIC MAP
	(
		clk_in_freq			=> sys_freq_in,
		clk_out_freq		=> vga_freq
	)
	PORT MAP 
	(
		-- Clocks and Reset
		rst_in				=> rst_in,
		clk_in				=> sys_clk_in,
		rst_out				=> vga_rst,
		clk_out				=> vga_clk
	);

inst_sdram_ctrl_wb64 : entity work.ctrl_ddr_wb64
	GENERIC MAP
	(
		F_SYSCLK			=> sys_freq_in,
		F_SDRCLK			=> sys_freq_in,
		FIFO_DEPTH			=> 5
	)
	PORT MAP
	(
		RST_I				=> RST_O,
		CLK_I				=> CLK_O,

		SDRAM_CLK_I			=> CLK_O,
		SDRAM_CLK_FB_I		=> sys_sdr_clk_fb,
		
		CYC_I				=> CYC_I_sdram,
		STB_I				=> STB_O,
		SEL_I				=> SEL_I_sdram,
		WE_I				=> WE_O,
		ACK_O				=> ACK_O_sdram,
		MRDY_I				=> MRDY_O,
		SRDY_O				=> SRDY_O_sdram,
		ADDR_I				=> ADDR_O,
		DAT_I				=> SDAT_I_sdram,
		DAT_O				=> SDAT_O_sdram,

		-- SDRAM signals
		sd_clk_p			=> sys_sdr_clk_p,
		sd_clk_n			=> sys_sdr_clk_n,
		sd_cke				=> sys_sdr_cke_q,
		sd_cs_n				=> sys_sdr_cs_qn,
		sd_cas_n			=> sys_sdr_cas_qn,
		sd_ras_n			=> sys_sdr_ras_qn,
		sd_we_n				=> sys_sdr_we_qn,
		sd_addr				=> sys_sdr_a_q,
		sd_ba				=> sys_sdr_ba_q,
		sd_dm				=> sys_sdr_dm_q,
		sd_dqs				=> sys_sdr_dqs_q,
		sd_data				=> sys_sdr_data
		
	);

inst_vga_frontend : entity work.vga_frontend64
	GENERIC MAP
	(
		fifo_depth					=> 2048,
		fifo_almost_full_thresh		=> 1860,
		fifo_almost_empty_thresh	=> 256,
		tsvga						=> tsvga
	)
	PORT MAP
	(
		-- System signals
		RST_I			=> RST_O,
		CLK_I			=> CLK_O,

		-- JBUS Master signals
		CYC_O			=> CYC_O_vga,
		STB_O			=> STB_O_vga,
		WE_O			=> WE_O_vga,
		SEL_O			=> SEL_O_vga,
		ACK_I			=> ACK_I_vga,
		SRDY_I			=> SRDY_I_vga,
		MRDY_O			=> MRDY_O_vga,
		ADDR_O			=> ADDR_O_vga,
		MDAT_I			=> MDAT_I_vga,
		MDAT_O			=> MDAT_O_vga,

		-- JBUS Slave signals
		CYC_I			=> CYC_I_vga,
		STB_I			=> STB_O,
		WE_I			=> WE_O,
		SEL_I			=> SEL_O,
		ACK_O			=> ACK_O_vga,
		SRDY_O			=> SRDY_O_vga,
		MRDY_I			=> MRDY_O,
		ADDR_I			=> ADDR_O,
		SDAT_I			=> MDAT_O,
		SDAT_O			=> SDAT_O_vga,

		-- VGA signals
		vga_clk_in		=> vga_clk,
		vga_clk_ce		=> vga_ce,
		vga_red			=> sys_vga_red,
		vga_green		=> sys_vga_green,
		vga_blue		=> sys_vga_blue,
		vga_blank_n		=> sys_vga_blank_n,
		vga_sync_n		=> sys_vga_sync_n,
		vga_hsync		=> sys_vga_hsync,
		vga_vsync		=> sys_vga_vsync	
	);

inst_ac97_wb : entity work.ac97_wb
	GENERIC MAP
	(
		fifo_depth		=> 4
	)
	PORT MAP
	(
		-- J-Bus domain
		CLK_I			=> CLK_O,
		RST_I			=> RST_O,
		CYC_I			=> CYC_I_ac97,
		STB_I			=> STB_O,
		WE_I			=> WE_O,
		ACK_O			=> ACK_O_ac97,
		SRDY_O			=> SRDY_O_ac97,
		MRDY_I			=> MRDY_O,
		ADDR_I			=> ADDR_O,
		DAT_I			=> MDAT_O,
		DAT_O			=> SDAT_O_ac97,
		INT_O			=> INT_O_ac97,

		-- AC97 domain
		ac97_sdata_in	=> sys_ac97_sdata_in,
		ac97_bit_clk	=> sys_ac97_bit_clk,          
		ac97_reset_n	=> ac97_rstn,
		ac97_sdata_out	=> sys_ac97_sdata_out,
		ac97_ssync		=> sys_ac97_ssync		
	);

inst_ps2_wb: entity work.ps2_wb
	GENERIC MAP
	(
		f_sys_clk	=> sys_freq_in
	)
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		CYC_I		=> CYC_I_ps2,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_ps2,
		SRDY_O		=> SRDY_O_ps2,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_ps2,
		INT_O		=> INT_O_ps2,
		clk_rx		=> ps2_clk_rx,
		data_rx		=> ps2_data_rx,
		clk_tx		=> ps2_clk_tx,
		data_tx		=> ps2_data_tx
	);

inst_ps2_phy: entity work.ps2_phy
	PORT MAP
	(
		rst => RST_O,
		clk => CLK_O,
		ps2_clk => sys_ps2_clk,
		ps2_data => sys_ps2_data,
		rx_clk => ps2_clk_rx,
		rx_data => ps2_data_rx,
		tx_clk => ps2_clk_tx,
		tx_data => ps2_data_tx
	);

inst_emac_jb : entity work.emac_top_jb
	PORT MAP
	(
		CLK_I		=> CLK_O,
		RST_I		=> RST_O,
		INT_O		=> INT_O_emac,
		CYC_I		=> CYC_I_emac,
		STB_I		=> STB_O,
		SEL_I		=> SEL_O,
		WE_I		=> WE_O,
		ACK_O		=> ACK_O_emac,
		SRDY_O		=> SRDY_O_emac,
		MRDY_I		=> MRDY_O,
		ADDR_I		=> ADDR_O,
		DAT_I		=> MDAT_O,
		DAT_O		=> SDAT_O_emac,
		mii_rx_clk	=> sys_phy_rx_clk,
		mii_rx_dv	=> sys_phy_rx_dv,
		mii_rx_er	=> sys_phy_rx_er,
		mii_rx		=> sys_phy_rx,
		mii_tx_clk	=> sys_phy_tx_clk,
		mii_tx_en	=> sys_phy_tx_en,
		mii_tx_er	=> sys_phy_tx_er,
		mii_tx		=> sys_phy_tx,
		mii_gtx_clk	=> sys_phy_gtx_clk,
		mii_crs		=> sys_phy_crs,
		mii_col		=> sys_phy_col
		
	);


	------------------------------------------------------------------
END;
