Goal & Data I am trying to make a VGA driver on a Spartan 6 (Embedded Micro Mojo board) to display something simple like the french flag on an LCD monitor, in 640x480 8 colors. I live in Europe and the monitor is 16:10 if it's important.

Wiring I wired hsync&vsync to my monitor following this diagram, and wired the R G and B signals to a 0.7V power supply to start with. I assume that voltage is the maximum (many people say it is at least), giving white.

Symptoms Launching the following code gives a black screen. No "Out of range [31kHz 40Hz]" message appears (like it did when I had a timing error), and if I make a poor contact with the 0.7V on any color pin (meaning, shivering a bit), random stripes of the corresponding color very briefly appear - if the contact is good the screen becomes pitch black again.

Question I think I have an idea of why it doesn't work, in my opinion it's the fact the colors are never switched back to black at the end of the period as the protocol suggests. If I am right (if I am not then why?), why is that necessary to form an image? The way I see it, it's only about applying the colors at the right time and resetting the vertical/horizontal plates ramp at the right time...


library IEEE;

entity main is
    Port ( 
              clk : in  STD_LOGIC;
           hsync : out  STD_LOGIC;
           vsync : out  STD_LOGIC;
           r : out  STD_LOGIC_VECTOR (2 downto 0) := "000";
           g : out  STD_LOGIC_VECTOR (2 downto 0) := "000";
           b : out  STD_LOGIC_VECTOR (1 downto 0) := "000"
end main;

architecture Behavioral of main is
    signal hcounter : integer := 0;
    signal vcounter : integer := 0;
    signal tick : STD_LOGIC := '0';

    clk_process : process(clk)
        if(rising_edge(clk)) then
            tick <= not tick;
            if(tick = '1') then         -- Happens at 25MHz (50MHz / 2)

                -- Reset the counter if column/line finished or increment it
                if(hcounter = 799) then
                    hcounter <= 0;
                    if vcounter = 524 then
                        vcounter <= 0;
                        vcounter <= vcounter + 1;
                    end if;
                    hcounter <= hcounter + 1;
                end if;

                -- Send a pulse of vsync to start a new column
                if vcounter >= 490 and vcounter < 492 then
                    vsync <= '0';
                    vsync <= '1';
                end if;

                -- Send a pulse of hsync to start a new line
                if hcounter >= 656 and hcounter < 752 then
                    hsync <= '0';
                    hsync <= '1';
                end if;

                -- If pixel time, draw something
                if hcounter < 640 and vcounter < 480 then
                    --display a colour on the RGB signals once I have opamps to get them through
                    --if hcounter < 213 then
                        -- Blue line
                        --b <= "111";
                        --r <= "000";
                        --g <= "000";
                    --elsif hcounter < 426 then
                       -- White line
                        --r <= "111";
                        --g <= "111";
                        --b <= "111";
                        -- Red line
                        -- r <= "111";
                        -- g <= "000";
                        -- b <= "000";
                    --end if;
                    --display black colour on the RGB signals
                    -- b <= "000";
                    -- r <= "000";
                    -- g <= "000";
                end if;
            end if;
        end if;
    end process;

end Behavioral;

What I understand

And might be wrong, see the following picture. Based on this, the aspect ratio and the full resolution vertical refresh rate is not important now is it (since with a smaller picture the refresh rate is higher) ? enter image description here

  • 1
    \$\begingroup\$ There a 3 PLL's in LCD monitors/TV's. V, H and pixel edge min. interval. There may be dozens of ratios acceptable, but your rates were out of range. If pixel rate is 25 MHz and H is 31k so P/H=806 (800 actual) then it expects V rate to be 525 H clocks +\-10% but it wasn't. H/V was 775 \$\endgroup\$ – user38637 Apr 20 '14 at 19:14
  • \$\begingroup\$ So you are telling me the entire area of monitors has to be scanned otherwise the monitor rejects the signal? Therefore if I keep the same back/front porches and change my Vcounter to reset at 775 will it work (sorry I can't try now...)? In that case why doesn't my monitor say "Out of range", like it did when I had another error? Or why do the colors kind of display when the connection on R G B lines is not stable? \$\endgroup\$ – Mister Mystère Apr 20 '14 at 19:56
  • 1
    \$\begingroup\$ Sometimes displays use the off-screen signal levels to set the 'black level'. If the 'black level' corresponds to the color you want to display, then all you get is black. Now, I have no idea if this particular display sets the black level like that or not, but I would recommend following the protocol exactly. \$\endgroup\$ – alex.forencich Apr 20 '14 at 21:01
  • \$\begingroup\$ LCD TV's like PC monitors can handle a wide variety of modes, ideal is the native mode using the same number of pixels in the same aspect ratio. But also older legacy rates and higher rates and will accept the analog inputs. The video level after sync is used for black level clamping called the back porch. There is no set rule but 800x600 is universal, in many cases so is 640x480 but this very low resolution 307.2 k pixels for a HDTV that supports 1920x1080 =2.07 Mpix, be it 1080p or 1080i, so there is no rule all TV's must support VGA. \$\endgroup\$ – user38637 Apr 21 '14 at 0:48
  • 1
    \$\begingroup\$ Also, I notice that the blue signal (b) is only two bits wide so your assignments to b should be adjusted accordingly. \$\endgroup\$ – aja Apr 21 '14 at 7:12

The pixel clock rate needs to be adjusted to achieve Vsync rates and Hsync rates that are acceptable for your multisync monitor.

Since 40Hz is not a common Vsync rate, try 30, 50 or 60 or higher.

640*480 * 40Hz = 12.3MHz so it seems pixels are pushed out at 1/2 of 25MHz clock rate

The NTSC timing for V Sync , front porch (480~494) , Hsync, back porch(495~525) as follows using 25MHz enter image description here Hsync can be varied as long with before after periods as long as sum is same. Some monitors have a 10% tolerance depending design.

| improve this answer | |
  • \$\begingroup\$ Thanks for your answer. That code is already set up to provide a 25MHz pixel clock, 60Hz vertical sync rate, which gives a 31.5kHz horizontal sync rate. I was surprised to see 40Hz on that screen, but I assume it has something to do with the aspect ratio (the monitor is not 4:3 but 16:10). The resulting picture should be smaller than the available real estate but still displayed, right? \$\endgroup\$ – Mister Mystère Apr 20 '14 at 17:05
  • \$\begingroup\$ The Sync rates are not what you expected, change TV mode to 4x3 or stretch. Verify sync freq. it appears pixel rate is only 12.3 MHz .. Yet H / V ratio is not 640 how many pixels are allocated for H sync and V sync \$\endgroup\$ – user38637 Apr 20 '14 at 17:19
  • 2
    \$\begingroup\$ Verify pixel rate with scope. Something wrong here \$\endgroup\$ – user38637 Apr 20 '14 at 17:30
  • \$\begingroup\$ Thanks for the diagram, they're always worth a thousand words. For this reason I uploaded a diagram of what I understand, because I still don't know why the 40Hz and the aspect ratio is an issue. I'll try with 4/3 on tuesday, I don't have the rig at hand (only the board). I simulated the design with ISim though and all the signals are correct (25MHz clock, and all timings to specs). \$\endgroup\$ – Mister Mystère Apr 20 '14 at 18:20

@alex.forencich gave the right answer in the comments: the black color is registered outside of the visible area, and since for my test setup I had wired every analog input to maximum luminance (0.7V) the black was registered as the same signal which was sent in the active region => black. I measured the input impedance of the monitor (apparently this 100ohm is standard), and added appropriate resistors (4R, 2R, R, where 7R makes a voltage divider with the input resistance) on the R(0 to 2) G(0 to 2) B(0 to 2) to get the appropriate voltage. Without changing anything about the counters, I managed to print my french flag. Thanks, if you post an answer I'll accept it.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.