-- ----------------------------------------------------------------------------- -- Copyright (c) 2013 Benjamin Krill -- -- 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;