-- ----------------------------------------------------------------------------- -- 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 encoder is port ( clk : in std_logic; rst_n : in std_logic; data_i : in std_logic_vector(7 downto 0); c0 : in std_logic; c1 : in std_logic; de : in std_logic; data_o : out std_logic_vector(9 downto 0) ); end encoder; architecture encoder of encoder is signal n1d : unsigned(3 downto 0); signal data_iq : std_logic_vector(7 downto 0); signal decision1 : std_logic; signal q_m : std_logic_vector(8 downto 0); signal n0q_m : unsigned(3 downto 0); -- number of 1s and 0s for q_m signal n1q_m : unsigned(3 downto 0); -- number of 1s and 0s for q_m signal n1q_i : unsigned(3 downto 0); -- number of 1s and 0s for q_m signal cnt : unsigned(4 downto 0); -- disparity counter, MSB is the sign bit signal decision2 : std_logic; signal decision3 : std_logic; type usigned_t is array(natural range <>) of unsigned(3 downto 0); signal data_iu : usigned_t(7 downto 0); signal q_mu : usigned_t(8 downto 0); signal de_q, de_reg : std_logic; signal c0_q, c1_q : std_logic; signal c0_reg, c1_reg : std_logic; signal c1c0 : std_logic_vector(1 downto 0); signal q_m_reg : std_logic_vector(8 downto 0); signal data_oq : std_logic_vector(9 downto 0); begin -- ---------------------------------------------------------- -- Counting number of 1s and 0s for each incoming pixel -- component. Pipe line the result. -- Register Data Input so it matches the pipe lined adder -- output -- ---------------------------------------------------------- tounsigned0: for I in 0 to 7 generate data_iu(I)(3 downto 1) <= "000"; data_iu(I)(0 downto 0) <= unsigned(data_i(I downto I)); end generate; process (clk, rst_n) begin if rst_n = '0' then n1d <= (others => '0'); data_iq <= (others => '0'); elsif rising_edge(clk) then n1d <= data_iu(0) + data_iu(1) + data_iu(2) + data_iu(3) + data_iu(4) + data_iu(5) + data_iu(6) + data_iu(7); data_iq <= data_i; end if; end process; -- ---------------------------------------------------------- -- Stage 1: 8 bit -> 9 bit -- Refer to DVI 1.0 Specification, page 29, Figure 3-5 -- ---------------------------------------------------------- decision1 <= '1' when n1d > x"4" or (n1d = x"4" and data_iq(0) = '0') else '0'; q_m(0) <= data_iq(0); q_m(1) <= (q_m(0) xnor data_iq(1)) when decision1 = '1' else q_m(0) xor data_iq(1); q_m(2) <= (q_m(1) xnor data_iq(2)) when decision1 = '1' else q_m(1) xor data_iq(2); q_m(3) <= (q_m(2) xnor data_iq(3)) when decision1 = '1' else q_m(2) xor data_iq(3); q_m(4) <= (q_m(3) xnor data_iq(4)) when decision1 = '1' else q_m(3) xor data_iq(4); q_m(5) <= (q_m(4) xnor data_iq(5)) when decision1 = '1' else q_m(4) xor data_iq(5); q_m(6) <= (q_m(5) xnor data_iq(6)) when decision1 = '1' else q_m(5) xor data_iq(6); q_m(7) <= (q_m(6) xnor data_iq(7)) when decision1 = '1' else q_m(6) xor data_iq(7); q_m(8) <= '0' when decision1 = '1' else '1'; -- ---------------------------------------------------------- -- Stage 2: 9 bit -> 10 bit -- Refer to DVI 1.0 Specification, page 29, Figure 3-5 -- ---------------------------------------------------------- tounsigned1: for I in 0 to 8 generate q_mu(I)(3 downto 1) <= "000"; q_mu(I)(0 downto 0) <= unsigned(q_m(I downto I)); end generate; n1q_i <= q_mu(0) + q_mu(1) + q_mu(2) + q_mu(3) + q_mu(4) + q_mu(5) + q_mu(6) + q_mu(7); process (clk, rst_n) begin if rst_n = '0' then n1q_m <= (others => '0'); n0q_m <= (others => '0'); elsif rising_edge(clk) then n1q_m <= n1q_i; n0q_m <= x"8" - n1q_i; end if; end process; decision2 <= '1' when cnt = "00000" or n1q_m = n0q_m else '0'; -- ---------------------------------------------------------- -- [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)] -- ---------------------------------------------------------- decision3 <= '1' when (cnt(4) = '0' and n1q_m > n0q_m) or (cnt(4) = '1' and n0q_m > n1q_m) else '0'; -- -------------------------- -- pipe line alignment -- -------------------------- process (clk, rst_n) begin if rst_n = '0' then de_q <= '0'; de_reg <= '0'; c0_q <= '0'; c0_reg <= '0'; c1_q <= '0'; c1_reg <= '0'; q_m_reg <= (others => '0'); elsif rising_edge(clk) then de_q <= de; de_reg <= de_q; c0_q <= c0; c0_reg <= c0_q; c1_q <= c1; c1_reg <= c1_q; q_m_reg <= q_m; end if; end process; -- -------------------------- -- 10-bit out -- disparity counter -- -------------------------- process (clk, rst_n) begin if rst_n = '0' then data_oq <= (others => '0'); cnt <= (others => '0'); elsif rising_edge(clk) then if de_reg = '1' then if decision2 = '1' then data_oq(9) <= not q_m_reg(8); data_oq(8) <= q_m_reg(8); if q_m_reg(8) = '1' then data_oq(7 downto 0) <= q_m_reg(7 downto 0); cnt <= cnt + n1q_m - n0q_m; else data_oq(7 downto 0) <= not q_m_reg(7 downto 0); cnt <= cnt + n0q_m - n1q_m; end if; elsif decision3 = '1' then data_oq(9) <= '1'; data_oq(8) <= q_m_reg(8); data_oq(7 downto 0) <= not q_m_reg(7 downto 0); cnt <= cnt + (q_m_reg(8) & '0') + (n0q_m - n1q_m); else data_oq(9) <= '0'; data_oq(8) <= q_m_reg(8); data_oq(7 downto 0) <= q_m_reg(7 downto 0); cnt <= cnt - (not q_m_reg(8) & '0') + (n1q_m - n0q_m); end if; else case c1c0 is when "00" => data_oq <= CTRLTOKEN0; when "01" => data_oq <= CTRLTOKEN1; when "10" => data_oq <= CTRLTOKEN2; when others => data_oq <= CTRLTOKEN3; end case; cnt <= (others => '0'); end if; end if; end process; c1c0 <= c1_reg & c0_reg; data_o <= data_oq; end encoder;