initial commit

This commit is contained in:
Benjamin Krill 2013-09-23 10:20:49 +02:00
commit 2e79b67236
11 changed files with 1672 additions and 0 deletions

42
DRAM16XN.vhd Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;