HDMI/DVI Encoder/Decoder
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

225 lines
7.7 KiB

-- -----------------------------------------------------------------------------
-- 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 decoder 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
din_p : in std_logic; -- data from dvi cable
din_n : in std_logic; -- data from dvi cable
other_valid_i : in std_logic_vector(1 downto 0); -- other has valid data now
other_ready_i : in std_logic_vector(1 downto 0); -- other has detected a valid starting pixel
valid_o : out std_logic; -- I have valid data now
ready_o : out std_logic; -- I have detected a valid new pixel
psalgnerr : out std_logic; -- Phase alignment error
c0_o : out std_logic;
c1_o : out std_logic;
de_o : out std_logic;
sdout_o : out std_logic_vector(9 downto 0);
dout_o : out std_logic_vector(7 downto 0)
);
end decoder;
architecture decoder of decoder is
signal rst : std_logic;
signal rxclk : std_logic;
signal flipgear : std_logic;
signal flipgearx2 : std_logic;
signal toggle : std_logic;
signal rx_toggle : std_logic;
signal raw5bit : std_logic_vector(4 downto 0);
signal raw5bit_q : std_logic_vector(4 downto 0);
signal rawword : std_logic_vector(9 downto 0);
signal bitslipx2 : std_logic;
signal bitslip_q : std_logic;
signal bitslip : std_logic;
signal psaligned : std_logic;
signal rawdata : std_logic_vector(9 downto 0);
signal sdata : std_logic_vector(9 downto 0);
signal ready : std_logic;
signal c0 : std_logic;
signal c1 : std_logic;
signal de : std_logic;
signal dout : std_logic_vector(7 downto 0);
signal dout_c : std_logic_vector(7 downto 0);
signal sdout : std_logic_vector(9 downto 0);
signal data : std_logic_vector(7 downto 0);
begin
rst <= not rst_n;
valid_o <= psaligned;
ready_o <= ready;
c0_o <= c0;
c1_o <= c1;
de_o <= de;
dout_o <= dout;
sdout_o <= sdout;
-- ----------------------------------------------------------
-- 5-bit to 10-bit gear box
-- ----------------------------------------------------------
rx_toggle <= toggle xor flipgearx2; -- reverse hi-lo position
process (pclkx2, rst_n)
begin
if rst_n = '0' then
toggle <= '0';
flipgearx2 <= '0';
raw5bit_q <= (others => '0');
elsif rising_edge(pclkx2) then
flipgearx2 <= flipgear;
raw5bit_q <= raw5bit;
toggle <= not toggle;
-- gear from 5 bit to 10 bit
if rx_toggle = '1' then
rawword <= raw5bit & raw5bit_q;
end if;
end if;
end process;
-- ----------------------------------------------------------
-- bitslip signal sync to pclkx2
-- ----------------------------------------------------------
process (pclkx2, rst_n)
begin
if rst_n = '0' then
bitslip_q <= '0';
bitslipx2 <= '0';
elsif rising_edge(pclkx2) then
bitslip_q <= bitslip;
bitslipx2 <= bitslip and not bitslip_q;
end if;
end process;
-- ----------------------------------------------------------
-- 1:5 de-serializer working at x2 pclk rate
-- ----------------------------------------------------------
des_0: entity work.serdes_1_to_5_diff_data
generic map (
DIFF_TERM => false,
BITSLIP_ENABLE => true
-- DIFF_TERM => "FALSE",
-- BITSLIP_ENABLE => "TRUE"
)
port map (
rst => rst,
gclk => pclkx2,
rxioclk_i => pclkx10,
datain_p => din_p,
datain_n => din_n,
use_phase_detector_i => '1',
rxserdesstrobe_i => serdesstrobe_i,
bitslip_i => bitslipx2,
data_o => raw5bit
);
-- ----------------------------------------------------------
-- Doing word boundary detection here
-- ----------------------------------------------------------
rawdata <= rawword;
-- ----------------------------------------------------------
-- Phase Alignment Instance
-- ----------------------------------------------------------
phsalgn_0: entity work.phsaligner
port map (
rst_n => rst_n,
clk => pclk,
sdata_i => rawdata,
bitslip_o => bitslip,
flipgear_o => flipgear,
psaligned_o => psaligned
);
-- ----------------------------------------------------------
-- Per Channel De-skew Instance
-- ----------------------------------------------------------
cbnd: entity work.chnlbond
port map (
clk => pclk,
rst_n => rst_n,
rawdata_i => rawdata,
psaligned_i => psaligned,
other_valid_i => other_valid_i,
other_ready_i => other_ready_i,
ready_o => ready,
sdata_o => sdata
);
-- ----------------------------------------------------------
-- performs the 10B-8B decoding function defined in DVI 1.0
-- Specification: Section 3.3.3, Figure 3-6, page 31.
-- ----------------------------------------------------------
data <= not sdata(7 downto 0) when sdata(9) = '1' else sdata(7 downto 0);
dout_c(0) <= data(0);
dout_c(1) <= data(1) xor data(0) when sdata(8) = '1' else (data(1) xnor data(0));
dout_c(2) <= data(2) xor data(1) when sdata(8) = '1' else (data(2) xnor data(1));
dout_c(3) <= data(3) xor data(2) when sdata(8) = '1' else (data(3) xnor data(2));
dout_c(4) <= data(4) xor data(3) when sdata(8) = '1' else (data(4) xnor data(3));
dout_c(5) <= data(5) xor data(4) when sdata(8) = '1' else (data(5) xnor data(4));
dout_c(6) <= data(6) xor data(5) when sdata(8) = '1' else (data(6) xnor data(5));
dout_c(7) <= data(7) xor data(6) when sdata(8) = '1' else (data(7) xnor data(6));
process (pclk, rst_n)
begin
if rst_n = '0' then
c0 <= '0';
c1 <= '0';
de <= '0';
sdout <= (others => '0');
dout <= (others => '0');
elsif rising_edge(pclk) then
if ready = '1' and other_ready_i = "11" then
case sdata is
when CTRLTOKEN0 =>
c0 <= '0'; c1 <= '0'; de <= '0';
when CTRLTOKEN1 =>
c0 <= '1'; c1 <= '0'; de <= '0';
when CTRLTOKEN2 =>
c0 <= '0'; c1 <= '1'; de <= '0';
when CTRLTOKEN3 =>
c0 <= '1'; c1 <= '1'; de <= '0';
when others =>
dout <= dout_c; de <= '1';
end case;
sdout <= sdata;
else
c0 <= '0'; c1 <= '0'; de <= '0';
sdout <= (others => '0');
dout <= (others => '0');
end if;
end if;
end process;
end decoder;