initial commit
This commit is contained in:
commit
2e79b67236
42
DRAM16XN.vhd
Normal file
42
DRAM16XN.vhd
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library UNISIM;
|
||||||
|
use UNISIM.Vcomponents.all;
|
||||||
|
|
||||||
|
entity DRAM16XN is
|
||||||
|
generic (data_width : integer := 20);
|
||||||
|
port (
|
||||||
|
DATA_IN : in std_logic_vector(data_width-1 downto 0);
|
||||||
|
ADDRESS : in std_logic_vector(3 downto 0);
|
||||||
|
ADDRESS_DP : in std_logic_vector(3 downto 0);
|
||||||
|
WRITE_EN : in std_logic;
|
||||||
|
CLK : in std_logic;
|
||||||
|
|
||||||
|
O_DATA_OUT_DP : out std_logic_vector(data_width-1 downto 0);
|
||||||
|
O_DATA_OUT : out std_logic_vector(data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end DRAM16XN;
|
||||||
|
|
||||||
|
architecture DRAM16XN of DRAM16XN is
|
||||||
|
begin
|
||||||
|
RAM: for I in 0 to data_width-1 generate
|
||||||
|
I_RAM16X1D: RAM16X1D
|
||||||
|
port map (
|
||||||
|
D => DATA_IN(I), --insert input signal
|
||||||
|
WE => WRITE_EN, --insert Write Enable signal
|
||||||
|
WCLK => CLK, --insert Write Clock signal
|
||||||
|
A0 => ADDRESS(0), --insert Address 0 signal port SPO
|
||||||
|
A1 => ADDRESS(1), --insert Address 1 signal port SPO
|
||||||
|
A2 => ADDRESS(2), --insert Address 2 signal port SPO
|
||||||
|
A3 => ADDRESS(3), --insert Address 3 signal port SPO
|
||||||
|
DPRA0 => ADDRESS_DP(0), --insert Address 0 signal dual port DPO
|
||||||
|
DPRA1 => ADDRESS_DP(1), --insert Address 1 signal dual port DPO
|
||||||
|
DPRA2 => ADDRESS_DP(2), --insert Address 2 signal dual port DPO
|
||||||
|
DPRA3 => ADDRESS_DP(3), --insert Address 3 signal dual port DPO
|
||||||
|
SPO => O_DATA_OUT(I), --insert output signal SPO
|
||||||
|
DPO => O_DATA_OUT_DP(I) --insert output signal DPO
|
||||||
|
);
|
||||||
|
end generate;
|
||||||
|
end DRAM16XN;
|
155
chnlbond.vhd
Normal file
155
chnlbond.vhd
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
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 chnlbond is
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
rst_n : in std_logic;
|
||||||
|
rawdata_i : in std_logic_vector(9 downto 0);
|
||||||
|
psaligned_i : in std_logic;
|
||||||
|
other_valid_i : in std_logic_vector(1 downto 0);
|
||||||
|
other_ready_i : in std_logic_vector(1 downto 0);
|
||||||
|
ready_o : out std_logic;
|
||||||
|
sdata_o : out std_logic_vector(9 downto 0)
|
||||||
|
);
|
||||||
|
end chnlbond;
|
||||||
|
|
||||||
|
architecture chnlbond of chnlbond is
|
||||||
|
signal rawdata_vld : std_logic;
|
||||||
|
signal we : std_logic;
|
||||||
|
signal wa, ra : unsigned(3 downto 0);
|
||||||
|
signal dpfo_dout : std_logic_vector(9 downto 0);
|
||||||
|
signal sdata : std_logic_vector(9 downto 0);
|
||||||
|
signal rcvd_ctkn : std_logic;
|
||||||
|
signal rcvd_ctkn_q : std_logic;
|
||||||
|
signal blnkbgn : std_logic;
|
||||||
|
signal skip_line : std_logic;
|
||||||
|
signal next_blnkbgn : std_logic;
|
||||||
|
signal ready : std_logic;
|
||||||
|
signal rawdata_vld_q : std_logic;
|
||||||
|
signal rawdata_vld_s : std_logic;
|
||||||
|
signal ra_en : std_logic;
|
||||||
|
begin
|
||||||
|
sdata_o <= sdata;
|
||||||
|
ready_o <= ready;
|
||||||
|
rawdata_vld <= other_valid_i(0) and other_valid_i(1) and psaligned_i;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- FIFO Write Control Logic
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
process (clk, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
we <= '0';
|
||||||
|
sdata <= (others => '0');
|
||||||
|
wa <= (others => '0');
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
we <= rawdata_vld;
|
||||||
|
if rawdata_vld = '1' then
|
||||||
|
wa <= wa + "1";
|
||||||
|
else
|
||||||
|
wa <= (others => '0');
|
||||||
|
end if;
|
||||||
|
|
||||||
|
sdata <= dpfo_dout;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- FIFO
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
cbfifo_i: entity work.DRAM16XN
|
||||||
|
generic map ( data_width => 10 )
|
||||||
|
port map (
|
||||||
|
DATA_IN => rawdata_i,
|
||||||
|
ADDRESS => std_logic_vector(wa),
|
||||||
|
ADDRESS_DP => std_logic_vector(ra),
|
||||||
|
WRITE_EN => we,
|
||||||
|
CLK => clk,
|
||||||
|
O_DATA_OUT => open,
|
||||||
|
O_DATA_OUT_DP => dpfo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- FIFO read Control Logic
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
next_blnkbgn <= skip_line and blnkbgn;
|
||||||
|
process (clk, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
rcvd_ctkn <= '0';
|
||||||
|
rcvd_ctkn_q <= '0';
|
||||||
|
ready <= '0';
|
||||||
|
skip_line <= '0';
|
||||||
|
rawdata_vld_q <= '0';
|
||||||
|
rawdata_vld_s <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
-- ---------------------------
|
||||||
|
-- Use blank period beginning
|
||||||
|
-- as a speical marker to
|
||||||
|
-- align all channel together
|
||||||
|
-- ---------------------------
|
||||||
|
rcvd_ctkn <= '0';
|
||||||
|
if sdata = CTRLTOKEN0 or sdata = CTRLTOKEN1
|
||||||
|
or sdata = CTRLTOKEN2 or sdata = CTRLTOKEN3 then
|
||||||
|
rcvd_ctkn <= '1';
|
||||||
|
end if;
|
||||||
|
rcvd_ctkn_q <= rcvd_ctkn;
|
||||||
|
blnkbgn <= rcvd_ctkn and not rcvd_ctkn_q;
|
||||||
|
|
||||||
|
-- ---------------------------
|
||||||
|
-- skip the current line
|
||||||
|
-- ---------------------------
|
||||||
|
if rawdata_vld = '0' then
|
||||||
|
skip_line <= '0';
|
||||||
|
elsif blnkbgn = '1' then
|
||||||
|
skip_line <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- ---------------------------
|
||||||
|
-- Declare my own readiness
|
||||||
|
-- ---------------------------
|
||||||
|
if rawdata_vld = '0' then
|
||||||
|
ready <= '0';
|
||||||
|
elsif next_blnkbgn = '1' then
|
||||||
|
ready <= '1';
|
||||||
|
end if;
|
||||||
|
rawdata_vld_q <= rawdata_vld;
|
||||||
|
rawdata_vld_s <= rawdata_vld and not rawdata_vld_q;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- 1. FIFO flow through first when all channels are found valid(phase aligned)
|
||||||
|
-- 2. When the speical marker on my channel is found, the fifo read is hold
|
||||||
|
-- 3. Until the same markers are found across all three channels, the fifo read resumes
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
process (clk, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
ra_en <= '0';
|
||||||
|
ra <= (others => '0');
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if rawdata_vld_s = '1' or (other_ready_i(0) = '1' and other_ready_i(1) = '1' and ready = '1') then
|
||||||
|
ra_en <= '1';
|
||||||
|
elsif next_blnkbgn = '1' and not (other_ready_i(0) = '1' and other_ready_i(1) = '1' and ready = '1') then
|
||||||
|
ra_en <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- ---------------------------
|
||||||
|
-- FIFO Read Address Counter
|
||||||
|
-- ---------------------------
|
||||||
|
if rawdata_vld = '0' then
|
||||||
|
ra <= (others => '0');
|
||||||
|
elsif ra_en = '1' then
|
||||||
|
ra <= ra + "1";
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end chnlbond;
|
143
convert_30to15_fifo.vhd
Normal file
143
convert_30to15_fifo.vhd
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
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 convert_30to15_fifo is
|
||||||
|
port (
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
clkx2 : in std_logic;
|
||||||
|
data_i : in std_logic_vector(29 downto 0); -- input data for 2:1 serialisation
|
||||||
|
data_o : out std_logic_vector(14 downto 0) -- 5-bit data out
|
||||||
|
);
|
||||||
|
end convert_30to15_fifo;
|
||||||
|
|
||||||
|
architecture convert_30to15_fifo of convert_30to15_fifo is
|
||||||
|
signal wa : std_logic_vector( 3 downto 0);
|
||||||
|
signal wa_q : std_logic_vector( 3 downto 0);
|
||||||
|
signal ra : std_logic_vector( 3 downto 0);
|
||||||
|
signal ra_q : std_logic_vector( 3 downto 0);
|
||||||
|
signal data_int : std_logic_vector(29 downto 0);
|
||||||
|
|
||||||
|
signal rstsync_q : std_logic;
|
||||||
|
signal rstsync : std_logic;
|
||||||
|
signal rstp : std_logic;
|
||||||
|
signal sync : std_logic;
|
||||||
|
signal syncn : std_logic;
|
||||||
|
signal db : std_logic_vector(29 downto 0);
|
||||||
|
signal mux : std_logic_vector(14 downto 0);
|
||||||
|
constant ADDR0 : std_logic_vector( 3 downto 0) := "0000";
|
||||||
|
constant ADDR1 : std_logic_vector( 3 downto 0) := "0001";
|
||||||
|
constant ADDR2 : std_logic_vector( 3 downto 0) := "0010";
|
||||||
|
constant ADDR3 : std_logic_vector( 3 downto 0) := "0011";
|
||||||
|
constant ADDR4 : std_logic_vector( 3 downto 0) := "0100";
|
||||||
|
constant ADDR5 : std_logic_vector( 3 downto 0) := "0101";
|
||||||
|
constant ADDR6 : std_logic_vector( 3 downto 0) := "0110";
|
||||||
|
constant ADDR7 : std_logic_vector( 3 downto 0) := "0111";
|
||||||
|
constant ADDR8 : std_logic_vector( 3 downto 0) := "1000";
|
||||||
|
constant ADDR9 : std_logic_vector( 3 downto 0) := "1001";
|
||||||
|
constant ADDR10 : std_logic_vector( 3 downto 0) := "1010";
|
||||||
|
constant ADDR11 : std_logic_vector( 3 downto 0) := "1011";
|
||||||
|
constant ADDR12 : std_logic_vector( 3 downto 0) := "1100";
|
||||||
|
constant ADDR13 : std_logic_vector( 3 downto 0) := "1101";
|
||||||
|
constant ADDR14 : std_logic_vector( 3 downto 0) := "1110";
|
||||||
|
constant ADDR15 : std_logic_vector( 3 downto 0) := "1111";
|
||||||
|
begin
|
||||||
|
-- --------------------------------------------------
|
||||||
|
-- Here we instantiate a 16x10 Dual Port RAM
|
||||||
|
-- and fill first it with data aligned to
|
||||||
|
-- clk domain
|
||||||
|
-- --------------------------------------------------
|
||||||
|
fdc_wa0: FDC port map (C => clk, D => wa_q(0), CLR => rst, Q => wa(0));
|
||||||
|
fdc_wa1: FDC port map (C => clk, D => wa_q(1), CLR => rst, Q => wa(1));
|
||||||
|
fdc_wa2: FDC port map (C => clk, D => wa_q(2), CLR => rst, Q => wa(2));
|
||||||
|
fdc_wa3: FDC port map (C => clk, D => wa_q(3), CLR => rst, Q => wa(3));
|
||||||
|
|
||||||
|
process (wa)
|
||||||
|
begin
|
||||||
|
case wa is
|
||||||
|
when ADDR0 => wa_q <= ADDR1;
|
||||||
|
when ADDR1 => wa_q <= ADDR2;
|
||||||
|
when ADDR2 => wa_q <= ADDR3;
|
||||||
|
when ADDR3 => wa_q <= ADDR4;
|
||||||
|
when ADDR4 => wa_q <= ADDR5;
|
||||||
|
when ADDR5 => wa_q <= ADDR6;
|
||||||
|
when ADDR6 => wa_q <= ADDR7;
|
||||||
|
when ADDR7 => wa_q <= ADDR8;
|
||||||
|
when ADDR8 => wa_q <= ADDR9;
|
||||||
|
when ADDR9 => wa_q <= ADDR10;
|
||||||
|
when ADDR10 => wa_q <= ADDR11;
|
||||||
|
when ADDR11 => wa_q <= ADDR12;
|
||||||
|
when ADDR12 => wa_q <= ADDR13;
|
||||||
|
when ADDR13 => wa_q <= ADDR14;
|
||||||
|
when ADDR14 => wa_q <= ADDR15;
|
||||||
|
when others => wa_q <= ADDR0;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fifo_u: entity work.DRAM16XN
|
||||||
|
generic map (data_width => 30)
|
||||||
|
port map (
|
||||||
|
DATA_IN => data_i,
|
||||||
|
ADDRESS => wa,
|
||||||
|
ADDRESS_DP => ra,
|
||||||
|
WRITE_EN => '1',
|
||||||
|
CLK => clk,
|
||||||
|
O_DATA_OUT => open,
|
||||||
|
O_DATA_OUT_DP => data_int
|
||||||
|
);
|
||||||
|
|
||||||
|
-- --------------------------------------------------
|
||||||
|
-- Here starts clk2x domain for fifo read out
|
||||||
|
-- FIFO read is set to be once every 2 cycles of clk2x in order
|
||||||
|
-- to keep up pace with the fifo write speed
|
||||||
|
-- Also FIFO read reset is delayed a bit in order to avoid
|
||||||
|
-- underflow.
|
||||||
|
-- --------------------------------------------------
|
||||||
|
fdc_ra0: FDRE port map (C => clkx2, D => ra_q(0), R => rstp, CE => sync, Q => ra(0));
|
||||||
|
fdc_ra1: FDRE port map (C => clkx2, D => ra_q(1), R => rstp, CE => sync, Q => ra(1));
|
||||||
|
fdc_ra2: FDRE port map (C => clkx2, D => ra_q(2), R => rstp, CE => sync, Q => ra(2));
|
||||||
|
fdc_ra3: FDRE port map (C => clkx2, D => ra_q(3), R => rstp, CE => sync, Q => ra(3));
|
||||||
|
process (ra)
|
||||||
|
begin
|
||||||
|
case ra is
|
||||||
|
when ADDR0 => ra_q <= ADDR1;
|
||||||
|
when ADDR1 => ra_q <= ADDR2;
|
||||||
|
when ADDR2 => ra_q <= ADDR3;
|
||||||
|
when ADDR3 => ra_q <= ADDR4;
|
||||||
|
when ADDR4 => ra_q <= ADDR5;
|
||||||
|
when ADDR5 => ra_q <= ADDR6;
|
||||||
|
when ADDR6 => ra_q <= ADDR7;
|
||||||
|
when ADDR7 => ra_q <= ADDR8;
|
||||||
|
when ADDR8 => ra_q <= ADDR9;
|
||||||
|
when ADDR9 => ra_q <= ADDR10;
|
||||||
|
when ADDR10 => ra_q <= ADDR11;
|
||||||
|
when ADDR11 => ra_q <= ADDR12;
|
||||||
|
when ADDR12 => ra_q <= ADDR13;
|
||||||
|
when ADDR13 => ra_q <= ADDR14;
|
||||||
|
when ADDR14 => ra_q <= ADDR15;
|
||||||
|
when others => ra_q <= ADDR0;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fdp_rst: FDP port map (C => clkx2, D => rst, PRE => rst, Q => rstsync);
|
||||||
|
fd_rstsync: FD port map (C => clkx2, D => rstsync, Q => rstsync_q);
|
||||||
|
fd_rstp: FD port map (C => clkx2, D => rstsync_q, Q => rstp);
|
||||||
|
sync_gen: FDR port map (Q => sync, C => clkx2, R => rstp, D => syncn);
|
||||||
|
syncn <= not sync;
|
||||||
|
|
||||||
|
fd_db: for I in 0 to 29 generate
|
||||||
|
fd_db_I: FDE port map (C => clkx2, D => data_int(I), CE => sync, Q => db(I));
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
mux <= db(14 downto 0) when sync = '0' else db(29 downto 15);
|
||||||
|
|
||||||
|
fd_out: for I in 0 to 14 generate
|
||||||
|
fd_outI: FD port map (C => clkx2, D => mux(I), Q => data_o(I));
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
end convert_30to15_fifo;
|
204
decoder.vhd
Normal file
204
decoder.vhd
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
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 decoder is
|
||||||
|
port (
|
||||||
|
rst_n : in std_logic; -- external reset input, e.g. reset button
|
||||||
|
pclk : in std_logic; -- pixel clock
|
||||||
|
pclkx2 : in std_logic; -- double pixel rate for gear box
|
||||||
|
pclkx10 : in std_logic; -- IOCLK
|
||||||
|
serdesstrobe_i : in std_logic; -- serdesstrobe for iserdes2
|
||||||
|
din_p : in std_logic; -- data from dvi cable
|
||||||
|
din_n : in std_logic; -- data from dvi cable
|
||||||
|
other_valid_i : in std_logic_vector(1 downto 0); -- other has valid data now
|
||||||
|
other_ready_i : in std_logic_vector(1 downto 0); -- other has detected a valid starting pixel
|
||||||
|
|
||||||
|
valid_o : out std_logic; -- I have valid data now
|
||||||
|
ready_o : out std_logic; -- I have detected a valid new pixel
|
||||||
|
psalgnerr : out std_logic; -- Phase alignment error
|
||||||
|
c0_o : out std_logic;
|
||||||
|
c1_o : out std_logic;
|
||||||
|
de_o : out std_logic;
|
||||||
|
sdout_o : out std_logic_vector(9 downto 0);
|
||||||
|
dout_o : out std_logic_vector(7 downto 0)
|
||||||
|
);
|
||||||
|
end decoder;
|
||||||
|
|
||||||
|
architecture decoder of decoder is
|
||||||
|
signal rst : std_logic;
|
||||||
|
signal rxclk : std_logic;
|
||||||
|
signal flipgear : std_logic;
|
||||||
|
signal flipgearx2 : std_logic;
|
||||||
|
signal toggle : std_logic;
|
||||||
|
signal rx_toggle : std_logic;
|
||||||
|
signal raw5bit : std_logic_vector(4 downto 0);
|
||||||
|
signal raw5bit_q : std_logic_vector(4 downto 0);
|
||||||
|
signal rawword : std_logic_vector(9 downto 0);
|
||||||
|
|
||||||
|
signal bitslipx2 : std_logic;
|
||||||
|
signal bitslip_q : std_logic;
|
||||||
|
signal bitslip : std_logic;
|
||||||
|
signal psaligned : std_logic;
|
||||||
|
|
||||||
|
signal rawdata : std_logic_vector(9 downto 0);
|
||||||
|
signal sdata : std_logic_vector(9 downto 0);
|
||||||
|
signal ready : std_logic;
|
||||||
|
signal c0 : std_logic;
|
||||||
|
signal c1 : std_logic;
|
||||||
|
signal de : std_logic;
|
||||||
|
signal dout : std_logic_vector(7 downto 0);
|
||||||
|
signal dout_c : std_logic_vector(7 downto 0);
|
||||||
|
signal sdout : std_logic_vector(9 downto 0);
|
||||||
|
signal data : std_logic_vector(7 downto 0);
|
||||||
|
begin
|
||||||
|
rst <= not rst_n;
|
||||||
|
valid_o <= psaligned;
|
||||||
|
ready_o <= ready;
|
||||||
|
c0_o <= c0;
|
||||||
|
c1_o <= c1;
|
||||||
|
de_o <= de;
|
||||||
|
dout_o <= dout;
|
||||||
|
sdout_o <= sdout;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- 5-bit to 10-bit gear box
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
rx_toggle <= toggle xor flipgearx2; -- reverse hi-lo position
|
||||||
|
|
||||||
|
process (pclkx2, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
toggle <= '0';
|
||||||
|
flipgearx2 <= '0';
|
||||||
|
raw5bit_q <= (others => '0');
|
||||||
|
elsif rising_edge(pclkx2) then
|
||||||
|
flipgearx2 <= flipgear;
|
||||||
|
raw5bit_q <= raw5bit;
|
||||||
|
toggle <= not toggle;
|
||||||
|
|
||||||
|
-- gear from 5 bit to 10 bit
|
||||||
|
if rx_toggle = '1' then
|
||||||
|
rawword <= raw5bit & raw5bit_q;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- bitslip signal sync to pclkx2
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
process (pclkx2, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
bitslip_q <= '0';
|
||||||
|
bitslipx2 <= '0';
|
||||||
|
elsif rising_edge(pclkx2) then
|
||||||
|
bitslip_q <= bitslip;
|
||||||
|
bitslipx2 <= bitslip and not bitslip_q;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- 1:5 de-serializer working at x2 pclk rate
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
des_0: entity work.serdes_1_to_5_diff_data
|
||||||
|
generic map (
|
||||||
|
DIFF_TERM => false,
|
||||||
|
BITSLIP_ENABLE => true
|
||||||
|
-- DIFF_TERM => "FALSE",
|
||||||
|
-- BITSLIP_ENABLE => "TRUE"
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
rst => rst,
|
||||||
|
gclk => pclkx2,
|
||||||
|
rxioclk_i => pclkx10,
|
||||||
|
datain_p => din_p,
|
||||||
|
datain_n => din_n,
|
||||||
|
use_phase_detector_i => '1',
|
||||||
|
rxserdesstrobe_i => serdesstrobe_i,
|
||||||
|
bitslip_i => bitslipx2,
|
||||||
|
data_o => raw5bit
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Doing word boundary detection here
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
rawdata <= rawword;
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Phase Alignment Instance
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
phsalgn_0: entity work.phsaligner
|
||||||
|
port map (
|
||||||
|
rst_n => rst_n,
|
||||||
|
clk => pclk,
|
||||||
|
sdata_i => rawdata,
|
||||||
|
bitslip_o => bitslip,
|
||||||
|
flipgear_o => flipgear,
|
||||||
|
psaligned_o => psaligned
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Per Channel De-skew Instance
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
cbnd: entity work.chnlbond
|
||||||
|
port map (
|
||||||
|
clk => pclk,
|
||||||
|
rst_n => rst_n,
|
||||||
|
rawdata_i => rawdata,
|
||||||
|
psaligned_i => psaligned,
|
||||||
|
other_valid_i => other_valid_i,
|
||||||
|
other_ready_i => other_ready_i,
|
||||||
|
ready_o => ready,
|
||||||
|
sdata_o => sdata
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- performs the 10B-8B decoding function defined in DVI 1.0
|
||||||
|
-- Specification: Section 3.3.3, Figure 3-6, page 31.
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
data <= not sdata(7 downto 0) when sdata(9) = '1' else sdata(7 downto 0);
|
||||||
|
dout_c(0) <= data(0);
|
||||||
|
dout_c(1) <= data(1) xor data(0) when sdata(8) = '1' else (data(1) xnor data(0));
|
||||||
|
dout_c(2) <= data(2) xor data(1) when sdata(8) = '1' else (data(2) xnor data(1));
|
||||||
|
dout_c(3) <= data(3) xor data(2) when sdata(8) = '1' else (data(3) xnor data(2));
|
||||||
|
dout_c(4) <= data(4) xor data(3) when sdata(8) = '1' else (data(4) xnor data(3));
|
||||||
|
dout_c(5) <= data(5) xor data(4) when sdata(8) = '1' else (data(5) xnor data(4));
|
||||||
|
dout_c(6) <= data(6) xor data(5) when sdata(8) = '1' else (data(6) xnor data(5));
|
||||||
|
dout_c(7) <= data(7) xor data(6) when sdata(8) = '1' else (data(7) xnor data(6));
|
||||||
|
process (pclk, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
c0 <= '0';
|
||||||
|
c1 <= '0';
|
||||||
|
de <= '0';
|
||||||
|
sdout <= (others => '0');
|
||||||
|
dout <= (others => '0');
|
||||||
|
elsif rising_edge(pclk) then
|
||||||
|
if ready = '1' and other_ready_i = "11" then
|
||||||
|
case sdata is
|
||||||
|
when CTRLTOKEN0 =>
|
||||||
|
c0 <= '0'; c1 <= '0'; de <= '0';
|
||||||
|
when CTRLTOKEN1 =>
|
||||||
|
c0 <= '1'; c1 <= '0'; de <= '0';
|
||||||
|
when CTRLTOKEN2 =>
|
||||||
|
c0 <= '0'; c1 <= '1'; de <= '0';
|
||||||
|
when CTRLTOKEN3 =>
|
||||||
|
c0 <= '1'; c1 <= '1'; de <= '0';
|
||||||
|
when others =>
|
||||||
|
dout <= dout_c; de <= '1';
|
||||||
|
end case;
|
||||||
|
sdout <= sdata;
|
||||||
|
else
|
||||||
|
c0 <= '0'; c1 <= '0'; de <= '0';
|
||||||
|
sdout <= (others => '0');
|
||||||
|
dout <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end decoder;
|
171
dvi_decoder.vhd
Normal file
171
dvi_decoder.vhd
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
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 dvi_decoder is
|
||||||
|
port (
|
||||||
|
ext_rst : in std_logic; -- external reset input, e.g. reset button
|
||||||
|
|
||||||
|
tmdsclk_p : in std_logic; -- tmds clock
|
||||||
|
tmdsclk_n : in std_logic; -- tmds clock
|
||||||
|
din_p : in std_logic_vector(COLOR_CNT-1 downto 0); -- data in
|
||||||
|
din_n : in std_logic_vector(COLOR_CNT-1 downto 0); -- data in
|
||||||
|
|
||||||
|
reset_n : out std_logic; -- rx reset_n
|
||||||
|
pclk_o : out std_logic; -- regenerated pixel clock
|
||||||
|
pclkx2_o : out std_logic; -- double rate pixel clock
|
||||||
|
pclkx10_o : out std_logic; -- 10x pixel as IOCLK
|
||||||
|
|
||||||
|
pll_lckd_o : out std_logic; -- send pll_lckd out so it can be fed into a different BUFPLL
|
||||||
|
serdesstrobe_o : out std_logic; -- BUFPLL serdesstrobe output
|
||||||
|
tmdsclk_o : out std_logic; -- TMDS cable clock
|
||||||
|
|
||||||
|
hsync_o : out std_logic; -- hsync data
|
||||||
|
vsync_o : out std_logic; -- vsync data
|
||||||
|
dat_en_o : out std_logic; -- data enable
|
||||||
|
valid_o : out std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
ready_o : out std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
psalgnerr_o : out std_logic;
|
||||||
|
sdout_o : out sdat_t(COLOR_CNT-1 downto 0);
|
||||||
|
color_o : out color_t(COLOR_CNT-1 downto 0) -- pixel data out
|
||||||
|
);
|
||||||
|
end dvi_decoder;
|
||||||
|
|
||||||
|
architecture dvi_decoder of dvi_decoder is
|
||||||
|
signal rst_n : std_logic;
|
||||||
|
signal rxclk_b : std_logic;
|
||||||
|
signal rxclk : std_logic;
|
||||||
|
signal clkfbout : std_logic;
|
||||||
|
signal pclk : std_logic;
|
||||||
|
signal pclkx2 : std_logic;
|
||||||
|
signal pclkx10 : std_logic;
|
||||||
|
signal pllclk0 : std_logic;
|
||||||
|
signal pllclk1 : std_logic;
|
||||||
|
signal pllclk2 : std_logic;
|
||||||
|
signal pll_locked : std_logic;
|
||||||
|
signal bufpll_lock : std_logic;
|
||||||
|
signal serdesstrobe : std_logic;
|
||||||
|
|
||||||
|
signal ready : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
signal hsync : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
signal vsync : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
signal valid : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
type matrix_t is array (natural range <>) of std_logic_vector(COLOR_CNT-2 downto 0);
|
||||||
|
signal other_ready : matrix_t(COLOR_CNT-1 downto 0);
|
||||||
|
signal other_valid : matrix_t(COLOR_CNT-1 downto 0);
|
||||||
|
signal psalgnerr : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
signal dat_en : std_logic_vector(COLOR_CNT-1 downto 0);
|
||||||
|
begin
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- I/O mapping
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
rst_n <= bufpll_lock;
|
||||||
|
reset_n <= rst_n;
|
||||||
|
pclk_o <= pclk;
|
||||||
|
pclkx2_o <= pclkx2;
|
||||||
|
pclkx10_o <= pclkx10;
|
||||||
|
pll_lckd_o <= pll_locked;
|
||||||
|
serdesstrobe_o <= serdesstrobe;
|
||||||
|
valid_o <= valid;
|
||||||
|
ready_o <= ready;
|
||||||
|
psalgnerr_o <= psalgnerr(RED) or psalgnerr(GREEN) or psalgnerr(BLUE);
|
||||||
|
dat_en_o <= dat_en(BLUE);
|
||||||
|
hsync_o <= hsync(BLUE);
|
||||||
|
vsync_o <= vsync(BLUE);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- clocking
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
ibuf_rxclk: IBUFDS
|
||||||
|
generic map ( IOSTANDARD => "TMDS_33", DIFF_TERM => false )
|
||||||
|
port map ( i => tmdsclk_p, ib => tmdsclk_n, o => rxclk_b );
|
||||||
|
|
||||||
|
bufio_tmdsclk_0: BUFIO2
|
||||||
|
generic map ( DIVIDE_BYPASS => true, DIVIDE => 1 )
|
||||||
|
port map ( DIVCLK => rxclk, IOCLK => open, SERDESSTROBE => open, I => rxclk_b );
|
||||||
|
|
||||||
|
tmdsclk_bufg: BUFG port map (I => rxclk, O => tmdsclk_o);
|
||||||
|
|
||||||
|
-- PLL is used to generate three clocks:
|
||||||
|
-- 1. pclk: same rate as TMDS clock
|
||||||
|
-- 2. pclkx2: double rate of pclk used for 5:10 soft gear box and ISERDES DIVCLK
|
||||||
|
-- 3. pclkx10: 10x rate of pclk used as IO clock
|
||||||
|
PLL_ISERDES: PLL_BASE
|
||||||
|
generic map (
|
||||||
|
CLKIN_PERIOD => 10.0,
|
||||||
|
CLKFBOUT_MULT => 10, -- set VCO to 10x of CLKIN
|
||||||
|
CLKOUT0_DIVIDE => 1,
|
||||||
|
CLKOUT1_DIVIDE => 10,
|
||||||
|
CLKOUT2_DIVIDE => 5,
|
||||||
|
COMPENSATION => "INTERNAL"
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
CLKFBOUT => clkfbout,
|
||||||
|
CLKOUT0 => pllclk0,
|
||||||
|
CLKOUT1 => pllclk1,
|
||||||
|
CLKOUT2 => pllclk2,
|
||||||
|
CLKOUT3 => open,
|
||||||
|
CLKOUT4 => open,
|
||||||
|
CLKOUT5 => open,
|
||||||
|
LOCKED => pll_locked,
|
||||||
|
CLKFBIN => clkfbout,
|
||||||
|
CLKIN => rxclk,
|
||||||
|
RST => ext_rst
|
||||||
|
);
|
||||||
|
|
||||||
|
--Pixel Rate clock buffer
|
||||||
|
pclkbufg: BUFG port map ( I => pllclk1, O => pclk);
|
||||||
|
-- 2x pclk is going to be used to drive IOSERDES2 DIVCLK
|
||||||
|
pclkx2bufg: BUFG port map (I => pllclk2, O => pclkx2);
|
||||||
|
|
||||||
|
-- 10x pclk is used to drive IOCLK network so a bit rate reference
|
||||||
|
-- can be used by IOSERDES2
|
||||||
|
ioclk_buf: BUFPLL
|
||||||
|
generic map( DIVIDE => 5 )
|
||||||
|
port map (
|
||||||
|
PLLIN => pllclk0,
|
||||||
|
GCLK => pclkx2,
|
||||||
|
LOCKED => pll_locked,
|
||||||
|
IOCLK => pclkx10,
|
||||||
|
SERDESSTROBE => serdesstrobe,
|
||||||
|
LOCK => bufpll_lock
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- decoder mapping
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
other_valid(RED) <= valid(BLUE) & valid(GREEN);
|
||||||
|
other_valid(GREEN) <= valid(BLUE) & valid(RED);
|
||||||
|
other_valid(BLUE) <= valid(RED) & valid(GREEN);
|
||||||
|
other_ready(RED) <= ready(BLUE) & ready(GREEN);
|
||||||
|
other_ready(GREEN) <= ready(BLUE) & ready(RED);
|
||||||
|
other_ready(BLUE) <= ready(RED) & ready(GREEN);
|
||||||
|
dec: for I in 0 to COLOR_CNT-1 generate
|
||||||
|
decoder: entity work.decoder
|
||||||
|
port map (
|
||||||
|
rst_n => rst_n,
|
||||||
|
pclk => pclk,
|
||||||
|
pclkx2 => pclkx2,
|
||||||
|
pclkx10 => pclkx10,
|
||||||
|
serdesstrobe_i => serdesstrobe,
|
||||||
|
din_p => din_p(I),
|
||||||
|
din_n => din_n(I),
|
||||||
|
other_valid_i => other_valid(I),
|
||||||
|
other_ready_i => other_ready(I),
|
||||||
|
|
||||||
|
valid_o => valid(I),
|
||||||
|
ready_o => ready(I),
|
||||||
|
psalgnerr => psalgnerr(I),
|
||||||
|
c0_o => hsync(I),
|
||||||
|
c1_o => vsync(I),
|
||||||
|
de_o => dat_en(I),
|
||||||
|
sdout_o => sdout_o(I),
|
||||||
|
dout_o => color_o(I)
|
||||||
|
);
|
||||||
|
end generate dec;
|
||||||
|
|
||||||
|
end dvi_decoder;
|
111
dvi_encoder.vhd
Normal file
111
dvi_encoder.vhd
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
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 dvi_encoder is
|
||||||
|
port (
|
||||||
|
rst_n : in std_logic; -- external reset input, e.g. reset button
|
||||||
|
pclk : in std_logic; -- pixel clock
|
||||||
|
pclkx2 : in std_logic; -- double pixel rate for gear box
|
||||||
|
pclkx10 : in std_logic; -- IOCLK
|
||||||
|
serdesstrobe_i : in std_logic; -- serdesstrobe for iserdes2
|
||||||
|
color_i : in color_t(COLOR_CNT-1 downto 0); -- pixel data out
|
||||||
|
hsync_i : in std_logic; -- hsync data
|
||||||
|
vsync_i : in std_logic; -- vsync data
|
||||||
|
dat_en_i : in std_logic; -- data enable
|
||||||
|
tmds_p : out std_logic_vector(3 downto 0); -- tmds
|
||||||
|
tmds_n : out std_logic_vector(3 downto 0) -- tmds
|
||||||
|
);
|
||||||
|
end dvi_encoder;
|
||||||
|
|
||||||
|
architecture dvi_encoder of dvi_encoder is
|
||||||
|
signal rst : std_logic;
|
||||||
|
signal toggle : std_logic;
|
||||||
|
signal tmdsclkint : std_logic_vector(4 downto 0);
|
||||||
|
signal data : sdat_t(COLOR_CNT-1 downto 0);
|
||||||
|
signal sdata : std_logic_vector(29 downto 0);
|
||||||
|
type data_5bit_t is array(natural range <>) of std_logic_vector(4 downto 0);
|
||||||
|
signal tmds_data : data_5bit_t(3 downto 0);
|
||||||
|
signal tmdsint : std_logic_vector(3 downto 0);
|
||||||
|
signal tmds_clk : std_logic;
|
||||||
|
begin
|
||||||
|
rst <= not rst_n;
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Forward TMDS Clock Using OSERDES2 block
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
process (pclkx2, rst_n)
|
||||||
|
begin
|
||||||
|
if rst_n = '0' then
|
||||||
|
toggle <= '0';
|
||||||
|
tmdsclkint <= (others => '0');
|
||||||
|
elsif rising_edge(pclkx2) then
|
||||||
|
toggle <= not toggle;
|
||||||
|
if toggle = '1' then
|
||||||
|
tmdsclkint <= (others => '1');
|
||||||
|
else
|
||||||
|
tmdsclkint <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
clkout: entity work.serdes_n_to_1
|
||||||
|
generic map (SF => 5)
|
||||||
|
port map (
|
||||||
|
ioclk => pclkx10,
|
||||||
|
gclk => pclkx2,
|
||||||
|
rst => rst,
|
||||||
|
serdesstrobe_i => serdesstrobe_i,
|
||||||
|
data_i => tmdsclkint,
|
||||||
|
data_o => tmds_clk
|
||||||
|
);
|
||||||
|
|
||||||
|
TMDS3: OBUFDS port map (I => tmds_clk, O => tmds_p(3), OB => tmds_n(3)); -- clock
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Forward TMDS Data: 3 channels
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
forward: for I in 0 to COLOR_CNT-1 generate
|
||||||
|
oserdes_I: entity work.serdes_n_to_1
|
||||||
|
generic map (SF => 5)
|
||||||
|
port map (
|
||||||
|
ioclk => pclkx10,
|
||||||
|
gclk => pclkx2,
|
||||||
|
rst => rst,
|
||||||
|
serdesstrobe_i => serdesstrobe_i,
|
||||||
|
data_i => tmds_data(I),
|
||||||
|
data_o => tmdsint(I)
|
||||||
|
);
|
||||||
|
|
||||||
|
TMDS_I: OBUFDS port map (I => tmdsint(I), O => tmds_p(I), OB => tmds_n(I));
|
||||||
|
|
||||||
|
enc_I: entity work.encoder
|
||||||
|
port map (
|
||||||
|
clk => pclk,
|
||||||
|
rst_n => rst_n,
|
||||||
|
data_i => color_i(I),
|
||||||
|
c0 => hsync_i,
|
||||||
|
c1 => vsync_i,
|
||||||
|
de => dat_en_i,
|
||||||
|
data_o => data(I)
|
||||||
|
);
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
sdata <= data(RED)(9 downto 5) & data(GREEN)(9 downto 5) & data(BLUE)(9 downto 5)
|
||||||
|
& data(RED)(4 downto 0) & data(GREEN)(4 downto 0) & data(BLUE)(4 downto 0);
|
||||||
|
|
||||||
|
pixel2x: entity work.convert_30to15_fifo
|
||||||
|
port map (
|
||||||
|
rst => rst,
|
||||||
|
clk => pclk,
|
||||||
|
clkx2 => pclkx2,
|
||||||
|
data_i => sdata,
|
||||||
|
data_o(14 downto 10) => tmds_data(2),
|
||||||
|
data_o( 9 downto 5) => tmds_data(1),
|
||||||
|
data_o( 4 downto 0) => tmds_data(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
end dvi_encoder;
|
18
dvi_package.vhd
Normal file
18
dvi_package.vhd
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package dvi_package is
|
||||||
|
constant COLOR_CNT : integer := 3;
|
||||||
|
constant RED : natural := 2;
|
||||||
|
constant GREEN : natural := 1;
|
||||||
|
constant BLUE : natural := 0;
|
||||||
|
|
||||||
|
constant CTRLTOKEN0 : std_logic_vector(9 downto 0) := "1101010100";
|
||||||
|
constant CTRLTOKEN1 : std_logic_vector(9 downto 0) := "0010101011";
|
||||||
|
constant CTRLTOKEN2 : std_logic_vector(9 downto 0) := "0101010100";
|
||||||
|
constant CTRLTOKEN3 : std_logic_vector(9 downto 0) := "1010101011";
|
||||||
|
|
||||||
|
type sdat_t is array (natural range <>) of std_logic_vector(9 downto 0);
|
||||||
|
type color_t is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||||
|
end package;
|
179
encoder.vhd
Normal file
179
encoder.vhd
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
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;
|
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;
|
320
serdes_1_to_5_diff_data.vhd
Normal file
320
serdes_1_to_5_diff_data.vhd
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library UNISIM;
|
||||||
|
use UNISIM.Vcomponents.all;
|
||||||
|
|
||||||
|
entity serdes_1_to_5_diff_data is
|
||||||
|
generic (
|
||||||
|
DIFF_TERM : boolean := true;
|
||||||
|
SIM_TAP_DELAY : integer := 49;
|
||||||
|
BITSLIP_ENABLE : boolean := false );
|
||||||
|
port (
|
||||||
|
rst : in std_logic; -- Reset line
|
||||||
|
gclk : in std_logic; -- Global clock
|
||||||
|
rxioclk_i : in std_logic; -- IO Clock network
|
||||||
|
datain_p : in std_logic; -- Input from LVDS receiver pin
|
||||||
|
datain_n : in std_logic; -- Input from LVDS receiver pin
|
||||||
|
use_phase_detector_i : in std_logic; -- '1' enables the phase detector logic
|
||||||
|
rxserdesstrobe_i : in std_logic; -- Parallel data capture strobe
|
||||||
|
bitslip_i : in std_logic; -- Bitslip control line
|
||||||
|
data_o : out std_logic_vector(4 downto 0) -- Output data
|
||||||
|
);
|
||||||
|
end serdes_1_to_5_diff_data;
|
||||||
|
|
||||||
|
architecture serdes_1_to_5_diff_data of serdes_1_to_5_diff_data is
|
||||||
|
type sm_cal_t is (IDLE, CALIBRATE, IODELAY_RST, IODELAY_WAIT,
|
||||||
|
IODELAY_WAIT_OCCASIONAL_ENABLE, CAL_SLAVE,
|
||||||
|
WAIT_COMMAND_ACCEPTED, IODELAY_WAIT_ALL);
|
||||||
|
signal sm_cal : sm_cal_t;
|
||||||
|
|
||||||
|
signal cal_cnt : unsigned(8 downto 0);
|
||||||
|
signal cal_enable : std_logic;
|
||||||
|
signal data_in : std_logic;
|
||||||
|
signal data_cal_master : std_logic;
|
||||||
|
signal data_cal_sint : std_logic;
|
||||||
|
signal data_busy : std_logic;
|
||||||
|
signal data_busy_q : std_logic;
|
||||||
|
signal data_rst : std_logic;
|
||||||
|
signal data_flag : std_logic;
|
||||||
|
signal data_ce : std_logic;
|
||||||
|
signal data_inc : std_logic;
|
||||||
|
signal data_ce_int : std_logic;
|
||||||
|
signal data_valid : std_logic;
|
||||||
|
signal data_valid_q : std_logic;
|
||||||
|
signal data_incdec : std_logic;
|
||||||
|
signal data_incdec_q : std_logic;
|
||||||
|
signal pdcounter : unsigned(4 downto 0);
|
||||||
|
signal ddly_s : std_logic;
|
||||||
|
signal ddly_m : std_logic;
|
||||||
|
signal pd_edge : std_logic;
|
||||||
|
signal cascade : std_logic;
|
||||||
|
begin
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- IDELAY Calibration FSM
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
process (gclk, rst)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
sm_cal <= IDLE;
|
||||||
|
cal_cnt <= (others => '0');
|
||||||
|
cal_enable <= '0';
|
||||||
|
data_cal_master <= '0';
|
||||||
|
data_cal_sint <= '0';
|
||||||
|
data_rst <= '0';
|
||||||
|
elsif rising_edge(gclk) then
|
||||||
|
cal_cnt <= cal_cnt + 1;
|
||||||
|
if cal_cnt(8) = '1' then
|
||||||
|
cal_cnt <= (others => '0');
|
||||||
|
end if;
|
||||||
|
cal_enable <= cal_enable;
|
||||||
|
if cal_cnt(5) = '1' then
|
||||||
|
cal_enable <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case sm_cal is
|
||||||
|
when IDLE =>
|
||||||
|
if cal_enable = '1' then
|
||||||
|
data_cal_master <= '0';
|
||||||
|
data_cal_sint <= '0';
|
||||||
|
data_rst <= '0';
|
||||||
|
if data_busy_q = '0' then
|
||||||
|
sm_cal <= CALIBRATE;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when CALIBRATE =>
|
||||||
|
data_cal_master <= '1';
|
||||||
|
data_cal_sint <= '1';
|
||||||
|
if data_busy_q = '1' then
|
||||||
|
sm_cal <= IODELAY_RST;
|
||||||
|
end if;
|
||||||
|
when IODELAY_RST =>
|
||||||
|
data_cal_master <= '0';
|
||||||
|
data_cal_sint <= '0';
|
||||||
|
if data_busy_q = '0' then
|
||||||
|
data_rst <= '1';
|
||||||
|
sm_cal <= IODELAY_WAIT;
|
||||||
|
end if;
|
||||||
|
when IODELAY_WAIT =>
|
||||||
|
data_rst <= '0';
|
||||||
|
if data_busy_q = '0' then
|
||||||
|
sm_cal <= IODELAY_WAIT_OCCASIONAL_ENABLE;
|
||||||
|
end if;
|
||||||
|
when IODELAY_WAIT_OCCASIONAL_ENABLE =>
|
||||||
|
if cal_cnt(8) = '1' then
|
||||||
|
sm_cal <= CAL_SLAVE;
|
||||||
|
end if;
|
||||||
|
when CAL_SLAVE =>
|
||||||
|
if data_busy_q = '0' then
|
||||||
|
data_cal_sint <= '1';
|
||||||
|
sm_cal <= WAIT_COMMAND_ACCEPTED;
|
||||||
|
end if;
|
||||||
|
when WAIT_COMMAND_ACCEPTED =>
|
||||||
|
data_cal_sint <= '0';
|
||||||
|
if data_busy_q = '1' then
|
||||||
|
sm_cal <= IODELAY_WAIT_ALL;
|
||||||
|
end if;
|
||||||
|
when IODELAY_WAIT_ALL =>
|
||||||
|
data_cal_sint <= '0';
|
||||||
|
if data_busy_q = '0' then
|
||||||
|
sm_cal <= IODELAY_WAIT_OCCASIONAL_ENABLE;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Per-bit phase detection state machine
|
||||||
|
process (gclk, rst)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
data_busy_q <= '0';
|
||||||
|
data_flag <= '0';
|
||||||
|
pdcounter <= "10000";
|
||||||
|
elsif rising_edge(gclk) then
|
||||||
|
data_busy_q <= data_busy;
|
||||||
|
|
||||||
|
if use_phase_detector_i = '1' then
|
||||||
|
data_incdec_q <= data_incdec;
|
||||||
|
data_valid_q <= data_valid;
|
||||||
|
|
||||||
|
if data_ce_int = '1' then
|
||||||
|
data_ce <= '1';
|
||||||
|
else
|
||||||
|
data_ce <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if sm_cal = IODELAY_WAIT_ALL then
|
||||||
|
data_flag <= '0';
|
||||||
|
elsif sm_cal /= IODELAY_WAIT_OCCASIONAL_ENABLE or data_busy_q = '1' then
|
||||||
|
-- Reset filter if state machine issues a cal command or unit is busy
|
||||||
|
pdcounter <= "10000";
|
||||||
|
data_ce_int <= '0';
|
||||||
|
elsif pdcounter = "11111" and data_flag = '0' then
|
||||||
|
-- Filter has reached positive max - increment the tap count
|
||||||
|
data_ce_int <= '1';
|
||||||
|
data_inc <= '1';
|
||||||
|
data_flag <= '1';
|
||||||
|
pdcounter <= "10000";
|
||||||
|
elsif pdcounter = "00000" and data_flag = '0' then
|
||||||
|
-- Filter has reached negative max - decrement the tap count
|
||||||
|
data_ce_int <= '1';
|
||||||
|
data_inc <= '0';
|
||||||
|
data_flag <= '1';
|
||||||
|
pdcounter <= "10000";
|
||||||
|
elsif data_valid_q = '1' then
|
||||||
|
-- increment filter
|
||||||
|
data_ce_int <= '0';
|
||||||
|
if data_incdec_q = '1' and pdcounter /= "11111" then
|
||||||
|
pdcounter <= pdcounter + "00001";
|
||||||
|
elsif data_incdec_q = '0' and pdcounter /= "00000" then
|
||||||
|
-- decrement filter
|
||||||
|
pdcounter <= pdcounter + "11111";
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
data_ce_int <= '0';
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
data_ce <= '0';
|
||||||
|
--data_inc <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
data_in_0: IBUFDS
|
||||||
|
generic map ( DIFF_TERM => DIFF_TERM )
|
||||||
|
port map ( I => datain_p, IB => datain_n, O => data_in );
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Master IDELAY
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
iodelay_m: IODELAY2
|
||||||
|
generic map (
|
||||||
|
DATA_RATE => "SDR",
|
||||||
|
IDELAY_VALUE => 0,
|
||||||
|
IDELAY2_VALUE => 0,
|
||||||
|
IDELAY_MODE => "NORMAL",
|
||||||
|
ODELAY_VALUE => 0,
|
||||||
|
IDELAY_TYPE => "DIFF_PHASE_DETECTOR",
|
||||||
|
COUNTER_WRAPAROUND => "STAY_AT_LIMIT", --("WRAPAROUND"),
|
||||||
|
DELAY_SRC => "IDATAIN",
|
||||||
|
SERDES_MODE => "MASTER",
|
||||||
|
SIM_TAPDELAY_VALUE => SIM_TAP_DELAY)
|
||||||
|
port map (
|
||||||
|
IDATAIN => data_in, -- data from IBUFDS
|
||||||
|
TOUT => open, -- tri-state signal to IOB
|
||||||
|
DOUT => open, -- output data to IOB
|
||||||
|
T => '1', -- tri-state control from OLOGIC/OSERDES2
|
||||||
|
ODATAIN => '0', -- data from OLOGIC/OSERDES2
|
||||||
|
DATAOUT => ddly_m, -- Output data 1 to ILOGIC/ISERDES2
|
||||||
|
DATAOUT2 => open, -- Output data 2 to ILOGIC/ISERDES2
|
||||||
|
IOCLK0 => rxioclk_i, -- High speed clock for calibration
|
||||||
|
IOCLK1 => '0', -- High speed clock for calibration
|
||||||
|
CLK => gclk, -- Fabric clock (GCLK) for control signals
|
||||||
|
CAL => data_cal_master, -- Calibrate control signal
|
||||||
|
INC => data_inc, -- Increment counter
|
||||||
|
CE => data_ce, -- Clock Enable
|
||||||
|
RST => data_rst, -- Reset delay line
|
||||||
|
BUSY => open -- output signal indicating sync circuit has finished / calibration has finished
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Slave IDELAY
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
iodelay_s: IODELAY2
|
||||||
|
generic map (
|
||||||
|
DATA_RATE => "SDR",
|
||||||
|
IDELAY_VALUE => 0,
|
||||||
|
IDELAY2_VALUE => 0,
|
||||||
|
IDELAY_MODE => "NORMAL",
|
||||||
|
ODELAY_VALUE => 0,
|
||||||
|
IDELAY_TYPE => "DIFF_PHASE_DETECTOR",
|
||||||
|
COUNTER_WRAPAROUND => "WRAPAROUND",
|
||||||
|
DELAY_SRC => "IDATAIN",
|
||||||
|
SERDES_MODE => "SLAVE",
|
||||||
|
SIM_TAPDELAY_VALUE => SIM_TAP_DELAY)
|
||||||
|
port map (
|
||||||
|
IDATAIN => data_in, -- data from IBUFDS
|
||||||
|
TOUT => open, -- tri-state signal to IOB
|
||||||
|
DOUT => open, -- output data to IOB
|
||||||
|
T => '1', -- tri-state control from OLOGIC/OSERDES2
|
||||||
|
ODATAIN => '0', -- data from OLOGIC/OSERDES2
|
||||||
|
DATAOUT => ddly_s, -- Slave output data to ILOGIC/ISERDES2
|
||||||
|
DATAOUT2 => open, --
|
||||||
|
IOCLK0 => rxioclk_i, -- High speed IO clock for calibration
|
||||||
|
IOCLK1 => '0',
|
||||||
|
CLK => gclk, -- Fabric clock (GCLK) for control signals
|
||||||
|
CAL => data_cal_sint, -- Calibrate control signal
|
||||||
|
INC => data_inc, -- Increment counter
|
||||||
|
CE => data_ce, -- Clock Enable
|
||||||
|
RST => data_rst, -- Reset delay line
|
||||||
|
BUSY => data_busy -- output signal indicating sync circuit has finished / calibration has finished
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Master ISERDES
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
iserdes_m: ISERDES2
|
||||||
|
generic map (
|
||||||
|
DATA_WIDTH => 5,
|
||||||
|
DATA_RATE => "SDR",
|
||||||
|
BITSLIP_ENABLE => BITSLIP_ENABLE,
|
||||||
|
SERDES_MODE => "MASTER",
|
||||||
|
INTERFACE_TYPE => "RETIMED")
|
||||||
|
port map (
|
||||||
|
D => ddly_m,
|
||||||
|
CE0 => '1',
|
||||||
|
CLK0 => rxioclk_i,
|
||||||
|
CLK1 => '0',
|
||||||
|
IOCE => rxserdesstrobe_i,
|
||||||
|
RST => rst,
|
||||||
|
CLKDIV => gclk,
|
||||||
|
SHIFTIN => pd_edge,
|
||||||
|
BITSLIP => bitslip_i,
|
||||||
|
FABRICOUT => open,
|
||||||
|
Q4 => data_o(4),
|
||||||
|
Q3 => data_o(3),
|
||||||
|
Q2 => data_o(2),
|
||||||
|
Q1 => data_o(1),
|
||||||
|
DFB => open,
|
||||||
|
CFB0 => open,
|
||||||
|
CFB1 => open,
|
||||||
|
VALID => data_valid,
|
||||||
|
INCDEC => data_incdec,
|
||||||
|
SHIFTOUT => cascade
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
-- Slave ISERDES
|
||||||
|
-- ----------------------------------------------------------
|
||||||
|
iserdes_s: ISERDES2
|
||||||
|
generic map (
|
||||||
|
DATA_WIDTH => 5,
|
||||||
|
DATA_RATE => "SDR",
|
||||||
|
BITSLIP_ENABLE => BITSLIP_ENABLE,
|
||||||
|
SERDES_MODE => "SLAVE",
|
||||||
|
INTERFACE_TYPE => "RETIMED")
|
||||||
|
port map (
|
||||||
|
D => ddly_s,
|
||||||
|
CE0 => '1',
|
||||||
|
CLK0 => rxioclk_i,
|
||||||
|
CLK1 => '0',
|
||||||
|
IOCE => rxserdesstrobe_i,
|
||||||
|
RST => rst,
|
||||||
|
CLKDIV => gclk,
|
||||||
|
SHIFTIN => cascade,
|
||||||
|
BITSLIP => bitslip_i,
|
||||||
|
FABRICOUT => open,
|
||||||
|
Q4 => data_o(0),
|
||||||
|
Q3 => open,
|
||||||
|
Q2 => open,
|
||||||
|
Q1 => open,
|
||||||
|
DFB => open,
|
||||||
|
CFB0 => open,
|
||||||
|
CFB1 => open,
|
||||||
|
VALID => open,
|
||||||
|
INCDEC => open,
|
||||||
|
SHIFTOUT => pd_edge
|
||||||
|
);
|
||||||
|
|
||||||
|
end serdes_1_to_5_diff_data;
|
108
serdes_n_to_1.vhd
Normal file
108
serdes_n_to_1.vhd
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
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 serdes_n_to_1 is
|
||||||
|
generic ( SF : integer := 0 );
|
||||||
|
port (
|
||||||
|
ioclk : in std_logic;
|
||||||
|
gclk : in std_logic;
|
||||||
|
rst : in std_logic;
|
||||||
|
serdesstrobe_i : in std_logic;
|
||||||
|
data_i : in std_logic_vector(SF-1 downto 0);
|
||||||
|
data_o : out std_logic
|
||||||
|
);
|
||||||
|
end serdes_n_to_1;
|
||||||
|
|
||||||
|
architecture serdes_n_to_1 of serdes_n_to_1 is
|
||||||
|
signal cascade_di : std_logic;
|
||||||
|
signal cascade_do : std_logic;
|
||||||
|
signal cascade_ti : std_logic;
|
||||||
|
signal cascade_to : std_logic;
|
||||||
|
signal mdatain : std_logic_vector(8 downto 0);
|
||||||
|
begin
|
||||||
|
datir: for I in 0 to SF-1 generate
|
||||||
|
mdatain(I) <= data_i(I);
|
||||||
|
end generate;
|
||||||
|
dati0: for I in SF to 8 generate
|
||||||
|
mdatain(I) <= '0';
|
||||||
|
end generate;
|
||||||
|
|
||||||
|
oserdes_m: OSERDES2
|
||||||
|
generic map (
|
||||||
|
DATA_WIDTH => SF, -- SERDES word width. This should match the setting is BUFPLL
|
||||||
|
DATA_RATE_OQ => "SDR", -- <SDR>, DDR
|
||||||
|
DATA_RATE_OT => "SDR", -- <SDR>, DDR
|
||||||
|
SERDES_MODE => "MASTER", -- <DEFAULT>, MASTER, SLAVE
|
||||||
|
OUTPUT_MODE => "DIFFERENTIAL"
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
OQ => data_o,
|
||||||
|
OCE => '1',
|
||||||
|
CLK0 => ioclk,
|
||||||
|
CLK1 => '0',
|
||||||
|
IOCE => serdesstrobe_i,
|
||||||
|
RST => rst,
|
||||||
|
CLKDIV => gclk,
|
||||||
|
D4 => mdatain(7),
|
||||||
|
D3 => mdatain(6),
|
||||||
|
D2 => mdatain(5),
|
||||||
|
D1 => mdatain(4),
|
||||||
|
TQ => open,
|
||||||
|
T1 => '0',
|
||||||
|
T2 => '0',
|
||||||
|
T3 => '0',
|
||||||
|
T4 => '0',
|
||||||
|
TRAIN => '0',
|
||||||
|
TCE => '1',
|
||||||
|
SHIFTIN1 => '1', -- Dummy input in Master
|
||||||
|
SHIFTIN2 => '1', -- Dummy input in Master
|
||||||
|
SHIFTIN3 => cascade_do, -- Cascade output D data from slave
|
||||||
|
SHIFTIN4 => cascade_to, -- Cascade output T data from slave
|
||||||
|
SHIFTOUT1 => cascade_di, -- Cascade input D data to slave
|
||||||
|
SHIFTOUT2 => cascade_ti, -- Cascade input T data to slave
|
||||||
|
SHIFTOUT3 => open, -- Dummy output in Master
|
||||||
|
SHIFTOUT4 => open -- Dummy output in Master
|
||||||
|
);
|
||||||
|
|
||||||
|
oserdes_s: OSERDES2
|
||||||
|
generic map (
|
||||||
|
DATA_WIDTH => SF, -- SERDES word width. This should match the setting is BUFPLL
|
||||||
|
DATA_RATE_OQ => "SDR", -- <SDR>, DDR
|
||||||
|
DATA_RATE_OT => "SDR", -- <SDR>, DDR
|
||||||
|
SERDES_MODE => "SLAVE", -- <DEFAULT>, MASTER, SLAVE
|
||||||
|
OUTPUT_MODE => "DIFFERENTIAL"
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
OQ => open,
|
||||||
|
OCE => '1',
|
||||||
|
CLK0 => ioclk,
|
||||||
|
CLK1 => '0',
|
||||||
|
IOCE => serdesstrobe_i,
|
||||||
|
RST => rst,
|
||||||
|
CLKDIV => gclk,
|
||||||
|
D4 => mdatain(3),
|
||||||
|
D3 => mdatain(2),
|
||||||
|
D2 => mdatain(1),
|
||||||
|
D1 => mdatain(0),
|
||||||
|
TQ => open,
|
||||||
|
T1 => '0',
|
||||||
|
T2 => '0',
|
||||||
|
T3 => '0',
|
||||||
|
T4 => '0',
|
||||||
|
TRAIN => '0',
|
||||||
|
TCE => '1',
|
||||||
|
SHIFTIN1 => cascade_di, -- Cascade input D from Master
|
||||||
|
SHIFTIN2 => cascade_ti, -- Cascade input T from Master
|
||||||
|
SHIFTIN3 => '1', -- Dummy input in Slave
|
||||||
|
SHIFTIN4 => '1', -- Dummy input in Slave
|
||||||
|
SHIFTOUT1 => open, -- Dummy output in Slave
|
||||||
|
SHIFTOUT2 => open, -- Dummy output in Slave
|
||||||
|
SHIFTOUT3 => cascade_do, -- Cascade output D data to Master
|
||||||
|
SHIFTOUT4 => cascade_to -- Cascade output T data to Master
|
||||||
|
);
|
||||||
|
end serdes_n_to_1;
|
Loading…
Reference in New Issue
Block a user