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 phsaligner is
|
|
|
|
generic (
|
|
|
|
OPENEYE_CNT_WD : integer := 3; -- valid open eye counter width
|
|
|
|
CTKNCNTWD : integer := 7; -- Control Token Counter Width
|
|
|
|
SRCHTIMERWD : integer := 12 -- Idle Timer Width
|
|
|
|
);
|
|
|
|
port (
|
|
|
|
rst_n : in std_logic;
|
|
|
|
clk : in std_logic;
|
|
|
|
sdata_i : in std_logic_vector(9 downto 0);
|
|
|
|
flipgear_o : out std_logic;
|
|
|
|
bitslip_o : out std_logic;
|
|
|
|
psaligned_o : out std_logic
|
|
|
|
);
|
|
|
|
end phsaligner;
|
|
|
|
|
|
|
|
architecture phsaligner of phsaligner is
|
|
|
|
signal flipgear : std_logic;
|
|
|
|
signal bitslip : std_logic;
|
|
|
|
signal psaligned : std_logic;
|
|
|
|
|
|
|
|
signal rcvd_ctkn : std_logic;
|
|
|
|
signal rcvd_ctkn_q : std_logic;
|
|
|
|
signal blnkbgn : std_logic; -- blank period begins
|
|
|
|
|
|
|
|
signal ctkn_srh_timer : unsigned(SRCHTIMERWD-1 downto 0);
|
|
|
|
signal ctkn_srh_rst : std_logic; -- FSM output
|
|
|
|
signal ctkn_counter : unsigned(CTKNCNTWD-1 downto 0);
|
|
|
|
signal ctkn_cnt_rst : std_logic; -- FSM output
|
|
|
|
signal ctkn_srh_tout : std_logic;
|
|
|
|
signal ctkn_cnt_tout : std_logic;
|
|
|
|
|
|
|
|
constant BLNKPRD_CNT_WD : integer := 1;
|
|
|
|
signal blnkprd_cnt : unsigned(BLNKPRD_CNT_WD-1 downto 0) := (others => '0');
|
|
|
|
signal bitslip_cnt : unsigned(2 downto 0);
|
|
|
|
|
|
|
|
type sm_t is (INIT, SEARCH, BITSLIPS, RCVDCTKN, BLNKPRD, PSALGND);
|
|
|
|
signal sm_c : sm_t;
|
|
|
|
signal sm_n : sm_t;
|
|
|
|
begin
|
|
|
|
flipgear_o <= flipgear;
|
|
|
|
bitslip_o <= bitslip;
|
|
|
|
psaligned_o <= psaligned;
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
-- Control Token Detection
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
rcvd_ctkn <= '0';
|
|
|
|
rcvd_ctkn_q <= '0';
|
|
|
|
blnkbgn <= '0';
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
rcvd_ctkn <= '0';
|
|
|
|
if sdata_i = CTRLTOKEN0 or sdata_i = CTRLTOKEN1
|
|
|
|
or sdata_i = CTRLTOKEN2 or sdata_i = CTRLTOKEN3 then
|
|
|
|
rcvd_ctkn <= '1';
|
|
|
|
end if;
|
|
|
|
rcvd_ctkn_q <= rcvd_ctkn;
|
|
|
|
blnkbgn <= rcvd_ctkn and not rcvd_ctkn_q;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
-- Control Token Search Timer
|
|
|
|
--
|
|
|
|
-- DVI 1.0 Spec. says periodic blanking should start
|
|
|
|
-- no less than every 50ms or 20HZ
|
|
|
|
-- 2^24 of 74.25MHZ cycles is about 200ms
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
ctkn_srh_timer <= (others => '0');
|
|
|
|
ctkn_srh_tout <= '0';
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
if ctkn_srh_rst = '1' then
|
|
|
|
ctkn_srh_timer <= (others => '0');
|
|
|
|
else
|
|
|
|
ctkn_srh_timer <= ctkn_srh_timer + "1";
|
|
|
|
end if;
|
|
|
|
|
|
|
|
ctkn_srh_tout <= '0';
|
|
|
|
if ctkn_srh_timer = (SRCHTIMERWD-1 downto 0 => '1') then
|
|
|
|
ctkn_srh_tout <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
-- Contorl Token Event Counter
|
|
|
|
--
|
|
|
|
-- DVI 1.0 Spec. says the minimal blanking period
|
|
|
|
-- is at least 128 pixels long in order to achieve
|
|
|
|
-- synchronization
|
|
|
|
--
|
|
|
|
-- HDMI reduces this to as little as 8
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
ctkn_counter <= (others => '0');
|
|
|
|
ctkn_cnt_tout <= '0';
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
if ctkn_cnt_rst = '1' then
|
|
|
|
ctkn_counter <= (others => '0');
|
|
|
|
else
|
|
|
|
ctkn_counter <= ctkn_counter + "1";
|
|
|
|
end if;
|
|
|
|
|
|
|
|
ctkn_cnt_tout <= '0';
|
|
|
|
if ctkn_srh_timer = (CTKNCNTWD-1 downto 0 => '1') then
|
|
|
|
ctkn_cnt_tout <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
-- Below starts the phase alignment state machine
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
sm_c <= INIT;
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
sm_c <= sm_n;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
-- Counter counts number of blank period detected
|
|
|
|
-- in order to qualify the bitslip position
|
|
|
|
-- ----------------------------------------------------------
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
sm_n <= INIT;
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
case sm_c is
|
|
|
|
when INIT =>
|
|
|
|
if ctkn_srh_tout = '1' then
|
|
|
|
sm_n <= SEARCH;
|
|
|
|
end if;
|
|
|
|
when SEARCH =>
|
|
|
|
if blnkbgn = '1' then
|
|
|
|
sm_n <= RCVDCTKN;
|
|
|
|
elsif ctkn_srh_tout = '1' then
|
|
|
|
sm_n <= BITSLIPS;
|
|
|
|
end if;
|
|
|
|
when BITSLIPS =>
|
|
|
|
sm_n <= SEARCH;
|
|
|
|
when RCVDCTKN =>
|
|
|
|
if rcvd_ctkn = '1' then
|
|
|
|
if ctkn_cnt_tout = '1' then
|
|
|
|
sm_n <= BLNKPRD;
|
|
|
|
end if;
|
|
|
|
else
|
|
|
|
sm_n <= SEARCH;
|
|
|
|
end if;
|
|
|
|
when BLNKPRD =>
|
|
|
|
if blnkprd_cnt = (BLNKPRD_CNT_WD-1 downto 0 => '1') then
|
|
|
|
sm_n <= PSALGND;
|
|
|
|
else
|
|
|
|
sm_n <= SEARCH;
|
|
|
|
end if;
|
|
|
|
when PSALGND =>
|
|
|
|
sm_n <= PSALGND; -- Phase aligned so hang around here
|
|
|
|
end case;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
process (clk, rst_n)
|
|
|
|
begin
|
|
|
|
if rst_n = '0' then
|
|
|
|
psaligned <= '0'; -- phase alignment success flag
|
|
|
|
bitslip <= '0';
|
|
|
|
ctkn_srh_rst <= '1'; -- control token search timer reset
|
|
|
|
ctkn_cnt_rst <= '1'; -- control token counter reset
|
|
|
|
bitslip_cnt <= (others => '0');
|
|
|
|
flipgear <= '0';
|
|
|
|
blnkprd_cnt <= (others => '0');
|
|
|
|
elsif rising_edge(clk) then
|
|
|
|
case sm_c is
|
|
|
|
when INIT =>
|
|
|
|
ctkn_srh_rst <= '0';
|
|
|
|
ctkn_cnt_rst <= '1';
|
|
|
|
psaligned <= '0';
|
|
|
|
bitslip <= '0';
|
|
|
|
bitslip_cnt <= (others => '0');
|
|
|
|
flipgear <= '0';
|
|
|
|
blnkprd_cnt <= (others => '0');
|
|
|
|
when SEARCH =>
|
|
|
|
ctkn_srh_rst <= '0';
|
|
|
|
ctkn_cnt_rst <= '1';
|
|
|
|
bitslip <= '0';
|
|
|
|
psaligned <= '0';
|
|
|
|
when BITSLIPS =>
|
|
|
|
ctkn_srh_rst <= '1';
|
|
|
|
bitslip <= '1';
|
|
|
|
bitslip_cnt <= bitslip_cnt + "1";
|
|
|
|
flipgear <= bitslip_cnt(2); -- bitslip has toggled for 4 times
|
|
|
|
when RCVDCTKN =>
|
|
|
|
ctkn_srh_rst <= '0';
|
|
|
|
ctkn_cnt_rst <= '0';
|
|
|
|
when BLNKPRD =>
|
|
|
|
blnkprd_cnt <= blnkprd_cnt + "1";
|
|
|
|
when PSALGND =>
|
|
|
|
psaligned <= '1';
|
|
|
|
end case;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
end phsaligner;
|