-------------------------------------------------------------------------------
-- CSEE 4840 Embedded System Design
-- Jaycam
-- Yaniv Schiller - yhs2001@columbia.edu
-- Avrum Tilman - amt77@columbia.edu
-- Josh Weinberg - jmw211@columbia.edu
-------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;		
use UNISIM.VCOMPONENTS.ALL;

entity pad_io is
    Port ( sys_clk : in std_logic;
           io_clock : in std_logic;
           read_early : in std_logic;
           write_early : in std_logic;
           
           rst : in std_logic;
           PB_A : out std_logic_vector(19 downto 0);
           PB_UB_N : out std_logic;
           PB_LB_N : out std_logic;
           PB_WE_N : out std_logic;
           PB_OE_N : out std_logic;
           RAM_CE_N : out std_logic;
           ETHERNET_CS_N : out std_logic;
           ETHERNET_RDY : in std_logic;
           ETHERNET_IREQ : in std_logic;
           ETHERNET_IOCS16_N : in std_logic;
           PB_D : inout std_logic_vector(15 downto 0);

           pb_addr : in std_logic_vector(19 downto 0);
           pb_ub : in std_logic;
           pb_lb : in std_logic;
           pb_wr : in std_logic;
           pb_rd : in std_logic;
           ram_ce : in std_logic;
           ethernet_ce : in std_logic;
           pb_dread : out std_logic_vector(15 downto 0);
           pb_dwrite : in std_logic_vector(15 downto 0));
end pad_io;

architecture Behavioral of pad_io is

component FDCE
port (C : in std_logic;
		CLR : in std_logic;
		CE : in std_logic;
		D : in std_logic;
		Q : out std_logic);
end component;

component FDPE
port (C : in std_logic;
		PRE : in std_logic;
		CE : in std_logic;
		D : in std_logic;
		Q : out std_logic);
end component;

attribute iob : string;
attribute iob of FDCE : component is "true";
attribute iob of FDPE : component is "true";

component OBUF_F_24
port (O : out STD_ULOGIC;
		I : in STD_ULOGIC);
end component;

component IOBUF_F_24
port (O : out STD_ULOGIC;
		IO : inout STD_ULOGIC;
		I : in STD_ULOGIC;
		T : in STD_ULOGIC);
end component;

signal io_half : std_logic;
signal pb_addr_1: std_logic_vector(19 downto 0);
signal pb_dwrite_1: std_logic_vector(15 downto 0);
signal pb_tristate: std_logic_vector(15 downto 0);
signal pb_tristate_1: std_logic_vector(15 downto 0);
signal pb_dread_a: std_logic_vector(15 downto 0);
signal we_n, pb_we_n1: std_logic;
signal oe_n, pb_oe_n1: std_logic;
signal lb_n, pb_lb_n1: std_logic;
signal ub_n, pb_ub_n1: std_logic;
signal ethce_n, eth_ce_n1 : std_logic;
signal ramce_n, ram_ce_n1: std_logic;
signal dataz : std_logic;	

signal rd_ce, wr_ce, din_ce, rd_early, wr_early : std_logic;

--attribute equivalent_register_removal: string;
--attribute equivalent_register_removal of pb_tristate_1 : signal is "no";
--attribute equivalent_register_removal of pb_dwrite_1 : signal is "no";


begin

------------------------ !!!!!!!!!!!!!!!!!!!!!!! ------------------------------
--process (io_clock)
--begin
--  if io_clock'event and io_clock = '1' then
--    io_half <= sys_clk;
--  end if;
--end process;
io_half <= not sys_clk;
-------------------------------------------------------------------------------

process(rst, sys_clk)
begin
	if rst='1' then
          rd_early <= '0';
          wr_early <= '0';
        elsif sys_clk'event and sys_clk='1' then
          rd_early <= read_early;
          wr_early <= write_early;
      end if;
end process;

dataz <= (not pb_wr) or pb_rd;
pb_tristate_1 <= "1111111111111111" when dataz ='1' else "0000000000000000";



-- control
pb_we_n1 <= not pb_wr; -- or (not io_half and wr_early);

pb_oe_n1 <= not pb_rd; --or (not io_half and rd_early);      

pb_lb_n1 <= '0' when (ram_ce='1') else (not pb_lb);

pb_ub_n1 <= '0' when (ram_ce='1') else (not pb_ub);

ram_ce_n1 <= not ram_ce;

eth_ce_n1 <= not ethernet_ce;


-- I/O BUFFERS

webuf : OBUF_F_24
port map (O => PB_WE_N,
			 I => pb_we_n1);

oebuf : OBUF_F_24
port map (O => PB_OE_N,
			 I => pb_oe_n1);

ramcebuf : OBUF_F_24
port map (O => RAM_CE_N,
			 I => ram_ce_n1);

ethcebuf : OBUF_F_24
port map (O => ETHERNET_CS_N,
			 I => eth_ce_n1);

--  ETHERNET_RDY : in std_logic;
--  ETHERNET_IREQ : in std_logic;
--  ETHERNET_IOCS16_N : in std_logic;
           



ubbuf : OBUF_F_24
port map (O => PB_UB_N,
			 I => pb_ub_n1);

lbbuf : OBUF_F_24
port map (O => PB_LB_N,
			 I => pb_lb_n1);

abuf : for i in 0 to 19 generate
	abuf : OBUF_F_24 port map (
		O => PB_A(i),
		I => pb_addr(i));
end generate;

dbuf : for i in 0 to 15 generate
	dbuf : IOBUF_F_24 port map (
		O => pb_dread(i),
		IO => PB_D(i),
		I => pb_dwrite(i),
		T => pb_tristate_1(i));
end generate;


      
end Behavioral;
