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