---------------------------------------------------------------------------- -- rgb_dvid.vhd -- Convert RGB + Sync Data to DVI-D -- Version 1.0 -- -- Copyright (C) 2014 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.vect_pkg.ALL; -- Vector Types entity rgb_dvid is port ( pix_clk : in std_logic; bit_clk : in std_logic; bit_clk_n : in std_logic; -- enable : in std_logic; reset : in std_logic; -- rgb : in vec8_a (2 downto 0); -- de : in std_logic; hsync : in std_logic; vsync : in std_logic; -- tmds : out std_logic_vector (3 downto 0) ); end entity rgb_dvid; architecture OSERDES_RTL of rgb_dvid is attribute KEEP_HIERARCHY of OSERDES_RTL : architecture is "TRUE"; signal rgb_data : vec8_a (2 downto 0) := (others => (others => '0')); signal rgb_ctrl : vec2_a (2 downto 0) := (others => (others => '0')); signal rgb_de : std_logic; alias rgb_hsync : std_logic is rgb_ctrl(2)(0); alias rgb_vsync : std_logic is rgb_ctrl(2)(1); signal enc_data : 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; begin rgb_data <= rgb; rgb_hsync <= hsync; rgb_vsync <= vsync; rgb_de <= de; ENC_GEN: for I in 2 downto 0 generate enc_tmds_inst : entity work.enc_tmds port map ( clk => enc_clk, din => rgb_data(I), ain => x"0", cin => rgb_ctrl(I), vde => rgb_de, ade => '0', dout => enc_data(I) ); end generate; enc_clk <= pix_clk; enc_data(3) <= "0000011111"; 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_data(I)(0), D2 => enc_data(I)(1), D3 => enc_data(I)(2), D4 => enc_data(I)(3), D5 => enc_data(I)(4), D6 => enc_data(I)(5), D7 => enc_data(I)(6), D8 => enc_data(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_data(I)(8), D4 => enc_data(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 OSERDES_RTL; architecture ODDR_RTL of rgb_dvid is attribute KEEP_HIERARCHY of ODDR_RTL : architecture is "TRUE"; signal rgb_data : vec8_a (2 downto 0) := (others => (others => '0')); signal rgb_ctrl : vec2_a (2 downto 0) := (others => (others => '0')); signal rgb_de : std_logic; alias rgb_hsync : std_logic is rgb_ctrl(2)(0); alias rgb_vsync : std_logic is rgb_ctrl(2)(1); signal enc_data : vec10_a (3 downto 0); signal enc_oddr : vec2_a (3 downto 0); signal enc_clk : std_logic; signal ddr_enable : std_logic; signal ddr_reset : std_logic; signal pix_sync : std_logic; signal fdpe_clk : std_logic; signal fdpe_enable : std_logic; signal fdpe_data : vec6_a (7 downto 0); signal fdpe_pre : vec10_a (3 downto 0); attribute RLOC of fdpe_data : signal is "X7Y0 X6Y0 X5Y0 X4Y0 X3Y0 X2Y0 X1Y0 X0Y0"; begin rgb_data <= rgb; rgb_hsync <= hsync; rgb_vsync <= vsync; rgb_de <= de; ENC_GEN: for I in 2 downto 0 generate enc_tmds_inst : entity work.enc_tmds port map ( clk => enc_clk, din => rgb_data(I), ain => x"0", cin => rgb_ctrl(I), vde => rgb_de, ade => '0', dout => enc_data(I) ); end generate; enc_clk <= pix_clk; enc_data(3) <= "0000011111"; ODDR_GEN: for I in 3 downto 0 generate ODDR_inst : ODDR generic map ( DDR_CLK_EDGE => "SAME_EDGE", INIT => '0', SRTYPE => "ASYNC" ) port map ( Q => tmds(I), D1 => enc_oddr(I)(0), D2 => enc_oddr(I)(1), C => bit_clk, CE => ddr_enable, R => ddr_reset, S => '0' ); end generate; ddr_enable <= enable; ddr_reset <= reset; CHAN_GEN: for I in 3 downto 0 generate EO_GEN: for J in 1 downto 0 generate attribute RLOC of SHIFT_GEN : label is "X0Y" & INTEGER'image(I*2 + J); begin SHIFT_GEN: for K in 4 downto 0 generate attribute RLOC of FDPE_inst : label is "X0Y0"; begin FDPE_inst : FDPE port map ( CE => fdpe_enable, PRE => fdpe_pre(I)(K*2 + J), C => fdpe_clk, D => '0', Q => fdpe_data(I*2 + J)(K + 1) ); end generate; fdpe_data(I*2 + J)(0) <= '0'; enc_oddr(I)(J) <= fdpe_data(I*2 + J)(5); end generate; end generate; fdpe_clk <= bit_clk; sync_proc : process (bit_clk, pix_clk) variable pix_clk_v : std_logic := '0'; begin if rising_edge(bit_clk) then if pix_clk = '1' and pix_clk_v = '0' then pix_sync <= '1'; else pix_sync <= '0'; end if; pix_clk_v := pix_clk; end if; end process; preset_proc : process (bit_clk) begin if rising_edge(bit_clk) then if pix_sync = '1' then fdpe_enable <= '0'; fdpe_pre <= enc_data; else fdpe_enable <= enable; fdpe_pre <= (others => (others => '0')); end if; end if; end process; end ODDR_RTL;