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.

242 lines
7.1 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. -- -----------------------------------------------------------------------------
  2. -- Copyright (c) 2013 Benjamin Krill <benjamin@krll.de>
  3. --
  4. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  5. -- of this software and associated documentation files (the "Software"), to deal
  6. -- in the Software without restriction, including without limitation the rights
  7. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. -- copies of the Software, and to permit persons to whom the Software is
  9. -- furnished to do so, subject to the following conditions:
  10. --
  11. -- The above copyright notice and this permission notice shall be included in
  12. -- all copies or substantial portions of the Software.
  13. --
  14. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. -- THE SOFTWARE.
  21. -- -----------------------------------------------------------------------------
  22. library ieee;
  23. use ieee.std_logic_1164.all;
  24. use ieee.numeric_std.all;
  25. use work.dvi_package.all;
  26. library UNISIM;
  27. use UNISIM.Vcomponents.all;
  28. entity phsaligner is
  29. generic (
  30. OPENEYE_CNT_WD : integer := 3; -- valid open eye counter width
  31. CTKNCNTWD : integer := 7; -- Control Token Counter Width
  32. SRCHTIMERWD : integer := 12 -- Idle Timer Width
  33. );
  34. port (
  35. rst_n : in std_logic;
  36. clk : in std_logic;
  37. sdata_i : in std_logic_vector(9 downto 0);
  38. flipgear_o : out std_logic;
  39. bitslip_o : out std_logic;
  40. psaligned_o : out std_logic
  41. );
  42. end phsaligner;
  43. architecture phsaligner of phsaligner is
  44. signal flipgear : std_logic;
  45. signal bitslip : std_logic;
  46. signal psaligned : std_logic;
  47. signal rcvd_ctkn : std_logic;
  48. signal rcvd_ctkn_q : std_logic;
  49. signal blnkbgn : std_logic; -- blank period begins
  50. signal ctkn_srh_timer : unsigned(SRCHTIMERWD-1 downto 0);
  51. signal ctkn_srh_rst : std_logic; -- FSM output
  52. signal ctkn_counter : unsigned(CTKNCNTWD-1 downto 0);
  53. signal ctkn_cnt_rst : std_logic; -- FSM output
  54. signal ctkn_srh_tout : std_logic;
  55. signal ctkn_cnt_tout : std_logic;
  56. constant BLNKPRD_CNT_WD : integer := 1;
  57. signal blnkprd_cnt : unsigned(BLNKPRD_CNT_WD-1 downto 0) := (others => '0');
  58. signal bitslip_cnt : unsigned(2 downto 0);
  59. type sm_t is (INIT, SEARCH, BITSLIPS, RCVDCTKN, BLNKPRD, PSALGND);
  60. signal sm_c : sm_t;
  61. signal sm_n : sm_t;
  62. begin
  63. flipgear_o <= flipgear;
  64. bitslip_o <= bitslip;
  65. psaligned_o <= psaligned;
  66. -- ----------------------------------------------------------
  67. -- Control Token Detection
  68. -- ----------------------------------------------------------
  69. process (clk, rst_n)
  70. begin
  71. if rst_n = '0' then
  72. rcvd_ctkn <= '0';
  73. rcvd_ctkn_q <= '0';
  74. blnkbgn <= '0';
  75. elsif rising_edge(clk) then
  76. rcvd_ctkn <= '0';
  77. if sdata_i = CTRLTOKEN0 or sdata_i = CTRLTOKEN1
  78. or sdata_i = CTRLTOKEN2 or sdata_i = CTRLTOKEN3 then
  79. rcvd_ctkn <= '1';
  80. end if;
  81. rcvd_ctkn_q <= rcvd_ctkn;
  82. blnkbgn <= rcvd_ctkn and not rcvd_ctkn_q;
  83. end if;
  84. end process;
  85. -- ----------------------------------------------------------
  86. -- Control Token Search Timer
  87. --
  88. -- DVI 1.0 Spec. says periodic blanking should start
  89. -- no less than every 50ms or 20HZ
  90. -- 2^24 of 74.25MHZ cycles is about 200ms
  91. -- ----------------------------------------------------------
  92. process (clk, rst_n)
  93. begin
  94. if rst_n = '0' then
  95. ctkn_srh_timer <= (others => '0');
  96. ctkn_srh_tout <= '0';
  97. elsif rising_edge(clk) then
  98. if ctkn_srh_rst = '1' then
  99. ctkn_srh_timer <= (others => '0');
  100. else
  101. ctkn_srh_timer <= ctkn_srh_timer + "1";
  102. end if;
  103. ctkn_srh_tout <= '0';
  104. if ctkn_srh_timer = (SRCHTIMERWD-1 downto 0 => '1') then
  105. ctkn_srh_tout <= '1';
  106. end if;
  107. end if;
  108. end process;
  109. -- ----------------------------------------------------------
  110. -- Contorl Token Event Counter
  111. --
  112. -- DVI 1.0 Spec. says the minimal blanking period
  113. -- is at least 128 pixels long in order to achieve
  114. -- synchronization
  115. --
  116. -- HDMI reduces this to as little as 8
  117. -- ----------------------------------------------------------
  118. process (clk, rst_n)
  119. begin
  120. if rst_n = '0' then
  121. ctkn_counter <= (others => '0');
  122. ctkn_cnt_tout <= '0';
  123. elsif rising_edge(clk) then
  124. if ctkn_cnt_rst = '1' then
  125. ctkn_counter <= (others => '0');
  126. else
  127. ctkn_counter <= ctkn_counter + "1";
  128. end if;
  129. ctkn_cnt_tout <= '0';
  130. if ctkn_srh_timer = (CTKNCNTWD-1 downto 0 => '1') then
  131. ctkn_cnt_tout <= '1';
  132. end if;
  133. end if;
  134. end process;
  135. -- ----------------------------------------------------------
  136. -- Below starts the phase alignment state machine
  137. -- ----------------------------------------------------------
  138. process (clk, rst_n)
  139. begin
  140. if rst_n = '0' then
  141. sm_c <= INIT;
  142. elsif rising_edge(clk) then
  143. sm_c <= sm_n;
  144. end if;
  145. end process;
  146. -- ----------------------------------------------------------
  147. -- Counter counts number of blank period detected
  148. -- in order to qualify the bitslip position
  149. -- ----------------------------------------------------------
  150. process (clk, rst_n)
  151. begin
  152. if rst_n = '0' then
  153. sm_n <= INIT;
  154. elsif rising_edge(clk) then
  155. case sm_c is
  156. when INIT =>
  157. if ctkn_srh_tout = '1' then
  158. sm_n <= SEARCH;
  159. end if;
  160. when SEARCH =>
  161. if blnkbgn = '1' then
  162. sm_n <= RCVDCTKN;
  163. elsif ctkn_srh_tout = '1' then
  164. sm_n <= BITSLIPS;
  165. end if;
  166. when BITSLIPS =>
  167. sm_n <= SEARCH;
  168. when RCVDCTKN =>
  169. if rcvd_ctkn = '1' then
  170. if ctkn_cnt_tout = '1' then
  171. sm_n <= BLNKPRD;
  172. end if;
  173. else
  174. sm_n <= SEARCH;
  175. end if;
  176. when BLNKPRD =>
  177. if blnkprd_cnt = (BLNKPRD_CNT_WD-1 downto 0 => '1') then
  178. sm_n <= PSALGND;
  179. else
  180. sm_n <= SEARCH;
  181. end if;
  182. when PSALGND =>
  183. sm_n <= PSALGND; -- Phase aligned so hang around here
  184. end case;
  185. end if;
  186. end process;
  187. process (clk, rst_n)
  188. begin
  189. if rst_n = '0' then
  190. psaligned <= '0'; -- phase alignment success flag
  191. bitslip <= '0';
  192. ctkn_srh_rst <= '1'; -- control token search timer reset
  193. ctkn_cnt_rst <= '1'; -- control token counter reset
  194. bitslip_cnt <= (others => '0');
  195. flipgear <= '0';
  196. blnkprd_cnt <= (others => '0');
  197. elsif rising_edge(clk) then
  198. case sm_c is
  199. when INIT =>
  200. ctkn_srh_rst <= '0';
  201. ctkn_cnt_rst <= '1';
  202. psaligned <= '0';
  203. bitslip <= '0';
  204. bitslip_cnt <= (others => '0');
  205. flipgear <= '0';
  206. blnkprd_cnt <= (others => '0');
  207. when SEARCH =>
  208. ctkn_srh_rst <= '0';
  209. ctkn_cnt_rst <= '1';
  210. bitslip <= '0';
  211. psaligned <= '0';
  212. when BITSLIPS =>
  213. ctkn_srh_rst <= '1';
  214. bitslip <= '1';
  215. bitslip_cnt <= bitslip_cnt + "1";
  216. flipgear <= bitslip_cnt(2); -- bitslip has toggled for 4 times
  217. when RCVDCTKN =>
  218. ctkn_srh_rst <= '0';
  219. ctkn_cnt_rst <= '0';
  220. when BLNKPRD =>
  221. blnkprd_cnt <= blnkprd_cnt + "1";
  222. when PSALGND =>
  223. psaligned <= '1';
  224. end case;
  225. end if;
  226. end process;
  227. end phsaligner;