DVI-D Serdes

From Hamsterworks Wiki!

Jump to: navigation, search

This |FPGA Project was completed in June 2014, and implemented on the Pipistrello FPGA board.

Clocking serializers is a bit of an dark art - you need to have the correct signals, and have them correctly passed through clock buffers and PLLs. Hopefully this little project will help you out with getting it right without a week of trial and error.

This project displays a 720p colour screen. If you wanted too, the input side of the DVID_OUT_FIFO does not need to run at the pixel clock (75 MHz in this case) but can run at a memory friendly clock speed - but the FIFO MUST NEVER RUN EMPTY - if it does then the display will fall out of sync. My tips would be to make the FIFO bigger (using a BRAM), and keep it as full as possible.

Contents

Source

The entire project can be had here:

File:Dvid serdes.zip

But here are the individual files.

dvid_serdes.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz<
-- 
-- Module Name:    dvid_serdes - Behavioral 
-- Description: Generating a DVI-D 720p signal using the OSERDES2 serialisers
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;

entity dvid_serdes is
    Port ( clk50 : in  STD_LOGIC;
           tmds_out_p : out  STD_LOGIC_VECTOR(3 downto 0);
           tmds_out_n : out  STD_LOGIC_VECTOR(3 downto 0));
end dvid_serdes;

architecture Behavioral of dvid_serdes is

	signal pixel_clock     : std_logic;
	signal data_load_clock : std_logic;
	signal ioclock         : std_logic;
   signal serdes_strobe   : std_logic;

	signal red   : std_logic_vector(7 downto 0);
	signal green : std_logic_vector(7 downto 0);
	signal blue  : std_logic_vector(7 downto 0);
	signal blank : std_logic;
	signal hsync : std_logic;
	signal vsync : std_logic;

   signal tmds_out_red   : std_logic;
   signal tmds_out_green : std_logic;
   signal tmds_out_blue  : std_logic;
   signal tmds_out_clock : std_logic;
  COMPONENT vga_gen
	PORT(
		clk75 : IN std_logic;          
		red   : OUT std_logic_vector(7 downto 0);
		green : OUT std_logic_vector(7 downto 0);
		blue  : OUT std_logic_vector(7 downto 0);
		blank : OUT std_logic;
		hsync : OUT std_logic;
		vsync : OUT std_logic
		);
	END COMPONENT;

	COMPONENT clocking
	PORT(
		clk50m          : IN  std_logic;          
		pixel_clock     : OUT std_logic;
		data_load_clock : OUT std_logic;
		ioclock         : OUT std_logic;
		serdes_strobe   : OUT std_logic
		);
	END COMPONENT;

	COMPONENT dvid_out
	PORT(
		pixel_clock     : IN std_logic;
		data_load_clock : IN std_logic;
		ioclock         : IN std_logic;
		serdes_strobe   : IN std_logic;
		red_p : IN std_logic_vector(7 downto 0);
		green_p : IN std_logic_vector(7 downto 0);
		blue_p : IN std_logic_vector(7 downto 0);
		blank : IN std_logic;
		hsync : IN std_logic;
		vsync : IN std_logic;          
		red_s : OUT std_logic;
		green_s : OUT std_logic;
		blue_s : OUT std_logic;
		clock_s : OUT std_logic
		);
	END COMPONENT;

begin

Inst_clocking: clocking PORT MAP(
		clk50m          => clk50,
		pixel_clock     => pixel_clock,
		data_load_clock => data_load_clock,
		ioclock         => ioclock,
		serdes_strobe   => serdes_strobe
	);

   
i_vga_gen: vga_gen PORT MAP(
		clk75 => pixel_clock,
		red   => green,
		green => red,
		blue  => blue,
		blank => blank,
		hsync => hsync,
		vsync => vsync
	);


i_dvid_out: dvid_out PORT MAP(
		pixel_clock     => pixel_clock,
		data_load_clock => data_load_clock,
		ioclock         => ioclock,
		serdes_strobe   => serdes_strobe,

		red_p           => red,
		green_p         => green,
		blue_p          => blue,
		blank           => blank,
		hsync           => hsync,
		vsync           => vsync,
      
		red_s           => tmds_out_red,
		green_s         => tmds_out_green,
		blue_s          => tmds_out_blue,
		clock_s         => tmds_out_clock
	);
   
  
OBUFDS_blue  : OBUFDS port map ( O  => tmds_out_p(0), OB => tmds_out_n(0), I  => tmds_out_blue);
OBUFDS_red   : OBUFDS port map ( O  => tmds_out_p(1), OB => tmds_out_n(1), I  => tmds_out_green);
OBUFDS_green : OBUFDS port map ( O  => tmds_out_p(2), OB => tmds_out_n(2), I  => tmds_out_red);
OBUFDS_clock : OBUFDS port map ( O  => tmds_out_p(3), OB => tmds_out_n(3), I  => tmds_out_clock);

end Behavioral;

clocking.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz<
-- 
-- Description: Generate clocking for sending TMDS data use the OSERDES2
-- 
-- WHEN SENDING SOMETHING OTHER THAN 5 BITS AT a timeCHANGE 'DIVIDE' 
--
-- REMEMBER TO CHECK CLKIN_PERIOD ON PLL_BASE
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity clocking is
    Port ( clk50m          : in  STD_LOGIC;
           pixel_clock     : out STD_LOGIC;  -- Global, The pixel clock.
           data_load_clock : out STD_LOGIC;  -- Global, At Pixel_clock x2, for when each 5 bits of TDMS data is loaded into the serialiser
           ioclock         : out STD_LOGIC;  -- In an I/O Bank, the x10 clock, for when bits are sent out of the serialiser
           serdes_strobe   : out STD_LOGIC); -- An 'enable load' signal, withing the ioclock domain, for when the serialiser loads data
end clocking;

architecture Behavioral of clocking is
   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 clk50m_buffered      : std_logic;
   signal pll_locked           : std_logic;
begin
   pixel_clock     <= clock_x1;
   data_load_clock <= clock_x2;
   
   -- Multiply clk50m by 10, then :
   -- * divide by 1 for the bit clock (pixel clock x10)
   -- * divide by 5 for the pixel clock x2 
   -- * divide by 10 for the pixel clock
   -- Because the all come from the same PLL the will all be in phase 
   PLL_BASE_inst : PLL_BASE
   generic map (
      CLKFBOUT_MULT => 15,                  
      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 => 20.0,                              -- IMPORTANT! 20.00 => 50MHz
      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    => clk50m_buffered, 
      RST      => '0'              -- 1-bit input: Reset input
   );

   BUFG_clk       : BUFG port map ( I => clk50m,               O => clk50m_buffered);
   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 );

  
  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 send 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   -- Whate clock to use - this must be unbuffered
   );
end Behavioral;

vga_gen.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: Generates a test 1280x720 signal 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity vga_gen is
    Port ( clk75 : in  STD_LOGIC;
           pclk  : out STD_LOGIC;
           red   : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           green : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           blue  : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
           blank : out STD_LOGIC := '0';
           hsync : out STD_LOGIC := '0';
           vsync : out STD_LOGIC := '0');
end vga_gen;

architecture Behavioral of vga_gen is
   constant h_rez        : natural := 1280;
   constant h_sync_start : natural := 1280+72;
   constant h_sync_end   : natural := 1280+80;
   constant h_max        : natural := 1647;
   signal   h_count      : unsigned(11 downto 0) := (others => '0');

   constant v_rez        : natural := 720;
   constant v_sync_start : natural := 720+3;
   constant v_sync_end   : natural := 720+3+5;
   constant v_max        : natural := 749;
   signal   v_count      : unsigned(11 downto 0) := (others => '0');
   
begin
   pclk <= clk75;
   
process(clk75)
   begin
      if rising_edge(clk75) then
         if h_count < h_rez and v_count < v_rez then
            red   <= std_logic_vector(h_count(7 downto 0));
            green <= std_logic_vector(v_count(7 downto 0));
            blue  <= std_logic_vector(h_count(7 downto 0)+v_count(7 downto 0));
            blank <= '0';
         else
            red   <= (others => '0');
            green <= (others => '0');
            blue  <= (others => '0');
            blank <= '1';
         end if;

         if h_count >= h_sync_start and h_count < h_sync_end then
            hsync <= '1';
         else
            hsync <= '0';
         end if;
         
         if v_count >= v_sync_start and v_count < v_sync_end then
            vsync <= '1';
         else
            vsync <= '0';
         end if;
         
         if h_count = h_max then
            h_count <= (others => '0');
            if v_count = v_max then
               v_count <= (others => '0');
            else
               v_count <= v_count+1;
            end if;
         else
            h_count <= h_count+1;
         end if;

      end if;
   end process;

end Behavioral;

dvid_out.vhd

--------------------------------------------------------------------------------
-- Engineer:      Mike Field <hamster@snap.net.nz>
-- Description:   Converts VGA signals into DVID bitstreams.
--
--                data_load_clock is 2x pixel_clock (used to load the 5:1 serialisers)
--                ioclock is serialiser output clock
--
--                'blank' should be asserted during the non-display 
--                portions of the frame
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;

entity dvid_out is
    Port ( pixel_clock     : IN std_logic;
		     data_load_clock : IN std_logic;
		     ioclock         : IN std_logic;
           serdes_strobe   : IN std_logic;
           red_p     : in  STD_LOGIC_VECTOR (7 downto 0);
           green_p   : in  STD_LOGIC_VECTOR (7 downto 0);
           blue_p    : in  STD_LOGIC_VECTOR (7 downto 0);
           blank     : in  STD_LOGIC;
           hsync     : in  STD_LOGIC;
           vsync     : in  STD_LOGIC;
           red_s     : out STD_LOGIC;
           green_s   : out STD_LOGIC;
           blue_s    : out STD_LOGIC;
           clock_s   : out STD_LOGIC);
end dvid_out;

architecture Behavioral of dvid_out is
   COMPONENT TMDS_encoder
   PORT(
         clk     : IN  std_logic;
         data    : IN  std_logic_vector(7 downto 0);
         c       : IN  std_logic_vector(1 downto 0);
         blank   : IN  std_logic;          
         encoded : OUT std_logic_vector(9 downto 0)
      );
   END COMPONENT;

   COMPONENT tmds_out_fifo
   PORT (
         wr_clk     : IN  STD_LOGIC;
         rd_clk     : IN  STD_LOGIC;
         din        : IN  STD_LOGIC_VECTOR(29 DOWNTO 0);
         wr_en      : IN  STD_LOGIC;
         rd_en      : IN  STD_LOGIC;
         dout       : OUT STD_LOGIC_VECTOR(29 DOWNTO 0);
         full       : OUT STD_LOGIC;
         empty      : OUT STD_LOGIC;
         prog_empty : OUT STD_LOGIC
      );
   END COMPONENT;

	COMPONENT output_serialiser
	PORT(
		clk_load   : IN  std_logic;
		clk_output : IN  std_logic;
      strobe     : IN  std_logic;
		ser_data   : IN  std_logic_vector(4 downto 0);          
		ser_output : OUT std_logic
		);
	END COMPONENT;

   signal encoded_red, encoded_green, encoded_blue : std_logic_vector(9 downto 0);
   signal latched_red, latched_green, latched_blue : std_logic_vector(9 downto 0) := (others => '0');
   signal ser_in_red,  ser_in_green,  ser_in_blue, ser_in_clock   : std_logic_vector(4 downto 0) := (others => '0');
   signal fifo_in       : std_logic_vector(29 downto 0);
   signal fifo_out      : std_logic_vector(29 downto 0);
   signal rd_enable     : std_logic := '0';
   signal not_ready_yet : std_logic;
   
   constant c_red       : std_logic_vector(1 downto 0) := (others => '0');
   constant c_green     : std_logic_vector(1 downto 0) := (others => '0');
   signal   c_blue      : std_logic_vector(1 downto 0);

begin   
   -- Send the pixels to the encoder
   c_blue <= vsync & hsync;
   TMDS_encoder_red:   TMDS_encoder PORT MAP(clk => pixel_clock, data => red_p,   c => c_red,   blank => blank, encoded => encoded_red);
   TMDS_encoder_green: TMDS_encoder PORT MAP(clk => pixel_clock, data => green_p, c => c_green, blank => blank, encoded => encoded_green);
   TMDS_encoder_blue:  TMDS_encoder PORT MAP(clk => pixel_clock, data => blue_p,  c => c_blue,  blank => blank, encoded => encoded_blue);

   -- Then to a small FIFO
   fifo_in <= encoded_red & encoded_green & encoded_blue;
   
out_fifo: tmds_out_fifo
  PORT MAP (
    wr_clk => pixel_clock,
    din    => fifo_in,
    wr_en  => '1',
    full   => open,
    
    rd_clk     => data_load_clock,
    rd_en      => rd_enable,
    dout       => fifo_out,
    empty      => open,
    prog_empty => not_ready_yet
  );
   
   -- Now at a x2 clock, send the data from the fifo to the serialisers
process(data_load_clock)
   begin
      if rising_edge(data_load_clock) then
         if not_ready_yet = '0' then
            if rd_enable = '1' then
               ser_in_red   <= fifo_out(29 downto 25);
               ser_in_green <= fifo_out(19 downto 15);
               ser_in_blue  <= fifo_out( 9 downto  5);
               ser_in_clock <= "11111";
               rd_enable <= '0';
            else
               ser_in_red   <= fifo_out(24 downto 20);
               ser_in_green <= fifo_out(14 downto 10);
               ser_in_blue  <= fifo_out( 4 downto  0);
               ser_in_clock <= "00000";
               rd_enable <= '1';
            end if;
         end if;
      end if;
   end process;

output_serialiser_r: output_serialiser PORT MAP(clk_load => data_load_clock, clk_output => ioclock, strobe => serdes_strobe, ser_data => ser_in_red,   ser_output => red_s);
output_serialiser_g: output_serialiser PORT MAP(clk_load => data_load_clock, clk_output => ioclock, strobe => serdes_strobe, ser_data => ser_in_green, ser_output => green_s);
output_serialiser_b: output_serialiser PORT MAP(clk_load => data_load_clock, clk_output => ioclock, strobe => serdes_strobe, ser_data => ser_in_blue,  ser_output => blue_s);
output_serialiser_c: output_serialiser PORT MAP(clk_load => data_load_clock, clk_output => ioclock, strobe => serdes_strobe, ser_data => ser_in_clock, ser_output => clock_s);
   
end Behavioral;

TMDS_encoder.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: TMDS Encoder 
--     8 bits colour, 2 control bits and one blanking bits in
--       10 bits of TMDS encoded data out
--     Clocked at the pixel clock
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity TMDS_encoder is
    Port ( clk     : in  STD_LOGIC;
           data    : in  STD_LOGIC_VECTOR (7 downto 0);
           c       : in  STD_LOGIC_VECTOR (1 downto 0);
           blank   : in  STD_LOGIC;
           encoded : out  STD_LOGIC_VECTOR (9 downto 0));
end TMDS_encoder;

architecture Behavioral of TMDS_encoder is
   signal xored  : STD_LOGIC_VECTOR (8 downto 0);
   signal xnored : STD_LOGIC_VECTOR (8 downto 0);
   
   signal ones                : STD_LOGIC_VECTOR (3 downto 0);
   signal data_word           : STD_LOGIC_VECTOR (8 downto 0);
   signal data_word_inv       : STD_LOGIC_VECTOR (8 downto 0);
   signal data_word_disparity : STD_LOGIC_VECTOR (3 downto 0);
   signal dc_bias             : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
begin
   -- Work our the two different encodings for the byte
   xored(0) <= data(0);
   xored(1) <= data(1) xor xored(0);
   xored(2) <= data(2) xor xored(1);
   xored(3) <= data(3) xor xored(2);
   xored(4) <= data(4) xor xored(3);
   xored(5) <= data(5) xor xored(4);
   xored(6) <= data(6) xor xored(5);
   xored(7) <= data(7) xor xored(6);
   xored(8) <= '1';

   xnored(0) <= data(0);
   xnored(1) <= data(1) xnor xnored(0);
   xnored(2) <= data(2) xnor xnored(1);
   xnored(3) <= data(3) xnor xnored(2);
   xnored(4) <= data(4) xnor xnored(3);
   xnored(5) <= data(5) xnor xnored(4);
   xnored(6) <= data(6) xnor xnored(5);
   xnored(7) <= data(7) xnor xnored(6);
   xnored(8) <= '0';
   
   -- Count how many ones are set in data
   ones <= "0000" + data(0) + data(1) + data(2) + data(3)
                   + data(4) + data(5) + data(6) + data(7);
 
   -- Decide which encoding to use
   process(ones, data(0), xnored, xored)
   begin
      if ones > 4 or (ones = 4 and data(0) = '0') then
         data_word     <= xnored;
         data_word_inv <= NOT(xnored);
      else
         data_word     <= xored;
         data_word_inv <= NOT(xored);
      end if;
   end process;                                          

   -- Work out the DC bias of the dataword;
   data_word_disparity  <= "1100" + data_word(0) + data_word(1) + data_word(2) + data_word(3) 
                                    + data_word(4) + data_word(5) + data_word(6) + data_word(7);
   
   -- Now work out what the output should be
   process(clk)
   begin
      if rising_edge(clk) then
         if blank = '1' then 
            -- In the control periods, all values have and have balanced bit count
            case c is            
               when "00"   => encoded <= "1101010100";
               when "01"   => encoded <= "0010101011";
               when "10"   => encoded <= "0101010100";
               when others => encoded <= "1010101011";
            end case;
            dc_bias <= (others => '0');
         else
            if dc_bias = "00000" or data_word_disparity = 0 then
               -- dataword has no disparity
               if data_word(8) = '1' then
                  encoded <= "01" & data_word(7 downto 0);
                  dc_bias <= dc_bias + data_word_disparity;
               else
                  encoded <= "10" & data_word_inv(7 downto 0);
                  dc_bias <= dc_bias - data_word_disparity;
               end if;
            elsif (dc_bias(3) = '0' and data_word_disparity(3) = '0') or 
                  (dc_bias(3) = '1' and data_word_disparity(3) = '1') then
               encoded <= '1' & data_word(8) & data_word_inv(7 downto 0);
               dc_bias <= dc_bias + data_word(8) - data_word_disparity;
            else
               encoded <= '0' & data_word;
               dc_bias <= dc_bias - data_word_inv(8) + data_word_disparity;
            end if;
         end if;
      end if;
   end process;      
end Behavioral;

dvid_out_fifo.vhd

This is a LUT-based 16 deep, 30-bit wide fifo, with a programmable empty set to 4. It is used to decouple the the signal generation logic from the physical I/O logic, which runs at twice the pixel clock.

Generate it using the IP CoreGen.

output_serialiser.vhd

----------------------------------------------------------------------------------
-- Engineer:   Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: output_serialiser - Behavioral 
-- Description: A 5-bit SDR output serialiser
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity output_serialiser is
    Port ( clk_load   : in  STD_LOGIC;
           clk_output : in  STD_LOGIC;
           strobe     : in  STD_LOGIC;
           ser_data   : in  STD_LOGIC_VECTOR (4 downto 0);
           ser_output : out STD_LOGIC);
end output_serialiser;

architecture Behavioral of output_serialiser is
   signal clk0,     clk1,     clkdiv : std_logic;
   signal cascade1, cascade2, cascade3, cascade4 : std_logic;
begin
   clkdiv <= clk_load;
   clk0   <= clk_output;
   clk1   <= '0';
   
OSERDES2_master : OSERDES2
   generic map (
      BYPASS_GCLK_FF => FALSE,       -- Bypass CLKDIV syncronization registers (TRUE/FALSE)
      DATA_RATE_OQ => "SDR",         -- Output Data Rate ("SDR" or "DDR")
      DATA_RATE_OT => "SDR",         -- 3-state Data Rate ("SDR" or "DDR")
      DATA_WIDTH => 5,               -- Parallel data width (2-8)
      OUTPUT_MODE => "SINGLE_ENDED", -- "SINGLE_ENDED" or "DIFFERENTIAL" 
      SERDES_MODE => "MASTER",       -- "NONE", "MASTER" or "SLAVE" 
      TRAIN_PATTERN => 0             -- Training Pattern (0-15)
   ) port map (
      OQ        => ser_output, -- 1-bit output: Data output to pad or IODELAY2
      SHIFTOUT1 => cascade1, -- 1-bit output: Cascade data output
      SHIFTOUT2 => cascade2, -- 1-bit output: Cascade 3-state output
      SHIFTOUT3 => open,     -- 1-bit output: Cascade differential data output
      SHIFTOUT4 => open,     -- 1-bit output: Cascade differential 3-state output
      SHIFTIN1  => '1',      -- 1-bit input: Cascade data input
      SHIFTIN2  => '1',      -- 1-bit input: Cascade 3-state input
      SHIFTIN3  => cascade3, -- 1-bit input: Cascade differential data input
      SHIFTIN4  => cascade4, -- 1-bit input: Cascade differential 3-state input
      TQ        => open,     -- 1-bit output: 3-state output to pad or IODELAY2
      CLK0      => CLK0,     -- 1-bit input: I/O clock input
      CLK1      => CLK1,     -- 1-bit input: Secondary I/O clock input
      CLKDIV    => CLKDIV,   -- 1-bit input: Logic domain clock input
      -- D1 - D4: 1-bit (each) input: Parallel data inputs
      D1        => ser_data(4),
      D2        => '0',
      D3        => '0',
      D4        => '0',
      IOCE      => strobe,   -- 1-bit input: Data strobe input
      OCE       => '1',      -- 1-bit input: Clock enable input
      RST       => '0',      -- 1-bit input: Asynchrnous reset input
      -- T1 - T4: 1-bit (each) input: 3-state control inputs
      T1       => '0',
      T2       => '0',
      T3       => '0',
      T4       => '0',
      TCE      => '1',       -- 1-bit input: 3-state clock enable input
      TRAIN    => '0'        -- 1-bit input: Training pattern enable input
   );

OSERDES2_slave : OSERDES2
   generic map (
      BYPASS_GCLK_FF => FALSE,       -- Bypass CLKDIV syncronization registers (TRUE/FALSE)
      DATA_RATE_OQ => "SDR",         -- Output Data Rate ("SDR" or "DDR")
      DATA_RATE_OT => "SDR",         -- 3-state Data Rate ("SDR" or "DDR")
      DATA_WIDTH => 5,               -- Parallel data width (2-8)
      OUTPUT_MODE => "SINGLE_ENDED", -- "SINGLE_ENDED" or "DIFFERENTIAL" 
      SERDES_MODE => "SLAVE",       -- "NONE", "MASTER" or "SLAVE" 
      TRAIN_PATTERN => 0             -- Training Pattern (0-15)
   ) port map (
      OQ        => open,            -- 1-bit output: Data output to pad or IODELAY2
      SHIFTOUT1 => open,     -- 1-bit output: Cascade data output
      SHIFTOUT2 => open,     -- 1-bit output: Cascade 3-state output
      SHIFTOUT3 => cascade3, -- 1-bit output: Cascade differential data output
      SHIFTOUT4 => cascade4, -- 1-bit output: Cascade differential 3-state output
      SHIFTIN1  => cascade1, -- 1-bit input: Cascade data input
      SHIFTIN2  => cascade2, -- 1-bit input: Cascade 3-state input
      SHIFTIN3  => '1',      -- 1-bit input: Cascade differential data input
      SHIFTIN4  => '1',      -- 1-bit input: Cascade differential 3-state input
      TQ        => open,      -- 1-bit output: 3-state output to pad or IODELAY2
      CLK0      => CLK0,      -- 1-bit input: I/O clock input
      CLK1      => CLK1,      -- 1-bit input: Secondary I/O clock input
      CLKDIV    => CLKDIV,    -- 1-bit input: Logic domain clock input
      -- D1 - D4: 1-bit (each) input: Parallel data inputs
      D1        => ser_data(0),
      D2        => ser_data(1),
      D3        => ser_data(2),
      D4        => ser_data(3),
      IOCE      => strobe,     -- 1-bit input: Data strobe input
      OCE       => '1',        -- 1-bit input: Clock enable input
      RST       => '0',        -- 1-bit input: Asynchrnous reset input
      -- T1 - T4: 1-bit (each) input: 3-state control inputs
      T1        => '0',
      T2        => '0',
      T3        => '0',
      T4        => '0',
      TCE       => '1',             -- 1-bit input: 3-state clock enable input
      TRAIN     => '0'             -- 1-bit input: Training pattern enable input
   );

end Behavioral;

pipistrello.ucf

NET "CLK50"    LOC = "H17" | IOSTANDARD = LVCMOS33 | PERIOD = 50 MHz;

# DVI-D interface
NET "TMDS_out_P(0)"  LOC = "T6" | IOSTANDARD = TMDS_33 ; # Blue
NET "TMDS_out_N(0)"  LOC = "V6" | IOSTANDARD = TMDS_33 ;
NET "TMDS_out_P(1)"  LOC = "U7" | IOSTANDARD = TMDS_33 ; # Red
NET "TMDS_out_N(1)"  LOC = "V7" | IOSTANDARD = TMDS_33 ;
NET "TMDS_out_P(2)"  LOC = "U8" | IOSTANDARD = TMDS_33 ; # Green
NET "TMDS_out_N(2)"  LOC = "V8" | IOSTANDARD = TMDS_33 ;
NET "TMDS_out_P(3)"  LOC = "U5" | IOSTANDARD = TMDS_33 ; # Clock
NET "TMDS_out_N(3)"  LOC = "V5" | IOSTANDARD = TMDS_33 ;

Personal tools