----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:18:39 03/01/2013 
-- Design Name: 
-- Module Name:    ddr3_interface - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity ddr3_interface is
	port(
		sys_clk125 : IN std_logic;
		sys_clk_ok : in std_logic;
		memory_controller_reset : IN std_logic;

		-- user interface channel 1
		ddr3_usr_clk : out std_logic;
		ddr3_init_done : out std_logic;

		-- data: read fifo 
		read_data_fifo_clr : in std_logic;
		read_data_fifo_rd_clk : in std_logic;
		read_data_fifo_rd_en : in std_logic;
		read_data_fifo_dout : out  std_logic_vector(255 downto 0); 
		read_data_fifo_rd_count : out  std_logic_vector(9 downto 0); 
		read_data_fifo_empty : out std_logic;

		-- address: read fifo 
		read_addr_fifo_clr : in std_logic;
		read_addr_fifo_wr_clk : in std_logic;
		read_addr_fifo_wr_en : in std_logic;
		read_addr_fifo_din : in std_logic_vector(31 downto 0); 
		read_addr_fifo_wr_count : out std_logic_vector(9 downto 0); 

		-- data: write fifo 
		write_fifo_wr_clk : in std_logic;
		write_fifo_wr_clr : in std_logic;
		write_data_fifo_wr_en : in std_logic;
		write_data_fifo_din : in std_logic_vector(255 downto 0); 
		write_data_fifo_wr_count : out std_logic_vector(9 downto 0); 

		-- address: write fifo 
		write_addr_fifo_wr_en : in std_logic;
		write_addr_fifo_din : in std_logic_vector(31 downto 0); 
		write_addr_fifo_wr_count : out std_logic_vector(9 downto 0);
		
		-- ddr3 pins
		ddr3_dq : INOUT std_logic_vector(63 downto 0);
		ddr3_dqs_p : INOUT std_logic_vector(7 downto 0);
		ddr3_dqs_n : INOUT std_logic_vector(7 downto 0);      
		ddr3_dm : OUT std_logic_vector(7 downto 0);
		ddr3_addr : OUT std_logic_vector(14 downto 0);
		ddr3_ba : OUT std_logic_vector(2 downto 0);
		ddr3_ras_n : OUT std_logic;
		ddr3_cas_n : OUT std_logic;
		ddr3_we_n : OUT std_logic;
		ddr3_reset_n : OUT std_logic;
		ddr3_cs_n : OUT std_logic_vector(0 to 0);
		ddr3_odt : OUT std_logic_vector(0 to 0);
		ddr3_cke : OUT std_logic_vector(0 to 0);
		ddr3_ck_p : OUT std_logic_vector(0 to 0);
		ddr3_ck_n : OUT std_logic_vector(0 to 0)
	);
end ddr3_interface;

architecture Behavioral of ddr3_interface is

	Function to_std_logic(X: in Boolean) return Std_Logic is
		variable ret : std_logic;
   begin
		if x then ret := '1';  else ret := '0'; end if;
		return ret;
   end to_std_logic;

	COMPONENT ddr3_controller
	PORT(
		mmcm_clk : IN std_logic;
		sys_rst : IN std_logic;    
		ddr3_dq : INOUT std_logic_vector(63 downto 0);
		ddr3_dqs_p : INOUT std_logic_vector(7 downto 0);
		ddr3_dqs_n : INOUT std_logic_vector(7 downto 0);      
		ddr3_dm : OUT std_logic_vector(7 downto 0);
		ddr3_addr : OUT std_logic_vector(14 downto 0);
		ddr3_ba : OUT std_logic_vector(2 downto 0);
		ddr3_ras_n : OUT std_logic;
		ddr3_cas_n : OUT std_logic;
		ddr3_we_n : OUT std_logic;
		ddr3_reset_n : OUT std_logic;
		ddr3_cs_n : OUT std_logic_vector(0 to 0);
		ddr3_odt : OUT std_logic_vector(0 to 0);
		ddr3_cke : OUT std_logic_vector(0 to 0);
		ddr3_ck_p : OUT std_logic_vector(0 to 0);
		ddr3_ck_n : OUT std_logic_vector(0 to 0);
		phy_init_done : OUT std_logic;
		app_addr : in std_logic_vector(28 downto 0); -- ADDR_WIDTH-1
		app_cmd : in std_logic_vector(2 downto 0);
		app_en : in std_logic;
		app_hi_pri : in std_logic;
		app_wdf_data : in std_logic_vector(255 downto 0);
		app_wdf_end : in std_logic;
		app_wdf_wren : in std_logic;
      app_wdf_rdy : out std_logic;
      app_rd_data : out std_logic_vector(255 downto 0);
      app_rd_data_end : out std_logic;
      app_rd_data_valid : out std_logic;
		usr_clk : out std_logic;
      app_rdy : out std_logic   
		);
	END COMPONENT;
	
	COMPONENT blk_asy_fifo_fwft_512x32
	PORT (
		rst : IN STD_LOGIC;
		wr_clk : IN STD_LOGIC;
		rd_clk : IN STD_LOGIC;
		din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
		wr_en : IN STD_LOGIC;
		rd_en : IN STD_LOGIC;
		dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
		full : OUT STD_LOGIC;
		empty : OUT STD_LOGIC;
		rd_data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0);
		wr_data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
	);
	END COMPONENT;
		
	COMPONENT blk_asy_fifo_fwft_512x256
	PORT (
		rst : IN STD_LOGIC;
		wr_clk : IN STD_LOGIC;
		rd_clk : IN STD_LOGIC;
		din : IN STD_LOGIC_VECTOR(255 DOWNTO 0);
		wr_en : IN STD_LOGIC;
		rd_en : IN STD_LOGIC;
		dout : OUT STD_LOGIC_VECTOR(255 DOWNTO 0);
		full : OUT STD_LOGIC;
		empty : OUT STD_LOGIC;
		rd_data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0);
		wr_data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
	);
	END COMPONENT;
	
	COMPONENT readwrite_controller
	PORT(
		clk : IN std_logic;
		rst : IN std_logic;
		read_intf_addr_fifo_rcnt : IN std_logic_vector(9 downto 0);
		read_intf_addr_fifo_empty : IN std_logic;
		write_intf_addr_fifo_rcnt : IN std_logic_vector(9 downto 0);
		write_intf_data_fifo_rcnt : IN std_logic_vector(9 downto 0);
		write_intf_addr_fifo_empty : IN std_logic;
		write_intf_data_fifo_empty : IN std_logic;
		app_rdy : IN std_logic;      
		app_wdf_rdy : in std_logic;    
		read_intf_addr_fifo_rden : OUT std_logic;
		write_intf_addr_fifo_rden : OUT std_logic;
		write_intf_data_fifo_rden : OUT std_logic;
		app_en : OUT std_logic;
		app_cmd : OUT std_logic_vector(2 downto 0);
		app_hi_pri : OUT std_logic;
		app_wdf_wren : OUT std_logic
		);
	END COMPONENT;
	
	signal usr_clk : std_logic;
	signal phy_init_done : std_logic;
	
	signal read_intf_addr_fifo_rst : std_logic;
	signal read_intf_data_fifo_rst : std_logic;
	signal write_intf_addr_fifo_rst : std_logic;
	signal write_intf_data_fifo_rst : std_logic;
	
	signal read_intf_addr_fifo_dout : std_logic_vector(31 downto 0);
	signal read_intf_addr_fifo_rcnt : std_logic_vector(9 downto 0);
	signal read_intf_addr_fifo_rden : std_logic;
	signal read_intf_addr_fifo_empty : std_logic;
	
	signal read_intf_data_fifo_wcnt : std_logic_vector(9 downto 0);
	
	signal write_intf_addr_fifo_dout : std_logic_vector(31 downto 0);
	signal write_intf_addr_fifo_rcnt : std_logic_vector(9 downto 0);
	signal write_intf_addr_fifo_empty : std_logic;
	signal write_intf_addr_fifo_rden : std_logic;
	
	signal write_intf_data_fifo_dout : std_logic_vector(31 downto 0);
	signal write_intf_data_fifo_rcnt : std_logic_vector(9 downto 0);
	signal write_intf_data_fifo_empty : std_logic;
	signal write_intf_data_fifo_rden : std_logic;
	
	signal app_addr : std_logic_vector(28 downto 0);
	signal app_cmd : std_logic_vector(2 downto 0);
	signal app_en : std_logic;
	signal app_hi_pri : std_logic;
	signal app_wdf_data : std_logic_vector(255 downto 0);
	signal app_wdf_wren : std_logic;
   signal app_wdf_rdy : std_logic;
   signal app_rd_data : std_logic_vector(255 downto 0);
   signal app_rd_data_valid : std_logic;
   signal app_rdy : std_logic;

begin

	read_intf_addr_fifo_rst <=    not phy_init_done
										or memory_controller_reset
										or read_addr_fifo_clr;

	read_intf_addr_fifo : blk_asy_fifo_fwft_512x32
	PORT MAP (
		rst => read_intf_addr_fifo_rst,
		wr_clk => read_addr_fifo_wr_clk,
		rd_clk => usr_clk,
		din => read_addr_fifo_din,
		wr_en => read_addr_fifo_wr_en,
		rd_en => read_intf_addr_fifo_rden,
		dout => read_intf_addr_fifo_dout,
		full => open,
		empty => read_intf_addr_fifo_empty,
		rd_data_count => read_intf_addr_fifo_rcnt,
		wr_data_count => read_addr_fifo_wr_count
	);
	
	read_intf_data_fifo_rst <=    not phy_init_done
										or memory_controller_reset
										or read_data_fifo_clr;

	read_intf_data_fifo : blk_asy_fifo_fwft_512x256
	PORT MAP (
		rst => read_intf_data_fifo_rst,
		wr_clk => usr_clk,
		rd_clk => read_data_fifo_rd_clk,
		din => app_rd_data,
		wr_en => app_rd_data_valid,
		rd_en => read_data_fifo_rd_en,
		dout => read_data_fifo_dout,
		full => open,
		empty => read_data_fifo_empty,
		rd_data_count => read_data_fifo_rd_count,
		wr_data_count => read_intf_data_fifo_wcnt
	);
	
	write_intf_addr_fifo_rst <=    not phy_init_done
										 or memory_controller_reset
										 or write_fifo_wr_clr;
	
	write_intf_addr_fifo : blk_asy_fifo_fwft_512x32
	PORT MAP (
		rst => write_intf_addr_fifo_rst,
		wr_clk => write_fifo_wr_clk,
		rd_clk => usr_clk,
		din => write_addr_fifo_din,
		wr_en => write_addr_fifo_wr_en,
		rd_en => write_intf_addr_fifo_rden,
		dout => write_intf_addr_fifo_dout,
		full => open,
		empty => write_intf_addr_fifo_empty,
		rd_data_count => write_intf_addr_fifo_rcnt,
		wr_data_count => write_addr_fifo_wr_count
	);
	
	write_intf_data_fifo_rst <=    not phy_init_done
										 or memory_controller_reset
										 or write_fifo_wr_clr;

	write_intf_data_fifo : blk_asy_fifo_fwft_512x256
	PORT MAP (
		rst => write_intf_data_fifo_rst,
		wr_clk => write_fifo_wr_clk,
		rd_clk => usr_clk,
		din => write_data_fifo_din,
		wr_en => write_data_fifo_wr_en,
		rd_en => write_intf_data_fifo_rden,
		dout => app_wdf_data,
		full => open,
		empty => write_intf_data_fifo_empty,
		rd_data_count => write_intf_data_fifo_rcnt,
		wr_data_count => write_data_fifo_wr_count
	);
	
	app_addr <= write_intf_addr_fifo_dout(28 downto 0) when write_intf_addr_fifo_rden = '1' else read_intf_addr_fifo_dout(28 downto 0);
	
	Inst_ddr3_controller: ddr3_controller PORT MAP(
		mmcm_clk => sys_clk125,
		ddr3_dq => ddr3_dq,
		ddr3_dm => ddr3_dm,
		ddr3_addr => ddr3_addr,
		ddr3_ba => ddr3_ba,
		ddr3_ras_n => ddr3_ras_n,
		ddr3_cas_n => ddr3_cas_n,
		ddr3_we_n => ddr3_we_n,
		ddr3_reset_n => ddr3_reset_n,
		ddr3_cs_n => open, -- hardwired to gnd on pcb
		ddr3_odt => ddr3_odt,
		ddr3_cke => ddr3_cke,
		ddr3_dqs_p => ddr3_dqs_p,
		ddr3_dqs_n => ddr3_dqs_n,
		ddr3_ck_p => ddr3_ck_p,
		ddr3_ck_n => ddr3_ck_n,
		
		phy_init_done => phy_init_done,
		sys_rst => memory_controller_reset,
		usr_clk => usr_clk,
		
		app_addr => app_addr,
		app_cmd => app_cmd,
		app_en => app_en,
		app_hi_pri => app_hi_pri,		
		
		app_wdf_data => app_wdf_data,
		app_wdf_wren => app_wdf_wren,
		app_wdf_end => app_wdf_wren, -- nur erlaubt bei burstlen = 4 -> 256bit user bus wird zu 4er burst auf 64bit memory bus
      app_wdf_rdy => app_wdf_rdy,		
		
      app_rd_data => app_rd_data,
      app_rd_data_end => open, -- end of read burst, wird nicht gebraucht
      app_rd_data_valid => app_rd_data_valid,		
		
      app_rdy => app_rdy
	);
	
	ddr3_usr_clk <= usr_clk;
	ddr3_init_done <= phy_init_done;
	
	Inst_readwrite_controller: readwrite_controller PORT MAP(
		clk => usr_clk,
		rst => memory_controller_reset,
		read_intf_addr_fifo_rcnt => read_intf_addr_fifo_rcnt,
		read_intf_addr_fifo_rden => read_intf_addr_fifo_rden,
		read_intf_addr_fifo_empty => read_intf_addr_fifo_empty,
		write_intf_addr_fifo_rcnt => write_intf_addr_fifo_rcnt,
		write_intf_data_fifo_rcnt => write_intf_data_fifo_rcnt,
		write_intf_addr_fifo_empty => write_intf_addr_fifo_empty,
		write_intf_data_fifo_empty => write_intf_data_fifo_empty,
		write_intf_addr_fifo_rden => write_intf_addr_fifo_rden,
		write_intf_data_fifo_rden => write_intf_data_fifo_rden,
		app_en => app_en,
		app_cmd => app_cmd,
		app_hi_pri => app_hi_pri,
		app_wdf_wren => app_wdf_wren,
		app_wdf_rdy => app_wdf_rdy,
		app_rdy => app_rdy
	);

end Behavioral;
