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

library UNISIM;
use UNISIM.Vcomponents.ALL;


entity iqdac_io is

    generic (
        dpins          : integer := 16 );
    port (
        clk_i          : in  std_logic;
        reset_io_i     : in  std_logic;

        iqdac_idata_i  : in  std_logic_vector(dpins-1 downto 0);
        iqdac_qdata_i  : in  std_logic_vector(dpins-1 downto 0);

        iqdac_data_p_o : out std_logic_vector(dpins-1 downto 0);
        iqdac_data_n_o : out std_logic_vector(dpins-1 downto 0);

        iqdac_dc_p_o   : out std_logic;
        iqdac_dc_n_o   : out std_logic );    
    
end entity;

architecture rtl of iqdac_io is

    signal dac_idata   : std_logic_vector(dpins downto 0);
    signal dac_qdata   : std_logic_vector(dpins downto 0);
    signal oddr_data   : std_logic_vector(dpins downto 0);
    signal obuf_data   : std_logic_vector(dpins downto 0);
    signal obuf_data_p : std_logic_vector(dpins downto 0);        
    signal obuf_data_n : std_logic_vector(dpins downto 0);    
    
begin

    -- Look. I and Q are _inverted_. The RF mixer post IQ DAC
    -- is an upside conversion to 247(=223.5+23.5) MHz. We need
    -- the downside conversion, so invert I and Q to the IQ DAC.
    dac_qdata <= '1' & iqdac_qdata_i;
    dac_idata <= '0' & iqdac_idata_i;    
    
    pins_g : for pin in 0 to dpins generate
    begin

        oddr_inst : oddr
            generic map (
                ddr_clk_edge   => "same_edge",
                init           => '0',
                srtype         => "async" )
            port map (
                d1             => dac_qdata(pin),
                d2             => dac_idata(pin),
                c              => clk_i,
                ce             => '1',
                q              => oddr_data(pin),
                r              => reset_io_i,
                s              => '0' );

        -- We could add a delay cell here, if necessary.

        obufds_inst : obufds
           generic map (
              iostandard => "lvds" )
           port map (
              o          => obuf_data_p(pin),
              ob         => obuf_data_n(pin),
              i          => oddr_data(pin));
        
    end generate;

    -- outputs
    iqdac_data_p_o <= obuf_data_p(dpins-1 downto 0);
    iqdac_data_n_o <= obuf_data_n(dpins-1 downto 0);
    iqdac_dc_p_o   <= obuf_data_p(dpins);
    iqdac_dc_n_o   <= obuf_data_n(dpins);    
    
end architecture;
