问题
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