0

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;

thoughtMaze
  • 3
  • 1
  • 7

3 Answers3

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';
  • thank you for your wonderful explanations David. I think I mostly get it now. But I am still confused about the v and h_count_reg signals, in that, I don't understand where they get their/any original value. for example, this statement: v_count_next <= v_count_reg+1; too me it looks like nothing + 1. Hope that makes sense. – thoughtMaze Nov 13 '14 at 16:17
  • "v_count_next <= v_count_reg+1; too me it looks like nothing + 1" ... in the first cycle, it is... But the clocked process then latches `v_count_next` into `v_count_reg` at which point, it becomes 1 + 1. –  Nov 13 '14 at 16:27
  • ahhh, very nice, thank you Brian! I have one last question, I don't don't fully understand how they downsize the clock to 25MHz. I know it happens here "--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'; " last question i Swear! – thoughtMaze Nov 13 '14 at 18:12
  • look for reset re: v and h_count_reg signals wherein they are initialized to all '0's. The clock 'downsizing' appears to be related to pixel_tick, an enable. The mod2 bit is a divide by 2 from an apparent 50 Mhz clock. Comments aren't necessarily the appropriate venue for additional questions. Once you have the reputation you can move comments to a discussion. –  Nov 13 '14 at 18:24
1

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;
  • thanks a lot Brian, I just tested my original code, works like a dream, well its not mine, it's text book – thoughtMaze Nov 13 '14 at 16:03
  • I will test your re-factoring when i get the chance – thoughtMaze Nov 13 '14 at 16:22
  • mind mentioning which textbook? I have my suspicions, trouble is there's more than one teaching terrible code... –  Nov 13 '14 at 16:24
  • haha sure, it Wiley FPGA Prototyping By VHDL Examples Xilinx Spartan 3 Version – thoughtMaze Nov 13 '14 at 18:15
  • tried testing this, some compile time errors with certain undefined signals h_count_reg ect... but when i corrected them still wouldnt implement, was telling my switches are missing haha, since they are in the constraint file.. oh well – thoughtMaze Nov 19 '14 at 00:41
  • My apologies for the name errors ... now resolved. I don't understand what you mean by the "switches are missing" error. –  Nov 19 '14 at 12:01
  • Thanks Brian, yeah sorry the circuit I was trying had switches to control red, green, blue output,,, sorry my fault. Either way I managed to bang out pong on the vga!!.. thanks for all your help! – thoughtMaze Nov 21 '14 at 16:57
0

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.

Paebbels
  • 15,573
  • 13
  • 70
  • 139