hdmi/dvi_decoder.vhd

193 lines
7.1 KiB
VHDL
Raw Permalink Normal View History

2013-10-07 09:07:08 +02:00
-- -----------------------------------------------------------------------------
-- Copyright (c) 2013 Benjamin Krill <benjamin@krll.de>
2013-10-07 09:34:06 +02:00
--
2013-10-07 09:07:08 +02:00
-- 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:
2013-10-07 09:34:06 +02:00
--
2013-10-07 09:07:08 +02:00
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
2013-10-07 09:34:06 +02:00
--
2013-10-07 09:07:08 +02:00
-- 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.
-- -----------------------------------------------------------------------------
2013-09-23 10:20:49 +02:00
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_decoder is
port (
ext_rst : in std_logic; -- external reset input, e.g. reset button
tmdsclk_p : in std_logic; -- tmds clock
tmdsclk_n : in std_logic; -- tmds clock
din_p : in std_logic_vector(COLOR_CNT-1 downto 0); -- data in
din_n : in std_logic_vector(COLOR_CNT-1 downto 0); -- data in
reset_n : out std_logic; -- rx reset_n
pclk_o : out std_logic; -- regenerated pixel clock
pclkx2_o : out std_logic; -- double rate pixel clock
pclkx10_o : out std_logic; -- 10x pixel as IOCLK
pll_lckd_o : out std_logic; -- send pll_lckd out so it can be fed into a different BUFPLL
serdesstrobe_o : out std_logic; -- BUFPLL serdesstrobe output
tmdsclk_o : out std_logic; -- TMDS cable clock
hsync_o : out std_logic; -- hsync data
vsync_o : out std_logic; -- vsync data
dat_en_o : out std_logic; -- data enable
valid_o : out std_logic_vector(COLOR_CNT-1 downto 0);
ready_o : out std_logic_vector(COLOR_CNT-1 downto 0);
psalgnerr_o : out std_logic;
sdout_o : out sdat_t(COLOR_CNT-1 downto 0);
color_o : out color_t(COLOR_CNT-1 downto 0) -- pixel data out
);
end dvi_decoder;
architecture dvi_decoder of dvi_decoder is
signal rst_n : std_logic;
signal rxclk_b : std_logic;
signal rxclk : std_logic;
signal clkfbout : std_logic;
signal pclk : std_logic;
signal pclkx2 : std_logic;
signal pclkx10 : std_logic;
signal pllclk0 : std_logic;
signal pllclk1 : std_logic;
signal pllclk2 : std_logic;
signal pll_locked : std_logic;
signal bufpll_lock : std_logic;
signal serdesstrobe : std_logic;
signal ready : std_logic_vector(COLOR_CNT-1 downto 0);
signal hsync : std_logic_vector(COLOR_CNT-1 downto 0);
signal vsync : std_logic_vector(COLOR_CNT-1 downto 0);
signal valid : std_logic_vector(COLOR_CNT-1 downto 0);
type matrix_t is array (natural range <>) of std_logic_vector(COLOR_CNT-2 downto 0);
signal other_ready : matrix_t(COLOR_CNT-1 downto 0);
signal other_valid : matrix_t(COLOR_CNT-1 downto 0);
signal psalgnerr : std_logic_vector(COLOR_CNT-1 downto 0);
signal dat_en : std_logic_vector(COLOR_CNT-1 downto 0);
begin
-- ----------------------------------------------------------
-- I/O mapping
-- ----------------------------------------------------------
rst_n <= bufpll_lock;
reset_n <= rst_n;
pclk_o <= pclk;
pclkx2_o <= pclkx2;
pclkx10_o <= pclkx10;
pll_lckd_o <= pll_locked;
serdesstrobe_o <= serdesstrobe;
valid_o <= valid;
ready_o <= ready;
psalgnerr_o <= psalgnerr(RED) or psalgnerr(GREEN) or psalgnerr(BLUE);
dat_en_o <= dat_en(BLUE);
hsync_o <= hsync(BLUE);
vsync_o <= vsync(BLUE);
-- ----------------------------------------------------------
-- clocking
-- ----------------------------------------------------------
ibuf_rxclk: IBUFDS
generic map ( IOSTANDARD => "TMDS_33", DIFF_TERM => false )
port map ( i => tmdsclk_p, ib => tmdsclk_n, o => rxclk_b );
bufio_tmdsclk_0: BUFIO2
generic map ( DIVIDE_BYPASS => true, DIVIDE => 1 )
port map ( DIVCLK => rxclk, IOCLK => open, SERDESSTROBE => open, I => rxclk_b );
tmdsclk_bufg: BUFG port map (I => rxclk, O => tmdsclk_o);
-- PLL is used to generate three clocks:
-- 1. pclk: same rate as TMDS clock
-- 2. pclkx2: double rate of pclk used for 5:10 soft gear box and ISERDES DIVCLK
-- 3. pclkx10: 10x rate of pclk used as IO clock
PLL_ISERDES: 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 => "INTERNAL"
)
port map (
CLKFBOUT => clkfbout,
CLKOUT0 => pllclk0,
CLKOUT1 => pllclk1,
CLKOUT2 => pllclk2,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => pll_locked,
CLKFBIN => clkfbout,
CLKIN => rxclk,
RST => ext_rst
);
--Pixel Rate clock buffer
pclkbufg: BUFG port map ( I => pllclk1, O => pclk);
-- 2x pclk is going to be used to drive IOSERDES2 DIVCLK
pclkx2bufg: BUFG port map (I => pllclk2, O => pclkx2);
-- 10x pclk is used to drive IOCLK network so a bit rate reference
-- can be used by IOSERDES2
ioclk_buf: BUFPLL
generic map( DIVIDE => 5 )
port map (
PLLIN => pllclk0,
GCLK => pclkx2,
LOCKED => pll_locked,
IOCLK => pclkx10,
SERDESSTROBE => serdesstrobe,
LOCK => bufpll_lock
);
-- ----------------------------------------------------------
-- decoder mapping
-- ----------------------------------------------------------
other_valid(RED) <= valid(BLUE) & valid(GREEN);
other_valid(GREEN) <= valid(BLUE) & valid(RED);
other_valid(BLUE) <= valid(RED) & valid(GREEN);
other_ready(RED) <= ready(BLUE) & ready(GREEN);
other_ready(GREEN) <= ready(BLUE) & ready(RED);
other_ready(BLUE) <= ready(RED) & ready(GREEN);
dec: for I in 0 to COLOR_CNT-1 generate
decoder: entity work.decoder
port map (
rst_n => rst_n,
pclk => pclk,
pclkx2 => pclkx2,
pclkx10 => pclkx10,
serdesstrobe_i => serdesstrobe,
din_p => din_p(I),
din_n => din_n(I),
other_valid_i => other_valid(I),
other_ready_i => other_ready(I),
valid_o => valid(I),
ready_o => ready(I),
psalgnerr => psalgnerr(I),
c0_o => hsync(I),
c1_o => vsync(I),
de_o => dat_en(I),
sdout_o => sdout_o(I),
dout_o => color_o(I)
);
end generate dec;
end dvi_decoder;