here my code. Look that I force the HSYNC to match the end of the line: 655 (for the sync) and the vsync to match the last scanline 262.5. CLOCK_50 = 25.17Mhz and CLOCK_25=12.58Mhz. I got less jitter using 25Mhz for the horizontal counter:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity vgaoutput is
generic(
front_porch : integer := 100;
top_border : integer := 35
);
port(CLOCK_50 : in std_logic;
CLOCK_25 : in std_logic;
VSYNC_IN : in std_logic;
HSYNC_IN : in std_logic;
RGB_IN : in unsigned(2 downto 0); -- r, g, b
VGA_OUT : out unsigned(4 downto 0) -- r, g, b, hsync, vsync
);
end vgaoutput;
architecture behavioral of vgaoutput is
signal hcount : unsigned(9 downto 0) := (others => '0');
signal vcount : unsigned(9 downto 0) := (others => '0');
signal pixelcolor : unsigned(2 downto 0) := "000";
signal videoon, videov, videoh, hsync, vsync : std_ulogic := '0';
signal reset : std_ulogic := '1';
signal vblank : std_ulogic := '1';
signal hblank : std_ulogic := '1';
signal hcount_in : unsigned(10 downto 0) := (others => '0');
signal vcount_in : unsigned(9 downto 0) := (others => '0');
type line_memory_t is array (0 to 640*204-1) of unsigned(2 downto 0);
shared variable line_memory : line_memory_t;
begin
-----------------------------------------
-- RGB INPUT
-----------------------------------------
vsyncin: process(CLOCK_25)
begin
if (rising_edge(CLOCK_25)) then
vblank <= '1';
if (VSYNC_IN = '1' and vcount_in >= 262 and hcount_in(10 downto 1) >= 399) then
vblank <= '0';
end if;
end if;
end process;
hsyncin: process(CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
hblank <= '1';
if (HSYNC_IN = '1' and hcount_in(10 downto 1) >= 655) then
hblank <= '0';
end if;
end if;
end process;
hcounter_in: process(CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
if hblank = '0' then
hcount_in <= (others => '0');
else
hcount_in <= hcount_in + 1;
end if;
end if;
end process;
vcounter_in: process (CLOCK_25)
begin
if(rising_edge(CLOCK_25)) then
if vblank = '0' then
vcount_in <= (others => '0');
elsif hblank = '0' then
vcount_in <= vcount_in + 1;
end if;
end if;
end process;
pixel_in: process(CLOCK_25)
variable addr: integer range 0 to 153600;
variable row, col: integer range 0 to 153600;
begin
if (rising_edge(CLOCK_25)) then
if (hcount_in(10 downto 1) >= front_porch and hcount_in(10 downto 1) < front_porch+640 and vcount_in >= top_border and vcount_in < top_border+204) then
col := to_integer(hcount_in(10 downto 1)) - front_porch;
row := to_integer(vcount_in) - top_border;
addr := (row * 640) + col;
line_memory(addr) := RGB_IN;
end if;
end if;
end process;
-----------------------------------------
-- VGA OUTPUT
-----------------------------------------
vcounter: process (CLOCK_50, hcount) --, vblank)
begin
if(rising_edge(CLOCK_50)) then
if hcount = 799 then
vcount <= vcount + 1;
end if;
if vcount = 525 then
vcount <= (others => '0');
end if;
end if;
end process;
v_sync: process(CLOCK_50, vcount)
begin
if(rising_edge(CLOCK_50)) then
vsync <= '1';
if (vcount <= 492 and vcount >= 490) then
vsync <= '0';
end if;
end if;
end process;
hcounter: process (CLOCK_50)
begin
if (rising_edge(CLOCK_50)) then
hcount <= hcount + 1;
if hcount=799 then
hcount <= (others => '0');
end if;
end if;
end process;
h_sync: process (CLOCK_50, hcount)
begin
if (rising_edge(CLOCK_50)) then
hsync <= '1';
if (hcount <= 752 and hcount >= 655) then
hsync <= '0';
end if;
end if;
end process;
pixel_out: process (CLOCK_50)
variable addr: integer range 0 to 153600;
variable row, col: integer range 0 to 153600;
begin
if (rising_edge(CLOCK_50)) then
if (hcount < 640 and vcount < 408) then
col := to_integer(hcount);
row := to_integer(vcount(9 downto 1));
addr := (row * 640) + col;
pixelcolor(2 downto 0) <= line_memory(addr)(2 downto 0);
end if;
end if;
end process;
process (vcount)
begin
videov <= '1';
if vcount > 479 then
videov <= '0';
end if;
end process;
process (hcount)
begin
videoh <= '1';
if hcount > 639 then
videoh <= '0';
end if;
end process;
videoon <= videoh and videov;
VGA_OUT(4 downto 2) <= pixelcolor and videoon&videoon&videoon;
VGA_OUT(1 downto 0) <= hsync & vsync;
end behavioral;