222 lines
5.8 KiB
VHDL
222 lines
5.8 KiB
VHDL
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;
|