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

library UNISIM;
use UNISIM.Vcomponents.ALL;

entity x8oddr is
   port (
      clk_rf_io_i : in  std_logic;
      clk_rf_i    : in  std_logic;
      rst_rf_n_i  : in  std_logic;
      clk_vtu_i   : in  std_logic;
      rst_vtu_n_i : in  std_logic;

      data_out_i  : in std_logic_vector(7 downto 0);
      hc_delay_i  : in std_logic;

      ddr_data_o  : out std_logic;

      dbg_o       : out std_logic_vector(15 downto 0) );
end entity;

architecture rtl of x8oddr is
    -- ddr
    signal didx        : unsigned(3 downto 0);
    signal didxp1      : unsigned(3 downto 0);
    signal clkcntrf    : unsigned(2 downto 0);
    signal clkcntrf_r  : unsigned(2 downto 0) := (others => '0');
    signal d1out       : std_logic;
    signal d2out       : std_logic;
    signal d1out_r     : std_logic;
    signal d2out_r     : std_logic;

    -- mode signals
    signal hc_delay_r     : std_logic;

    signal data_out_clean          : std_logic_vector(7 downto 0);
    signal data_out_clean_r        : std_logic_vector(7 downto 0);
    signal data_x16_out_nohc       : std_logic_vector(15 downto 0);
    signal data_x16_out_hc         : std_logic_vector(15 downto 0);
    signal data_x16_out            : std_logic_vector(15 downto 0);
    signal data_x16_out_r          : std_logic_vector(15 downto 0);

    signal vtuclk_r : std_logic;
    signal vtu_clk_rising_edge : std_logic;

begin

    data_out_clean          <= (others => '0') when rst_rf_n_i = '0' else data_out_i;

    data_x16_out_nohc       <= data_out_clean(0) & data_out_clean(0) &
                               data_out_clean(1) & data_out_clean(1) &
                               data_out_clean(2) & data_out_clean(2) &
                               data_out_clean(3) & data_out_clean(3) &
                               data_out_clean(4) & data_out_clean(4) &
                               data_out_clean(5) & data_out_clean(5) &
                               data_out_clean(6) & data_out_clean(6) &
                               data_out_clean(7) & data_out_clean(7);
    data_x16_out_hc         <= data_out_clean(0) & data_out_clean(1) &
                               data_out_clean(1) & data_out_clean(2) &
                               data_out_clean(2) & data_out_clean(3) &
                               data_out_clean(3) & data_out_clean(4) &
                               data_out_clean(4) & data_out_clean(5) &
                               data_out_clean(5) & data_out_clean(6) &
                               data_out_clean(6) & data_out_clean(7) &
                               data_out_clean(7) & data_out_clean_r(0);
    data_x16_out            <= data_x16_out_nohc when hc_delay_i = '0' else data_x16_out_hc;

    process (clk_vtu_i) is
    begin
       if rising_edge(clk_vtu_i) then
          data_out_clean_r <= data_out_clean;
          hc_delay_r       <= hc_delay_i;
          data_x16_out_r   <= data_x16_out;
       end if;
    end process;

    vtu_clk_rising_edge <= '1'            when vtuclk_r = '0' and clk_vtu_i = '1' else '0';
    clkcntrf            <= clkcntrf_r + 1 when vtu_clk_rising_edge = '0'          else (others => '0');

    didx   <= clkcntrf & '0';
    didxp1 <= clkcntrf & '1';    
    d1out  <= data_x16_out_r(to_integer(unsigned(didx)));
    d2out  <= data_x16_out_r(to_integer(unsigned(didxp1)));

    process (clk_rf_i) is
    begin
       if rising_edge(clk_rf_i) then
          clkcntrf_r <= clkcntrf  after 1 ns;
          vtuclk_r   <= clk_vtu_i after 1 ns;
       end if;
    end process;

    process (clk_rf_i) is
    begin
       if rising_edge(clk_rf_i) then
          if (rst_rf_n_i = '0') then
             d1out_r    <= '0' after 1 ns;
             d2out_r    <= '0' after 1 ns;
          else
             d1out_r    <= d1out after 1 ns;
             d2out_r    <= d2out after 1 ns;
          end if;
       end if;
    end process;
    
    oddr_inst : oddr
       generic map (
          ddr_clk_edge   => "same_edge",
          init           => '0',
          srtype         => "async" )
       port map (
          D1             => d1out_r,
          D2             => d2out_r,
          c              => clk_rf_i,
          ce             => '1',
          q              => ddr_data_o,
          r              => '0',
          s              => '0' );

    dbg_o(2 downto 0) <= std_logic_vector(clkcntrf_r);
    dbg_o(3) <= d1out_r;
    dbg_o(4) <= d2out_r;
    dbg_o(15 downto 5) <= X"00" & "000";

end architecture;
