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;