---------------------------------------------------------------------------- -- hdmi_tmds.vhd -- Convert HDMI Data to TMDS -- Version 1.0 -- -- Copyright (C) 2015 H.Poetzl -- -- This program is free software: you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation, either version -- 2 of the License, or (at your option) any later version. ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.ALL; package vect_pkg is type vec2_a is array (natural range <>) of std_logic_vector (1 downto 0); type vec4_a is array (natural range <>) of std_logic_vector (3 downto 0); type vec6_a is array (natural range <>) of std_logic_vector (5 downto 0); type vec8_a is array (natural range <>) of std_logic_vector (7 downto 0); type vec10_a is array (natural range <>) of std_logic_vector (9 downto 0); end vect_pkg; library IEEE; use IEEE.std_logic_1164.ALL; use IEEE.numeric_std.ALL; library unisim; use unisim.VCOMPONENTS.ALL; use work.vivado_pkg.ALL; -- Vivado Attributes use work.helper_pkg.ALL; -- Vivado Attributes use work.vect_pkg.ALL; -- Vector Types entity hdmi_tmds is port ( pix_clk : in std_logic; bit_clk : in std_logic; -- enable : in std_logic; reset : in std_logic; -- rgb : in vec8_a (2 downto 0); -- pream : in std_logic; guard : in std_logic; blank : in std_logic; hsync : in std_logic; vsync : in std_logic; -- d0idx : in std_logic_vector (1 downto 0); d1idx : in std_logic_vector (1 downto 0); d2idx : in std_logic_vector (1 downto 0); clidx : in std_logic_vector (1 downto 0); -- d0inv : in std_logic; d1inv : in std_logic; d2inv : in std_logic; clinv : in std_logic; -- tmds : out std_logic_vector (3 downto 0) ); end entity hdmi_tmds; architecture RTL of hdmi_tmds is attribute KEEP_HIERARCHY of RTL : architecture is "TRUE"; signal bgr_data : vec8_a (2 downto 0) := (others => (others => '0')); signal bgr_ctrl : vec2_a (2 downto 0) := (others => (others => '0')); signal bgr_de : std_logic; signal guard_d : std_logic := '0'; alias bgr_hsync : std_logic is bgr_ctrl(0)(0); alias bgr_vsync : std_logic is bgr_ctrl(0)(1); alias bgr_ctl0 : std_logic is bgr_ctrl(1)(0); alias bgr_ctl1 : std_logic is bgr_ctrl(1)(1); alias bgr_ctl2 : std_logic is bgr_ctrl(2)(0); alias bgr_ctl3 : std_logic is bgr_ctrl(2)(1); signal enc_tmds : vec10_a (3 downto 0); signal enc_data : vec10_a (3 downto 0); signal enc_sout : vec10_a (3 downto 0); signal slave_sout1 : std_logic_vector (3 downto 0); signal slave_sout2 : std_logic_vector (3 downto 0); signal enc_clk : std_logic; signal ser_clk : std_logic; signal ser_clk_div : std_logic; signal ser_enable : std_logic; signal ser_reset : std_logic; signal d0_index : natural; signal d1_index : natural; signal d2_index : natural; signal cl_index : natural; begin bgr_data(0) <= rgb(2); bgr_data(1) <= rgb(1); bgr_data(2) <= rgb(0); bgr_hsync <= hsync; bgr_vsync <= vsync; bgr_de <= not blank; bgr_ctl0 <= pream; bgr_ctl1 <= '0'; bgr_ctl2 <= '0'; bgr_ctl3 <= '0'; ENC_GEN: for I in 2 downto 0 generate enc_tmds_inst : entity work.enc_tmds port map ( clk => enc_clk, din => bgr_data(I), ain => x"0", cin => bgr_ctrl(I), vde => bgr_de, ade => '0', dout => enc_tmds(I) ); end generate; enc_clk <= pix_clk; d0_index <= to_index(d0idx); d1_index <= to_index(d1idx); d2_index <= to_index(d2idx); cl_index <= to_index(clidx); enc_proc : process (enc_clk) begin if rising_edge(enc_clk) then if guard_d then enc_data(0) <= "1011001100"; enc_data(1) <= "0100110011"; enc_data(2) <= "1011001100"; else enc_data(0) <= enc_tmds(0); enc_data(1) <= enc_tmds(1); enc_data(2) <= enc_tmds(2); end if; guard_d <= guard; end if; end process; enc_data(3) <= "1111100000"; enc_sout(0) <= not enc_data(d0_index) when d0inv = '1' else enc_data(d0_index); enc_sout(1) <= not enc_data(d1_index) when d1inv = '1' else enc_data(d1_index); enc_sout(2) <= not enc_data(d2_index) when d2inv = '1' else enc_data(d2_index); enc_sout(3) <= not enc_data(cl_index) when clinv = '1' else enc_data(cl_index); OSERDES_GEN: for I in 3 downto 0 generate OSERDES_master_inst : entity work.oserdes_wrap generic map ( DATA_RATE_OQ => "DDR", -- DDR, SDR DATA_WIDTH => 10, -- Parallel data width (2-8,10,14) SERDES_MODE => "MASTER" ) -- MASTER, SLAVE port map ( CLK => ser_clk, -- 1-bit input: High speed clock CLKDIV => ser_clk_div, -- 1-bit input: Divided clock OCE => ser_enable, -- 1-bit input: Output data clock enable RST => ser_reset, -- 1-bit input: Reset D1 => enc_sout(I)(0), D2 => enc_sout(I)(1), D3 => enc_sout(I)(2), D4 => enc_sout(I)(3), D5 => enc_sout(I)(4), D6 => enc_sout(I)(5), D7 => enc_sout(I)(6), D8 => enc_sout(I)(7), OQ => tmds(I), -- 1-bit output: Data path output SHIFTIN1 => slave_sout1(I), SHIFTIN2 => slave_sout2(I) ); OSERDES_slave_inst : entity work.oserdes_wrap generic map ( DATA_RATE_OQ => "DDR", -- DDR, SDR DATA_WIDTH => 10, -- Parallel data width (2-8,10,14) SERDES_MODE => "SLAVE" ) -- MASTER, SLAVE port map ( CLK => ser_clk, -- 1-bit input: High speed clock CLKDIV => ser_clk_div, -- 1-bit input: Divided clock OCE => ser_enable, -- 1-bit input: Output data clock enable RST => ser_reset, -- 1-bit input: Reset D3 => enc_sout(I)(8), D4 => enc_sout(I)(9), SHIFTOUT1 => slave_sout1(I), SHIFTOUT2 => slave_sout2(I) ); end generate; ser_clk <= bit_clk; ser_clk_div <= pix_clk; ser_enable <= enable; ser_reset <= reset; end RTL;