VHDL VGA sync circuit

你说的曾经没有我的故事 提交于 2019-12-08 10:32:33

问题


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;


回答1:


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';



回答2:


Just for interest, here's a single-process refactoring of the above.

It's considerably shorter and, to my eyes at least, much easier to understand, modify and get right. Multiple trivial processes with unnecessary signals simply to communicate between them obscure the design (as you noted!) - and provide a fertile breeding ground for bugs.

One warning : I have not verified that this is an exact implementation of your design; if you choose to use it, that would be your responsibility.

Opinions welcome.

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"
-- derived constants to make code clearer
constant H_Last       : integer := HD+HF+HB+HR-1;
constant H_Sync_First : integer := HD+HF;
constant H_Sync_Last  : integer := HD+HF+HR-1;
constant V_Last       : integer := VD+VF+VB+VR-1;
constant V_Sync_First : integer := VD+VF;
constant V_Sync_Last  : integer := VD+VF+VR-1;

-- sync counters,  two counters for the horizontal and vertical scans
signal v_count : unsigned(9 downto 0);
signal h_count : unsigned(9 downto 0);

--status signal
signal pixel_tick: std_logic;

begin
    --register
    process(clk,reset)
        begin
            if (reset='1') then
                pixel_tick   <= '0';
                v_count      <= (others=>'0');
                h_count      <= (others=>'0');
                vsync       <= '0';
                hsync       <= '0';
            elsif(clk'event and clk='1')then
                pixel_tick     <= not pixel_tick;

                -- H and V pixel counters
                if pixel_tick = '1' then
                   if h_count = h_last then
                      h_count <= (others=>'0');
                      -- and start the next line
                      if v_count = v_last then
                         v_count <= (others=>'0');
                      else
                         v_count <= v_count + 1;
                      end if;
                   else
                      h_count <= h_count + 1;
                   end if;
                end if;

                -- default assignments for sync
                hsync <= '0';
                vsync <= '0';
                -- H and V sync pulses
                if h_count >= H_Sync_First and h_count <= H_Sync_Last then
                   hsync <= '1';
                end if;
                if v_count >= V_Sync_First and v_count <= V_Sync_Last then
                   vsync <= '1';
                end if;
            end if;
    end process;

    --video on/off ... was unregistered so I'll leave it that way
    video_on <= '1' when (h_count < HD) and (v_count < VD) else '0';

    --output signals 
    pixel_x <= std_logic_vector(h_count);
    pixel_y <= std_logic_vector(v_count);
    p_tick <= pixel_tick;

end Behavioral;



回答3:


The buffers (register is a better name, because it's not an output buffer) are needed -- not only to suppress glitches --, but rather then to ensure equal output delay timings for every pin (v_sync, h_sync and color). If you do not use the registers before your downstream output buffer, you will get bad color effects on the screen.

Please be aware, that your x,y coordinate counter circuit addresses the next pixel not the current. So there must be a delays between the counter values and h/v_sync depending on the delay between counter -> get-pixel-information -> pixel color output.



来源:https://stackoverflow.com/questions/26876103/vhdl-vga-sync-circuit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!