-- ----------------------------------------------------------------------------- -- Copyright (c) 2013 Benjamin Krill -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- ----------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.dvi_package.all; library work; use work.all; library UNISIM; use UNISIM.Vcomponents.all; entity atlys is generic ( MODE : string := "encode"); --generic ( MODE : string := "direct"); port ( rstbtn_n : in std_logic; -- The pink reset button clk100 : in std_logic; -- 100 MHz osicallator tx0_tmds : out std_logic_vector(3 downto 0); tx0_tmds_n : out std_logic_vector(3 downto 0); rx0_tmds : in std_logic_vector(3 downto 0); rx0_tmds_n : in std_logic_vector(3 downto 0); rx0_sda : inout std_logic; rx0_scl : in std_logic; tx1_tmds : out std_logic_vector(3 downto 0); tx1_tmds_n : out std_logic_vector(3 downto 0); rx1_tmds : in std_logic_vector(3 downto 0); rx1_tmds_n : in std_logic_vector(3 downto 0); switch : in std_logic_vector(1 downto 0); led : out std_logic_vector(7 downto 0) ); end atlys; architecture top of atlys is signal rstbtn : std_logic; signal rst_n : std_logic; signal rst : std_logic; signal pclk : std_logic; signal pclkx2 : std_logic; signal pclkx10 : std_logic; signal pllclk1 : std_logic; signal pllclk1bg : std_logic; signal pll_lckd : std_logic; signal serdesstrobe : std_logic; signal tmdsclk : std_logic; signal hsync : std_logic; signal vsync : std_logic; signal dat_en : std_logic; signal valid : std_logic_vector(COLOR_CNT-1 downto 0); signal ready : std_logic_vector(COLOR_CNT-1 downto 0); signal psalgnerr : std_logic; signal color : color_t(COLOR_CNT-1 downto 0); signal sdout : sdat_t(COLOR_CNT-1 downto 0); signal rx0_sda_i : std_logic; signal rx0_sda_o : std_logic; signal rx0_tmds_s : std_logic_vector(3 downto 0); signal toggle : std_logic; signal tmdsclkint : std_logic_vector(4 downto 0); type tmds_data_t is array(natural range <>) of std_logic_vector(4 downto 0); signal tmds_data : tmds_data_t(COLOR_CNT-1 downto 0); signal tmdsint : std_logic_vector(2 downto 0); signal tmds_clk : std_logic; signal sdata : std_logic_vector(29 downto 0); signal tx0_pclkx2 : std_logic; signal tx0_pclkx10 : std_logic; signal tx0_reset_n : std_logic; signal tx0_serdesstrobe : std_logic; signal tx0_clkfbout : std_logic; signal tx0_clkfbin : std_logic; signal tx0_plllckd : std_logic; signal tx0_pllclk0 : std_logic; signal tx0_pllclk2 : std_logic; signal tx0_bufpll_lock : std_logic; begin rstbtn <= not rstbtn_n; rst <= not rst_n; led <= ready(RED) & ready(GREEN) & ready(BLUE) & valid(RED) & valid(GREEN) & valid(BLUE) & dat_en & rst_n; dvi_decoder_0: entity work.dvi_decoder port map ( ext_rst => rstbtn, tmdsclk_p => rx0_tmds(3), tmdsclk_n => rx0_tmds_n(3), din_p => rx0_tmds(2 downto 0), din_n => rx0_tmds_n(2 downto 0), reset_n => rst_n, -- rx reset pclk_o => pclk, -- regenerated pixel clock pclkx2_o => pclkx2, -- double rate pixel clock pclkx10_o => pclkx10, -- 10x pixel as IOCLK pll_lckd_o => pll_lckd, -- send pll_lckd out so it can be fed into a different BUFPLL serdesstrobe_o => serdesstrobe, -- BUFPLL serdesstrobe output tmdsclk_o => tmdsclk, -- TMDS cable clock hsync_o => hsync, -- hsync data vsync_o => vsync, -- vsync data dat_en_o => dat_en, -- data enable valid_o => valid, ready_o => ready, psalgnerr_o => psalgnerr, sdout_o => sdout, color_o => color ); direct: if MODE = "direct" generate -- ---------------------------------------------------------- -- Forward TMDS Clock Using OSERDES2 block -- ---------------------------------------------------------- process (pclkx2, rst_n) begin if rst_n = '0' then toggle <= '0'; tmdsclkint <= (others => '0'); elsif rising_edge(pclkx2) then toggle <= not toggle; if toggle = '1' then tmdsclkint <= (others => '1'); else tmdsclkint <= (others => '0'); end if; end if; end process; clkout: entity work.serdes_n_to_1 generic map (SF => 5) port map ( ioclk => pclkx10, gclk => pclkx2, rst => rst, serdesstrobe_i => serdesstrobe, data_i => tmdsclkint, data_o => tmds_clk ); TMDS3: OBUFDS port map (I => tmds_clk, O => tx0_tmds(3), OB => tx0_tmds_n(3)); -- clock d: for I in 0 to COLOR_CNT-1 generate outI: entity work.serdes_n_to_1 generic map (SF => 5) port map ( ioclk => pclkx10, gclk => pclkx2, rst => rst, serdesstrobe_i => serdesstrobe, data_i => tmds_data(I), data_o => tmdsint(I) ); tx_tmdsI: OBUFDS port map (i => tmdsint(I), o => tx0_tmds(I), ob => tx0_tmds_n(I)); end generate; sdata <= sdout(RED)(9 downto 5) & sdout(GREEN)(9 downto 5) & sdout(BLUE)(9 downto 5) & sdout(RED)(4 downto 0) & sdout(GREEN)(4 downto 0) & sdout(BLUE)(4 downto 0); pixel2x: entity work.convert_30to15_fifo port map ( rst => rst, clk => pclk, clkx2 => pclkx2, data_i => sdata, data_o( 4 downto 0) => tmds_data(0), data_o( 9 downto 5) => tmds_data(1), data_o(14 downto 10) => tmds_data(2) ); end generate; decode: if MODE = "encode" generate -- ---------------------------------------------------------------------------- -- Instantiate a dedicate PLL for output port -- ---------------------------------------------------------------------------- pll_oserdes_0: PLL_BASE generic map ( CLKIN_PERIOD => 10.0, CLKFBOUT_MULT => 10, --set VCO to 10x of CLKIN CLKOUT0_DIVIDE => 1, CLKOUT1_DIVIDE => 10, CLKOUT2_DIVIDE => 5, COMPENSATION => "SOURCE_SYNCHRONOUS" ) port map ( CLKFBOUT => tx0_clkfbout, CLKOUT0 => tx0_pllclk0, CLKOUT1 => open, CLKOUT2 => tx0_pllclk2, CLKOUT3 => open, CLKOUT4 => open, CLKOUT5 => open, LOCKED => tx0_plllckd, CLKFBIN => tx0_clkfbin, CLKIN => pclk, -- pllclk1bg, RST => rst ); -- ---------------------------------------------------------------------------- -- This BUFG is needed in order to deskew between PLL clkin and clkout -- So the tx0 pclkx2 and pclkx10 will have the same phase as the pclk input -- ---------------------------------------------------------------------------- tx0_clkfb_buf: BUFG port map(I => tx0_clkfbout, O => tx0_clkfbin); -- -------------------------------- -- regenerate pclkx2 for TX -- -------------------------------- tx0_pclkx2_buf: BUFG port map(I => tx0_pllclk2, O => tx0_pclkx2); -- -------------------------------- -- regenerate pclkx10 for TX -- -------------------------------- tx0_ioclk_buf: BUFPLL generic map ( DIVIDE => 5 ) port map ( PLLIN => tx0_pllclk0, GCLK => tx0_pclkx2, LOCKED => tx0_plllckd, IOCLK => tx0_pclkx10, SERDESSTROBE => tx0_serdesstrobe, LOCK => tx0_bufpll_lock ); tx0_reset_n <= tx0_bufpll_lock; dvi_encoder_0: entity work.dvi_encoder port map ( rst_n => tx0_reset_n, pclk => pclk, pclkx2 => tx0_pclkx2, pclkx10 => tx0_pclkx10, serdesstrobe_i => tx0_serdesstrobe, color_i => color, hsync_i => hsync, vsync_i => vsync, dat_en_i => dat_en, tmds_p => tx0_tmds, tmds_n => tx0_tmds_n ); end generate; -- ---------------------------------------------------------------------------- -- I2C EDID Emulation -- ---------------------------------------------------------------------------- rx0_sda_i <= rx0_sda; rx0_sda <= '0' when rx0_sda_o = '0' else 'Z'; i2c_rom_0: entity work.i2c_rom port map ( clk => clk100, rst_n => rstbtn_n, sda_i => rx0_sda_i, sda_o => rx0_sda_o, scl_i => rx0_scl ); end top;