VGA ROM - red-bote/VHDL_Demos GitHub Wiki

Demonstrates initializing Block RAM from external data file for loading image data to display on a VGA monitor.

rams_20c is used in this project to demonstrate file IO with VHDL. However, on the Artix-7 it does not seem to infer a Block RAM with the data only being 64-bytes long.

In a new Vivado project import rams_20c.vhd and copy the data file to the same directory that Vivado copied the imported rams_20c.vhdl e.g.

src/VHDL_Demos/vga/vga_bitmap/vga_bitmap.srcs/sources_1/imports/HDL_Coding_Techniques/rams/rams_20c.vhd

In this project a new module crtc is created to encapsulate the VGA Controller and related logic:

entity vga_top is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           Hsync : out STD_LOGIC;
           Vsync : out STD_LOGIC;
           vgaRed : out STD_LOGIC_VECTOR (3 downto 0);
           vgaGreen : out STD_LOGIC_VECTOR (3 downto 0);
           vgaBlue : out STD_LOGIC_VECTOR (3 downto 0));
end vga_top;

architecture Behavioral of vga_top is
    signal clk_count : std_logic_vector(3 downto 0);
    signal clk_vga : std_logic;
    signal reset_l : std_logic;
begin
    u_clkdiv : entity work.counters_1
    port map(
        C => clk,
        CLR => reset,
        Q => clk_count
        );

    reset_l <= not reset;

    u_crtc : entity work.crtc
    port map(
        i_clk_vga => clk_count(1), -- pixel clock set to 25Mhz
        i_reset_l => reset_l,
        o_hsync => Hsync,
        o_vsync => Vsync,
        o_red => vgaRed,
        o_green => vgaGreen,
        o_blue => vgaBlue
        );
end Behavioral;

The crtc (CRT Controller) architecture creates an instance of rams_20c. It is used as a ROM so we and din are terminated with 0.

ram_addr is a 6-bit but formed from vga_row and vga_col and illustrates the conversion of a VHDL integer type to a std_logic_vector using the unsigned macro (requires use IEEE.NUMERIC_STD.ALL).

The VGA outputs are driven by arbitrary connections to signal bus ram_dout.

entity crtc is
    Port ( i_clk_vga : in STD_LOGIC;
           i_reset_l : in STD_LOGIC;
           o_hsync : out STD_LOGIC;
           o_vsync : out STD_LOGIC;
           o_red : out STD_LOGIC_VECTOR (3 downto 0);
           o_green : out STD_LOGIC_VECTOR (3 downto 0);
           o_blue : out STD_LOGIC_VECTOR (3 downto 0));
end crtc;

architecture Behavioral of crtc is
    signal vga_col : integer;
    signal vga_row : integer;
    signal disp_ena : std_logic;

    signal ram_addr : std_logic_vector(5 downto 0);   
    signal ram_dout : std_logic_vector(31 downto 0);
begin
    u_vga_control : entity work.vga_controller
        generic map (
            h_pulse  => 96,
            h_bp     => 46,
            h_pixels => 640,
            h_fp     => 16,
            h_pol    => '0',
            v_pulse  => 2,
            v_bp     => 33,
            v_pixels => 480,
            v_fp     => 10,
            v_pol    => '0')
        port map(
            pixel_clk => i_clk_vga, -- 25 Mhz
            reset_n => i_reset_l,
            h_sync => o_hsync,
            v_sync => o_vsync,
            disp_ena => disp_ena,
            column => vga_col,
            row => vga_row,
            n_blank => open,
            n_sync => open
        );

    p_addr_gen : process(vga_row, vga_col)
        variable row_bits : std_logic_vector(9 downto 0) := std_logic_vector(to_unsigned(vga_row, 10));
        variable col_bits : std_logic_vector(9 downto 0) := std_logic_vector(to_unsigned(vga_col, 10));
    begin
        -- decode row and column into a 6-bit RAM address
        ram_addr <= row_bits(7 downto 6) & col_bits(8 downto 5);
    end process p_addr_gen;

    u_vram : entity work.rams_20c
    port map(
         clk => i_clk_vga,
         we => '0',
         addr => ram_addr,
         din => (others => '0'),
         dout => ram_dout
         );

    o_red    <= ram_dout(11 downto 8) when disp_ena = '1' else (others => '0');
    o_green  <= ram_dout(7 downto 4) when disp_ena = '1' else (others => '0');
    o_blue   <= ram_dout(3 downto 0) when disp_ena = '1' else (others => '0');

end Behavioral;

Next