Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

VGA output from SDRAM

Hello,

I am working on a system that can output data from the SDRAM of a DE2 board to a VGA display. I am currently able to read 16-bits of data, and output these to the entire display. I would like split the display into smaller tiles, that gets their data from different locations in the SDRAM, but I am unsure of how to implement this. If anyone has any ideas it would be greatly appreciated :)

My current code for the VGA module is shown below, it consists of four processes. One for vertical sync, one for horzontal sync, one for drawing to the display, and one for reading the SDRAM.


library ieee;use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mm_bus_vga is
	port (
                -- Avalon Master interface
		csi_clockreset_clk     : in  std_logic;                     -- Avalon Clk
		csi_clockreset_reset_n : in  std_logic;                     -- Avalon Reset
	
		-- read master
		avm_read_master_read 		 : out std_logic;
		avm_read_master_address 	 : out std_logic_vector (31 downto 0);
		avm_read_master_readdata 	 : in std_logic_vector (15 downto 0);
		avm_read_master_waitrequest  : in std_logic;
	
		avm_read_master_datavalid 	 : in std_logic;
		-- VGA signals
		vga_clk_25								: in std_logic;
		red, green, blue 						: out std_logic_vector(9 downto 0);
		hsync, vsync, clockOut, blank, compSync : out std_logic);
end mm_bus_vga;
architecture testGenerator of mm_bus_vga is
-- vga stuff
-- horizontal Timing constants for 640 x 480 @ 60Hz
constant hFrontPorch : natural := 16; -- units are number of 25 MHz clocks
constant hBackPorch : natural := 48; 
constant hDataLen : natural := 640;
constant hSynWidth : natural := 96;
-- vertical Timing constants for 640 x 480 @ 60Hz 
constant vFrontPorch : natural := 10;  -- units are number of lines
constant vBackPorch : natural := 33;
constant vDataLen : natural := 480;
constant vSynWidth : natural := 2;
-- signal declaration
signal hSyncCounter, vSyncCounter : integer range 0 to 1023; -- contrain integer to 10 bit.
signal hSyncOut,vSyncOut,vBlank,hBlank : std_logic;
-- attributes ensuring the signals defined below are not reduced away before simulation.
attribute keep: boolean; 						 -- don't reduce vSyncCounter and hSyncCounter signals away, so we can watch these signals i simulator
attribute keep of vSyncCounter : signal is true;  --   ||   --
attribute keep of hSyncCounter : signal is true;   --   ||   --
-- avalon stuff
-- state machine states
constant sdram_address : std_logic_vector(31 downto 0) := X"00800000";
type read_states_T is (idle, running, stopping);
signal read_state : read_states_T;
-- extra read master signals
signal read_address : std_logic_vector (31 downto 0);         -- the current read address
signal read_data : std_logic_vector (15 downto 0) := X"FFFF";
-- increment syncCounter, produce blanking and sync output.  
procedure syncGenerator( 
	signal syncCounter  : inout integer range 0 to 1023; 
	signal syncOut		: out std_logic; 
	signal blankOut		: out std_logic; 
	constant frontPorch : in natural; 
	constant backPorch  : in natural; 
	constant dataLen		: in natural; 
	constant syncWidth  : in natural) is
begin
	if (backPorch + dataLen + frontPorch + syncWidth < syncCounter) then
		syncCounter <= 0;
	else
		syncCounter <= syncCounter + 1;
	end if;
	
	if (backPorch > syncCounter and backPorch + dataLen > syncCounter) then
		blankOut <= '1';
	else
		blankOut <= '0';
	end if;
	if ( backPorch + dataLen + frontPorch < syncCounter) then
		syncOut <= '1';
	else
		syncOut <= '0';
	end if;
end;
begin
	-- horizontal process using the generic syncGenerator function to generate a proper hsync pulse.
	hsyn: process (csi_clockreset_reset_n,vga_clk_25) -- reacts on reset and 25 MHz clock.
	begin
		if csi_clockreset_reset_n = '0' then
			hSyncCounter <= 0;
		elsif rising_edge(vga_clk_25) then
			syncGenerator(hSyncCounter,hSyncOut,hBlank,hFrontPorch,hBackPorch,hDataLen,hSynWidth); -- generates active low pulse after every line
	  end if;
	end process;
	-- vertical process using the generic syncGenerator function to generate a proper vsync pulse.
	vsyn: process (csi_clockreset_reset_n,hSyncOut) -- reacts on reset and hsync (meaning every line).
	begin
	  if csi_clockreset_reset_n = '0' then
		 vSyncCounter <= 0;
	  elsif rising_edge(hSyncOut) then
		 syncGenerator(vSyncCounter,vSyncOut,vBlank,vFrontPorch,vBackPorch,vDataLen,vSynWidth); -- generates active low pulse after every picture
	  end if;
	end process;
	color: process (csi_clockreset_reset_n, hSyncCounter, vSyncCounter)  -- draws to display
	begin	
		red   <= std_logic_vector(resize(unsigned(read_data), 10));
		green <= std_logic_vector(resize(unsigned(read_data), 10));
		blue  <= std_logic_vector(resize(unsigned(read_data), 10));
	end process;
	
	
	read_sdram: process (csi_clockreset_reset_n, csi_clockreset_clk)
	begin
	if csi_clockreset_reset_n = '0' then
		read_state <= idle;
		read_address <= (others => '0');
	elsif rising_edge(csi_clockreset_clk) then
		case read_state is
			when idle =>
				read_address <= sdram_address;
				read_state <= running;
				avm_read_master_read <= '1';
			when running =>
				if avm_read_master_waitrequest /= '1' then
					read_state <= stopping;
					avm_read_master_read <= '0';
				end if;
			when stopping =>
				if avm_read_master_datavalid = '1' then
					read_data <= avm_read_master_readdata;
					read_state <= idle;
				end if;
		
		end case;
	end if;
	end process;
	vsync <= vSyncOut;				 -- connect vsync to entity
	hsync <= hSyncOut;               -- connect hsync to entity
	clockOut <= vga_clk_25;          -- 25 MHz clock for DAC 
	blank <= not (vBlank or hBlank); -- active low blanking
	compSync <= '1'; 				 -- never perform any composite sync
	
	-- map the internal address to the external port
	avm_read_master_address <= read_address;
	
end testGenerator;
No RepliesBe the first to reply