⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga_driver.vhd

📁 VGA控制器源码
💻 VHD
字号:
-- ================================================================================
-- (c) 2005 Altera Corporation. All rights reserved.
-- Altera products are protected under numerous U.S. and foreign patents, maskwork
-- rights, copyrights and other intellectual property laws.
-- 
-- This reference design file, and your use thereof, is subject to and governed
-- by the terms and conditions of the applicable Altera Reference Design License
-- Agreement (either as signed by you, agreed by you upon download or as a
-- "click-through" agreement upon installation andor found at www.altera.com).
-- By using this reference design file, you indicate your acceptance of such terms
-- and conditions between you and Altera Corporation.  In the event that you do
-- not agree with such terms and conditions, you may not use the reference design
-- file and please promptly destroy any copies you have made.
-- 
-- This reference design file is being provided on an "as-is" basis and as an
-- accommodation and therefore all warranties, representations or guarantees of
-- any kind (whether express, implied or statutory) including, without limitation,
-- warranties of merchantability, non-infringement, or fitness for a particular
-- purpose, are specifically disclaimed.  By making this reference design file
-- available, Altera expressly does not recommend, suggest or require that this
-- reference design file be used in combination with any other product not
-- provided by Altera.
--================================================================================
--
-- This design implements an 8-bit 640x480 VGA driver.  The driver sources
-- it's data from a 256 word buffer. The frame buffer holds 32-bit 
-- words therefore each word read from the frame buffer will contain 4 8-bit pixels.  
-- The buffer can therefore hold 1024 pixels at a time.  
--
-- For more details on VGA timing view the image_package.vhd file.
--
--


LIBRARY ieee,work;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_arith.ALL;
USE work.image_package.ALL;

ENTITY vga_driver IS 
	PORT (
		reset_n			: IN std_logic;
		clk			: IN std_logic; -- Avalon clock
		clock25			: IN std_logic; -- 25 MHz clock to run VGA internals
		vga_clk			: IN std_logic; -- 25 MHz clock to drive to Video DAC, could be tied to clock25
		
		-- control signals
		enable_irq		: IN std_logic;
		enable			: IN std_logic;
		mode			: IN std_logic;

		-- video memory signals
		video_data		: IN std_logic_vector(15 downto 0);
		video_address		: OUT std_logic_vector(31 downto 0);

		-- parameter signals from avalon slave interface
		num_lines		: IN std_logic_vector(9 downto 0);
		num_pixels_per_line	: IN std_logic_vector(9 downto 0);

		set_picture_end_irq	: OUT std_logic;

		-- blanking outputs to any external logic that might need it
		hblank			: OUT std_logic;
		vblank			: OUT std_logic;

		-- outputs to VGA daughter card
		clockext		: OUT std_logic;
		sync_n			: OUT std_logic := '0';
		sync_t			: OUT std_logic := '0';
		blank_n			: OUT std_logic := '0';
		M1			: OUT std_logic := '0';
		M2			: OUT std_logic := '0';
		vsync			: OUT std_logic;
		hsync			: OUT std_logic;
		R			: OUT std_logic_vector(7 downto 0);
		G			: OUT std_logic_vector(7 downto 0);
		B			: OUT std_logic_vector(7 downto 0)
	);
END vga_driver;

ARCHITECTURE rtl OF vga_driver IS

	SIGNAL pixel_counter		: std_logic_vector(9 downto 0);
	SIGNAL line_counter		: std_logic_vector(9 downto 0);	
	SIGNAL video_address_sig	: std_logic_vector(31 downto 0);
	SIGNAL video_address_sig_delay	: std_logic;
	SIGNAL stored_address		: std_logic_vector(31 downto 0);
	SIGNAL vblank_sig		: std_logic;
	SIGNAL vblank_delay		: std_logic;
	SIGNAL hblank_sig		: std_logic;
	SIGNAL clockext_sig		: std_logic;
	SIGNAL pixel_value : std_logic_vector(23 downto 0);

	-- These signals determine the location of an images smaller than
	-- 640x480 on the screen
	SIGNAL x_offset			: std_logic_vector(9 downto 0);
	SIGNAL y_offset			: std_logic_vector(9 downto 0);

	SIGNAL active			: std_logic;
	SIGNAL active_delay		: std_logic;

	SIGNAL actual_num_lines	: std_logic_vector(9 downto 0);
	SIGNAL actual_num_pixels_per_line : std_logic_vector(9 downto 0);

	TYPE TI8134B_state IS (initial, config1, config2, config3, config4);
	SIGNAL TI8134B_config_state : TI8134B_state;

	SIGNAL gnd			: std_logic;
	SIGNAL gnd_vector		: std_logic_vector(31 downto 0);

BEGIN

gnd <= '0';
gnd_vector <= (others => '0');

PROCESS(video_address_sig,mode,num_lines,num_pixels_per_line)
BEGIN
	IF mode = '0' THEN  -- normal mode
		video_address <= video_address_sig;
		actual_num_lines <= num_lines;
		actual_num_pixels_per_line <= num_pixels_per_line;
	ELSE  -- double pixel mode
		video_address <= '0' & video_address_sig(31 downto 1);
		actual_num_lines <= num_lines(8 downto 0) & '0';
		actual_num_pixels_per_line <= num_pixels_per_line(8 downto 0) & '0';
	END IF;
END PROCESS;

hblank <= hblank_sig;
vblank <= vblank_sig;
clockext <= vga_clk;

-- Drive the blanking signal to the TI8134B Video DAC
PROCESS(clock25, reset_n)
BEGIN
	IF reset_n = '0' THEN
		blank_n <= '0';
	ELSIF rising_edge(clock25) THEN
		blank_n <= hblank_sig AND vblank_sig;
	END IF;
END PROCESS;

-- Configure the TI8134B Video DAC on power-up
PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		TI8134B_config_state <= initial;
		sync_n <= '0';
		M1 <= '0';
		M2 <= '0';
		sync_t <= '0';
	ELSIF rising_edge(clock25) THEN
		CASE TI8134B_config_state IS
			WHEN initial =>
				TI8134B_config_state <= config1;
				sync_n <= '0';
				M1 <= '0';
				M2 <= '0';
				sync_t <= '0';
			WHEN config1 =>
				TI8134B_config_state <= config2;
				sync_n <= '1';
				M1 <= '0';
				M2 <= '0';
				sync_t <= '0';
			WHEN config2 =>
				TI8134B_config_state <= config3;
				sync_n <= '0';
				M1 <= '0';
				M2 <= '1';
				sync_t <= '0';
			WHEN config3 =>
				TI8134B_config_state <= config4;
				sync_n <= '0';
				M1 <= '0';
				M2 <= '1';
				sync_t <= '0';
			WHEN config4 =>
				TI8134B_config_state <= config4;
				sync_n <= '1';
				M1 <= '0';
				M2 <= '0';
				sync_t <= '0';
			WHEN others =>
				TI8134B_config_state <= config4;
				sync_n <= '1';
				M1 <= '0';
				M2 <= '0';
				sync_t <= '0';
		END CASE;
	END IF;
END PROCESS;

-- This is a roll-over counter which will count a period
-- from 0 to HWIDTH.  It is used to update the pixels as
-- horizontally across the screen.
pixel_count: PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		pixel_counter <= (others => '0');
	ELSIF rising_edge(clock25) THEN
		IF pixel_counter < HWIDTH THEN
			pixel_counter <= pixel_counter + 1;
		ELSE
			pixel_counter <= (others => '0');
		END IF;
	END IF;
END PROCESS;

-- This counter keeps track of the current line being displayed
-- on the screen.  It resets when it reaches a value of VDEPTH.
-- The line counter is enabled whenever the pixel counter has 
-- reached a value of END_HSYNC
line_count: PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		line_counter <= (others => '0');
	ELSIF rising_edge(clock25) THEN
		IF pixel_counter = END_HSYNC THEN
			IF line_counter < VDEPTH THEN
				line_counter <= line_counter + 1;
			ELSE
				line_counter <= (others => '0');
			END IF;
		END IF;
	END IF;		
END PROCESS;

-- The driver supports images that are smaller than 640x480.  It looks a little
-- nicer to display smaller images directly in the center of the screen so we 
-- need to calculate the offset in both the x and y domains.
PROCESS(clock25,reset_n)
	VARIABLE x_offset_reg : std_logic_vector(9 downto 0);
	VARIABLE y_offset_reg : std_logic_vector(9 downto 0);
BEGIN
	IF reset_n = '0' THEN
		x_offset_reg := (others => '0');
		y_offset_reg := (others => '0');
	ELSIF rising_edge(clock25) THEN
		IF vblank_sig = '0' THEN
			x_offset_reg := LINE_WIDTH - actual_num_pixels_per_line;
			y_offset_reg := NUMBER_LINES - actual_num_lines;
		END IF;
	END IF;
	-- divide offsets by 2 to balance borders on each side of image
	x_offset <= '0' & x_offset_reg(9 downto 1);
	y_offset <= '0' & y_offset_reg(9 downto 1);
END PROCESS;

-- Generation of the hsync and hblank pulses and address signal to line buffer
-- *** Important Note ***
-- This vga driver pulls images from a line buffer therefore the video adddress
-- signal to the line buffer will get reset after each line has been transmitted.
-- If at some point a frame buffer is needed instead of a line buffer then this
-- process will need to be modified such that the address gets reset on every
-- frame instead of on every line.
hsync_gen: PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		hsync <= '0';
		hblank_sig <= '0';
		video_address_sig <= (others => '0');
		active <= '0';
		vblank_sig <= '0';
		video_address_sig_delay <= '0';
	ELSIF rising_edge(clock25) THEN
		video_address_sig_delay <= video_address_sig(0);
		-- generate the blanking signal and the address to the line buffer
		IF (pixel_counter >= BEGIN_HBLANK AND pixel_counter < END_HBLANK) THEN
			hblank_sig <= '1';
		ELSE 
			hblank_sig <= '0';
		END IF;
		
		-- Generate the active signal.  This signal indicates when we are driving a pixel
		-- out.  The active singal would normally be asserted for the duration of hblank
		-- for a 640x480 image.  However, for smaller images we want to wrap a black border
		-- around the image.  Therefore the active signal will be of shorter duration than 
		-- the hblank signal when transmitting smaller images.
		IF (line_counter > (CONV_STD_LOGIC_VECTOR(BEGIN_VBLANK,10) + y_offset) AND line_counter <= (CONV_STD_LOGIC_VECTOR(END_VBLANK,10) - y_offset)) THEN
			IF (pixel_counter > (CONV_STD_LOGIC_VECTOR(BEGIN_HBLANK,10) + x_offset-2) AND pixel_counter <= (CONV_STD_LOGIC_VECTOR(END_HBLANK,10) - x_offset-2)) THEN
				-- This is an active window to increment the address counter
				active <= '1';
				video_address_sig <= video_address_sig + 1;
			ELSE 
				active <= '0';
				-- at the end of a line reset the address to the line buffer
				video_address_sig <= (others => '0');
			END IF;
		ELSE
			active <= '0';
			video_address_sig <= (others => '0');
		END IF;
		IF (line_counter > (CONV_STD_LOGIC_VECTOR(BEGIN_VBLANK,10) + y_offset) AND line_counter <= (CONV_STD_LOGIC_VECTOR(END_VBLANK,10) - y_offset-1)) THEN
			vblank_sig <= '1';
		-- make sure we drop the vblank signal before the next hsync starts
		ELSIF line_counter = (CONV_STD_LOGIC_VECTOR(END_VBLANK,10) - y_offset) AND pixel_counter /= end_hsync THEN
			vblank_sig <= '1';
		ELSE
			vblank_sig <= '0';
		END IF;

		-- Generate the hsync signal to send the the VGA daughter card
		IF (pixel_counter < END_HSYNC) THEN
			hsync <= '0';
		ELSE
			hsync <= '1';
		END IF;
	END IF;
END PROCESS;

-- set the irq on the falling edge of vblank.  This indicate the last pixel of the image
-- has been read from the frame buffer.
PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		set_picture_end_irq <= '0';
		vblank_delay <= '0';
	ELSIF rising_edge(clock25) THEN
		vblank_delay <= vblank_sig;
		IF enable_irq = '1' THEN
			IF vblank_sig = '0' AND vblank_delay = '1' THEN
				set_picture_end_irq <= '1';
			ELSE
				set_picture_end_irq <= '0';
			END IF;
		ELSE
			set_picture_end_irq <= '0';
		END IF;
	END IF;
END PROCESS;

-- Generate the vertical synchronization and blanking signals
vsync_gen: PROCESS(clock25,reset_n)
BEGIN
	IF reset_n = '0' THEN
		vsync <= '0';
	ELSIF rising_edge(clock25) THEN
		-- If the hsync signal is transitioning from a 1 to a 0 then...
		IF pixel_counter = end_hsync THEN
			IF (line_counter < END_VSYNC) THEN
				vsync <= '0';
			ELSE
				vsync <= '1';
			END IF;
		END IF;
	END IF;
END PROCESS;


-- This process generates the RGB signals.  Whenever the active signal
-- is asserted the process will drive the video_data out onto the RGB
-- signals.  If active is low the RGB signals will be driven to black.
-- The 16-bit video_data signal is also converted to a 24-bit RGB 
-- value by stuffing 1's onto the LSBs of the RGB signals.
color_generator: PROCESS(reset_n,clock25)
BEGIN
	IF reset_n = '0' THEN
		R <= (others => '0');
		G <= (others => '0');
		B <= (others => '0');
		active_delay <= '0';
	ELSIF rising_edge(clock25) THEN
		active_delay <= active;
		IF active_delay = '1' AND enable = '1' THEN
			R <= video_data(15 downto 11) & "111";
			G <= video_data(10 downto 5) & "11";
			B <= video_data(4 downto 0) & "111";
		ELSE
			R <= X"00";
			G <= X"00";
			B <= X"00";
		END IF;
	END IF;
END PROCESS;

END rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -