Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

VGA VHDL DE2 problem

Hi,

I'm currently trying to use the VGA capabilities of the ALTERA DE2 board to display a red screen with VHDL. The resolution i'm using is 640x480. I've written a code for it but it doesn't work, the monitor displays that it doesn't recieve a signal. I've run the simulation and i can't find the problem. Is there anyone who has an idea what i'm doing wrong?

Here is my code:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY vga IS
PORT (CLOCK_50 : IN std_logic;          --50Mhz clock
      KEY : IN std_logic_vector(3 downto 0); --RESET
      VGA_B: OUT std_logic_vector(9 downto 0); 
      VGA_R: OUT std_logic_vector(9 downto 0); 
      VGA_G: OUT std_logic_vector(9 downto 0); 
      VGA_CLK : OUT std_logic; 
      VGA_BLANK :OUT std_logic; --active low
       VGA_SYNC : OUT std_logic;
      VGA_HS : OUT std_logic; 
      VGA_VS : OUT std_logic);
END vga;
ARCHITECTURE vg OF vga IS
       SIGNAL line_fin : std_logic;    --variable to determine if a line has finished drawing
       SIGNAL line_count : integer;     --variable for counting the amount of lines drawn
       SIGNAL frame_fin : std_logic;   --variable to determine if a frame had finished drawing 
       SIGNAL CLOCK_25 : std_logic;    --25Mhz clock
       CONSTANT P1 : integer := 24;    --Front porch (horizontal)
       CONSTANT P2 : integer := 48;    --Back porch (horizontal)
       CONSTANT HSYNC_TIME : integer := 95; -- H_Sync pulse lenght 
       CONSTANT V1 : integer := 11250; --Front porch (vertical)
       CONSTANT V2 : integer := 25500; --Back porch (vertical)
       CONSTANT VSYNC_TIME : integer := 1600; -- V_Sync pulse lenght 
   BEGIN
   VGA_SYNC<= '0';
       
pixel_draw : PROCESS(CLOCK_25,KEY(0)) --for drawing pixels and generating blank pulses
        VARIABLE hcount : INTEGER := 0;
        VARIABLE vcount : INTEGER := 0;
    BEGIN
       IF KEY(0)= '0' THEN
          hcount := 0;
          vcount := 0;
          line_fin <= '0';
          frame_fin <= '0';
          line_count <= 0;
          VGA_BLANK <= '1'; 
       ELSIF rising_edge(CLOCK_25) THEN
         IF line_count < 480 THEN
          IF hcount < 640 THEN
              VGA_R <= "1111111111";--send pixel information each clock_cycle
              VGA_B <= "0000000000";
              VGA_G <= "0000000000";
              VGA_BLANK <= '1';
              hcount := hcount+1;
              line_fin <= '0';
          ELSIF hcount = 640 THEN 
              line_fin <= '1'; --line finished, pulse line_fin and start blank pulse
              hcount := hcount+1; 
              VGA_BLANK <= '0';
          ELSIF hcount >640 and hcount <= 640+P1+HSYNC_TIME+P2 THEN
              hcount := hcount+1;--keep blank pulse low for a set amount of time
              line_fin <= '0';
              VGA_BLANK <= '0';
          ELSE
              hcount := 1; --reset counters and increment line_counter
              line_count <= line_count+1;
          END IF;
        ELSIF line_count = 480 THEN
          IF vcount < 1 THEN --frame is finished; pulse frame_fin and initiate vertical blank pulse
              vcount := vcount+1;
              VGA_BLANK <= '0';
              frame_fin <= '1';
          ELSIF vcount >= 1 and vcount <  V1+V2+VSYNC_TIME THEN
              vcount := vcount+1; --keep blank pulse low for a set amount of time
              frame_fin <= '0';
              VGA_BLANK <= '0';
          ELSE
              vcount := 0; -- reset counters and line_counter
              VGA_BLANK <= '1';
              line_count <= 0;
        END IF;
       END IF; 
     END IF;
    END PROCESS;
    
horizontal_synchronisation : PROCESS(CLOCK_25,KEY(0))
       VARIABLE hsync_counter : INTEGER := 0;
       VARIABLE hsync_started : INTEGER := 0;
   BEGIN
        IF KEY(0)= '0' THEN
          VGA_HS <= '1';
          hsync_counter := 0;
          hsync_started := 0;
        ELSIF rising_edge(CLOCK_25) THEN
            IF line_fin = '1' or hsync_started = 1 THEN
               hsync_started:= 1;
               IF hsync_counter <= P1 THEN
                   hsync_counter := hsync_counter+1;--hsync stays high during front porch
                   VGA_HS <= '1';
               ELSIF hsync_counter >= P1-1 and hsync_counter <= HSYNC_TIME+P1 THEN
                   hsync_counter := hsync_counter+1;--hsync activated
                   VGA_HS <= '0';
               ELSIF hsync_counter >= HSYNC_TIME+P1-1 and hsync_counter < HSYNC_TIME+P1+P2 THEN
                   hsync_counter := hsync_counter+1;--hsync stays high during back porch
                   VGA_HS <= '1';
               ELSE 
                   hsync_counter := 0;--reset variables and counters 
                   VGA_HS <= '1';
                   hsync_started := 0;
               END IF;
            ELSE 
               VGA_HS <= '1';
        END IF;
    END IF;
   END PROCESS;
   
vertical_synchronisation : PROCESS(CLOCK_25,KEY(0))
      VARIABLE vsync_counter : INTEGER := 0;
      VARIABLE vsync_started : INTEGER := 0;
   BEGIN
        IF KEY(0) = '0' THEN 
           VGA_VS <= '1';
           vsync_counter := 0;
           vsync_started := 0;
        ELSIF rising_edge(CLOCK_25) THEN
            IF frame_fin = '1' or vsync_started = 1 THEN
              vsync_started := 1;
              IF vsync_counter < V1-1 THEN
                  vsync_counter := vsync_counter+1;
                  VGA_VS <= '1';
              ELSIF vsync_counter >= V1-1 and vsync_counter < VSYNC_TIME+V1-1 THEN
                   vsync_counter := vsync_counter+1;
                   VGA_VS <= '0';
              ELSIF vsync_counter >= VSYNC_TIME+V1-1 and vsync_counter < VSYNC_TIME+V1+V2 THEN
                   vsync_counter := vsync_counter+1;
                   VGA_VS <= '1';
              ELSE 
                   vsync_counter := 0;
                   VGA_VS <= '1';
                   vsync_started := 0;
               END IF;
            ELSE 
               VGA_VS <= '1';
        END IF;
     END IF;
   END PROCESS;
   
vga_clk_gen : PROCESS(CLOCK_50,KEY(0))--devides 50MHz clock in 2, making it a 25MHz clock
       VARIABLE count : INTEGER := 0;
    BEGIN
       IF KEY(0)= '0' THEN
          CLOCK_25 <= '0';
          VGA_CLK <= '0';
          count := 0;
       ELSIF rising_edge(CLOCK_50) THEN
          IF count = 0 THEN
              CLOCK_25 <= '1';   --1 period of 50MHz high
              VGA_CLK <= '1';
              count := 1;
          ELSIF count = 1 THEN
              CLOCK_25 <= '0';   --1 period of 50MHz low
              VGA_CLK <= '0';    
              count := 0;
          END IF;
       END IF; 
    END PROCESS;
END vg;
   
Here is my testfile for modelsim:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY vga_test IS
END vga_test;
ARCHITECTURE vgt OF vga_test IS
  SIGNAL KEY        : std_logic_vector(3 downto 0);
  SIGNAL CLOCK_50   : std_logic := '0';
  SIGNAL VGA_HS : std_logic;
  SIGNAL VGA_R : std_logic_vector(9 downto 0);
  SIGNAL VGA_G : std_logic_vector(9 downto 0);
  SIGNAL VGA_B : std_logic_vector(9 downto 0);
  SIGNAL VGA_BLANK : std_logic;
  SIGNAL VGA_SYNC : std_logic;
  SIGNAL finished   : boolean := FALSE;
BEGIN
    hs : ENTITY work.vga PORT MAP (
    KEY => KEY,
    CLOCK_50 => CLOCK_50,
    VGA_R => VGA_R,
    VGA_G => VGA_G,
    VGA_B => VGA_B,
    VGA_HS => VGA_HS,
    VGA_BLANK => VGA_BLANK,
    VGA_SYNC => VGA_SYNC
    );
    CLOCK_50 <= NOT CLOCK_50 AFTER 10 ns WHEN not finished;     
    PROCESS
    BEGIN
        KEY <= "0000";
        KEY(0) <= '0';
        WAIT FOR 100 ns;
        KEY(0) <= '1';
        WAIT FOR 50 ms;
        finished <= true; 
        WAIT;
    END PROCESS;
END vgt;
Thanks in advance,

Roelof

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I attached a working 640x480 driver for debug / comparison.

    If the timing is off the nicer LCD monitors will just reject the signal. It can be helpful to plug it into an older CRT to get more information about what went wrong.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    Thanks for your reply. I did some timing analysis with my oscilloscope and i measured some frequency's. The timing is the same as in the document i was using:

    http://www.epanorama.net/documents/pc/vga_timing.html

    I also tried a old crt monitor, this doesn't work either. It displays that the singals are "out of range". Maybe the document is wrong?

    I'm going to try your verilog file now.

    Roelof
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The verilog file works after a few changes, i'm trying to convert it to vhdl.

    Roelof
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello I work with the board DE2, i'm spanish but i study in france and i forgot my inglish so excuse my if i make one mistake. My proyect is the show a controls board of a car in a touch-screen LCD. I dont know how start. If you can helps me with the control vga i do the rest. Thanks.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi hencel,

    I tried to make the vhdl code to work, but there is a tiny flaw in the code. When I checked my signals with an oscilloscope or with my simulation, it looked like it should work. After a while I decided to learn verilog because it is very hard to keep vhdl compact. Verilog might be a bit harder but if you can read it it's much more convenient (well-organized). If you only know VHDL you could try to alter my code in the first post, I only have a working verilog driver.

    There are a lot of universities who use the de2 board, if you check their websites there are lots of examples how to use VGA in both verilog and VHDL.

    If you dont know how VGA works, you could check:

    http://www.epanorama.net/documents/pc/vga_timing.html

    For the list of links of universities:

    http://www.terasic.com.tw/cgi-bin/page/archive.pl?language=english&categoryno=39&no=30

    This link helped me a lot:

    http://www1.cs.columbia.edu/~sedwards/classes/2007/4840/video.pdf (http://www1.cs.columbia.edu/%7esedwards/classes/2007/4840/video.pdf)

    -Roelof
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I attached a working 640x480 driver for debug / comparison.

    If the timing is off the nicer LCD monitors will just reject the signal. It can be helpful to plug it into an older CRT to get more information about what went wrong.

    --- Quote End ---

    Should this code put anything out on the VGA or is it just a driver. Sorry im confused!?:confused: