VHDL-VGA

From Wikiversity
Jump to navigation Jump to search

Problem[edit]

The beat bearing drum sequencer interface involves a VGA LCD monitor video. The problem is how to drive the monitor without a PC.

Conceive[edit]

The goal is to design a beat boarding board with out a PC, without software. The concept is to use FPGA technology to create a circuit that displays only what is necessary for the beat bearing project.

Design[edit]

This design started off with this hardware:

vga_generator VHDL code
--------------------------------------------------------------------------------
---- Howard Community College Spring 2014 ENES-245 ----
---- This file is part of the Chapter 19 lab ----
---- Description: 
---- Date: 3/20/14 ----
---- Current Status: Complete ----
---- Original Author: unknown ----
--------------------------------------------------------------------------------
---- Modification Description: Edited SwitchesLinkedToColor project to include ----
---- 					all 256 colors (controlled by the 8 switches); displays a ----
---- 					50x50 px box on a screen, move the box across the screen ----
---- 					with the joystick ----
---- Date: 3/27/14 ----
---- Author: King Carmichael III ----
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

entity vga_generator is
        port(
                ext_CLK, reset: in std_logic;
                SWITCH: in std_logic_vector(7 downto 0);
                VGA_HSYNC, VGA_VSYNC: out std_logic;
					 JOY_RIGHT, JOY_LEFT, JOY_UP, JOY_DOWN: in STD_LOGIC;
                rgb: out std_logic_vector(7 downto 0)
        );
end vga_generator;

architecture arch of vga_generator is
        -- vga clock
        component dcm_32_to_50p35
                port(
                        clkin_in : in std_logic;          
                        clkfx_out : out std_logic;
                        clkin_ibufg_out : out std_logic;
                        clk0_out : out std_logic
                );
        end component;
        signal clk: std_logic;

        signal rgb_reg: std_logic_vector(7 downto 0);
        signal video_on, antisquare: std_logic;
		  		  
begin
		  inst_dcm_32_to_50p35: dcm_32_to_50p35
                port map(
                        clkin_in => ext_CLK,
                        clkfx_out => clk,
                        clkin_ibufg_out => open,
                        clk0_out => open
                );

        vga_sync_unit: entity work.vga_sync
                port map(
                        clk => clk,
                        reset => reset,
                        hsync => VGA_HSYNC,
                        vsync => VGA_VSYNC,
                        video_on => video_on,
								antivid => antisquare,
								right => JOY_RIGHT,
								left => JOY_LEFT,
								up => JOY_UP,
								down => JOY_DOWN,
                        p_tick => open,
                        pixel_x => open,
                        pixel_y => open
                );

        process(clk, reset)
        begin
                if reset = '1' then
                        rgb_reg <= (others => '0');
                elsif clk'event and clk = '1' then
                        rgb_reg <= SWITCH(7 downto 0);
                end if;
        end process;

        rgb <= rgb_reg when video_on = '1' and antisquare = '0' else
					NOT rgb_reg when video_on = '1' and antisquare = '1' else "00000000";
end arch;
VGA sync VHDL code
--------------------------------------------------------------------------------
---- Howard Community College Spring 2014 ENES-245 ----
---- This file is part of the Chapter 19 lab ----
---- Description: VGA sync - tells determines when the video will be on, syncs ----
---- 					timing of pixel ticks (when to scan horizontally/vertically ----
----					and when to restart), etc.
---- Date: 3/20/14 ----
---- Current Status: Complete ----
---- Original Author: unknown ----
--------------------------------------------------------------------------------
---- Modification Description: Move the box across the screen with the joystick. ----
----									 Second block element on (second video_on) when ----
----									 block is at the end of pixel range. ----
---- Date: 3/27/14 ----
---- Author: King Carmichael III Email: ----
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity vga_sync is
        port(
                clk, reset: in std_logic;
                hsync, vsync: out std_logic;
                video_on, antivid, p_tick: out std_logic;
					 right, left, up, down: in std_logic;
                pixel_x, pixel_y: out std_logic_vector(9 downto 0)
        );
end vga_sync;

architecture arch of vga_sync is
        -- VGA 640x480
        
        -- horizontal timings, in pixels
        constant h_display_area: integer := 640;
        constant h_front_porch: integer := 16;
        constant h_sync: integer := 96;
        constant h_back_porch: integer := 48;
        
        -- vertical timings, in lines
        constant v_display_area: integer := 480;
        constant v_front_porch: integer := 10;
        constant v_sync: integer := 2;
        constant v_back_porch: integer := 33;
        
        -- derived horizontal constants
        constant hsync_start: integer := h_display_area + h_front_porch;
        constant hsync_end: integer := hsync_start + h_sync;
        constant end_of_line: integer := hsync_end + h_back_porch - 1;
        
        -- derived vertical constants
        constant vsync_start: integer := v_display_area + v_front_porch;
        constant vsync_end: integer := vsync_start + v_sync;
        constant end_of_frame: integer := vsync_start + v_back_porch - 1;
        
        -- mod-2 counter
        signal mod2_reg, mod2_next: std_logic;
        
        -- sync counters
        signal v_count_reg, v_count_next: unsigned(9 downto 0);
        signal h_count_reg, h_count_next: unsigned(9 downto 0);
        
        -- output buffer
        signal v_sync_reg, h_sync_reg: std_logic;
        signal v_sync_next, h_sync_next: std_logic;
        
        -- status signals
        signal h_end, v_end, pixel_tick: std_logic;
		  
		  --30 bit counter
		  signal count: std_logic_vector(29 downto 0) := (others => '0');
		  
		  --pixel region to display
		  signal pixx, pixy: unsigned(10 downto 0);-- := (others => '0');		--Need at least 10 bits to have decimal number 799
		  signal neg: std_logic;
--		  constant pixx_set: integer := 424;		--initial test to display rectangle
--		  constant pixy_set: integer := 286;		--initial test to display rectangle
begin
        -- registers
        process(clk, reset)
        begin
                if reset = '1' then
                        mod2_reg <= '0';
                        v_count_reg <= (others => '0');
                        h_count_reg <= (others => '0');
                        v_sync_reg <= '0';
                        h_sync_reg <= '0';
                elsif clk'event and clk = '1' then
                        mod2_reg <= mod2_next;
                        v_count_reg <= v_count_next;
                        h_count_reg <= h_count_next;
                        v_sync_reg <= v_sync_next;
                        h_sync_reg <= h_sync_next;
                end if;
        end process;
        
        -- mod-2 circuit to generate 25.125MHz enable tick
        mod2_next <= not mod2_reg;
        
        -- 25.125MHz pixel tick
        pixel_tick <= '1' when mod2_reg = '1' else '0';
        
        -- status
        h_end <=
                '1' when h_count_reg = end_of_line else
                '0';
        v_end <=
                '1' when v_count_reg = end_of_frame else
                '0';
        
        -- mod-800 horizontal sync counter
        process(h_count_reg, h_end, pixel_tick)
        begin
                if pixel_tick = '1' then
                        if h_end = '1' then
                                h_count_next <= (others => '0');
                        else
                                h_count_next <= h_count_reg + 1;
                        end if;
                else
                        h_count_next <= h_count_reg;
                end if;
        end process;
        
        -- mod-525 vertical sync counter
        process(v_count_reg, h_end, v_end, pixel_tick)
        begin
                if pixel_tick = '1' and h_end = '1' then
                        if v_end = '1' then
                                v_count_next <= (others => '0');
                        else
                                v_count_next <= v_count_reg + 1;
                        end if;
                else
                        v_count_next <= v_count_reg;
                end if;
        end process;
        
        -- hsync and vsync, buffered to avoid glitch
        h_sync_next <=
                '1' when hsync_start <= h_count_reg and h_count_reg < hsync_end else
                '0';
        v_sync_next <=
                '1' when vsync_start <= v_count_reg and v_count_reg < vsync_end else
                '0';
		
		  --Block controls
		  process(clk)--pixel_tick)
		  begin
					 if rising_edge(clk) then
								count <= count + 1;
								if count = 200000 then		--change value to change how fast block moves
									count <= (others => '0');
									if right = '0' and pixx < 591 then
										pixx <= pixx + 1;
									elsif left = '0' and pixx > 0 then
										pixx <= pixx - 1;
									elsif up = '0' and pixy > 0 then
										pixy <= pixy - 1;
									elsif down = '0' and pixy < 431 then
										pixy <= pixy + 1;
									end if;
								end if;
                end if;
        end process;
		  
		  -- video on/off
        video_on <=
                '1' when h_count_reg < 50 + pixx and h_count_reg > pixx		--pixx and pixy +51 because rectangle is 50x50 pixels
							and v_count_reg < 50 + pixy and v_count_reg > pixy else
                '0';
					 
					 --original code - displayed a rectangle the size of the screen
--					 '1' when h_count_reg < h_display_area and v_count_reg < v_display_area else
--                '0';
		  
		  neg <= '1' when pixx = 0 else
					'1' when pixx = 591 else
					'1' when pixy = 0 else
					'1' when pixy = 431 else
					'0';
		  
        -- output signals
        hsync <= h_sync_reg;
        vsync <= v_sync_reg;
		  antivid <= neg;
        pixel_x <= std_logic_vector(h_count_reg);
        pixel_y <= std_logic_vector(v_count_reg);
        p_tick <= pixel_tick;
end arch;
The constraints file being used with the logic start board
NET ext_CLK          LOC="P89"  | IOSTANDARD=LVTTL | PERIOD=31.25ns;               # CLK

NET VGA_VSYNC    LOC="P85"  | IOSTANDARD=LVTTL;                                # B0
NET VGA_HSYNC    LOC="P83"  | IOSTANDARD=LVTTL;                                # B1
NET "rgb<7>" LOC = "P78"  | IOSTANDARD=LVTTL;  
NET "rgb<6>" LOC = "P71"  | IOSTANDARD=LVTTL;  
NET "rgb<5>" LOC = "P68"  | IOSTANDARD=LVTTL;  
NET "rgb<4>" LOC = "P66"  | IOSTANDARD=LVTTL;  
NET "rgb<3>" LOC = "P63"  | IOSTANDARD=LVTTL;  
NET "rgb<2>" LOC = "P61"  | IOSTANDARD=LVTTL;  
NET "rgb<1>" LOC = "P58"  | IOSTANDARD=LVTTL;  
NET "rgb<0>" LOC = "P54"  | IOSTANDARD=LVTTL;  

NET SWITCH(0)    LOC="P91"  | IOSTANDARD=LVTTL;                                # C0
NET SWITCH(1)    LOC="P92"  | IOSTANDARD=LVTTL;                                # C1
NET SWITCH(2)    LOC="P94"  | IOSTANDARD=LVTTL;                                # C2
NET SWITCH(3)    LOC="P95"  | IOSTANDARD=LVTTL;                                # C3
NET SWITCH(4)    LOC="P98"  | IOSTANDARD=LVTTL;                                # C4
NET SWITCH(5)    LOC="P2"   | IOSTANDARD=LVTTL;                                # C5
NET SWITCH(6)    LOC="P3"   | IOSTANDARD=LVTTL;                                # C6
NET SWITCH(7)    LOC="P4"   | IOSTANDARD=LVTTL;                                # C7

Implement[edit]

The goal is to simulate this video with out using a PC running some program like processing or visual basic. So the switches on the logic start board are used to simulate one row of the beat bearing board.

The switches add a white explosion underneath the blue squares.

Squares are used instead of circles because implementing a circuit that does the math would not fit on such a small FPGA.

Operate[edit]

  1. Connect a papilo 250K FPGA with a logic start circuit board to a USB file to a computer that has the papilo boot loader installed.
  2. Connect a VGA cable from the logic start board to a monitor.
  3. Apply power to both.
  4. Download this bit file.
  5. Right mouse on the bit file and send it to the papilo.

Demo[edit]

Next Steps[edit]

  • Turn squares off totally and have an two step explosion of color
  • Create test program to test and exercise each row
  • Use putty through usb cable to configure speed of bar, colors of squares
  • Connect to arduino serial out to change configuration
  • Physically connect to beat bearing board and read column of four switches

(need 6 pins free on Papilio)