+-- Module Name: dvi_video_test
+-- File Description: A 'test playground' for VGA, DVI, and i2c testing.
+-- Project: FPGA Image Registration
+-- Target Device: XC5VSX50T (Xilinx Virtex5 SXT)
+-- Target Board: ML506
+-- Synthesis Tool: Xilinx ISE 9.2
+-- Copyright (C) 2008 Brandyn Allen White
+-- Contact: bwhite(at)cs.ucf.edu
+-- Project Website: http://code.google.com/p/fpga-image-registration/
+
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+LIBRARY UNISIM;
+USE UNISIM.VComponents.ALL;
+
+ENTITY dvi_video_test IS
+ PORT (CLK_P : IN std_logic;
+ CLK_N : IN std_logic;
+ -- I2C Signals
+ I2C_SDA : OUT std_logic;
+ I2C_SCL : OUT std_logic;
+
+ -- DVI Signals
+ DVI_D : OUT std_logic_vector (11 DOWNTO 0);
+ DVI_H : OUT std_logic;
+ DVI_V : OUT std_logic;
+ DVI_DE : OUT std_logic;
+ DVI_XCLK_N : OUT std_logic;
+ DVI_XCLK_P : OUT std_logic;
+ DVI_RESET_B : OUT std_logic;
+
+ -- VGA Chip connections
+ VGA_PIXEL_CLK : IN std_logic;
+ VGA_Y_GREEN : IN std_logic_vector (7 DOWNTO 0);
+ VGA_CBCR_RED : IN std_logic_vector (7 DOWNTO 0);
+ VGA_BLUE : IN std_logic_vector(7 DOWNTO 0);
+ VGA_HSYNC : IN std_logic;
+ VGA_VSYNC : IN std_logic;
+ VGA_ODD_EVEN_B : IN std_logic;
+ VGA_SOGOUT : IN std_logic;
+ VGA_CLAMP : IN std_logic;
+ VGA_COAST : IN std_logic;
+
+ -- Dummy Chipscope outputs
+ SOGOUT : OUT std_logic;
+ PIXEL_X_COORD : OUT std_logic_vector(9 DOWNTO 0);
+ PIXEL_Y_COORD : OUT std_logic_vector(9 DOWNTO 0);
+ TOTAL_PIXEL_COUNT : OUT std_logic_vector(19 DOWNTO 0);
+ VGA_DATA_VALID : OUT std_logic;
+ Y : OUT std_logic_vector (7 DOWNTO 0);
+ HSYNC : OUT std_logic;
+ VSYNC : OUT std_logic;
+ DVI_PIXEL_COUNT : OUT std_logic_vector(19 DOWNTO 0);
+ DVI_X_COORD : OUT std_logic_vector(9 DOWNTO 0);
+ DVI_Y_COORD : OUT std_logic_vector(9 DOWNTO 0);
+ DVI_DATA_VALID : OUT std_logic
+ );
+END dvi_video_test;
+
+ARCHITECTURE Behavioral OF dvi_video_test IS
+ COMPONENT vga_timing_generator IS
+ GENERIC (WIDTH : integer := 1024;
+ H_FP : integer := 24;
+ H_SYNC : integer := 136;
+ H_BP : integer := 160;
+ HEIGHT : integer := 768;
+ V_FP : integer := 3;
+ V_SYNC : integer := 6;
+ V_BP : integer := 29;
+ HEIGHT_BITS : integer := 10;
+ WIDTH_BITS : integer := 10;
+ DATA_DELAY : integer := 0
+ );
+ PORT (CLK : IN std_logic;
+ RST : IN std_logic;
+ HSYNC : OUT std_logic;
+ VSYNC : OUT std_logic;
+ X_COORD : OUT unsigned(WIDTH_BITS-1 DOWNTO 0);
+ Y_COORD : OUT unsigned(HEIGHT_BITS-1 DOWNTO 0);
+ PIXEL_COUNT : OUT unsigned(WIDTH_BITS+HEIGHT_BITS-1 DOWNTO 0);
+ DATA_VALID : OUT std_logic;
+ DATA_VALID_EXT : OUT std_logic);
+ END COMPONENT;
+
+ COMPONENT vga_timing_decode IS
+ GENERIC (
+ HEIGHT : integer := 480;
+ WIDTH : integer := 640;
+ H_BP : integer := 117;
+ V_BP : integer := 34;
+ HEIGHT_BITS : integer := 10;
+ WIDTH_BITS : integer := 10;
+ DATA_DELAY : integer := 0
+ );
+ PORT (CLK : IN std_logic;
+ RST : IN std_logic;
+ VSYNC : IN std_logic;
+ HSYNC : IN std_logic;
+ X_COORD : OUT unsigned(WIDTH_BITS-1 DOWNTO 0);
+ Y_COORD : OUT unsigned(HEIGHT_BITS-1 DOWNTO 0);
+ PIXEL_COUNT : OUT unsigned(HEIGHT_BITS+WIDTH_BITS-1 DOWNTO 0);
+ DATA_VALID : OUT std_logic);
+ END COMPONENT;
+
+ COMPONENT i2c_video_programmer IS
+ PORT (CLK200Mhz : IN std_logic;
+ RST : IN std_logic;
+ I2C_SDA : OUT std_logic;
+ I2C_SCL : OUT std_logic);
+ END COMPONENT;
+
+ SIGNAL pix_clk : std_logic; -- This is the pixel clock for the DVI output and sync generator
+ SIGNAL clk_fb, data_valid, data_valid_ext, clk_buf : std_logic;
+ SIGNAL dvi_red, dvi_green, dvi_blue, dvi_gray : std_logic_vector(7 DOWNTO 0); -- These hold the values for the packed RGB DVI output data
+ SIGNAL dvi_h_wire, dvi_v_wire : std_logic;
+ SIGNAL dvi_x_coord_wire, dvi_y_coord_wire : unsigned(9 DOWNTO 0);
+ SIGNAL dvi_pixel_count_wire : unsigned(19 DOWNTO 0);
+ SIGNAL vga_x_coord_wire, vga_y_coord_wire : unsigned(9 DOWNTO 0);
+ SIGNAL vga_pixel_count_wire : unsigned(19 DOWNTO 0);
+BEGIN
+
+ -----------------------------------------------------------------------------
+ -- CLK Management
+-- IBUFGDS_inst : IBUFGDS
+-- GENERIC MAP (
+-- IOSTANDARD => "DEFAULT")
+-- PORT MAP (
+-- O => clk_buf, -- Clock buffer output
+-- I => CLK_P, -- Diff_p clock buffer input
+-- IB => CLK_N -- Diff_n clock buffer input
+-- );
+ BUF_inst : BUF
+ PORT MAP (
+ O => clk_buf, -- Clock buffer output
+ I => CLK_P -- Diff_p clock buffer input
+ );
+
+ DCM_BASE_dvi : DCM_BASE
+ GENERIC MAP (
+ CLKDV_DIVIDE => 4.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
+ -- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
+ CLKFX_DIVIDE => 16, -- Can be any interger from 1 to 32
+ CLKFX_MULTIPLY => 2, -- Can be any integer from 2 to 32
+ CLKIN_DIVIDE_BY_2 => false, -- TRUE/FALSE to enable CLKIN divide by two feature
+ CLKIN_PERIOD => 10.0, -- Specify period of input clock in ns from 1.25 to 1000.00
+ CLKOUT_PHASE_SHIFT => "NONE", -- Specify phase shift mode of NONE or FIXED
+ CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE or 1X
+ DCM_AUTOCALIBRATION => true, -- DCM calibrartion circuitry TRUE/FALSE
+ DCM_PERFORMANCE_MODE => "MAX_SPEED", -- Can be MAX_SPEED or MAX_RANGE
+ DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
+ -- an integer from 0 to 15
+ DFS_FREQUENCY_MODE => "HIGH", -- LOW or HIGH frequency mode for frequency synthesis
+ DLL_FREQUENCY_MODE => "LOW", -- LOW, HIGH, or HIGH_SER frequency mode for DLL
+ DUTY_CYCLE_CORRECTION => true, -- Duty cycle correction, TRUE or FALSE
+ FACTORY_JF => X"F0F0", -- FACTORY JF Values Suggested to be set to X"F0F0"
+ PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 1023
+ STARTUP_WAIT => false) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
+ PORT MAP (
+ CLK0 => clk_fb, -- 0 degree DCM CLK ouptput
+ CLKDV => pix_clk,
+ CLKFB => clk_fb, -- DCM clock feedback
+ CLKIN => clk_buf, -- Clock input (from IBUFG, BUFG or DCM)
+ RST => '0' -- DCM asynchronous reset input
+ );
+
+ -----------------------------------------------------------------------------
+ -- I2C Code
+ i2c_video_programmer_i : i2c_video_programmer
+ PORT MAP (
+ CLK200Mhz => clk_buf,
+ RST => '0',
+ I2C_SDA => I2C_SDA,
+ I2C_SCL => I2C_SCL);
+
+
+ -------------------------------------------------------------------------------
+ -- DVI Code
+ DVI_DE <= data_valid_ext;
+
+ -- This is a way to generate a differential clock with low jitter (as both
+ -- edges are handled in the same way)
+ ODDR_xclk_p : ODDR
+ GENERIC MAP(
+ DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
+ PORT MAP (
+ Q => DVI_XCLK_P, -- 1-bit DDR output
+ C => pix_clk, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => '1', -- 1-bit data input (positive edge)
+ D2 => '0', -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+ ODDR_xclk_n : ODDR
+ GENERIC MAP(
+ DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC") -- Reset Type ("ASYNC" or "SYNC")
+ PORT MAP (
+ Q => DVI_XCLK_N, -- 1-bit DDR output
+ C => pix_clk, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => '0', -- 1-bit data input (positive edge)
+ D2 => '1', -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+
+ DVI_RESET_B <= '1';
+ PROCESS (dvi_x_coord_wire) IS
+ BEGIN -- PROCESS
+ IF dvi_y_coord_wire(0) = '1' THEN
+ CASE to_integer(dvi_x_coord_wire) IS
+ WHEN 1 =>
+ dvi_gray <= "11111111";
+ WHEN 2 =>
+ dvi_gray <= "00000000";
+ WHEN 5 =>
+ dvi_gray <= "11111111";
+ WHEN 6 =>
+ dvi_gray <= "11111111";
+ WHEN 7 =>
+ dvi_gray <= "00000000";
+ WHEN 8 =>
+ dvi_gray <= "00000000";
+ WHEN 12 =>
+ dvi_gray <= "11111111";
+ WHEN 13 =>
+ dvi_gray <= "11111111";
+ WHEN 14 =>
+ dvi_gray <= "11111111";
+ WHEN 15 =>
+ dvi_gray <= "00000000";
+ WHEN 16 =>
+ dvi_gray <= "00000000";
+ WHEN 17 =>
+ dvi_gray <= "00000000";
+
+ WHEN 639-1 =>
+ dvi_gray <= "11111111";
+ WHEN 639-2 =>
+ dvi_gray <= "00000000";
+ WHEN 639-5 =>
+ dvi_gray <= "11111111";
+ WHEN 639-6 =>
+ dvi_gray <= "11111111";
+ WHEN 639-7 =>
+ dvi_gray <= "00000000";
+ WHEN 639-8 =>
+ dvi_gray <= "00000000";
+ WHEN 639-12 =>
+ dvi_gray <= "11111111";
+ WHEN 639-13 =>
+ dvi_gray <= "11111111";
+ WHEN 639-14 =>
+ dvi_gray <= "11111111";
+ WHEN 639-15 =>
+ dvi_gray <= "00000000";
+ WHEN 639-16 =>
+ dvi_gray <= "00000000";
+ WHEN 639-17 =>
+ dvi_gray <= "00000000";
+ WHEN OTHERS =>
+ dvi_gray <= "01111111";
+ END CASE;
+ ELSE
+ CASE to_integer(dvi_x_coord_wire) IS
+ WHEN 1 =>
+ dvi_gray <= "00000000";
+ WHEN 2 =>
+ dvi_gray <= "11111111";
+ WHEN 5 =>
+ dvi_gray <= "00000000";
+ WHEN 6 =>
+ dvi_gray <= "00000000";
+ WHEN 7 =>
+ dvi_gray <= "11111111";
+ WHEN 8 =>
+ dvi_gray <= "11111111";
+ WHEN 12 =>
+ dvi_gray <= "00000000";
+ WHEN 13 =>
+ dvi_gray <= "00000000";
+ WHEN 14 =>
+ dvi_gray <= "00000000";
+ WHEN 15 =>
+ dvi_gray <= "11111111";
+ WHEN 16 =>
+ dvi_gray <= "11111111";
+ WHEN 17 =>
+ dvi_gray <= "11111111";
+
+ WHEN 639-1 =>
+ dvi_gray <= "00000000";
+ WHEN 639-2 =>
+ dvi_gray <= "11111111";
+ WHEN 639-5 =>
+ dvi_gray <= "00000000";
+ WHEN 639-6 =>
+ dvi_gray <= "00000000";
+ WHEN 639-7 =>
+ dvi_gray <= "11111111";
+ WHEN 639-8 =>
+ dvi_gray <= "11111111";
+ WHEN 639-12 =>
+ dvi_gray <= "00000000";
+ WHEN 639-13 =>
+ dvi_gray <= "00000000";
+ WHEN 639-14 =>
+ dvi_gray <= "00000000";
+ WHEN 639-15 =>
+ dvi_gray <= "11111111";
+ WHEN 639-16 =>
+ dvi_gray <= "11111111";
+ WHEN 639-17 =>
+ dvi_gray <= "11111111";
+ WHEN OTHERS =>
+ dvi_gray <= "01111111";
+ END CASE;
+ END IF;
+
+ dvi_red <= dvi_gray;
+ dvi_blue <= dvi_gray;
+ dvi_green <= dvi_gray;
+-- IF h_pixel_count < "00000000100" THEN
+-- dvi_red <= "00000000";
+-- dvi_green <= "00000000";
+-- dvi_blue <= "11111111";
+-- ELSIF h_pixel_count < "00000001000" THEN
+-- dvi_red <= "00000000";
+-- dvi_green <= "11111111";
+-- dvi_blue <= "00000000";
+-- ELSIF h_pixel_count > "01001111000" THEN
+-- dvi_red <= "11111111";
+-- dvi_green <= "00000000";
+-- dvi_blue <= "00000000";
+-- ELSE
+-- dvi_red <= "00000000";
+-- dvi_green <= "00000000";
+-- dvi_blue <= "11111111";
+-- END IF;
+ END PROCESS;
+ -- This outputs the color values in the DVI chips DDR mode, if the
+ -- dvi_reg/green/blue wires are used on the posedge of the pix_clk, then
+ -- knowledge of this DDR format isn't necessary
+ ODDR_dvi_d0 : ODDR
+ PORT MAP (DVI_D(0), pix_clk, '1', dvi_green(4), dvi_blue(0), NOT data_valid_ext, '0');
+ ODDR_dvi_d1 : ODDR
+ PORT MAP (DVI_D(1), pix_clk, '1', dvi_green(5), dvi_blue(1), NOT data_valid_ext, '0');
+ ODDR_dvi_d2 : ODDR
+ PORT MAP (DVI_D(2), pix_clk, '1', dvi_green(6), dvi_blue(2), NOT data_valid_ext, '0');
+ ODDR_dvi_d3 : ODDR
+ PORT MAP (DVI_D(3), pix_clk, '1', dvi_green(7), dvi_blue(3), NOT data_valid_ext, '0');
+ ODDR_dvi_d4 : ODDR
+ PORT MAP (DVI_D(4), pix_clk, '1', dvi_red(0), dvi_blue(4), NOT data_valid_ext, '0');
+ ODDR_dvi_d5 : ODDR
+ PORT MAP (DVI_D(5), pix_clk, '1', dvi_red(1), dvi_blue(5), NOT data_valid_ext, '0');
+ ODDR_dvi_d6 : ODDR
+ PORT MAP (DVI_D(6), pix_clk, '1', dvi_red(2), dvi_blue(6), NOT data_valid_ext, '0');
+ ODDR_dvi_d7 : ODDR
+ PORT MAP (DVI_D(7), pix_clk, '1', dvi_red(3), dvi_blue(7), NOT data_valid_ext, '0');
+ ODDR_dvi_d8 : ODDR
+ PORT MAP (DVI_D(8), pix_clk, '1', dvi_red(4), dvi_green(0), NOT data_valid_ext, '0');
+ ODDR_dvi_d9 : ODDR
+ PORT MAP (DVI_D(9), pix_clk, '1', dvi_red(5), dvi_green(1), NOT data_valid_ext, '0');
+ ODDR_dvi_d10 : ODDR
+ PORT MAP (DVI_D(10), pix_clk, '1', dvi_red(6), dvi_green(2), NOT data_valid_ext, '0');
+ ODDR_dvi_d11 : ODDR
+ PORT MAP (DVI_D(11), pix_clk, '1', dvi_red(7), dvi_green(3), NOT data_valid_ext, '0');
+
+ vga_timing_generator_i : vga_timing_generator
+ GENERIC MAP(WIDTH => 640,
+ H_FP => 16,
+ H_SYNC => 96,
+ H_BP => 48,
+
+ HEIGHT => 480,
+ V_FP => 12,
+ V_SYNC => 2,
+ V_BP => 31,
+ DATA_DELAY => 0)
+
+ PORT MAP (
+ RST => '0',
+ HSYNC => dvi_h_wire,
+ VSYNC => dvi_v_wire,
+ DATA_VALID => data_valid,
+ DATA_VALID_EXT => data_valid_ext,
+ X_COORD => dvi_x_coord_wire,
+ Y_COORD => dvi_y_coord_wire,
+ PIXEL_COUNT => dvi_pixel_count_wire,
+ CLK => pix_clk);
+ DVI_DATA_VALID <= data_valid;
+ DVI_H <= NOT dvi_h_wire;
+ DVI_V <= NOT dvi_v_wire;
+ DVI_X_COORD <= std_logic_vector(dvi_x_coord_wire);
+ DVI_Y_COORD <= std_logic_vector(dvi_y_coord_wire);
+ DVI_PIXEL_COUNT <= std_logic_vector(dvi_pixel_count_wire);
+
+ -----------------------------------------------------------------------------
+ -- VGA Input
+
+ -- Hooks to chipscope outputs
+ Y <= VGA_Y_GREEN;
+ HSYNC <= VGA_HSYNC;
+ VSYNC <= VGA_VSYNC;
+ SOGOUT <= VGA_SOGOUT;
+ vga_timing_decode_i : vga_timing_decode
+ PORT MAP (
+ CLK => VGA_PIXEL_CLK,
+ RST => '0',
+ VSYNC => VGA_VSYNC,
+ HSYNC => VGA_HSYNC,
+ DATA_VALID => VGA_DATA_VALID,
+ X_COORD => vga_x_coord_wire,
+ Y_COORD => vga_y_coord_wire,
+ PIXEL_COUNT => vga_pixel_count_wire);
+ PIXEL_X_COORD <= std_logic_vector(vga_x_coord_wire);
+ PIXEL_Y_COORD <= std_logic_vector(vga_y_coord_wire);
+ TOTAL_PIXEL_COUNT <= std_logic_vector(vga_pixel_count_wire);
+END Behavioral;