Search code examples
vhdlvga

VHDL VGA sync circuit


Can some one please tell me how this circuit increments h_count_reg and v_count_reg?? I don't really see it. Also what do they mean by the output is buffered exactly? It's just delayed by one pixel? don't really see that either. thanks!

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity vgaController is Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; hsync : out STD_LOGIC; vsync : out STD_LOGIC; video_on : out STD_LOGIC; p_tick : out STD_LOGIC; pixel_x : out STD_LOGIC_VECTOR (9 downto 0); pixel_y : out STD_LOGIC_VECTOR (9 downto 0)); end vgaController; architecture Behavioral of vgaController is -- VGA 640 -by - 480 sync p a r a m e t e r s constant HD: integer:=640; --horizontal display area constant HF: integer:=16 ; --h. front porch constant HB: integer:=48 ; --h. back porch constant HR: integer:=96 ; --h. retrace "Sync Pulse" constant VD: integer:=480; -- vertical display area constant VF: integer:=10 ; -- v. front porch constant VB: integer:=33 ; -- v. back porch constant VR: integer:=2 ; -- v. retrace "sync pulse" -- mod-2 counter signal mod2_reg, mod2_next : std_logic;--mod-2 counter to generate the 25-MHz enable tick -- sync counters, two counters for the horizontal and vertical scans signal v_count_reg, v_count_next : unsigned(9 downto 0); signal h_count_reg, h_count_next : unsigned(9 downto 0); --To remove --potential glitches, output buffers are inserted for the hsync and vsync signals. This leads --to a one-clock-cycle delay. add a similar buffer for the rgb signal in the pixel --generation circuit to compensate for the delay. -- output buffer signal v_sync_reg, h_sync_reg: std_logic; signal v_sync_next ,h_sync_next : std_logic; --status signal signal h_end , v_end , pixel_tick: std_logic; begin --register process(clk,reset) begin if (reset='1') then mod2_reg <='0'; v_count_reg <=(others=>'0'); h_count_reg <=(others=>'0'); v_sync_reg <='0'; h_sync_reg <='0'; elsif(clk'event and clk='1')then mod2_reg <=mod2_next; v_count_reg <=v_count_next; h_count_reg <=h_count_next; v_sync_reg <=v_sync_next; h_sync_reg <=h_sync_next; end if; end process; --mod-2 circuit to generate 25 MHz enable tick mod2_next <= not mod2_reg; -- 25 MHz pixel tick pixel_tick <= '1' when mod2_reg = '1' else '0'; --status h_end <= --end of horizonal counter '1' when h_count_reg = (HD+HF+HB+HR-1) else --799 '0'; v_end <= --end of vertial counter '1' when v_count_reg = (VD+VF+VB+VR-1) else --524 '0'; -- mod-800 horizontal sync counter process(h_count_reg,h_end,pixel_tick) begin if (pixel_tick='1') then --25 MHz tick if h_end='1' then h_count_next <= (others=>'0'); else h_count_next <= h_count_reg+1; end if; else h_count_next <= h_count_reg; end if; end process; -- mode-525 vertical sync counter process(v_count_reg,h_end,v_end,pixel_tick) begin if (pixel_tick='1' and h_end='1') then if (v_end='1') then v_count_next <= (others=>'0'); else v_count_next <= v_count_reg+1; end if; else v_count_next <= v_count_reg; end if; end process; -- horizontal and vertial sync, buffered to avoid glitch h_sync_next <= '1' when (h_count_reg >= (HD+HF)) --656 and (h_count_reg <= (HD+HF+HR-1)) else --751 '0'; v_sync_next <= '1' when (v_count_reg >= (VD+VF)) --490 and (v_count_reg <= (VD+VF+VR-1)) else --491 '0'; --video on/off video_on <= '1' when (h_count_reg < HD) and (v_count_reg < VD) else '0'; --output signals hsync <= h_sync_reg; vsync <= v_sync_reg; pixel_x <= std_logic_vector(h_count_reg); pixel_y <= std_logic_vector(v_count_reg); p_tick <= pixel_tick; end Behavioral;


Solution

  • The vertical and horizontal counters are spread across two processes:

    --register
    process(clk,reset)
        begin
            if (reset='1') then
                mod2_reg     <='0';
                v_count_reg  <=(others=>'0');
                h_count_reg  <=(others=>'0');
                v_sync_reg   <='0';
                h_sync_reg   <='0';
            elsif(clk'event and clk='1')then
                mod2_reg     <=mod2_next;
                v_count_reg  <=v_count_next;
                h_count_reg  <=h_count_next;
                v_sync_reg   <=v_sync_next;
                h_sync_reg   <=h_sync_next;
            end if;
    end process;
    

    Where in the elsif condition the counters are loaded from v_count_next and h_count_next, which are produced in two different processes:

    -- mod-800 horizontal sync counter
    process(h_count_reg,h_end,pixel_tick)
        begin
            if (pixel_tick='1') then --25 MHz tick
                if h_end='1' then 
                    h_count_next <= (others=>'0');
                else
                    h_count_next <= h_count_reg+1;
                end if;
            else
                h_count_next <= h_count_reg;
            end if;
    end process;
    
    -- mode-525 vertical sync counter
    process(v_count_reg,h_end,v_end,pixel_tick)
        begin
            if (pixel_tick='1' and h_end='1') then
                if (v_end='1') then
                    v_count_next <= (others=>'0');
                else
                    v_count_next <= v_count_reg+1;
                end if;
            else
                v_count_next <= v_count_reg;
            end if;
    end process;
    

    (And about now you could imagine it's a good idea to actually label process statements).

    As far as the "buffered":

    --To remove
    --potential glitches, output buffers are inserted for the hsync and vsync signals. This leads
    --to a one-clock-cycle delay. add a similar buffer for the rgb signal in the pixel
    --generation circuit to compensate for the delay.
    -- output buffer
    signal v_sync_reg, h_sync_reg: std_logic;
    signal v_sync_next ,h_sync_next : std_logic;
    --status signal
    signal h_end , v_end , pixel_tick: std_logic;
    

    Those are the last two assignments in the --register process above. And from the comments the one clock delay through flip flops is to remove combinatoric glitches caused by relational operators:

    h_sync_next <=
        '1' when (h_count_reg >= (HD+HF))  --656
              and (h_count_reg <= (HD+HF+HR-1)) else --751
        '0';
    
    v_sync_next <=
        '1' when (v_count_reg >= (VD+VF))  --490
             and (v_count_reg <= (VD+VF+VR-1)) else --491
        '0';