--------------------------------------------------------------------------------
-- TEM : TS
-- Terasic C5G : Cyclone V GX Starter Kit
--------------------------------------------------------------------------------
-- DO 5/2015
--------------------------------------------------------------------------------
-- Cyclone V GX 5CGXFC5C6F27C7N
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

LIBRARY work;
USE work.base_pack.ALL;
USE work.plomb_pack.ALL;
USE work.ts_pack.ALL;

ENTITY c5g_ts IS
  PORT (
    -- ADC
    adc_convst : OUT    std_logic;
    adc_sck    : OUT    std_logic;
    adc_sdi    : OUT    std_logic;
    adc_sdo    : IN     std_logic;

    -- AUD
    aud_adcdat  : IN    std_logic;
    aud_adclrck : INOUT std_logic;
    aud_bclk    : INOUT std_logic;
    aud_dacdat  : OUT   std_logic;
    aud_daclrck : INOUT std_logic;
    aud_xck     : OUT   std_logic;

    -- CLOCK
    clock_125_p  : IN   std_logic;
    
    clock_50_b5b : IN   std_logic;
    clock_50_b6a : IN   std_logic;
    clock_50_b7a : IN   std_logic;
    clock_50_b8a : IN   std_logic;
    
    -- CPU
    cpu_reset_n  : IN   std_logic;
    
    -- DDR2LP
    ddr2lp_ca      : OUT    std_logic_vector(9  DOWNTO 0); -- <DDR2LP>
    ddr2lp_cke     : OUT    std_logic_vector(1  DOWNTO 0); -- <DDR2LP>
    ddr2lp_ck_n    : OUT    std_logic;                     -- <DDR2LP>
    ddr2lp_ck_p    : OUT    std_logic;                     -- <DDR2LP>
    ddr2lp_cs_n    : OUT    std_logic_vector(1  DOWNTO 0); -- <DDR2LP>
    ddr2lp_dm      : OUT    std_logic_vector(3  DOWNTO 0); -- <DDR2LP>
    ddr2lp_dq      : INOUT  std_logic_vector(31 DOWNTO 0); -- <DDR2LP>
    ddr2lp_dqs_n   : INOUT  std_logic_vector(3  DOWNTO 0); -- <DDR2LP>
    ddr2lp_dqs_p   : INOUT  std_logic_vector(3  DOWNTO 0); -- <DDR2LP>
    ddr2lp_oct_rzq : IN     std_logic;                     -- <DDR2LP>
    
    -- GPIO
    gpio           : INOUT  std_logic_vector(21 DOWNTO 0);  -- <GPIO>
    
    -- HEX
    hex0           : OUT    std_logic_vector(6  DOWNTO 0);
    hex1           : OUT    std_logic_vector(6  DOWNTO 0);
    hex2           : OUT    std_logic_vector(6  DOWNTO 0);
    hex3           : OUT    std_logic_vector(6  DOWNTO 0);
    
    -- HDMI
    hdmi_tx_clk    : OUT    std_logic;
    hdmi_tx_d      : OUT    std_logic_vector(23 DOWNTO 0);
    hdmi_tx_de     : OUT    std_logic;
    hdmi_tx_hs     : OUT    std_logic;
    hdmi_tx_int    : IN     std_logic;
    hdmi_tx_vs     : OUT    std_logic;
    
    -- I2C HDMI (x72) + Sound (x34) + Clk Synth (xE0)
    i2c_scl        : OUT    std_logic;
    i2c_sda        : INOUT  std_logic;
    
    -- HSMC
    hsmc_clkin0    : IN     std_logic;
    hsmc_clkin_n   : IN     std_logic_vector(2 DOWNTO 1);
    hsmc_clkin_p   : IN     std_logic_vector(2 DOWNTO 1);
    hsmc_clkout0   : OUT    std_logic;
    hsmc_clkout_n  : OUT    std_logic_vector(2 DOWNTO 1);
    hsmc_clkout_p  : OUT    std_logic_vector(2 DOWNTO 1);
    hsmc_d         : INOUT  std_logic_vector(3 DOWNTO 0);
    --hsmc_gxb_rx_p  : IN     std_logic_vector(3 DOWNTO 0);  -- <HSMC_XCVR>
    --hsmc_gxb_tx_p  : OUT    std_logic_vector(3 DOWNTO 0);  -- <HSMC_XCVR>
    hsmc_rx_n      : INOUT  std_logic_vector(16 DOWNTO 0);
    hsmc_rx_p      : INOUT  std_logic_vector(16 DOWNTO 0);
    hsmc_tx_n      : INOUT  std_logic_vector(16 DOWNTO 0);
    hsmc_tx_p      : INOUT  std_logic_vector(16 DOWNTO 0);
    
    -- KEY
    key            : IN     std_logic_vector(3 DOWNTO 0);
    
    -- LED
    ledg           : OUT    std_logic_vector(7 DOWNTO 0);
    ledr           : OUT    std_logic_vector(9 DOWNTO 0);
    
    -- REFCLK
    refclk_p0      : IN     std_logic;  -- <REFCLK>
    refclk_p1      : IN     std_logic;  -- <REFCLK>
    
    -- SD
    sd_clk         : OUT    std_logic;
    sd_cmd         : INOUT  std_logic;
    sd_dat         : INOUT  std_logic_vector(3 DOWNTO 0);
    
    -- SMA
    --sma_gxb_rx_p   : IN     std_logic;  -- <SMA>
    --sma_gxb_tx_p   : OUT    std_logic;  -- <SMA>
    
    -- SRAM
    sram_a         : OUT    std_logic_vector(17 DOWNTO 0);
    sram_ce_n      : OUT    std_logic;
    sram_d         : INOUT  std_logic_vector(15 DOWNTO 0);
    sram_lb_n      : OUT    std_logic;
    sram_oe_n      : OUT    std_logic;
    sram_ub_n      : OUT    std_logic;
    sram_we_n      : OUT    std_logic;
    
    -- SW
    sw             : IN     std_logic_vector(9 DOWNTO 0);
    
    -- UART
    uart_rx        : IN     std_logic;
    uart_tx        : OUT    std_logic
    );
END ENTITY c5g_ts;

--##############################################################################
ARCHITECTURE rtl OF c5g_ts IS

  --###################################################################
  CONSTANT SYSFREQ   : natural := 50_000_000;
  CONSTANT SS20      : boolean := false; -- false = SS5     | true = SS20
  CONSTANT TCX_ACCEL : boolean := true;  -- false = Disable | true = Accelerator
  CONSTANT TCX_CG3   : boolean := true;  -- false = Disable | true = CG3 option
  --###################################################################

  SIGNAL sclk : std_logic;
  
  -- Core
  SIGNAL dram_pw,vram_pw : type_plomb_w;
  SIGNAL dram_pr,vram_pr : type_plomb_r;
  SIGNAL flash_w,ibram_w : type_pvc_w;
  SIGNAL flash_r,ibram_r : type_pvc_r;
  SIGNAL rxd1,rxd2,rxd3,rxd4,cts : std_logic;
  SIGNAL txd1,txd2,txd3,txd4,rts : std_logic;
  SIGNAL conf : unsigned(3 DOWNTO 0);
  SIGNAL reset_na,reset_na2,reset_na3 : std_logic;
  SIGNAL led : uv4;
  SIGNAL gpio_i,gpio_o,gpio_en : uv4;
  SIGNAL button : uv4;

  SIGNAL dram_w,vram_w : type_pvc_w;
  SIGNAL dram_r,vram_r : type_pvc_r;
  
  -- SCSI
  SIGNAL scsi_w : type_scsi_w;
  SIGNAL scsi_r : type_scsi_r;
  SIGNAL disk_busy : std_logic;
  SIGNAL id_sd : unsigned(2 DOWNTO 0);
  SIGNAL sd_reg_w : type_sd_reg_w;
  SIGNAL sd_reg_r : type_sd_reg_r;
  
  -- SD/MMC
  SIGNAL sd_clk_o : std_logic;
  SIGNAL sd_clk_i : std_logic;
  SIGNAL sd_dat_o,sd_dat_i : uv4;
  SIGNAL sd_dat_en : std_logic;
  SIGNAL sd_cmd_o,sd_cmd_i : std_logic;
  SIGNAL sd_cmd_en : std_logic;
  
  -- PHY Ethernet (absent)
  SIGNAL phy_mdio_o,phy_mdc,phy_mdio_i : std_logic;
  SIGNAL phy_mdio_en,phy_int_n,phy_reset_n : std_logic;
  SIGNAL phy_txd,phy_rxd : unsigned(3 DOWNTO 0);
  SIGNAL phy_tx_en,phy_tx_er,phy_col : std_logic;
  SIGNAL phy_rx_dv,phy_rx_er,phy_crs : std_logic;
  SIGNAL phy_tx_clk,phy_rx_clk : std_logic;
  SIGNAL phy_txd_i,phy_rxd_i : unsigned(3 DOWNTO 0);
  SIGNAL mac_emi_clk : std_logic;
  
  -- Video
  SIGNAL vga_r,vga_g,vga_b : uv8;
  SIGNAL vga_de : std_logic;
  SIGNAL vga_hsyn,vga_vsyn,vga_clk,vga_en : std_logic;
  SIGNAL iic1_scl,iic1_sda_i,iic1_sda_o : std_logic;
  SIGNAL iic2_scl,iic2_sda_i,iic2_sda_o : std_logic;
  SIGNAL iic3_scl,iic3_sda_i,iic3_sda_o : std_logic;

  -- ASMI EPCQ256
  SIGNAL asmi_clkin      : std_logic;
  SIGNAL asmi_read       : std_logic;
  SIGNAL asmi_rden       : std_logic;
  SIGNAL asmi_addr       : std_logic_vector(31 DOWNTO 0);
  SIGNAL asmi_reset      : std_logic;              
  SIGNAL asmi_dataout    : std_logic_vector(7 DOWNTO 0);
  SIGNAL asmi_busy       : std_logic;
  SIGNAL asmi_data_valid : std_logic;
  SIGNAL asmi_wren       : std_logic;
  SIGNAL asmi_en4b_addr  : std_logic;

  -- SRAM
  SIGNAL sram_be_n : unsigned(0 TO 1);
  SIGNAL sram_dr,sram_dw : uv16;
  SIGNAL sram_den : std_logic;
  SIGNAL sram_a_i : unsigned(18 DOWNTO 1);
  
  -- MEM
  SIGNAL mem_cke,mem_cs_n  : std_logic_vector(0 DOWNTO 0);
  SIGNAL mem_ck_p,mem_ck_n : std_logic_vector(0 DOWNTO 0);

  SIGNAL avl_clk : std_logic;
  SIGNAL avl_ready_0,avl_ready_1             : std_logic;
  SIGNAL avl_burstbegin_0,avl_burstbegin_1   : std_logic;
  SIGNAL avl_addr_0,avl_addr_1               : std_logic_vector(26 downto 0);
  SIGNAL avl_rdata_valid_0,avl_rdata_valid_1 : std_logic;
  SIGNAL avl_rdata_0,avl_rdata_1             : std_logic_vector(31 downto 0);
  SIGNAL avl_wdata_0,avl_wdata_1             : std_logic_vector(31 downto 0);
  SIGNAL avl_be_0,avl_be_1                   : std_logic_vector(3 downto 0);
  SIGNAL avl_read_req_0,avl_read_req_1       : std_logic;
  SIGNAL avl_write_req_0,avl_write_req_1     : std_logic;
  SIGNAL avl_size_0,avl_size_1               : std_logic_vector(3 downto 0);
  
  -- PLL, RESET
  SIGNAL global_reset_n,soft_reset_n : std_logic;
  SIGNAL afi_clk     : std_logic;
  SIGNAL afi_reset_n : std_logic;
  
  SIGNAL local_init_done           : std_logic;
  SIGNAL local_cal_success         : std_logic;
  SIGNAL local_cal_fail            : std_logic;

  SIGNAL pll_ref_clk      : std_logic;

  COMPONENT lpddr2 IS
    PORT (
      pll_ref_clk                : in    std_logic                     := '0';
      global_reset_n             : in    std_logic                     := '0';
      soft_reset_n               : in    std_logic                     := '0';
      afi_clk                    : out   std_logic;
      afi_half_clk               : out   std_logic;
      afi_reset_n                : out   std_logic;
      afi_reset_export_n         : out   std_logic;
      mem_ca                     : out   std_logic_vector(9 downto 0);
      mem_ck                     : out   std_logic_vector(0 downto 0);
      mem_ck_n                   : out   std_logic_vector(0 downto 0);
      mem_cke                    : out   std_logic_vector(0 downto 0);
      mem_cs_n                   : out   std_logic_vector(0 downto 0);
      mem_dm                     : out   std_logic_vector(3 downto 0);
      mem_dq                     : inout std_logic_vector(31 downto 0) := (others => '0');
      mem_dqs                    : inout std_logic_vector(3 downto 0)  := (others => '0');
      mem_dqs_n                  : inout std_logic_vector(3 downto 0)  := (others => '0');
      avl_ready_0                : out   std_logic;
      avl_burstbegin_0           : in    std_logic                     := '0';
      avl_addr_0                 : in    std_logic_vector(26 downto 0) := (others => '0');
      avl_rdata_valid_0          : out   std_logic;
      avl_rdata_0                : out   std_logic_vector(31 downto 0);
      avl_wdata_0                : in    std_logic_vector(31 downto 0) := (others => '0');
      avl_be_0                   : in    std_logic_vector(3 downto 0)  := (others => '0');
      avl_read_req_0             : in    std_logic                     := '0';
      avl_write_req_0            : in    std_logic                     := '0';
      avl_size_0                 : in    std_logic_vector(3 downto 0)  := (others => '0');
      avl_ready_1                : out   std_logic;
      avl_burstbegin_1           : in    std_logic                     := '0';
      avl_addr_1                 : in    std_logic_vector(26 downto 0) := (others => '0');
      avl_rdata_valid_1          : out   std_logic;
      avl_rdata_1                : out   std_logic_vector(31 downto 0);
      avl_wdata_1                : in    std_logic_vector(31 downto 0) := (others => '0');
      avl_be_1                   : in    std_logic_vector(3 downto 0)  := (others => '0');
      avl_read_req_1             : in    std_logic                     := '0';
      avl_write_req_1            : in    std_logic                     := '0';
      avl_size_1                 : in    std_logic_vector(3 downto 0)  := (others => '0');
      mp_cmd_clk_0_clk           : in    std_logic                     := '0';
      mp_cmd_reset_n_0_reset_n   : in    std_logic                     := '0';
      mp_cmd_clk_1_clk           : in    std_logic                     := '0';
      mp_cmd_reset_n_1_reset_n   : in    std_logic                     := '0';
      mp_rfifo_clk_0_clk         : in    std_logic                     := '0';
      mp_rfifo_reset_n_0_reset_n : in    std_logic                     := '0';
      mp_wfifo_clk_0_clk         : in    std_logic                     := '0';
      mp_wfifo_reset_n_0_reset_n : in    std_logic                     := '0';
      mp_rfifo_clk_1_clk         : in    std_logic                     := '0';
      mp_rfifo_reset_n_1_reset_n : in    std_logic                     := '0';
      mp_wfifo_clk_1_clk         : in    std_logic                     := '0';
      mp_wfifo_reset_n_1_reset_n : in    std_logic                     := '0';
      local_init_done            : out   std_logic;
      local_cal_success          : out   std_logic;
      local_cal_fail             : out   std_logic;
      oct_rzqin                  : in    std_logic                     := '0';
      pll_mem_clk                : out   std_logic;
      pll_write_clk              : out   std_logic;
      pll_locked                 : out   std_logic;
      pll_write_clk_pre_phy_clk  : out   std_logic;
      pll_addr_cmd_clk           : out   std_logic;
      pll_avl_clk                : out   std_logic;
      pll_config_clk             : out   std_logic;
      pll_mem_phy_clk            : out   std_logic;
      afi_phy_clk                : out   std_logic;
      pll_avl_phy_clk            : out   std_logic);
  END COMPONENT lpddr2;
  
  component asmi is
    port (
      clkin      : in  std_logic                     := 'X';             -- clk
      read       : in  std_logic                     := 'X';             -- read
      rden       : in  std_logic                     := 'X';             -- rden
      addr       : in  std_logic_vector(31 downto 0) := (others => 'X'); -- addr
      reset      : in  std_logic                     := 'X';             -- reset
      dataout    : out std_logic_vector(7 downto 0);                     -- dataout
      busy       : out std_logic;                                        -- busy
      data_valid : out std_logic;                                        -- data_valid
      wren       : in  std_logic                     := 'X';             -- wren
      en4b_addr  : in  std_logic                     := 'X'              -- en4b_addr
      );
  end component asmi;
  
  ------------------------------------------
  -- TEST
  SIGNAL cpt_1hz : natural RANGE 0 TO 50_000_000;

  SIGNAL cli_1hz : std_logic :='0';
  SIGNAL xz0,xz1 : std_logic;
  
BEGIN
  
  -----------------------------------
  -- Ref. Clk for Memctrl. PLL
  pll_ref_clk<=clock_50_b5b;

  -- Avalon clock
  avl_clk<=sclk;

  -- System clock
  sclk<=clock_50_b6a;

  -- Video clock : 125MHz/2 = 62.5MHz
  vga_clk<=NOT vga_clk WHEN rising_edge(clock_125_p);
  
  ------------------------------------------
  i_ts_core: ENTITY work.ts_core
    GENERIC MAP (
      ACIABREAK  => true,
      SS20       => SS20,
      ETHERNET   => false,
      TCX_ACCEL  => TCX_ACCEL,
      TCX_CG3    => TCX_CG3,
      SYSFREQ    => SYSFREQ,
      SERIALRATE => 115200)
    PORT MAP (
      dram_pw     => dram_pw,
      dram_pr     => dram_pr,
      vram_pw     => vram_pw,
      vram_pr     => vram_pr,
      vga_r       => vga_r,
      vga_g       => vga_g,
      vga_b       => vga_b,
      vga_de      => vga_de,
      vga_hsyn    => vga_hsyn,
      vga_vsyn    => vga_vsyn,
      vga_clk     => vga_clk,
      scsi_w      => scsi_w,
      scsi_r      => scsi_r,
      sd_reg_w    => sd_reg_w,
      sd_reg_r    => sd_reg_r,
      phy_txd     => phy_txd,
      phy_tx_clk  => phy_tx_clk,
      phy_tx_en   => phy_tx_en,
      phy_tx_er   => phy_tx_er,
      phy_col     => phy_col,
      phy_rxd     => phy_rxd,
      phy_rx_dv   => phy_rx_dv,
      phy_rx_er   => phy_rx_er,
      phy_rx_clk  => phy_rx_clk,
      phy_crs     => phy_crs,
      phy_mdc     => phy_mdc,
      phy_mdio_o  => phy_mdio_o,
      phy_mdio_en => phy_mdio_en,
      phy_mdio_i  => phy_mdio_i,
      phy_int_n   => phy_int_n,
      phy_reset_n => phy_reset_n,
      flash_w     => flash_w,
      flash_r     => flash_r,
      ibram_w     => ibram_w,
      ibram_r     => ibram_r,
      iic1_scl    => iic1_scl,
      iic1_sda_o  => iic1_sda_o,
      iic1_sda_i  => iic1_sda_i,
      iic2_scl    => iic2_scl,
      iic2_sda_o  => iic2_sda_o,
      iic2_sda_i  => iic2_sda_i,
      iic3_scl    => iic3_scl,
      iic3_sda_o  => iic3_sda_o,
      iic3_sda_i  => iic3_sda_i,
      rxd1        => rxd1,
      rxd2        => rxd2,
      rxd3        => rxd3,
      rxd4        => rxd4,
      txd1        => txd1,
      txd2        => txd2,
      txd3        => txd3,
      txd4        => txd4,
      cts         => cts,
      rts         => rts,
      led         => led,
      gpio_i      => gpio_i,
      gpio_o      => gpio_o,
      gpio_en     => gpio_en,
      reset_na    => reset_na,
      conf        => conf,
      button      => button,
      sclk        => sclk);

  -----------------------------------
  i_scsi_sd: ENTITY work.scsi_sd
    GENERIC MAP (
      SYSFREQ => SYSFREQ)
    PORT MAP (
      scsi_w    => scsi_w,
      scsi_r    => scsi_r,
      id        => id_sd,
      busy      => disk_busy,
      sd_clk_o  => sd_clk_o,
      sd_clk_i  => sd_clk_i,
      sd_dat_o  => sd_dat_o,
      sd_dat_i  => sd_dat_i,
      sd_dat_en => sd_dat_en,
      sd_cmd_o  => sd_cmd_o,
      sd_cmd_i  => sd_cmd_i,
      sd_cmd_en => sd_cmd_en,
      reg_w     => sd_reg_w,
      reg_r     => sd_reg_r,
      clk       => sclk,
      reset_na  => reset_na);

  id_sd<="000";
  sd_clk<=sd_clk_o;
  sd_clk_i<=sd_clk_o;
  sd_dat<=std_logic_vector(sd_dat_o) WHEN sd_dat_en='1' ELSE "ZZZZ";
  sd_dat_i<=unsigned(sd_dat);
  sd_cmd<=sd_cmd_o WHEN sd_cmd_en='1' ELSE 'Z';
  sd_cmd_i<=sd_cmd;
  
  -----------------------------------
  ddr2lp_cke(0) <=mem_cke(0);
  ddr2lp_cs_n(0)<=mem_cs_n(0);
  ddr2lp_ck_p<=mem_ck_p(0);
  ddr2lp_ck_n<=mem_ck_n(0);

  i_lpddr2: lpddr2
    PORT MAP (
      pll_ref_clk                => pll_ref_clk,         -- IN : 50MHz
      global_reset_n             => global_reset_n,      -- IN
      soft_reset_n               => soft_reset_n,        -- IN
      afi_clk                    => afi_clk,             -- OUT
      afi_half_clk               => OPEN,                -- OUT
      afi_reset_n                => afi_reset_n,         -- OUT
      afi_reset_export_n         => OPEN,                -- OUT
      
      mem_ca                     => ddr2lp_ca,           -- OUT
      mem_ck                     => mem_ck_p,            -- OUT
      mem_ck_n                   => mem_ck_n,            -- OUT
      mem_cke                    => mem_cke,             -- OUT
      mem_cs_n                   => mem_cs_n,            -- OUT
      mem_dm                     => ddr2lp_dm,           -- OUT
      mem_dq                     => ddr2lp_dq,           -- INOUT
      mem_dqs                    => ddr2lp_dqs_p,        -- INOUT
      mem_dqs_n                  => ddr2lp_dqs_n,        -- INOUT
      
      avl_ready_0                => avl_ready_0,         -- OUT
      avl_burstbegin_0           => avl_burstbegin_0,    -- IN
      avl_addr_0                 => avl_addr_0,          -- IN
      avl_rdata_valid_0          => avl_rdata_valid_0,   -- OUT
      avl_rdata_0                => avl_rdata_0,         -- OUT
      avl_wdata_0                => avl_wdata_0,         -- IN
      avl_be_0                   => avl_be_0,            -- IN
      avl_read_req_0             => avl_read_req_0,      -- IN
      avl_write_req_0            => avl_write_req_0,     -- IN
      avl_size_0                 => avl_size_0,          -- IN
      
      avl_ready_1                => avl_ready_1,         -- OUT
      avl_burstbegin_1           => avl_burstbegin_1,    -- IN
      avl_addr_1                 => avl_addr_1,          -- IN
      avl_rdata_valid_1          => avl_rdata_valid_1,   -- OUT
      avl_rdata_1                => avl_rdata_1,         -- OUT
      avl_wdata_1                => avl_wdata_1,         -- IN
      avl_be_1                   => avl_be_1,            -- IN
      avl_read_req_1             => avl_read_req_1,      -- IN
      avl_write_req_1            => avl_write_req_1,     -- IN
      avl_size_1                 => avl_size_1,          -- IN
      
      mp_cmd_clk_0_clk           => avl_clk,        -- IN
      mp_cmd_reset_n_0_reset_n   => reset_na,       -- IN
      mp_cmd_clk_1_clk           => avl_clk,        -- IN
      mp_cmd_reset_n_1_reset_n   => reset_na,       -- IN
      mp_rfifo_clk_0_clk         => avl_clk,        -- IN
      mp_rfifo_reset_n_0_reset_n => reset_na,       -- IN
      mp_wfifo_clk_0_clk         => avl_clk,        -- IN
      mp_wfifo_reset_n_0_reset_n => reset_na,       -- IN
      mp_rfifo_clk_1_clk         => avl_clk,        -- IN
      mp_rfifo_reset_n_1_reset_n => reset_na,       -- IN
      mp_wfifo_clk_1_clk         => avl_clk,        -- IN
      mp_wfifo_reset_n_1_reset_n => reset_na,       -- IN
      
      local_init_done            => local_init_done,     -- OUT
      local_cal_success          => local_cal_success,   -- OUT
      local_cal_fail             => local_cal_fail,      -- OUT
      
      oct_rzqin                  => ddr2lp_oct_rzq,      -- IN
      
      pll_mem_clk                => OPEN,                -- OUT
      pll_write_clk              => OPEN,                -- OUT
      pll_locked                 => OPEN,                -- OUT
      pll_write_clk_pre_phy_clk  => OPEN,                -- OUT
      pll_addr_cmd_clk           => OPEN,                -- OUT
      pll_avl_clk                => OPEN,                -- OUT
      pll_config_clk             => OPEN,                -- OUT
      pll_mem_phy_clk            => OPEN,                -- OUT
      afi_phy_clk                => OPEN,                -- OUT
      pll_avl_phy_clk            => OPEN);               -- OUT 
  
  -----------------------------------
  i_plomb_avalon_dram: ENTITY work.plomb_avalon
    GENERIC MAP (N => 29)
    PORT MAP (
      pw              => dram_pw,
      pr              => dram_pr,
      avl_ready       => avl_ready_0,
      avl_burstbegin  => avl_burstbegin_0,
      avl_addr        => avl_addr_0,
      avl_rdata_valid => avl_rdata_valid_0,
      avl_rdata       => avl_rdata_0,
      avl_wdata       => avl_wdata_0,
      avl_be          => avl_be_0,
      avl_read_req    => avl_read_req_0,
      avl_write_req   => avl_write_req_0,
      avl_size        => avl_size_0,
      clk             => avl_clk,
      reset_na        => reset_na);

  i_plomb_avalon_vram: ENTITY work.plomb_avalon
    GENERIC MAP (N => 29)
    PORT MAP (
      pw              => vram_pw,
      pr              => vram_pr,
      avl_ready       => avl_ready_1,
      avl_burstbegin  => avl_burstbegin_1,
      avl_addr        => avl_addr_1,
      avl_rdata_valid => avl_rdata_valid_1,
      avl_rdata       => avl_rdata_1,
      avl_wdata       => avl_wdata_1,
      avl_be          => avl_be_1,
      avl_read_req    => avl_read_req_1,
      avl_write_req   => avl_write_req_1,
      avl_size        => avl_size_1,
      clk             => avl_clk,
      reset_na        => reset_na);

  -- ###################################################################
  -- Trying direct internal RAMs, bypassing the external DRAM controller :
  --avl_burstbegin_0<='0';
  --avl_read_req_0<='0';
  --avl_write_req_0<='0';
  
  --avl_burstbegin_1<='0';
  --avl_read_req_1<='0';
  --avl_write_req_1<='0';
  
  --i_plomb_pvc_vram: ENTITY work.plomb_pvc
  --  GENERIC MAP (
  --    MODE => RW)
  --  PORT MAP (
  --    bus_w    => vram_pw,
  --    bus_r    => vram_pr,
  --    mem_w    => vram_w,
  --    mem_r    => vram_r,
  --    clk      => avl_clk,
  --    reset_na => reset_na);

  --i_plomb_pvc_dram: ENTITY work.plomb_pvc
  --  GENERIC MAP (
  --    MODE => RW)
  --  PORT MAP (
  --    bus_w    => dram_pw,
  --    bus_r    => dram_pr,
  --    mem_w    => dram_w,
  --    mem_r    => dram_r,
  --    clk      => avl_clk,
  --    reset_na => reset_na);
  
  --i_iram_dram: ENTITY work.iram
  --  GENERIC MAP (
  --    N    => 12,
  --    VAR  => 0,
  --    OCT  => true,
  --    INIT => "void.sr")
  --  PORT MAP (
  --    mem_w    => dram_w,
  --    mem_r    => dram_r,
  --    clk      => avl_clk,
  --    reset_na => reset_na);
  
  --i_iram_vram: ENTITY work.iram
  --  GENERIC MAP (
  --    N    => 12,
  --    VAR  => 0,
  --    OCT  => true,
  --    INIT => "void.sr")
  --  PORT MAP (
  --    mem_w    => vram_w,
  --    mem_r    => vram_r,
  --    clk      => avl_clk,
  --    reset_na => reset_na);
  -- ###################################################################
  
  -----------------------------------
  -- VGA -> HDMI
  hdmi_tx_clk   <= vga_clk;
  hdmi_tx_d     <= std_logic_vector(vga_r) &
                   std_logic_vector(vga_g) &
                   std_logic_vector(vga_b);
  hdmi_tx_de    <= vga_de;
  hdmi_tx_hs    <= vga_hsyn;
  hdmi_tx_vs    <= vga_vsyn;
  --hdmi_tx_int
  i2c_scl       <= '0' WHEN iic1_scl='0'   ELSE 'Z';
  i2c_sda       <= '0' WHEN iic1_sda_o='0' ELSE 'Z';
  iic1_sda_i    <= i2c_sda;

  -----------------------------------
  -- KBD/MOUSE
  -- GPIO 0 : IN  : KBD   : [21]
  -- GPIO 1 : OUT : KBD   : [20]
  -- GPIO 2 : IN  : MOUSE : [19]
  gpio_i(0)<=gpio(21);
  gpio(21)<='Z';
  
  gpio(20)<=gpio_o(1);
  
  gpio_i(2)<=gpio(19);
  gpio(19)<='Z';

  -----------------------------------
  -- UART
  uart_tx<=txd3;
  rxd3<=uart_rx;
  
  -----------------------------------
  -- LEDs
  -- LED Green 0 : Debug STOP
  -- LED Green 1 : ?
  -- LED Green 2 : TRAP_STOP : Interrupts
  -- LED Green 3 : Disk activity
  -- LED Green 4 : Serial port Multiplexer : OFF = Terminal ON=Debugger
  ledg(0)<=led(0);
  ledg(1)<=led(1);
  ledg(2)<=led(2);
  ledg(3)<=disk_busy WHEN rising_edge(sclk);
  ledg(4)<=led(3);

  conf<=unsigned(sw(3 DOWNTO 0));
  -- Switch 0 : OFF = ?
  -- Switch 1 : OFF = Boot EPCQ, ON = Boot RAM
  -- Switch 2 : OFF = ?
  -- Switch 3 : OFF = Cache disabled ON = Cache enabled

  Blink0:PROCESS(sclk)
  BEGIN
    IF rising_edge(sclk) THEN
      IF cpt_1hz/=0 THEN
        cpt_1hz<=cpt_1hz-1;
      ELSE
        cpt_1hz<=25_000_000 -1;
        cli_1hz<=NOT cli_1hz;
      END IF;
      
    END IF;

  END PROCESS Blink0;
  
  -- LED Red 0 : 1 Hz blink
  -- LED Red 1 : EPCQ mem access
  -- LED Red 2 : External RAM access
  -- LED Red 3 : LPDDR2 access
  ledr(0)<=cli_1hz;
  ledr(1)<=flash_w.req WHEN rising_edge(sclk);
  ledr(2)<=ibram_w.req WHEN rising_edge(sclk);
  ledr(3)<=dram_pw.req WHEN rising_edge(sclk);

  ledr(4)<=xz0;
  ledr(5)<=xz1;

  ledr(6)<=local_init_done WHEN rising_edge(sclk);
  ledr(7)<=local_cal_success WHEN rising_edge(sclk);
  ledr(8)<=local_cal_fail WHEN rising_edge(sclk);

  xz0<=NOT xz0 WHEN rising_edge(refclk_p0);
  xz1<=NOT xz1 WHEN rising_edge(refclk_p1);
  
  -----------------------------------
  -- FLASH EPCQ256 : 256Mbits = 32MB = 0x200_0000
  i_pvc_asmi: ENTITY work.pvc_asmi
    GENERIC MAP (
      AMASK => x"0100_0000")            -- Offset for OpenBIOS !
    PORT MAP (
      w          => flash_w,
      r          => flash_r,
      clkin      => asmi_clkin,
      read       => asmi_read,
      rden       => asmi_rden,
      addr       => asmi_addr,
      reset      => asmi_reset,
      dataout    => asmi_dataout,
      busy       => asmi_busy,
      data_valid => asmi_data_valid,
      wren       => asmi_wren,
      en4b_addr  => asmi_en4b_addr,
      clk        => sclk,
      reset_na   => reset_na);
  
  i_asmi: asmi
    PORT MAP (
      clkin      => asmi_clkin,
      read       => asmi_read,
      rden       => asmi_rden,
      addr       => asmi_addr,
      reset      => asmi_reset,
      dataout    => asmi_dataout,
      busy       => asmi_busy,
      data_valid => asmi_data_valid,
      wren       => asmi_wren,
      en4b_addr  => asmi_en4b_addr);
  
  -----------------------------------
  i_asynchram: ENTITY work.aflash
    GENERIC MAP (
      N   => 19,                        -- 512KB
      ACC => 3)
    PORT MAP (
      mem_w    => ibram_w,
      mem_r    => ibram_r,
      a        => sram_a_i,
      dr       => sram_dr,
      dw       => sram_dw,
      den      => sram_den,
      cs_n     => sram_ce_n,
      oe_n     => sram_oe_n,
      we_n     => sram_we_n,
      be_n     => sram_be_n,
      clk      => sclk,
      reset_na => reset_na);

  sram_dr<=unsigned(sram_d);
  sram_d<=std_logic_vector(sram_dw) WHEN sram_den='1' ELSE "ZZZZZZZZZZZZZZZZ";
  sram_ub_n<=sram_be_n(0);
  sram_lb_n<=sram_be_n(1);
  sram_a<=std_logic_vector(sram_a_i);
  -----------------------------------

  PROCESS (sclk,cpu_reset_n) IS
  BEGIN
    IF cpu_reset_n='0' THEN
      reset_na<='0';
      reset_na2<='0';
      reset_na3<='0';
    ELSIF rising_edge(sclk) THEN
      reset_na3<='1';
      reset_na2<=reset_na3;
      reset_na<=reset_na2;
    END IF;
  END PROCESS;

  global_reset_n<=reset_na;
  soft_reset_n<=reset_na;
  
END ARCHITECTURE rtl;
      
    
