hdmi/dvi_encoder.vhd

133 lines
4.7 KiB
VHDL

-- -----------------------------------------------------------------------------
-- Copyright (c) 2013 Benjamin Krill <benjamin@krll.de>
--
-- 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 UNISIM;
use UNISIM.Vcomponents.all;
entity dvi_encoder is
port (
rst_n : in std_logic; -- external reset input, e.g. reset button
pclk : in std_logic; -- pixel clock
pclkx2 : in std_logic; -- double pixel rate for gear box
pclkx10 : in std_logic; -- IOCLK
serdesstrobe_i : in std_logic; -- serdesstrobe for iserdes2
color_i : in color_t(COLOR_CNT-1 downto 0); -- pixel data out
hsync_i : in std_logic; -- hsync data
vsync_i : in std_logic; -- vsync data
dat_en_i : in std_logic; -- data enable
tmds_p : out std_logic_vector(3 downto 0); -- tmds
tmds_n : out std_logic_vector(3 downto 0) -- tmds
);
end dvi_encoder;
architecture dvi_encoder of dvi_encoder is
signal rst : std_logic;
signal toggle : std_logic;
signal tmdsclkint : std_logic_vector(4 downto 0);
signal data : sdat_t(COLOR_CNT-1 downto 0);
signal sdata : std_logic_vector(29 downto 0);
type data_5bit_t is array(natural range <>) of std_logic_vector(4 downto 0);
signal tmds_data : data_5bit_t(3 downto 0);
signal tmdsint : std_logic_vector(3 downto 0);
signal tmds_clk : std_logic;
begin
rst <= not rst_n;
-- ----------------------------------------------------------
-- 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_i,
data_i => tmdsclkint,
data_o => tmds_clk
);
TMDS3: OBUFDS port map (I => tmds_clk, O => tmds_p(3), OB => tmds_n(3)); -- clock
-- ----------------------------------------------------------
-- Forward TMDS Data: 3 channels
-- ----------------------------------------------------------
forward: for I in 0 to COLOR_CNT-1 generate
oserdes_I: entity work.serdes_n_to_1
generic map (SF => 5)
port map (
ioclk => pclkx10,
gclk => pclkx2,
rst => rst,
serdesstrobe_i => serdesstrobe_i,
data_i => tmds_data(I),
data_o => tmdsint(I)
);
TMDS_I: OBUFDS port map (I => tmdsint(I), O => tmds_p(I), OB => tmds_n(I));
enc_I: entity work.encoder
port map (
clk => pclk,
rst_n => rst_n,
data_i => color_i(I),
c0 => hsync_i,
c1 => vsync_i,
de => dat_en_i,
data_o => data(I)
);
end generate;
sdata <= data(RED)(9 downto 5) & data(GREEN)(9 downto 5) & data(BLUE)(9 downto 5)
& data(RED)(4 downto 0) & data(GREEN)(4 downto 0) & data(BLUE)(4 downto 0);
pixel2x: entity work.convert_30to15_fifo
port map (
rst => rst,
clk => pclk,
clkx2 => pclkx2,
data_i => sdata,
data_o(14 downto 10) => tmds_data(2),
data_o( 9 downto 5) => tmds_data(1),
data_o( 4 downto 0) => tmds_data(0)
);
end dvi_encoder;