Алга 0 25 июля, 2016 Опубликовано 25 июля, 2016 · Жалоба Есть и другой у Xilinx AN, например Xapp495. xapp495.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Алга 0 25 июля, 2016 Опубликовано 25 июля, 2016 (изменено) · Жалоба У Альтеры как пример AN-236 AN-236 Изменено 25 июля, 2016 пользователем Алга Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 27 июля, 2016 Опубликовано 27 июля, 2016 · Жалоба посмотрите, может подойдет: dvi_in.vhd ---------------------------------------------------------------------------------- -- -- Module Name: dvi_in.vhd - Behavioral -- -- Description: Design to capture raw DVI-D input -- -- REALLY IMPORTANT NOTE - on my PCB some of the + and - differential -- pairs are transposed to allow better routing and avioding vias. -- You most likely want to change the value of "invert" on the gearbox -- instances. -- -- I've also got do do some work to automatically adjust the phase of the -- bit clocks, at the moment it needs to be manually tuned to match your source ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all; entity dvi_in is Port ( clk32 : in STD_LOGIC; hdmi_clk_p : in STD_LOGIC; hdmi_clk_n : in STD_LOGIC; hdmi_c0_p : in STD_LOGIC; hdmi_c0_n : in STD_LOGIC; hdmi_c1_p : in STD_LOGIC; hdmi_c1_n : in STD_LOGIC; hdmi_c2_p : in STD_LOGIC; hdmi_c2_n : in STD_LOGIC; hdmi_sclk : inout STD_LOGIC; hdmi_sdat : inout STD_LOGIC; red : out std_logic_vector(2 downto 0); green : out std_logic_vector(2 downto 0); blue : out std_logic_vector(1 downto 0); hsync : out std_logic; vsync : out std_logic; btns : in std_logic_vector(3 downto 0); leds : out std_logic_vector(3 downto 0)); end dvi_in; architecture Behavioral of dvi_in is signal hdmi_clk : std_logic; signal hdmi_clk_buffered : std_logic; signal ioclock : std_logic; signal serdes_strobe : std_logic; signal clock_x1 : std_logic; signal clock_x2 : std_logic; signal clock_x10 : std_logic; signal clock_x10_unbuffered : std_logic; signal clock_x2_unbuffered : std_logic; signal clock_x1_unbuffered : std_logic; signal clk_feedback : std_logic; signal pll_locked : std_logic; signal sync_seen : std_logic; signal c0_d : std_logic_vector(7 downto 0); signal c0_c : std_logic_vector(1 downto 0); signal c0_active : std_logic; signal c1_d : std_logic_vector(7 downto 0); signal c1_c : std_logic_vector(1 downto 0); signal c1_active : std_logic; signal c2_d : std_logic_vector(7 downto 0); signal c2_c : std_logic_vector(1 downto 0); signal c2_active : std_logic; signal led_count : unsigned( 2 downto 0) := (others => '0'); signal framing : std_logic_vector(3 downto 0) := (others => '0'); signal since_sync : unsigned(14 downto 0) := (others => '0'); signal start_calibrate : std_logic; signal reset_delay : std_logic; signal cal_start_count : unsigned(7 downto 0) := (others => '0'); COMPONENT input_channel GENERIC( fixed_delay : in natural ); PORT( clk_fabric : IN std_logic; clk_fabric_x2 : IN std_logic; clk_input : IN std_logic; strobe : IN std_logic; tmds_p : in STD_LOGIC; tmds_n : in STD_LOGIC; invert : IN std_logic; framing : IN std_logic_vector(3 downto 0); data_out : OUT std_logic_vector(7 downto 0); control : OUT std_logic_vector(1 downto 0); active_data : OUT std_logic; sync_seen : OUT std_logic; adjust_delay : IN std_logic; increase_delay : IN std_logic; reset_delay : IN std_logic; start_calibrate : IN std_logic; calibrate_busy : OUT std_logic ); END COMPONENT; begin ---------------------------------- -- Output the decoded VGA signals ---------------------------------- red <= c0_d(7 downto 5); blue <= c1_d(7 downto 6); green <= c2_d(7 downto 5); hsync <= c2_c(0); vsync <= c2_c(1); ---------------------------------- -- Debug ---------------------------------- leds <= framing; ---------------------------------- -- EDID I2C signals (not implemented) ---------------------------------- hdmi_sclk <= '1'; hdmi_sdat <= '1'; ------------------------------------------ -- Receive the differential clock ------------------------------------------ clk_diff_input : IBUFDS generic map ( DIFF_TERM => FALSE, IBUF_LOW_PWR => TRUE, IOSTANDARD => "TMDS_33") port map ( O => hdmi_clk, I => hdmi_clk_p, IB => hdmi_clk_n ); ------------------------------------------ -- Buffer it before the PLL ------------------------------------------ BUFG_clk : BUFG port map ( I => hdmi_clk, O => hdmi_clk_buffered); ------------------------------------------ -- Generate the bit clocks for the serdes -- -- Adjust the phase in a 10:2:1 ratio (e.g. 50:10:5) ------------------------------------------ PLL_BASE_inst : PLL_BASE generic map ( CLKFBOUT_MULT => 10, -- Almost works with Western Digital Live @ 720p/60 -Noise on blue channel. --CLKOUT0_DIVIDE => 1, CLKOUT0_PHASE => 200.0, -- Output 10x original frequency --CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 40.0, -- Output 2x original frequency --CLKOUT2_DIVIDE => 10, CLKOUT2_PHASE => 20.0, -- Output 1x original frequency -- Works with Western Digital Live @ 640x480/60Hz CLKOUT0_DIVIDE => 1, CLKOUT0_PHASE => 0.0, -- Output 10x original frequency CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 0.0, -- Output 2x original frequency CLKOUT2_DIVIDE => 10, CLKOUT2_PHASE => 0.0, -- Output 1x original frequency CLK_FEEDBACK => "CLKFBOUT", -- Clock source to drive CLKFBIN ("CLKFBOUT" or "CLKOUT0") CLKIN_PERIOD => 10.0, -- IMPORTANT! Approx 77 MHz DIVCLK_DIVIDE => 1 -- Division value for all output clocks (1-52) ) port map ( CLKFBOUT => clk_feedback, CLKOUT0 => clock_x10_unbuffered, CLKOUT1 => clock_x2_unbuffered, CLKOUT2 => clock_x1_unbuffered, CLKOUT3 => open, CLKOUT4 => open, CLKOUT5 => open, LOCKED => pll_locked, CLKFBIN => clk_feedback, CLKIN => hdmi_clk_buffered, RST => '0' -- 1-bit input: Reset input ); BUFG_pclockx2 : BUFG port map ( I => clock_x2_unbuffered, O => clock_x2); BUFG_pclock : BUFG port map ( I => clock_x1_unbuffered, O => clock_x1); BUFG_pclockx10 : BUFG port map ( I => clock_x10_unbuffered, O => clock_x10 ); ------------------------------------------------ -- Buffer the clocks ready to go the serialisers ------------------------------------------------ BUFPLL_inst : BUFPLL generic map ( DIVIDE => 5, -- DIVCLK divider (1-8) !!!! IMPORTANT TO CHANGE THIS AS NEEDED !!!! ENABLE_SYNC => TRUE -- Enable synchrnonization between PLL and GCLK (TRUE/FALSE) -- should be true ) port map ( IOCLK => ioclock, -- Clock used to receive bits LOCK => open, SERDESSTROBE => serdes_strobe, -- Clock use to load data into SERDES GCLK => clock_x2, -- Global clock use as a reference for serdes_strobe LOCKED => pll_locked, -- When the upstream PLL is locked PLLIN => clock_x10_unbuffered -- Clock to use for bit capture - this must be unbuffered ); ---------------------------------------- -- c0 channel input - Carries the RED channel ---------------------------------------- input_channel_c0: input_channel GENERIC MAP( fixed_delay => 30 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c0_p, tmds_n => hdmi_c0_n, invert => '0', framing => framing, data_out => c0_d, control => c0_c, active_data => c0_active, sync_seen => open, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); ---------------------------------------- -- c1 channel input - Carries the BLUE channel ---------------------------------------- input_channel_c1: input_channel GENERIC MAP( fixed_delay => 40 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c1_n, tmds_n => hdmi_c1_p, invert => '1', framing => framing, data_out => c1_d, control => c1_c, active_data => c1_active, sync_seen => open, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); ---------------------------------------- -- c2 channel input - Carries the GREEN channel and syncs ---------------------------------------- input_channel_c2: input_channel GENERIC MAP( fixed_delay => 30 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c2_n, tmds_n => hdmi_c2_p, invert => '1', framing => framing, data_out => c2_d, control => c2_c, active_data => c2_active, sync_seen => sync_seen, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); calibrate_preocess: process (clock_x2) begin if rising_edge(clock_x2) then if cal_start_count = "10000000" then start_calibrate <= '0'; else start_calibrate <= '0'; end if; if cal_start_count = "11111100" then reset_delay <= '0'; else reset_delay <= '0'; end if; if cal_start_count /= "11111111" then cal_start_count <= cal_start_count + 1; end if; end if; end process; process(clock_x1) begin if rising_edge(clock_x1) then -- Work out what we need to do to frame the TMDS data correctly if sync_seen = '1' then ------------------------------------------------------------ -- We've just seen a sync codeword, so restart the counter -- This means that we are in sync ------------------------------------------------------------ since_sync <= (others => '0'); elsif since_sync = "111111111111111" then ------------------------------------------------------------ -- We haven't seen a sync in 16383 pixel cycles, so it can't -- be in sync. By incrementing 'framing' we bitslip one bit. -- -- The 16k number is special, as they two sync codewords -- being looked for will not be seen during the VSYNC period -- (assuming that you are looking in the channel that -- includes the encoded HSYNC/VSYNC signals ------------------------------------------------------------ if framing = "1001" then framing <= (others =>'0'); else framing <= std_logic_vector(unsigned(framing) + 1); end if; since_sync <= since_sync + 1; else ------------------------------------------------------------ -- Keep counting and hoping for a sync codeword ------------------------------------------------------------ since_sync <= since_sync + 1; end if; end if; end process; end Behavioral; input_channel.vhd ---------------------------------------------------------------------------------- -- -- Module Name: input_channel - Behavioral -- Description: The end-to-end processing of a TMDS input channel -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; library UNISIM; use UNISIM.VComponents.all; entity input_channel is GENERIC( fixed_delay : in natural ); Port ( clk_fabric : in STD_LOGIC; clk_fabric_x2 : in STD_LOGIC; clk_input : in STD_LOGIC; strobe : in STD_LOGIC; tmds_p : in STD_LOGIC; tmds_n : in STD_LOGIC; invert : in STD_LOGIC; framing : in std_logic_vector(3 downto 0); data_out : out STD_LOGIC_VECTOR (7 downto 0); control : out STD_LOGIC_VECTOR (1 downto 0); active_data : out std_logic; sync_seen : out std_logic; adjust_delay : IN std_logic; increase_delay : IN std_logic; reset_delay : IN std_logic; start_calibrate : IN std_logic; calibrate_busy : OUT std_logic ); end input_channel; architecture Behavioral of input_channel is COMPONENT input_serialiser PORT( clk_fabric_x2 : IN std_logic; clk_input : IN std_logic; strobe : IN std_logic; ser_input : IN std_logic; ser_data : OUT std_logic_vector(4 downto 0) ); END COMPONENT; COMPONENT gearbox PORT( clk_fabric_x2 : IN std_logic; framing : IN std_logic_vector(3 downto 0); invert : IN std_logic; data_in : IN std_logic_vector(4 downto 0); data_out : OUT std_logic_vector(9 downto 0) ); END COMPONENT; COMPONENT tmds_decode PORT( clk : IN std_logic; data_in : IN std_logic_vector(9 downto 0); data_out : OUT std_logic_vector(7 downto 0); c : OUT std_logic_vector(1 downto 0); active_data : OUT std_logic ); END COMPONENT; signal serial_data : std_logic; signal raw_tmds_word : std_logic_vector(9 downto 0); signal half_words : std_logic_vector(4 downto 0); begin diff_input : IBUFDS generic map ( DIFF_TERM => FALSE, IBUF_LOW_PWR => TRUE, IOSTANDARD => "TMDS_33") port map ( O => serial_data, I => tmds_p, IB => tmds_n ); i_input_serialiser: input_serialiser PORT MAP( clk_fabric_x2 => clk_fabric_x2, clk_input => clk_input, strobe => strobe, ser_input => serial_data, ser_data => half_words ); i_gearbox: gearbox PORT MAP( clk_fabric_x2 => clk_fabric_x2, invert => invert, framing => framing, data_in => half_words, data_out => raw_tmds_word ); i_tmds_decode: tmds_decode PORT MAP( clk => clk_fabric, data_in => raw_tmds_word, data_out => data_out, c => control, active_data => active_data ); look_for_sync: process (clk_fabric) begin if rising_edge(clk_fabric) then ------------------------------------------------------------ -- Is the TMDS data one of two special sync codewords? ------------------------------------------------------------ if raw_tmds_word = "1101010100" or raw_tmds_word = "0010101011" then sync_seen <= '1'; else sync_seen <= '0'; end if; end if; end process; end Behavioral; gearbox.vhd This 'gearbox' takes 5-bit data at 2x the pixel clock, and converts it to 10-bit data at the pixel clock. ---------------------------------------------------------------------------------- -- -- Module Name: Gearbox - Behavioral -- Project Name: DVI-I Input -- Description: Receives the 5-bits-per-cycle data from the serialisers at twice -- the pixel clock, then 'downshifts' the data to 10-bit words. -- -- The 'framing' signal allows to bit-slip to different word -- framing, allowing the design to hunt for the sync codewords. -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity gearbox is Port ( clk_fabric_x2 : in STD_LOGIC; invert : in STD_LOGIC; framing : in std_logic_vector(3 downto 0); data_in : in std_logic_vector(4 downto 0); data_out : out std_logic_vector(9 downto 0)); end gearbox; architecture Behavioral of gearbox is signal every_other : std_logic := '0'; signal joined : std_logic_vector(14 downto 0); begin process(clk_fabric_x2) begin if rising_edge(clk_fabric_x2) then if every_other = '1' then case framing is when "0000" => data_out <= joined( 9 downto 0); when "0001" => data_out <= joined(10 downto 1); when "0010" => data_out <= joined(11 downto 2); when "0011" => data_out <= joined(12 downto 3); when "0100" => data_out <= joined(13 downto 4); when others => NULL; end case; else case framing is when "0101" => data_out <= joined( 9 downto 0); when "0110" => data_out <= joined(10 downto 1); when "0111" => data_out <= joined(11 downto 2); when "1000" => data_out <= joined(12 downto 3); when "1001" => data_out <= joined(13 downto 4); when others => NULL; end case; end if; if invert = '1' then joined <= data_in & joined(joined'high downto 5) ; else joined <= (data_in xor "11111") & joined(joined'high downto 5) ; end if; every_other <= not every_other; end if; end process; end Behavioral; tmds_decode.vhd ---------------------------------------------------------------------------------- -- -- Module Name: tmds_decode - Behavioral -- -- Description: TMDS decode as per Digital Display Working Groups Digital Visual -- Interface Revision 1.0 section 3.3.3 -- -- This doesn't seem 100% correct - "elsif sometimes_inverted(8) = '0' then" should -- be "elsif sometimes_inverted(8) = '1' then" according to the standard. -- -- However it does actually work! ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity tmds_decode is Port ( clk : in STD_LOGIC; data_in : in STD_LOGIC_VECTOR (9 downto 0); data_out : out STD_LOGIC_VECTOR (7 downto 0); c : out STD_LOGIC_VECTOR (1 downto 0); active_data : out std_logic); end tmds_decode; architecture Behavioral of tmds_decode is signal data_delayed : STD_LOGIC_VECTOR(9 downto 0); signal sometimes_inverted : STD_LOGIC_VECTOR(8 downto 0); signal next_c : STD_LOGIC_VECTOR(1 downto 0); signal next_active_data : STD_LOGIC; begin process(clk) begin if rising_edge(clk) then c <= next_c; active_data <= next_active_data; if next_active_data = '0' then data_out <= (others => '0'); elsif sometimes_inverted(8) = '0' then data_out(0) <= sometimes_inverted(0); data_out(1) <= sometimes_inverted(1) XOR sometimes_inverted(0); data_out(2) <= sometimes_inverted(2) XOR sometimes_inverted(1); data_out(3) <= sometimes_inverted(3) XOR sometimes_inverted(2); data_out(4) <= sometimes_inverted(4) XOR sometimes_inverted(3); data_out(5) <= sometimes_inverted(5) XOR sometimes_inverted(4); data_out(6) <= sometimes_inverted(6) XOR sometimes_inverted(5); data_out(7) <= sometimes_inverted(7) XOR sometimes_inverted(6); else data_out(0) <= sometimes_inverted(0); data_out(1) <= sometimes_inverted(1) XNOR sometimes_inverted(0); data_out(2) <= sometimes_inverted(2) XNOR sometimes_inverted(1); data_out(3) <= sometimes_inverted(3) XNOR sometimes_inverted(2); data_out(4) <= sometimes_inverted(4) XNOR sometimes_inverted(3); data_out(5) <= sometimes_inverted(5) XNOR sometimes_inverted(4); data_out(6) <= sometimes_inverted(6) XNOR sometimes_inverted(5); data_out(7) <= sometimes_inverted(7) XNOR sometimes_inverted(6); end if; if data_delayed(9) = '1' then sometimes_inverted <= data_delayed(8 downto 0) xor "011111111"; else sometimes_inverted <= data_delayed(8 downto 0); end if; case data_in is when "0010101011" => next_c <= "01"; next_active_data <= '0'; when "1101010100" => next_c <= "00"; next_active_data <= '0'; when "0101010100" => next_c <= "10"; next_active_data <= '0'; when "1010101011" => next_c <= "11"; next_active_data <= '0'; when others => next_c <= "00"; next_active_data <= '1'; end case; data_delayed <= data_in; end if; end process; end Behavioral; input_serialiser.vhd ---------------------------------------------------------------------------------- -- -- Module Name: input_serialiser -- -- Description: A 5-bits per cycle SDR input serialiser -- -- Maybe in the future the 'bitslip' funciton can be implemented. ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; library UNISIM; use UNISIM.VComponents.all; entity input_serialiser is Port ( clk_fabric_x2 : in STD_LOGIC; clk_input : in STD_LOGIC; strobe : in STD_LOGIC; ser_data : out STD_LOGIC_VECTOR (4 downto 0); ser_input : in STD_LOGIC); end input_serialiser; architecture Behavioral of input_serialiser is signal clk0, clk1, clkdiv : std_logic; signal cascade : std_logic; signal bitslip : std_logic := '0'; begin clkdiv <= clk_fabric_x2; clk0 <= clk_input; clk1 <= '0'; ISERDES2_master : ISERDES2 generic map ( BITSLIP_ENABLE => TRUE, -- Enable Bitslip Functionality (TRUE/FALSE) DATA_RATE => "SDR", -- Data-rate ("SDR" or "DDR") DATA_WIDTH => 5, -- Parallel data width selection (2-8) INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" SERDES_MODE => "MASTER" -- "NONE", "MASTER" or "SLAVE" ) port map ( CFB0 => open, -- 1-bit output: Clock feed-through route output CFB1 => open, -- 1-bit output: Clock feed-through route output DFB => open, -- 1-bit output: Feed-through clock output FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output INCDEC => open, -- 1-bit output: Phase detector output -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic Q1 => ser_data(1), Q2 => ser_data(2), Q3 => ser_data(3), Q4 => ser_data(4), SHIFTOUT => cascade, -- 1-bit output: Cascade output signal for master/slave I/O VALID => open, -- 1-bit output: Output status of the phase detector BITSLIP => bitslip , -- 1-bit input: Bitslip enable input CE0 => '1', -- 1-bit input: Clock enable input CLK0 => clk0, -- 1-bit input: I/O clock network input CLK1 => clk1, -- 1-bit input: Secondary I/O clock network input CLKDIV => clkdiv, -- 1-bit input: FPGA logic domain clock input D => ser_input, -- 1-bit input: Input data IOCE => strobe, -- 1-bit input: Data strobe input RST => '0', -- 1-bit input: Asynchronous reset input SHIFTIN => '0' -- 1-bit input: Cascade input signal for master/slave I/O ); ISERDES2_slave : ISERDES2 generic map ( BITSLIP_ENABLE => TRUE, -- Enable Bitslip Functionality (TRUE/FALSE) DATA_RATE => "SDR", -- Data-rate ("SDR" or "DDR") DATA_WIDTH => 5, -- Parallel data width selection (2-8) INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" SERDES_MODE => "SLAVE" -- "NONE", "MASTER" or "SLAVE" ) port map ( CFB0 => open, -- 1-bit output: Clock feed-through route output CFB1 => open, -- 1-bit output: Clock feed-through route output DFB => open, -- 1-bit output: Feed-through clock output FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output INCDEC => open, -- 1-bit output: Phase detector output -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic Q1 => open, Q2 => open, Q3 => open, Q4 => ser_data(0), SHIFTOUT => open, -- 1-bit output: Cascade output signal for master/slave I/O VALID => open, -- 1-bit output: Output status of the phase detector BITSLIP => bitslip, -- 1-bit input: Bitslip enable input CE0 => '1', -- 1-bit input: Clock enable input CLK0 => clk0, -- 1-bit input: I/O clock network input CLK1 => clk1, -- 1-bit input: Secondary I/O clock network input CLKDIV => clkdiv, -- 1-bit input: FPGA logic domain clock input D => '0', -- 1-bit input: Input data IOCE => '1', -- 1-bit input: Data strobe input RST => '0', -- 1-bit input: Asynchronous reset input SHIFTIN => cascade -- 1-bit input: Cascade input signal for master/slave I/O ); end Behavioral; At the moment it can receive 720p in DVI-D format and display it on an Analogue VGA output. With the Spartan 6 FPGA you need external termination resistors if you want to receive TMDS signals - a 50 ohm resistor is needed from 3.3 V to each of the signal lines. Also the Extended Display Identification Data (EDID) interface runs at 5V logic, so a level converter is needed. The revision 0.1 PCB has an error on it, so I've got a v0.2 on its way. It is missing the 3.3V supply to the I2C level translator (D'oh!). It needs eight 50 Ohm (or slightly bigger) resistors, and an HDMI socket. If you want to use EDID support you will need to add a wire bodge to power the level translator. I'm actually surprised that it actually worked - the three channels are running at 750 Mb/s each, and the termination resistors are quite far from the FPGA - in fact it is the other side of a 0.1" header! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 27 июля, 2016 Опубликовано 27 июля, 2016 · Жалоба посмотрите, может подойдет: dvi_in.vhd ---------------------------------------------------------------------------------- -- -- Module Name: dvi_in.vhd - Behavioral -- -- Description: Design to capture raw DVI-D input -- -- REALLY IMPORTANT NOTE - on my PCB some of the + and - differential -- pairs are transposed to allow better routing and avioding vias. -- You most likely want to change the value of "invert" on the gearbox -- instances. -- -- I've also got do do some work to automatically adjust the phase of the -- bit clocks, at the moment it needs to be manually tuned to match your source ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all; entity dvi_in is Port ( clk32 : in STD_LOGIC; hdmi_clk_p : in STD_LOGIC; hdmi_clk_n : in STD_LOGIC; hdmi_c0_p : in STD_LOGIC; hdmi_c0_n : in STD_LOGIC; hdmi_c1_p : in STD_LOGIC; hdmi_c1_n : in STD_LOGIC; hdmi_c2_p : in STD_LOGIC; hdmi_c2_n : in STD_LOGIC; hdmi_sclk : inout STD_LOGIC; hdmi_sdat : inout STD_LOGIC; red : out std_logic_vector(2 downto 0); green : out std_logic_vector(2 downto 0); blue : out std_logic_vector(1 downto 0); hsync : out std_logic; vsync : out std_logic; btns : in std_logic_vector(3 downto 0); leds : out std_logic_vector(3 downto 0)); end dvi_in; architecture Behavioral of dvi_in is signal hdmi_clk : std_logic; signal hdmi_clk_buffered : std_logic; signal ioclock : std_logic; signal serdes_strobe : std_logic; signal clock_x1 : std_logic; signal clock_x2 : std_logic; signal clock_x10 : std_logic; signal clock_x10_unbuffered : std_logic; signal clock_x2_unbuffered : std_logic; signal clock_x1_unbuffered : std_logic; signal clk_feedback : std_logic; signal pll_locked : std_logic; signal sync_seen : std_logic; signal c0_d : std_logic_vector(7 downto 0); signal c0_c : std_logic_vector(1 downto 0); signal c0_active : std_logic; signal c1_d : std_logic_vector(7 downto 0); signal c1_c : std_logic_vector(1 downto 0); signal c1_active : std_logic; signal c2_d : std_logic_vector(7 downto 0); signal c2_c : std_logic_vector(1 downto 0); signal c2_active : std_logic; signal led_count : unsigned( 2 downto 0) := (others => '0'); signal framing : std_logic_vector(3 downto 0) := (others => '0'); signal since_sync : unsigned(14 downto 0) := (others => '0'); signal start_calibrate : std_logic; signal reset_delay : std_logic; signal cal_start_count : unsigned(7 downto 0) := (others => '0'); COMPONENT input_channel GENERIC( fixed_delay : in natural ); PORT( clk_fabric : IN std_logic; clk_fabric_x2 : IN std_logic; clk_input : IN std_logic; strobe : IN std_logic; tmds_p : in STD_LOGIC; tmds_n : in STD_LOGIC; invert : IN std_logic; framing : IN std_logic_vector(3 downto 0); data_out : OUT std_logic_vector(7 downto 0); control : OUT std_logic_vector(1 downto 0); active_data : OUT std_logic; sync_seen : OUT std_logic; adjust_delay : IN std_logic; increase_delay : IN std_logic; reset_delay : IN std_logic; start_calibrate : IN std_logic; calibrate_busy : OUT std_logic ); END COMPONENT; begin ---------------------------------- -- Output the decoded VGA signals ---------------------------------- red <= c0_d(7 downto 5); blue <= c1_d(7 downto 6); green <= c2_d(7 downto 5); hsync <= c2_c(0); vsync <= c2_c(1); ---------------------------------- -- Debug ---------------------------------- leds <= framing; ---------------------------------- -- EDID I2C signals (not implemented) ---------------------------------- hdmi_sclk <= '1'; hdmi_sdat <= '1'; ------------------------------------------ -- Receive the differential clock ------------------------------------------ clk_diff_input : IBUFDS generic map ( DIFF_TERM => FALSE, IBUF_LOW_PWR => TRUE, IOSTANDARD => "TMDS_33") port map ( O => hdmi_clk, I => hdmi_clk_p, IB => hdmi_clk_n ); ------------------------------------------ -- Buffer it before the PLL ------------------------------------------ BUFG_clk : BUFG port map ( I => hdmi_clk, O => hdmi_clk_buffered); ------------------------------------------ -- Generate the bit clocks for the serdes -- -- Adjust the phase in a 10:2:1 ratio (e.g. 50:10:5) ------------------------------------------ PLL_BASE_inst : PLL_BASE generic map ( CLKFBOUT_MULT => 10, -- Almost works with Western Digital Live @ 720p/60 -Noise on blue channel. --CLKOUT0_DIVIDE => 1, CLKOUT0_PHASE => 200.0, -- Output 10x original frequency --CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 40.0, -- Output 2x original frequency --CLKOUT2_DIVIDE => 10, CLKOUT2_PHASE => 20.0, -- Output 1x original frequency -- Works with Western Digital Live @ 640x480/60Hz CLKOUT0_DIVIDE => 1, CLKOUT0_PHASE => 0.0, -- Output 10x original frequency CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 0.0, -- Output 2x original frequency CLKOUT2_DIVIDE => 10, CLKOUT2_PHASE => 0.0, -- Output 1x original frequency CLK_FEEDBACK => "CLKFBOUT", -- Clock source to drive CLKFBIN ("CLKFBOUT" or "CLKOUT0") CLKIN_PERIOD => 10.0, -- IMPORTANT! Approx 77 MHz DIVCLK_DIVIDE => 1 -- Division value for all output clocks (1-52) ) port map ( CLKFBOUT => clk_feedback, CLKOUT0 => clock_x10_unbuffered, CLKOUT1 => clock_x2_unbuffered, CLKOUT2 => clock_x1_unbuffered, CLKOUT3 => open, CLKOUT4 => open, CLKOUT5 => open, LOCKED => pll_locked, CLKFBIN => clk_feedback, CLKIN => hdmi_clk_buffered, RST => '0' -- 1-bit input: Reset input ); BUFG_pclockx2 : BUFG port map ( I => clock_x2_unbuffered, O => clock_x2); BUFG_pclock : BUFG port map ( I => clock_x1_unbuffered, O => clock_x1); BUFG_pclockx10 : BUFG port map ( I => clock_x10_unbuffered, O => clock_x10 ); ------------------------------------------------ -- Buffer the clocks ready to go the serialisers ------------------------------------------------ BUFPLL_inst : BUFPLL generic map ( DIVIDE => 5, -- DIVCLK divider (1-8) !!!! IMPORTANT TO CHANGE THIS AS NEEDED !!!! ENABLE_SYNC => TRUE -- Enable synchrnonization between PLL and GCLK (TRUE/FALSE) -- should be true ) port map ( IOCLK => ioclock, -- Clock used to receive bits LOCK => open, SERDESSTROBE => serdes_strobe, -- Clock use to load data into SERDES GCLK => clock_x2, -- Global clock use as a reference for serdes_strobe LOCKED => pll_locked, -- When the upstream PLL is locked PLLIN => clock_x10_unbuffered -- Clock to use for bit capture - this must be unbuffered ); ---------------------------------------- -- c0 channel input - Carries the RED channel ---------------------------------------- input_channel_c0: input_channel GENERIC MAP( fixed_delay => 30 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c0_p, tmds_n => hdmi_c0_n, invert => '0', framing => framing, data_out => c0_d, control => c0_c, active_data => c0_active, sync_seen => open, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); ---------------------------------------- -- c1 channel input - Carries the BLUE channel ---------------------------------------- input_channel_c1: input_channel GENERIC MAP( fixed_delay => 40 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c1_n, tmds_n => hdmi_c1_p, invert => '1', framing => framing, data_out => c1_d, control => c1_c, active_data => c1_active, sync_seen => open, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); ---------------------------------------- -- c2 channel input - Carries the GREEN channel and syncs ---------------------------------------- input_channel_c2: input_channel GENERIC MAP( fixed_delay => 30 ) PORT MAP( clk_fabric => clock_x1, clk_fabric_x2 => clock_x2, clk_input => ioclock, strobe => serdes_strobe, tmds_p => hdmi_c2_n, tmds_n => hdmi_c2_p, invert => '1', framing => framing, data_out => c2_d, control => c2_c, active_data => c2_active, sync_seen => sync_seen, adjust_delay => '0', increase_delay => '0', reset_delay => reset_delay, start_calibrate => start_calibrate, calibrate_busy => open ); calibrate_preocess: process (clock_x2) begin if rising_edge(clock_x2) then if cal_start_count = "10000000" then start_calibrate <= '0'; else start_calibrate <= '0'; end if; if cal_start_count = "11111100" then reset_delay <= '0'; else reset_delay <= '0'; end if; if cal_start_count /= "11111111" then cal_start_count <= cal_start_count + 1; end if; end if; end process; process(clock_x1) begin if rising_edge(clock_x1) then -- Work out what we need to do to frame the TMDS data correctly if sync_seen = '1' then ------------------------------------------------------------ -- We've just seen a sync codeword, so restart the counter -- This means that we are in sync ------------------------------------------------------------ since_sync <= (others => '0'); elsif since_sync = "111111111111111" then ------------------------------------------------------------ -- We haven't seen a sync in 16383 pixel cycles, so it can't -- be in sync. By incrementing 'framing' we bitslip one bit. -- -- The 16k number is special, as they two sync codewords -- being looked for will not be seen during the VSYNC period -- (assuming that you are looking in the channel that -- includes the encoded HSYNC/VSYNC signals ------------------------------------------------------------ if framing = "1001" then framing <= (others =>'0'); else framing <= std_logic_vector(unsigned(framing) + 1); end if; since_sync <= since_sync + 1; else ------------------------------------------------------------ -- Keep counting and hoping for a sync codeword ------------------------------------------------------------ since_sync <= since_sync + 1; end if; end if; end process; end Behavioral; input_channel.vhd ---------------------------------------------------------------------------------- -- -- Module Name: input_channel - Behavioral -- Description: The end-to-end processing of a TMDS input channel -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; library UNISIM; use UNISIM.VComponents.all; entity input_channel is GENERIC( fixed_delay : in natural ); Port ( clk_fabric : in STD_LOGIC; clk_fabric_x2 : in STD_LOGIC; clk_input : in STD_LOGIC; strobe : in STD_LOGIC; tmds_p : in STD_LOGIC; tmds_n : in STD_LOGIC; invert : in STD_LOGIC; framing : in std_logic_vector(3 downto 0); data_out : out STD_LOGIC_VECTOR (7 downto 0); control : out STD_LOGIC_VECTOR (1 downto 0); active_data : out std_logic; sync_seen : out std_logic; adjust_delay : IN std_logic; increase_delay : IN std_logic; reset_delay : IN std_logic; start_calibrate : IN std_logic; calibrate_busy : OUT std_logic ); end input_channel; architecture Behavioral of input_channel is COMPONENT input_serialiser PORT( clk_fabric_x2 : IN std_logic; clk_input : IN std_logic; strobe : IN std_logic; ser_input : IN std_logic; ser_data : OUT std_logic_vector(4 downto 0) ); END COMPONENT; COMPONENT gearbox PORT( clk_fabric_x2 : IN std_logic; framing : IN std_logic_vector(3 downto 0); invert : IN std_logic; data_in : IN std_logic_vector(4 downto 0); data_out : OUT std_logic_vector(9 downto 0) ); END COMPONENT; COMPONENT tmds_decode PORT( clk : IN std_logic; data_in : IN std_logic_vector(9 downto 0); data_out : OUT std_logic_vector(7 downto 0); c : OUT std_logic_vector(1 downto 0); active_data : OUT std_logic ); END COMPONENT; signal serial_data : std_logic; signal raw_tmds_word : std_logic_vector(9 downto 0); signal half_words : std_logic_vector(4 downto 0); begin diff_input : IBUFDS generic map ( DIFF_TERM => FALSE, IBUF_LOW_PWR => TRUE, IOSTANDARD => "TMDS_33") port map ( O => serial_data, I => tmds_p, IB => tmds_n ); i_input_serialiser: input_serialiser PORT MAP( clk_fabric_x2 => clk_fabric_x2, clk_input => clk_input, strobe => strobe, ser_input => serial_data, ser_data => half_words ); i_gearbox: gearbox PORT MAP( clk_fabric_x2 => clk_fabric_x2, invert => invert, framing => framing, data_in => half_words, data_out => raw_tmds_word ); i_tmds_decode: tmds_decode PORT MAP( clk => clk_fabric, data_in => raw_tmds_word, data_out => data_out, c => control, active_data => active_data ); look_for_sync: process (clk_fabric) begin if rising_edge(clk_fabric) then ------------------------------------------------------------ -- Is the TMDS data one of two special sync codewords? ------------------------------------------------------------ if raw_tmds_word = "1101010100" or raw_tmds_word = "0010101011" then sync_seen <= '1'; else sync_seen <= '0'; end if; end if; end process; end Behavioral; gearbox.vhd This 'gearbox' takes 5-bit data at 2x the pixel clock, and converts it to 10-bit data at the pixel clock. ---------------------------------------------------------------------------------- -- -- Module Name: Gearbox - Behavioral -- Project Name: DVI-I Input -- Description: Receives the 5-bits-per-cycle data from the serialisers at twice -- the pixel clock, then 'downshifts' the data to 10-bit words. -- -- The 'framing' signal allows to bit-slip to different word -- framing, allowing the design to hunt for the sync codewords. -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity gearbox is Port ( clk_fabric_x2 : in STD_LOGIC; invert : in STD_LOGIC; framing : in std_logic_vector(3 downto 0); data_in : in std_logic_vector(4 downto 0); data_out : out std_logic_vector(9 downto 0)); end gearbox; architecture Behavioral of gearbox is signal every_other : std_logic := '0'; signal joined : std_logic_vector(14 downto 0); begin process(clk_fabric_x2) begin if rising_edge(clk_fabric_x2) then if every_other = '1' then case framing is when "0000" => data_out <= joined( 9 downto 0); when "0001" => data_out <= joined(10 downto 1); when "0010" => data_out <= joined(11 downto 2); when "0011" => data_out <= joined(12 downto 3); when "0100" => data_out <= joined(13 downto 4); when others => NULL; end case; else case framing is when "0101" => data_out <= joined( 9 downto 0); when "0110" => data_out <= joined(10 downto 1); when "0111" => data_out <= joined(11 downto 2); when "1000" => data_out <= joined(12 downto 3); when "1001" => data_out <= joined(13 downto 4); when others => NULL; end case; end if; if invert = '1' then joined <= data_in & joined(joined'high downto 5) ; else joined <= (data_in xor "11111") & joined(joined'high downto 5) ; end if; every_other <= not every_other; end if; end process; end Behavioral; tmds_decode.vhd ---------------------------------------------------------------------------------- -- -- Module Name: tmds_decode - Behavioral -- -- Description: TMDS decode as per Digital Display Working Groups Digital Visual -- Interface Revision 1.0 section 3.3.3 -- -- This doesn't seem 100% correct - "elsif sometimes_inverted(8) = '0' then" should -- be "elsif sometimes_inverted(8) = '1' then" according to the standard. -- -- However it does actually work! ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity tmds_decode is Port ( clk : in STD_LOGIC; data_in : in STD_LOGIC_VECTOR (9 downto 0); data_out : out STD_LOGIC_VECTOR (7 downto 0); c : out STD_LOGIC_VECTOR (1 downto 0); active_data : out std_logic); end tmds_decode; architecture Behavioral of tmds_decode is signal data_delayed : STD_LOGIC_VECTOR(9 downto 0); signal sometimes_inverted : STD_LOGIC_VECTOR(8 downto 0); signal next_c : STD_LOGIC_VECTOR(1 downto 0); signal next_active_data : STD_LOGIC; begin process(clk) begin if rising_edge(clk) then c <= next_c; active_data <= next_active_data; if next_active_data = '0' then data_out <= (others => '0'); elsif sometimes_inverted(8) = '0' then data_out(0) <= sometimes_inverted(0); data_out(1) <= sometimes_inverted(1) XOR sometimes_inverted(0); data_out(2) <= sometimes_inverted(2) XOR sometimes_inverted(1); data_out(3) <= sometimes_inverted(3) XOR sometimes_inverted(2); data_out(4) <= sometimes_inverted(4) XOR sometimes_inverted(3); data_out(5) <= sometimes_inverted(5) XOR sometimes_inverted(4); data_out(6) <= sometimes_inverted(6) XOR sometimes_inverted(5); data_out(7) <= sometimes_inverted(7) XOR sometimes_inverted(6); else data_out(0) <= sometimes_inverted(0); data_out(1) <= sometimes_inverted(1) XNOR sometimes_inverted(0); data_out(2) <= sometimes_inverted(2) XNOR sometimes_inverted(1); data_out(3) <= sometimes_inverted(3) XNOR sometimes_inverted(2); data_out(4) <= sometimes_inverted(4) XNOR sometimes_inverted(3); data_out(5) <= sometimes_inverted(5) XNOR sometimes_inverted(4); data_out(6) <= sometimes_inverted(6) XNOR sometimes_inverted(5); data_out(7) <= sometimes_inverted(7) XNOR sometimes_inverted(6); end if; if data_delayed(9) = '1' then sometimes_inverted <= data_delayed(8 downto 0) xor "011111111"; else sometimes_inverted <= data_delayed(8 downto 0); end if; case data_in is when "0010101011" => next_c <= "01"; next_active_data <= '0'; when "1101010100" => next_c <= "00"; next_active_data <= '0'; when "0101010100" => next_c <= "10"; next_active_data <= '0'; when "1010101011" => next_c <= "11"; next_active_data <= '0'; when others => next_c <= "00"; next_active_data <= '1'; end case; data_delayed <= data_in; end if; end process; end Behavioral; input_serialiser.vhd ---------------------------------------------------------------------------------- -- -- Module Name: input_serialiser -- -- Description: A 5-bits per cycle SDR input serialiser -- -- Maybe in the future the 'bitslip' funciton can be implemented. ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; library UNISIM; use UNISIM.VComponents.all; entity input_serialiser is Port ( clk_fabric_x2 : in STD_LOGIC; clk_input : in STD_LOGIC; strobe : in STD_LOGIC; ser_data : out STD_LOGIC_VECTOR (4 downto 0); ser_input : in STD_LOGIC); end input_serialiser; architecture Behavioral of input_serialiser is signal clk0, clk1, clkdiv : std_logic; signal cascade : std_logic; signal bitslip : std_logic := '0'; begin clkdiv <= clk_fabric_x2; clk0 <= clk_input; clk1 <= '0'; ISERDES2_master : ISERDES2 generic map ( BITSLIP_ENABLE => TRUE, -- Enable Bitslip Functionality (TRUE/FALSE) DATA_RATE => "SDR", -- Data-rate ("SDR" or "DDR") DATA_WIDTH => 5, -- Parallel data width selection (2-8) INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" SERDES_MODE => "MASTER" -- "NONE", "MASTER" or "SLAVE" ) port map ( CFB0 => open, -- 1-bit output: Clock feed-through route output CFB1 => open, -- 1-bit output: Clock feed-through route output DFB => open, -- 1-bit output: Feed-through clock output FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output INCDEC => open, -- 1-bit output: Phase detector output -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic Q1 => ser_data(1), Q2 => ser_data(2), Q3 => ser_data(3), Q4 => ser_data(4), SHIFTOUT => cascade, -- 1-bit output: Cascade output signal for master/slave I/O VALID => open, -- 1-bit output: Output status of the phase detector BITSLIP => bitslip , -- 1-bit input: Bitslip enable input CE0 => '1', -- 1-bit input: Clock enable input CLK0 => clk0, -- 1-bit input: I/O clock network input CLK1 => clk1, -- 1-bit input: Secondary I/O clock network input CLKDIV => clkdiv, -- 1-bit input: FPGA logic domain clock input D => ser_input, -- 1-bit input: Input data IOCE => strobe, -- 1-bit input: Data strobe input RST => '0', -- 1-bit input: Asynchronous reset input SHIFTIN => '0' -- 1-bit input: Cascade input signal for master/slave I/O ); ISERDES2_slave : ISERDES2 generic map ( BITSLIP_ENABLE => TRUE, -- Enable Bitslip Functionality (TRUE/FALSE) DATA_RATE => "SDR", -- Data-rate ("SDR" or "DDR") DATA_WIDTH => 5, -- Parallel data width selection (2-8) INTERFACE_TYPE => "RETIMED", -- "NETWORKING", "NETWORKING_PIPELINED" or "RETIMED" SERDES_MODE => "SLAVE" -- "NONE", "MASTER" or "SLAVE" ) port map ( CFB0 => open, -- 1-bit output: Clock feed-through route output CFB1 => open, -- 1-bit output: Clock feed-through route output DFB => open, -- 1-bit output: Feed-through clock output FABRICOUT => open, -- 1-bit output: Unsynchrnonized data output INCDEC => open, -- 1-bit output: Phase detector output -- Q1 - Q4: 1-bit (each) output: Registered outputs to FPGA logic Q1 => open, Q2 => open, Q3 => open, Q4 => ser_data(0), SHIFTOUT => open, -- 1-bit output: Cascade output signal for master/slave I/O VALID => open, -- 1-bit output: Output status of the phase detector BITSLIP => bitslip, -- 1-bit input: Bitslip enable input CE0 => '1', -- 1-bit input: Clock enable input CLK0 => clk0, -- 1-bit input: I/O clock network input CLK1 => clk1, -- 1-bit input: Secondary I/O clock network input CLKDIV => clkdiv, -- 1-bit input: FPGA logic domain clock input D => '0', -- 1-bit input: Input data IOCE => '1', -- 1-bit input: Data strobe input RST => '0', -- 1-bit input: Asynchronous reset input SHIFTIN => cascade -- 1-bit input: Cascade input signal for master/slave I/O ); end Behavioral; Спасибо. Но тут маленькая, но очень неприятная проблема. Здесь активно применяются примитивы, существующие только у Xilinx. Данный проект без примитивов на альтеру не перенести. И меня больше всего интересует алгоритм работы блоков: Который "избавляется" от jitter. И как работает проскальзывание битов ( bitslip). Нашёл практически готовое текстовое описание DVI рессивера для Xilinx. Но в нём разобраться практически невозможно, ибо там FIFO память присутствует, там присутствует 1_to_5 desserilaiser, и без общего алгоритма работы приёмника всё это понять очень сложно. Пытаюсь это сделать, читаю их дадашиты, но очень сильно мешает то, что даташиты на английском. А у меня, к сожалению английский хромает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 27 июля, 2016 Опубликовано 27 июля, 2016 · Жалоба пробовали? (стр. 5 "Supports Digital Visual Interface (DVI)") Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 июля, 2016 Опубликовано 28 июля, 2016 (изменено) · Жалоба пробовали? (стр. 5 "Supports Digital Visual Interface (DVI)") Не пока не пробовал. Я хочу сам разобраться с алгоритмами. Чтобы понимать как все это работает. Не хочу просто брать готовое, и ни фига не понимать. Изменено 28 июля, 2016 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 2 августа, 2016 Опубликовано 2 августа, 2016 (изменено) · Жалоба Можете меня больно ударить. Но мой мозг не хочет понимать, каким образом в https://www.altera.com/en_US/pdfs/literature/an/an236.pdf определяет битовый интервал. Вот хоть убейте не понимаю. Смысл то понятен, что при помощии 8 частот сдвинутых друг от друга мы семплируем бит данных. Но как в итоге выбирается нужная частота я не понимаю..... Судя по прочитанному, они сначала выбирают необходимую частоту из 8 сгенерированных, а потом уже проверяют данные в регистрах. Это как так ? Как можно семплировать данные, не зная что там передается ? Попытался применить встроенный LVDS приемник (ALTLVDS_RX) но что-то он мне какой-то бред выдает. И в настройках частоты там должна строго указываться частота, с какой скоростью приходят данные. Или номинальная частота работы десерилайзера ? Изменено 2 августа, 2016 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bogaev_roman 0 2 августа, 2016 Опубликовано 2 августа, 2016 · Жалоба Про паттерны Вам уже писали в 12 посте. Поиском в документе, Вами приведенном, ключевое слово pattern - известная последовательность. Это если режим DPA, если CDR, то там принцип другой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 2 августа, 2016 Опубликовано 2 августа, 2016 (изменено) · Жалоба Про паттерны Вам уже писали в 12 посте. Поиском в документе, Вами приведенном, ключевое слово pattern - известная последовательность. Это если режим DPA, если CDR, то там принцип другой. Ели кратко то сначала для каждой линии находим положение фронтов битового интервала относительно тактовой (10х пиксельной) двигая автоматом IOdelay на входной ножке, а затем ставим задержку в середину найденного битового интервала. Вот это меня и смущает. Абсолютно непонятно как это реализовать, поскольку нету у Altera примитива IOdealy. А в том апноте, что я читал применяется несколько другой алгоритм, через несколько частот семплирующих один бит. Чтобы сравнить что-то с контрольным словом, сначала надо это что-то принять. Вот мне и непонятно, как они выбрали из 8 частот ту по которой идет запись в регистры. Изменено 2 августа, 2016 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bogaev_roman 0 2 августа, 2016 Опубликовано 2 августа, 2016 · Жалоба А в том апноте, что я читал применяется несколько другой алгоритм, через несколько частот семплирующих один бит. Чтобы сравнить что-то с контрольным словом, сначала надо это что-то принять. Вот мне и непонятно, как они выбрали из 8 частот ту по которой идет запись в регистры. В той документашке используется готовая корка под названием serdes и там принцип немного другой - на pll формируется 8 частот, сдвинутых относительно друг друга на 45 градусов. По тестовой последовательности определяется центр окна данных последовательным перебором частот - это первый этап синхронизации, затем по другой последовательности определяется порядок компоновки разрядов в слове - 2 этап синхронизации. То что Вы выделили жирным шрифтом - это может быть и не serdes, а просто скажем altdq_dqs, в котором задействован вход core_delayctrlin (6 бит вроде), с помощью которого можно перебрать разные задержки на входе (после пина). Принцип работы схожий - по известной тестовой последовательности выбирается центр окна данных. PS/ Сам я уже не работал с альтерой больше 2-х лет, поэтому может чего и напутал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Алга 0 2 августа, 2016 Опубликовано 2 августа, 2016 · Жалоба Битовый интервал вы задаете сами, исходя из своей задачи путем программирования PLL. Эта та частота, на которой в вашей системе идет прием данных. На PLL подается частота кадра (frame clk, допустим 100 Mhz) И повышается на число принимаемых бит (как пример 8 бит). На выходе PLL имеем частоту 800 Mhz (период бита 1.25нс) , c которой происходит прием данных в SERDES. Это и есть частота семплирования. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Алга 0 3 августа, 2016 Опубликовано 3 августа, 2016 · Жалоба Также посмотрите AN202 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться