library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

use work.typedef_package.all;

entity xillydemo is
  port (
    clk_100         : IN std_logic;
    otg_oc          : IN std_logic;
    GPIO_LED        : OUT std_logic_vector(3 DOWNTO 0);
    vga4_blue       : OUT std_logic_vector(3 DOWNTO 0);
    vga4_green      : OUT std_logic_vector(3 DOWNTO 0);
    vga4_red        : OUT std_logic_vector(3 DOWNTO 0);
    vga_hsync       : OUT std_logic;
    vga_vsync       : OUT std_logic;
    audio_mclk      : OUT std_logic;
    audio_dac       : OUT std_logic;
    audio_adc       : IN std_logic;
    audio_bclk      : IN std_logic;
    audio_lrclk     : IN std_logic;
    smb_sclk        : OUT std_logic;
    smb_sdata       : INOUT std_logic;
    smbus_addr      : OUT std_logic_vector(1 DOWNTO 0);
    --FEEDBACK_TOP
    clk_ext         : in std_logic;
    areset          : in std_logic;
    areset_debug    : in std_logic;
    async_pulse     : in std_logic;
    astandby        : in std_logic;
    adc_data_in1    : in std_logic;
    adc_data_in2    : in std_logic;
    adc_cs_n        : out std_logic;
    adc_sclk        : out std_logic;
    dac_data_out    : out std_logic;
    dac_cs_n        : out std_logic;
    dac_ldac        : out std_logic;
    dac_sclk        : out std_logic;
    leds            : out std_logic_vector(LED_WIDTH-1 downto 0)
  );
end xillydemo;

architecture sample_arch of xillydemo is
  
  component xillybus
    port (
      PS_CLK : IN std_logic;
      PS_PORB : IN std_logic;
      PS_SRSTB : IN std_logic;
      clk_100 : IN std_logic;
      otg_oc : IN std_logic;
      DDR_Addr : INOUT std_logic_vector(14 DOWNTO 0);
      DDR_BankAddr : INOUT std_logic_vector(2 DOWNTO 0);
      DDR_CAS_n : INOUT std_logic;
      DDR_CKE : INOUT std_logic;
      DDR_CS_n : INOUT std_logic;
      DDR_Clk : INOUT std_logic;
      DDR_Clk_n : INOUT std_logic;
      DDR_DM : INOUT std_logic_vector(3 DOWNTO 0);
      DDR_DQ : INOUT std_logic_vector(31 DOWNTO 0);
      DDR_DQS : INOUT std_logic_vector(3 DOWNTO 0);
      DDR_DQS_n : INOUT std_logic_vector(3 DOWNTO 0);
      DDR_DRSTB : INOUT std_logic;
      DDR_ODT : INOUT std_logic;
      DDR_RAS_n : INOUT std_logic;
      DDR_VRN : INOUT std_logic;
      DDR_VRP : INOUT std_logic;
      MIO : INOUT std_logic_vector(53 DOWNTO 0);
      DDR_WEB : OUT std_logic;
      GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
      bus_clk : OUT std_logic;
      quiesce : OUT std_logic;
      vga4_blue : OUT std_logic_vector(3 DOWNTO 0);
      vga4_green : OUT std_logic_vector(3 DOWNTO 0);
      vga4_red : OUT std_logic_vector(3 DOWNTO 0);
      vga_hsync : OUT std_logic;
      vga_vsync : OUT std_logic;
      user_r_audio_rden : OUT std_logic;
      user_r_audio_empty : IN std_logic;
      user_r_audio_data : IN std_logic_vector(31 DOWNTO 0);
      user_r_audio_eof : IN std_logic;
      user_r_audio_open : OUT std_logic;
      user_w_audio_wren : OUT std_logic;
      user_w_audio_full : IN std_logic;
      user_w_audio_data : OUT std_logic_vector(31 DOWNTO 0);
      user_w_audio_open : OUT std_logic;
      user_w_config_wren : OUT std_logic;
      user_w_config_full : IN std_logic;
      user_w_config_data : OUT std_logic_vector(31 DOWNTO 0);
      user_w_config_open : OUT std_logic;
      user_config_addr : OUT std_logic_vector(15 DOWNTO 0);
      user_config_addr_update : OUT std_logic;
      user_r_debug_rden : OUT std_logic;
      user_r_debug_empty : IN std_logic;
      user_r_debug_data : IN std_logic_vector(31 DOWNTO 0);
      user_r_debug_eof : IN std_logic;
      user_r_debug_open : OUT std_logic;
      user_r_smb_rden : OUT std_logic;
      user_r_smb_empty : IN std_logic;
      user_r_smb_data : IN std_logic_vector(7 DOWNTO 0);
      user_r_smb_eof : IN std_logic;
      user_r_smb_open : OUT std_logic;
      user_w_smb_wren : OUT std_logic;
      user_w_smb_full : IN std_logic;
      user_w_smb_data : OUT std_logic_vector(7 DOWNTO 0);
      user_w_smb_open : OUT std_logic;
      user_clk : OUT std_logic;
      user_wren : OUT std_logic;
      user_rden : OUT std_logic;
      user_wstrb : OUT std_logic_vector(3 DOWNTO 0);
      user_addr : OUT std_logic_vector(31 DOWNTO 0);
      user_rd_data : IN std_logic_vector(31 DOWNTO 0);
      user_wr_data : OUT std_logic_vector(31 DOWNTO 0);
      user_irq : IN std_logic);
  end component;

  component i2s_audio
    port (
      bus_clk : IN std_logic;
      clk_100 : IN std_logic;
      quiesce : IN std_logic;
      audio_mclk : OUT std_logic;
      audio_dac : OUT std_logic;
      audio_adc : IN std_logic;
      audio_bclk : IN std_logic;
      audio_lrclk : IN std_logic;
      user_r_audio_rden : IN std_logic;
      user_r_audio_empty : OUT std_logic;
      user_r_audio_data : OUT std_logic_vector(31 DOWNTO 0);
      user_r_audio_eof : OUT std_logic;
      user_r_audio_open : IN std_logic;
      user_w_audio_wren : IN std_logic;
      user_w_audio_full : OUT std_logic;
      user_w_audio_data : IN std_logic_vector(31 DOWNTO 0);
      user_w_audio_open : IN std_logic);
  end component;

  component smbus
    port (
      bus_clk : IN std_logic;
      quiesce : IN std_logic;
      smb_sclk : OUT std_logic;
      smb_sdata : INOUT std_logic;
      smbus_addr : OUT std_logic_vector(1 DOWNTO 0);
      user_r_smb_rden : IN std_logic;
      user_r_smb_empty : OUT std_logic;
      user_r_smb_data : OUT std_logic_vector(7 DOWNTO 0);
      user_r_smb_eof : OUT std_logic;
      user_r_smb_open : IN std_logic;
      user_w_smb_wren : IN std_logic;
      user_w_smb_full : OUT std_logic;
      user_w_smb_data : IN std_logic_vector(7 DOWNTO 0);
      user_w_smb_open : IN std_logic);
  end component;
  
  component feedback_top is
    port (
      --XILLYBUS
      xillybus_clk    : in std_logic;
      fifo_rd_data    : out std_logic_vector(DEBUG_FIFO_DATA_WIDTH-1 downto 0);
      fifo_ren        : in std_logic;
      fifo_empty      : out std_logic;
      mem_addr        : in std_logic_vector(CONFIG_MEM_ADDR_WIDTH downto 0);
      mem_wr_data     : in std_logic_vector(CONFIG_MEM_DATA_WIDTH-1 downto 0);
      mem_wen         : in std_logic;
      mem_full        : out std_logic;
      --FPGA
      clk_in          : in std_logic;
      areset          : in std_logic;
      areset_debug    : in std_logic;
      async_pulse     : in std_logic;
      astandby        : in std_logic;
      adc_data_in1    : in std_logic;
      adc_data_in2    : in std_logic;
      adc_cs_n        : out std_logic;
      adc_sclk        : out std_logic;
      dac_data_out    : out std_logic;
      dac_cs_n        : out std_logic;
      dac_ldac        : out std_logic;
      dac_sclk        : out std_logic;
      leds            : out std_logic_vector(LED_WIDTH-1 downto 0)
    );
  end component;
  
  signal bus_clk :  std_logic;
  signal quiesce : std_logic;

  signal user_r_audio_rden :  std_logic;
  signal user_r_audio_empty :  std_logic;
  signal user_r_audio_data :  std_logic_vector(31 DOWNTO 0);
  signal user_r_audio_eof :  std_logic;
  signal user_r_audio_open :  std_logic;
  signal user_w_audio_wren :  std_logic;
  signal user_w_audio_full :  std_logic;
  signal user_w_audio_data :  std_logic_vector(31 DOWNTO 0);
  signal user_w_audio_open :  std_logic;
  signal user_r_smb_rden :  std_logic;
  signal user_r_smb_empty :  std_logic;
  signal user_r_smb_data :  std_logic_vector(7 DOWNTO 0);
  signal user_r_smb_eof :  std_logic;
  signal user_r_smb_open :  std_logic;
  signal user_w_smb_wren :  std_logic;
  signal user_w_smb_full :  std_logic;
  signal user_w_smb_data :  std_logic_vector(7 DOWNTO 0);
  signal user_w_smb_open :  std_logic;

  -- Note that none of the ARM processor's direct connections to pads is
  -- defined as I/O on this module. Normally, they should be connected
  -- as toplevel ports here, but that confuses Vivado 2013.4 to think that
  -- some of these ports are real I/Os, causing an implementation failure.
  -- This detachment results in a lot of warnings during synthesis and
  -- implementation, but has no practical significance, as these pads are
  -- completely unrelated to the FPGA bitstream.

  signal PS_CLK :  std_logic;
  signal PS_PORB :  std_logic;
  signal PS_SRSTB :  std_logic;
  signal DDR_Addr : std_logic_vector(14 DOWNTO 0);
  signal DDR_BankAddr : std_logic_vector(2 DOWNTO 0);
  signal DDR_CAS_n : std_logic;
  signal DDR_CKE : std_logic;
  signal DDR_CS_n : std_logic;
  signal DDR_Clk : std_logic;
  signal DDR_Clk_n : std_logic;
  signal DDR_DM : std_logic_vector(3 DOWNTO 0);
  signal DDR_DQ : std_logic_vector(31 DOWNTO 0);
  signal DDR_DQS : std_logic_vector(3 DOWNTO 0);
  signal DDR_DQS_n : std_logic_vector(3 DOWNTO 0);
  signal DDR_DRSTB : std_logic;
  signal DDR_ODT : std_logic;
  signal DDR_RAS_n : std_logic;
  signal DDR_VRN : std_logic;
  signal DDR_VRP : std_logic;
  signal MIO : std_logic_vector(53 DOWNTO 0);
  signal DDR_WEB : std_logic;
  
  signal user_r_debug_data : std_logic_vector(DEBUG_FIFO_DATA_WIDTH-1 downto 0) := (others => '0');
  signal user_r_debug_rden, user_r_debug_empty : std_logic := '0';
  signal user_config_addr : std_logic_vector(CONFIG_MEM_ADDR_WIDTH downto 0) := (others => '0');
  signal user_w_config_data : std_logic_vector(CONFIG_MEM_DATA_WIDTH-1 downto 0) := (others => '0');
  signal user_w_config_wren, user_w_config_full : std_logic := '0';
  
begin
  xillybus_ins : xillybus
    port map (
      -- Ports related to /dev/xillybus_config
      -- CPU to FPGA signals:
      user_w_config_wren        => user_w_config_wren,
      user_w_config_full        => user_w_config_full,
      user_w_config_data        => user_w_config_data,
      user_w_config_open        => open,
      -- Address signals:
      user_config_addr          => user_config_addr,
      user_config_addr_update   => open,

      -- Ports related to /dev/xillybus_debug
      -- FPGA to CPU signals:
      user_r_debug_rden     => user_r_debug_rden,
      user_r_debug_empty    => user_r_debug_empty,
      user_r_debug_data     => user_r_debug_data,
      user_r_debug_eof      => '0',
      user_r_debug_open     => open,

      -- Ports related to Xillybus Lite
      -- UNUSED
      user_clk      => open,
      user_wren     => open,
      user_wstrb    => open,
      user_rden     => open,
      user_rd_data  => (others => '0'),
      user_wr_data  => open,
      user_addr     => open,
      user_irq      => '0',

      -- Ports related to /dev/xillybus_audio
      -- FPGA to CPU signals:
      user_r_audio_rden => user_r_audio_rden,
      user_r_audio_empty => user_r_audio_empty,
      user_r_audio_data => user_r_audio_data,
      user_r_audio_eof => user_r_audio_eof,
      user_r_audio_open => user_r_audio_open,
      -- CPU to FPGA signals:
      user_w_audio_wren => user_w_audio_wren,
      user_w_audio_full => user_w_audio_full,
      user_w_audio_data => user_w_audio_data,
      user_w_audio_open => user_w_audio_open,

      -- Ports related to /dev/xillybus_smb
      -- FPGA to CPU signals:
      user_r_smb_rden => user_r_smb_rden,
      user_r_smb_empty => user_r_smb_empty,
      user_r_smb_data => user_r_smb_data,
      user_r_smb_eof => user_r_smb_eof,
      user_r_smb_open => user_r_smb_open,
      -- CPU to FPGA signals:
      user_w_smb_wren => user_w_smb_wren,
      user_w_smb_full => user_w_smb_full,
      user_w_smb_data => user_w_smb_data,
      user_w_smb_open => user_w_smb_open,

      -- General signals
      PS_CLK => PS_CLK,
      PS_PORB => PS_PORB,
      PS_SRSTB => PS_SRSTB,
      clk_100 => clk_100,
      otg_oc => otg_oc,
      DDR_Addr => DDR_Addr,
      DDR_BankAddr => DDR_BankAddr,
      DDR_CAS_n => DDR_CAS_n,
      DDR_CKE => DDR_CKE,
      DDR_CS_n => DDR_CS_n,
      DDR_Clk => DDR_Clk,
      DDR_Clk_n => DDR_Clk_n,
      DDR_DM => DDR_DM,
      DDR_DQ => DDR_DQ,
      DDR_DQS => DDR_DQS,
      DDR_DQS_n => DDR_DQS_n,
      DDR_DRSTB => DDR_DRSTB,
      DDR_ODT => DDR_ODT,
      DDR_RAS_n => DDR_RAS_n,
      DDR_VRN => DDR_VRN,
      DDR_VRP => DDR_VRP,
      MIO => MIO,
      DDR_WEB => DDR_WEB,
      GPIO_LED => GPIO_LED,
      bus_clk => bus_clk,
      quiesce => quiesce,
      vga4_blue => vga4_blue,
      vga4_green => vga4_green,
      vga4_red => vga4_red,
      vga_hsync => vga_hsync,
      vga_vsync => vga_vsync
  );
  
  feedback_inst : feedback_top
    port map (
      --XILLYBUS
      xillybus_clk    => bus_clk,
      fifo_rd_data    => user_r_debug_data,
      fifo_ren        => user_r_debug_rden,
      fifo_empty      => user_r_debug_empty,
      mem_addr        => user_config_addr,
      mem_wr_data     => user_w_config_data,
      mem_wen         => user_w_config_wren,
      mem_full        => user_w_config_full,
      --FPGA
      clk_in          => clk_100,
      areset          => areset,
      areset_debug    => areset_debug,
      async_pulse     => async_pulse,
      astandby        => astandby,
      adc_data_in1    => adc_data_in1,
      adc_data_in2    => adc_data_in2,
      adc_cs_n        => adc_cs_n,
      adc_sclk        => adc_sclk,
      dac_data_out    => dac_data_out,
      dac_cs_n        => dac_cs_n,
      dac_ldac        => dac_ldac,
      dac_sclk        => dac_sclk,
      leds            => leds
    );
  
  audio_ins : i2s_audio
    port map(
      bus_clk => bus_clk,
      clk_100 => clk_100,
      quiesce => quiesce,
      audio_mclk => audio_mclk,
      audio_dac => audio_dac,
      audio_adc => audio_adc,
      audio_bclk => audio_bclk,
      audio_lrclk => audio_lrclk,
      user_r_audio_rden => user_r_audio_rden,
      user_r_audio_empty => user_r_audio_empty,
      user_r_audio_data => user_r_audio_data,
      user_r_audio_eof => user_r_audio_eof,
      user_r_audio_open => user_r_audio_open,
      user_w_audio_wren => user_w_audio_wren,
      user_w_audio_full => user_w_audio_full,
      user_w_audio_data => user_w_audio_data,
      user_w_audio_open => user_w_audio_open
      );

  smbus_ins : smbus
    port map(
      bus_clk => bus_clk,
      quiesce => quiesce,
      smb_sclk => smb_sclk,
      smb_sdata => smb_sdata,
      smbus_addr => smbus_addr,
      user_r_smb_rden => user_r_smb_rden,
      user_r_smb_empty => user_r_smb_empty,
      user_r_smb_data => user_r_smb_data,
      user_r_smb_eof => user_r_smb_eof,
      user_r_smb_open => user_r_smb_open,
      user_w_smb_wren => user_w_smb_wren,
      user_w_smb_full => user_w_smb_full,
      user_w_smb_data => user_w_smb_data,
      user_w_smb_open => user_w_smb_open
      );
  
end sample_arch;
