-- VGA interface library ieee; use ieee.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.STD_LOGIC_ARITH.ALL; entity vga is port ( clk25 : in std_logic; -- clock rst : in std_logic; -- reset -- Alphabet ROM interface ROM_data : in std_logic_vector(0 to 15); line_address : out std_logic_vector(3 downto 0); -- line number within character SRAM_address : out std_logic_vector(10 downto 0); -- video out hsync : inout std_logic; -- horizontal synchro vsync : out std_logic; -- vertical synchro r : out std_logic_vector(1 downto 0); g : out std_logic_vector(1 downto 0); b : out std_logic_vector(1 downto 0)); end vga; -------------------------------------------------------------------------------- architecture bhv of vga is constant MAX_ROWS : natural := 30; constant MAX_SYMBOLS : natural := 39; -- vga timing signal pixel_data : std_logic_vector(0 to 15); signal pixel, line : natural; -- horizontal/vertical counters signal char_row, char_col : natural range 0 to 15; -- row/col within char signal text_row: natural range 0 to MAX_ROWS; -- text row signal text_col: natural range 0 to MAX_SYMBOLS; -- text column signal h_blank, v_blank, blank : std_logic; -- blanking -- Mode clock h v P HB HE BP L VB VE BL -- 640x480 25MHz 31.5kHz 60Hz 629 653 747 794 480 494 496 528 -- constant P: natural:= 623; -- blanking start constant HB: natural:= 652; -- h-sync start constant HE: natural:= 746; -- h-sync end constant BP: natural:= 793; -- blanking end constant L: natural:= 479; -- v blanking start constant VB: natural:= 493; -- v-sync start constant VE: natural:= 495; -- v-sync end constant BL: natural:= 527; -- v blanking end begin ------------------------------------ -- horizontal timing horizontal_sync: process(clk25, rst) begin if rst = '1' then pixel <= 0; elsif rising_edge(clk25) then if pixel = BP then pixel <= 0; else pixel <= pixel + 1; end if; end if; end process horizontal_sync; horizontal_text: process(clk25, rst) begin if rst = '1' then char_col <= 0; text_col <= 0; elsif rising_edge(clk25) then if pixel > P then char_col <= 0; text_col <= 0; else if char_col = 15 then char_col <= 0; text_col <= text_col + 1; else char_col <= char_col + 1; end if; end if; end if; end process horizontal_text; -- blanking horiz_blanking: process (clk25, rst) begin if rst = '1' then h_blank <= '1'; elsif rising_edge(clk25) then if (pixel > P) and (pixel < BP) then h_blank <= '1'; else h_blank <= '0'; end if; end if; end process horiz_blanking; -- horizontal synchronization pulse horizontal_pulse: process(clk25, rst) begin if rst = '1' then hsync <= '0'; elsif rising_edge(clk25) then if (pixel >= HB) and (pixel < HE) then hsync <= '0'; else hsync <= '1'; end if; end if; end process horizontal_pulse; ------------------------------------ -- vertical timing vertical_sync: process(hsync, rst) begin if rst = '1' then line <= 0; elsif rising_edge(hsync) then if line = BL then line <= 0; else line <= line + 1; end if; end if; end process vertical_sync; vertical_text: process(hsync, rst) begin if rst = '1' then char_row <= 0; text_row <= 0; elsif rising_edge(hsync) then if line > L then char_row <= 0; text_row <= 0; else if char_row = 15 then char_row <= 0; text_row <= text_row + 1; else char_row <= char_row + 1; end if; end if; end if; end process vertical_text; -- blanking vertical_blanking: process(hsync, rst) begin if rst = '1' then v_blank <= '1'; elsif rising_edge(hsync) then if (line > L) and (line < BL) then v_blank <= '1'; else v_blank <= '0'; end if; end if; end process vertical_blanking; -- vertical synchronization pulse vertical_pulse: process(hsync, rst) begin if rst = '1' then vsync <= '0'; elsif rising_edge(hsync) then if (line >= VB) and (line < VE) then vsync <= '0'; else vsync <= '1'; end if; end if; end process vertical_pulse; SRAM_address_calculation: process (clk25, rst) begin if (rst = '1') then SRAM_address <= (others => '0'); line_address <= (others => '0'); elsif rising_edge(clk25) then line_address <= conv_std_logic_vector(char_row, line_address'length); if (text_row = 0) and (text_col = 0) and (pixel > P) then -- ler o 1º caracter SRAM_address <= (others => '0'); else -- temos que ler o caracter seguinte em relação àquele que está a ser visualizado SRAM_address <= conv_std_logic_vector(text_row * MAX_SYMBOLS + text_col + 1, SRAM_address'length); end if; end if; end process SRAM_address_calculation; process (clk25, rst) begin if (rst = '1') then pixel_data <= (others => '0'); elsif rising_edge(clk25) then if (char_col = 0) then pixel_data <= ROM_data; else pixel_data <= pixel_data(1 to 15) & '0'; end if; end if; end process; ------------------------------------ -- output signals blank <= h_blank or v_blank; r <= "00" when blank = '1' else (pixel_data(0), pixel_data(0)); g <= "00" when blank = '1' else (pixel_data(0), pixel_data(0)); b <= "00" when blank = '1' else "11"; end bhv;