DVI support -- initial demo works
[fleet.git] / src / edu / berkeley / fleet / fpga / dvi / vga_timing_decode.vhd
1 -- Module Name:  vga_timing_decode.vhd
2 -- File Description:  Takes in VGA timing signals, outputs pixel oriented
3 -- signals. Valid output starts at the beginning of the next valid frame.
4 -- Project:  FPGA Image Registration
5 -- Target Device:  XC5VSX50T (Xilinx Virtex5 SXT)
6 -- Target Board:  ML506
7 -- Synthesis Tool:  Xilinx ISE 9.2
8 -- Copyright (C) 2008 Brandyn Allen White
9 -- Contact:  bwhite(at)cs.ucf.edu
10 -- Project Website:  http://code.google.com/p/fpga-image-registration/
11
12 -- This program is free software: you can redistribute it and/or modify
13 -- it under the terms of the GNU General Public License as published by
14 -- the Free Software Foundation, either version 3 of the License, or
15 -- (at your option) any later version.
16
17 -- This program is distributed in the hope that it will be useful,
18 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
19 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 -- GNU General Public License for more details.
21
22 -- You should have received a copy of the GNU General Public License
23 -- along with this program. If not, see <http://www.gnu.org/licenses/>.
24
25 LIBRARY IEEE;
26 USE IEEE.STD_LOGIC_1164.ALL;
27 USE ieee.numeric_std.ALL;
28
29 ENTITY vga_timing_decode IS
30   GENERIC (
31     HEIGHT      : integer := 480;
32     WIDTH       : integer := 640;
33     H_BP        : integer := 117;
34     V_BP        : integer := 34;
35     HEIGHT_BITS : integer := 10;
36     WIDTH_BITS  : integer := 10;
37     HCOUNT_BITS : integer := 11;
38     VCOUNT_BITS : integer := 11;
39     DATA_DELAY  : integer := 0
40     );
41   PORT (CLK         : IN  std_logic;
42         RST         : IN  std_logic;
43         HSYNC       : IN  std_logic;
44         VSYNC       : IN  std_logic;
45         X_COORD     : OUT unsigned(WIDTH_BITS-1 DOWNTO 0);
46         Y_COORD     : OUT unsigned(HEIGHT_BITS-1 DOWNTO 0);
47         PIXEL_COUNT : OUT unsigned(HEIGHT_BITS+WIDTH_BITS-1 DOWNTO 0);
48         DATA_VALID  : OUT std_logic;
49         DONE        : OUT std_logic);
50 END vga_timing_decode;
51
52 ARCHITECTURE Behavioral OF vga_timing_decode IS
53   SIGNAL hcount                   : unsigned(HCOUNT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
54   SIGNAL vcount                   : unsigned(VCOUNT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
55   SIGNAL pixel_count_reg          : unsigned(HEIGHT_BITS+WIDTH_BITS-1 DOWNTO 0) := (OTHERS => '0');
56   SIGNAL x_coord_reg              : unsigned(WIDTH_BITS-1 DOWNTO 0)             := (OTHERS => '0');
57   SIGNAL y_coord_reg              : unsigned(HEIGHT_BITS-1 DOWNTO 0)            := (OTHERS => '0');
58   SIGNAL prev_hsync, prev_vsync   : std_logic                                   := '0';
59   SIGNAL data_valid_reg           : std_logic                                   := '0';
60   SIGNAL vsync_asserted, done_reg : std_logic                                   := '0';  -- Used to ensure that we only signal the output as valid when we have started from the beginning of a frame
61 BEGIN
62   X_COORD     <= x_coord_reg;
63   Y_COORD     <= y_coord_reg;
64   PIXEL_COUNT <= pixel_count_reg;
65   -- Output data as valid only starting at the first full frame we receive
66   DATA_VALID  <= data_valid_reg WHEN vsync_asserted = '1' ELSE '0';
67   DONE        <= done_reg;
68   PROCESS (CLK) IS
69   BEGIN  -- PROCESS 
70     IF CLK'event AND CLK = '1' THEN
71       IF RST = '1' THEN
72         hcount          <= (OTHERS => '0');
73         vcount          <= (OTHERS => '0');
74         pixel_count_reg <= (OTHERS => '0');
75         x_coord_reg     <= (OTHERS => '0');
76         y_coord_reg     <= (OTHERS => '0');
77         prev_hsync      <= '0';
78         data_valid_reg  <= '0';
79         vsync_asserted  <= '0';
80         done_reg        <= '0';
81       ELSE
82         prev_hsync <= HSYNC;
83         prev_vsync <= VSYNC;
84         -----------------------------------------------------------------------
85         -- Zones w.r.t. hcount
86         -- 0<=X<H_BP-1                  -       Back Porch of H
87         -- H_BP-1=<X<H_BP+WIDTH-1       -       Active horizontal data
88         -- H_BP+WIDTH-1<=X              -       Front Porch/HSYNC
89
90         -- The backporch -1 is due to the register delay
91         IF HSYNC = '0' AND VSYNC = '0' AND hcount >= H_BP-DATA_DELAY-1 AND hcount < H_BP+WIDTH-DATA_DELAY-1 AND vcount >= V_BP AND vcount < V_BP+HEIGHT THEN    
92           IF vsync_asserted='1' THEN
93             data_valid_reg <= '1';
94           END IF;
95
96           IF data_valid_reg = '1' THEN  -- This makes the first valid pixel 0,
97                                         -- instead of 1
98             x_coord_reg <= x_coord_reg + 1;
99           END IF;
100
101           -- This makes the first valid pixel 0, and properly increments the
102           -- first pixels of every other line
103           IF (data_valid_reg = '1' AND vcount = V_BP) OR vcount > V_BP THEN
104             pixel_count_reg <= pixel_count_reg + 1;
105           END IF;
106         ELSE
107           data_valid_reg <= '0';
108           x_coord_reg    <= (OTHERS => '0');
109         END IF;
110
111         IF VSYNC = '0' THEN
112           IF HSYNC = '1' AND prev_hsync = '0' AND vcount >= V_BP AND vcount < V_BP+HEIGHT-1 THEN
113             y_coord_reg <= y_coord_reg + 1;
114           END IF;
115         ELSE          -- End of Frame
116           vcount          <= (OTHERS => '0');
117           pixel_count_reg <= (OTHERS => '0');
118           y_coord_reg     <= (OTHERS => '0');
119           vsync_asserted  <= '1';
120           -- We are done when we have been in the VSYNC='1' region previously,
121           -- and the last CT we were in the VSYNC='0' region, which means we
122           -- have been through all of the coordinates.  It will be high for one
123           -- CT, then reset to 0.
124           -- NOTE: This assumes that the VSYNC level has no glitches
125           -- NOTE: Done will be high for one CT every full frame processed
126           IF prev_vsync = '0' AND vsync_asserted = '1' THEN
127             done_reg <= '1';
128           ELSE
129             done_reg <= '0';
130           END IF;     
131         END IF;
132
133         IF HSYNC = '0' THEN
134           hcount <= hcount + 1;
135         ELSE
136           hcount <= (OTHERS => '0');
137           IF prev_hsync = '0' THEN
138             vcount <= vcount + 1;
139           END IF;
140         END IF;
141       END IF;
142     END IF;
143   END PROCESS;
144 END Behavioral;