I am at the moment trying to make an vga driver for my FPGA, but something isn't going right, and I can't seem to find out what is going wrong…
The code is based on this code example:
Example VGA controller
Here is my code:
(I've only changed the resolution and some variable names, other than that it should be exactly the same.)
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 03/07/2016 08:53:44 AM
-- Design Name:
-- Module Name: vga - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity vga is
GENERIC(
constant HR:integer:=640;--Horizontal Resolution
constant HFP:integer:=16;--Horizontal Front Porch
constant HBP:integer:=48;--Horizontal Back Porch
constant HRet:integer:=96;--Horizontal retrace
h_pol : STD_LOGIC := '0'; --horizontal sync pulse polarity (1 = positive, 0 = negative)
constant VR:integer:=480;--Vertical Resolution
constant VFP:integer:=10;--Vertical Front Porch
constant VBP:integer:=33;--Vertical Back Porch
constant VRet:integer:=2;--Vertical Retrace);
v_pol : STD_LOGIC := '0' --vertical sync pulse polarity (1 = positive, 0 = negative)
);
Port ( clk : in STD_LOGIC;
LED0: out std_logic;
vga_r: out std_logic_vector(4 downto 0);
vga_g: out std_logic_vector(5 downto 0);
vga_b: out std_logic_vector(4 downto 0);
vga_vs: out std_logic;
vga_hs: out std_logic);
end vga;
architecture Behavioral of vga is
signal COUNT : integer range 0 to 100000000;
constant x_counter: integer := HR + HFP + HBP + HRet;
constant y_counter: integer := VR + VFP + VBP + VRet;
signal newCounter: integer range 0 to 4 := 0;
signal newClk: std_logic;
begin
alive: process(CLK)
begin
if rising_edge(CLK) then
COUNT <= COUNT + 1;
if COUNT = 100000000 then
COUNT <= 0;
end if;
if COUNT < 100000000/2 then
-- LED0 <= '1';
else
-- LED0 <= '0';
end if;
end if;
end process;
prescaler: process(clk)
begin
if rising_edge(clk) then
newCounter <= newCounter +1;
if newCounter = 4 then
newClk <= ‘1’;
newCounter <= 0;
else
newClk <= ‘0’;
end if;
end if;
end process;
screen:process(newClk)
VARIABLE h_count : INTEGER RANGE 0 TO x_counter - 1 := 0; --horizontal counter (counts the columns)
VARIABLE v_count : INTEGER RANGE 0 TO y_counter - 1 := 0; --vertical counter (counts the rows)
begin
-- Horizontal 640
-- Vertical 480
if rising_edge(newClk) then
-- Increase Horizontal counter
if (h_count < x_counter - 1 ) then
h_count := h_count + 1;
else
h_count := 0 ;
-- Increase Vertical counter
if (v_count < y_counter - 1 ) then
v_count := v_count + 1;
else
v_count := 0 ;
end if;
end if;
--horizontal sync signal
IF(h_count < HR + HFP OR h_count > HR + HFP + HRet) THEN
vga_hs <= NOT h_pol; --deassert horiztonal sync pulse
LED0 <= NOT h_pol;
ELSE
vga_hs <= h_pol; --assert horiztonal sync pulse
LED0 <= h_pol;
END IF;
--vertical sync signal
IF(v_count < VR + VFP OR v_count > VR + VFP + VRet) THEN
vga_vs <= NOT v_pol; --deassert vertical sync pulse
ELSE
vga_vs <= v_pol; --assert vertical sync pulse
END IF;
end if;
end process;
vga_r <= "11111";
vga_g <= "000000";
vga_b <= "00000";
end Behavioral;
Best Answer
You assign constant values to your VGA color lines, which will not work.
An analog VGA monitor expects to see a reference "black" level during part of the off-screen duration of the trace. If you drive a substantially non-zero value there, it will adapt to the idea that this voltage means black, and you will not get the expected rectangle of color (on some monitors, you might get a brief flash of color upon connection, before going to all black).
You will need to toggle your color lines between the desired color and black during the periods of time when they should be signalling color in the active area or black reference outside of it.
Two very useful tools will be a timing diagram of what VGA should look like, and if possible an oscilloscope comparing your signal to that of a VGA card setup to output something similar (full color screensaver?)