initial commit
This commit is contained in:
221
phsaligner.vhd
Normal file
221
phsaligner.vhd
Normal file
@@ -0,0 +1,221 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user