altera - VHDL VGA interface -
i've been modelling vga interface on de0 board. have following model 640x480 display refreshes @ 60hz:
main model:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity vga port (clk : in std_logic; -- demo had 2 bit vector vga_hs, vga_vs : out std_logic; vga_r, vga_g, vga_b : out std_logic_vector(3 downto 0)); end entity vga; architecture a1 of vga signal rst, clk25 : std_logic; -- rst resets pixel clock begin sync1 : entity work.sync(a1) port map (clk25, vga_hs, vga_vs, vga_r, vga_g, vga_b); clk_25 : entity work.pll(rtl) port map (clk, rst, clk25); end architecture a1; sync model:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity sync port( clk : in std_logic; h_sync, v_sync : out std_logic; r, g, b : out std_logic_vector(3 downto 0) ); end entity sync; architecture a1 of sync signal h_pos: integer range 0 800:=0; signal v_pos : integer range 0 520:=0; begin timing :process(clk) begin if rising_edge(clk) if (h_pos = 480 or v_pos = 280) -- middle of screen pic res/2 + (fp + sync + bp) r <= (others => '1'); g <= (others => '1'); b <= (others => '1'); else r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; if (h_pos < 800) h_pos <= h_pos + 1; else h_pos <= 1; if (v_pos < 520) v_pos <= v_pos + 1; else v_pos <= 1; end if; end if; if (h_pos > 16 , h_pos < 112 ) -- h_pos between end of fp , end of h_sync h_sync <= '0'; -- h_sync needs stay low during display else h_sync <= '1'; end if; if (v_pos > 8 , v_pos < 10 ) --v_pos between end of fp , end of v_sync v_sync <= '0'; -- v_sync needs stay low during display else v_sync <= '1'; end if; if ((h_pos > 0 , h_pos < 160) or (v_pos > 0 , v_pos < 40 )) then--during of sync i.e fp + sync + bp colour signals stay low r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; end if; end process timing; end architecture a1; ----------amendments made model 09/02 13:42---------- the other direct instantiation pll generated quartus ii seems work fine.. thank mr zilmer :). model compiles fine. load de0. connect monitor , nothing on display. should display cross in centre of screen. display using samsung 1920x1080. stop model displaying anything? or have made obvious mistake in model. have changed of standard timing values fit 60hz refresh 25mz clk. d
your vhdl code entity sync doesn't analyze. missing end if , initial values h_sync , v_sync violate subtype constraint:
signal h_pos: integer range 1 800 := 0; signal v_pos: integer range 1 520 := 0; where 0 outside bounds of 1 800 or 1 520.
this raises question of whether or not have architecture entity sync, or whether sync unbound. either of might give incorrect indication (and error isn't demonstrated in question).
we can use testbench demonstrate sync in simulation 25 mhz clock:
library ieee; use ieee.std_logic_1164.all; --use ieee.numeric_std.all; entity sync port ( clk: in std_logic; h_sync, v_sync: out std_logic; r, g, b: out std_logic_vector(3 downto 0) ); end entity sync; architecture a1 of sync signal h_pos: integer range 1 800 := 1; -- := 0; signal v_pos: integer range 1 520 := 1; -- := 0; begin timing: process (clk) begin if rising_edge(clk) if h_pos = 480 or v_pos = 280 -- middle of screen r <= (others => '1'); g <= (others => '1'); b <= (others => '1'); else r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; if h_pos < 800 h_pos <= h_pos + 1; else h_pos <= 1; if v_pos < 520 v_pos <= v_pos + 1; else v_pos <= 1; end if; if h_pos > 16 , h_pos < 112 h_sync <= '0'; -- h_sync low during display else h_sync <= '1'; end if; if v_pos > 8 , v_pos < 10 v_sync <= '0'; -- v_sync low during display else v_sync <= '1'; end if; if (h_pos > 1 , h_pos < 160) or (v_pos > 1 , v_pos < 40 ) -- black during blanking r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; end if; end if; -- added misssing end if end process timing; end architecture a1; library ieee; use ieee.std_logic_1164.all; entity sync_tb end entity; architecture foo of sync_tb signal clk: std_logic := '0'; signal h_sync: std_logic; signal v_sync: std_logic; signal r, g, b: std_logic_vector (3 downto 0); begin dut: entity work.sync port map ( clk => clk, h_sync => h_sync, v_sync => v_sync, r => r, g => g, b => b ); clock: process begin wait 20 ns; -- clock period 25 mhz = 40 ns; clk <= not clk; if > 20 ms -- 1 frame time plus bit wait; end if; end process; end architecture; and troubleshoot:
the first thing notice h_sync wrong. note v_sync appears around 16.667 ms (1/60th of second).
we can add h_pos , v_pos counters can @ h_sync, know h_pos counter running v_sync can see in right neighborhood of 60 hz.
so picked wrong place add end if. correcting separates operating counters operating on outputs (h_sync, v_sync , r,g,b).
timing: process (clk) begin if rising_edge(clk) if h_pos = 480 or v_pos = 280 -- middle of screen r <= (others => '1'); g <= (others => '1'); b <= (others => '1'); else r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; if h_pos < 800 h_pos <= h_pos + 1; else h_pos <= 1; if v_pos < 520 v_pos <= v_pos + 1; else v_pos <= 1; end if; end if; -- separate counters produce -- hsync if h_pos > 16 , h_pos < 112 h_sync <= '0'; -- h_sync low during display else h_sync <= '1'; end if; -- vsync if v_pos > 8 , v_pos < 10 v_sync <= '0'; -- v_sync low during display else v_sync <= '1'; end if; -- blanking if (h_pos > 1 , h_pos < 160) or (v_pos > 1 , v_pos < 40 ) r <= (others => '0'); g <= (others => '0'); b <= (others => '0'); end if; end if; end process timing; we have h_sync now:
notice can see vertical blanking interval too.
zooming in can see there horizontal white line @ v_pos 280:
along vertical line @ h_pos 480 (+1):
and looks might work.
the design change might tempted make start visible portion of line @ h_pos = 0 , the visible portion of frame @ v_pos = 0. allow else address pixels writing in frame buffer without adding additional pixel counters or having offset arithmetic. (pixel addressing starts @ 0 x , y axis).




Comments
Post a Comment