OpenCores
URL https://opencores.org/ocsvn/pdp1/pdp1/trunk

Subversion Repositories pdp1

[/] [pdp1/] [trunk/] [rtl/] [vhdl/] [vga.vhd] - Rev 3

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    22:05:52 11/22/2009 
-- Design Name: 
-- Module Name:    top - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;
 
entity vga is
    Port ( VGA_R : out  STD_LOGIC_VECTOR (3 downto 0);
           VGA_G : out  STD_LOGIC_VECTOR (3 downto 0);
           VGA_B : out  STD_LOGIC_VECTOR (3 downto 0);
           VGA_HSYNC : out  STD_LOGIC := '0';
           VGA_VSYNC : out  STD_LOGIC := '0';
           CLK_50M : in STD_LOGIC;
			  CLK_133M33 : in STD_LOGIC);
end vga;
 
architecture Behavioral of vga is
  signal VGA_CLK : std_logic;
 
	-- displayed stuff
  signal cell : std_logic := '1';
  signal fbwa, fbra : integer range 0 to 2048-1;
  signal fbwe : boolean := false;
  signal fbwd, fbrd : std_logic;
  type linebuffer is array (0 to 2048-1) of std_logic;
  signal pixels : linebuffer;
 
  type modeline is record
    pixelclock : real;     -- calculations for the DCM need to be done by hand
    hdisp      : positive;
	 hsyncstart : positive;
	 hsyncend   : positive;
	 htotal     : positive;
	 vdisp      : positive;
	 vsyncstart : positive;
	 vsyncend   : positive;
	 vtotal     : positive;
	 hpulse     : std_logic;  -- pulse level (i.e. '0' for -hsync, or '1' for +hsync)
	 vpulse     : std_logic;
  end record modeline;
 
  -- Modelines taken from http://www.mythtv.org/wiki/Modeline_Database
 
  -- 640x480 VGA -- all -vsync -hsync
  constant VGA60: modeline := (25.18, 640, 656, 752, 800, 480, 490, 492, 525, '0', '0');  -- pitifully, 25 is as close as I get.
  constant VGA75: modeline := (31.50, 640, 656, 720, 840, 480, 481, 484, 500, '0', '0');  -- 50/27*17 ~ 31.48
  -- from VESA modepool
  constant SXGA60: modeline := (108.00, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, '1', '1'); -- 108 ~ 50/6*13 ~ 133.33/21*17
  -- 1920x1200@60Hz nvidia mode pool
  constant WUXGA60: modeline := (193.16, 1920, 2048, 2256, 2592, 1200, 1201, 1204, 1242, '1', '1'); -- 193.16 ~ 50/7*27 ~ 133.33/11*16
 
  constant mode: modeline := SXGA60;
  alias pixclksrc is CLK_133M33;
  constant pixclkperiod: real := 7.5;
  constant pixclkdiv: positive := 21;
  constant pixclkmul: positive := 17;
 
--  constant mode: modeline := VGA60;
--  alias pixclksrc is CLK_50M;
--  constant pixclkperiod: real := 20.0;
--  constant pixclkdiv: positive := 4;
--  constant pixclkmul: positive := 2;
 
  signal column: integer range 0 to mode.htotal-1 := 0;
  signal row: integer range 0 to mode.vtotal-1 := 0;
 
  signal vblank, hblank, linestart, framestart : boolean := false;
begin
   DCM_1 : DCM_SP
   generic map (                        -- synthesize 193.33MHz; we're a bit off.
      --CLKDV_DIVIDE => 2.0, --  Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
                           --     7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
      CLKFX_DIVIDE => pixclkdiv,   --  Can be any interger from 1 to 32
      CLKFX_MULTIPLY => pixclkmul, --  Can be any integer from 1 to 32
      --CLKIN_DIVIDE_BY_2 => FALSE, --  TRUE/FALSE to enable CLKIN divide by two feature
      CLKIN_PERIOD => pixclkperiod,--20.0, --  Specify period of input clock
      --CLKOUT_PHASE_SHIFT => "NONE", --  Specify phase shift of "NONE", "FIXED" or "VARIABLE" 
      CLK_FEEDBACK => "NONE",         --  Specify clock feedback of "NONE", "1X" or "2X" 
      --DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- "SOURCE_SYNCHRONOUS", "SYSTEM_SYNCHRONOUS" or
                                             --     an integer from 0 to 15
      --DLL_FREQUENCY_MODE => "LOW",     -- "HIGH" or "LOW" frequency mode for DLL
      DUTY_CYCLE_CORRECTION => TRUE, --  Duty cycle correction, TRUE or FALSE
      PHASE_SHIFT => 0,        --  Amount of fixed phase shift from -255 to 255
      STARTUP_WAIT => TRUE) --  Delay configuration DONE until DCM_SP LOCK, TRUE/FALSE
   port map (
      --CLK0 => open,     -- 0 degree DCM CLK ouptput
      --CLK180 => open, -- 180 degree DCM CLK output
      --CLK270 => open, -- 270 degree DCM CLK output
      --CLK2X => open,   -- 2X DCM CLK output
      --CLK2X180 => open, -- 2X, 180 degree DCM CLK out
      --CLK90 => open,   -- 90 degree DCM CLK output
      --CLKDV => open,   -- Divided DCM CLK out (CLKDV_DIVIDE)
      CLKFX => VGA_CLK,   -- DCM CLK synthesis out (M/D)
      --CLKFX180 => open, -- 180 degree CLK synthesis out
      --LOCKED => AWAKE, -- DCM LOCK status output
      --PSDONE => open, -- Dynamic phase adjust done output
      --STATUS => open, -- 8-bit DCM status bits output
      --CLKFB => open,   -- DCM clock feedback
      CLKIN => pixclksrc,   -- Clock input (from IBUFG, BUFG or DCM)
      --PSCLK => open,   -- Dynamic phase adjust clock input
      --PSEN => open,     -- Dynamic phase adjust enable input
      --PSINCDEC => open, -- Dynamic phase adjust increment/decrement
      RST => '0'        -- DCM asynchronous reset input
   );
 
  sync: process (VGA_CLK)
  begin
    if rising_edge(VGA_CLK) then
	   linestart <= false;
	   if column=mode.htotal-1 then
		  column <= 0;
		else
		  column <= column+1;
		end if;
		case column is
		  when mode.hdisp-1 =>
		    hblank <= true;
		  when mode.hsyncstart =>
		    VGA_HSYNC <= mode.hpulse;
          framestart <= false;
		    case row is
		      when mode.vsyncstart =>
		        VGA_VSYNC <= mode.vpulse;
		      when mode.vsyncend =>
		        VGA_VSYNC <= not mode.vpulse;
			   when mode.vdisp-1 =>
			     vblank <= true;
			   when mode.vtotal-1 =>
			     vblank <= false;
				  framestart <= true;
				when others =>
				  null;
		    end case;
	       if row=mode.vtotal-1 then
		      row <= 0;
		    else
		      row <= row+1;
		    end if;
		  when mode.hsyncend =>
		    VGA_HSYNC <= not mode.hpulse;
		  when mode.htotal-1 =>
		    linestart <= true;
			 hblank <= false;
		  when others =>
		    null;
		end case;
	 end if;
  end process;
 
  memwr: process (VGA_CLK)
  begin  -- process memwr
    if VGA_CLK'event and VGA_CLK = '1' then  -- rising clock edge
      if fbwe then
        pixels(fbwa) <= fbwd;
      end if;
    end if;
  end process memwr;
  memrd: process (VGA_CLK)
  begin
    if rising_edge(VGA_CLK) then
      fbrd <= pixels(fbra);
    end if;
  end process memrd;
 
  -- purpose: calculates upcoming pixels
  -- type   : sequential
  -- inputs : VGA_CLK, vblank, newline
  -- outputs: cell
  wolfram: process (VGA_CLK)
    variable rule : unsigned(7 downto 0) := to_unsigned(30,8);
    variable x : integer range 0 to 2048-1 := 0;
    variable x0 : integer range 0 to 4 := 0;
    constant init : unsigned(0 to 4) := "00101";
    variable prev : unsigned(0 to 2) := "000";
  begin  -- process
    if rising_edge(VGA_CLK) then
      fbwe<=true;
      if linestart then
        x:=0;
        x0:=0;
      elsif x/=2048-1 then
        x:=x+1;
      end if;
      fbwa<=x;
		fbra<=x+4;
      if framestart then
        -- Wolfram rules:
        -- the three prior cells (left, self, right) are read as a binary number
        -- the rule number is converted to binary; each bit position corresponds
        -- to a configuration. thus, rule 34 is
        --  00100010 - only configuration 1 and 5 lead to state 1.
        -- that's 001 and 101, so the rule can only grow in one diagonal direction
		  cell <= '0';
		  fbwd <= '0';
		  -- initial conditions for different rules
		  case to_integer(rule) is
		    when 34 =>
            fbwd<=init(x0);
            cell <= init(x0);
          when others =>
			   if x=mode.hdisp/2 then
		          fbwd <= '1';
			       cell <= '1';
            end if;
		  end case;
        if x0=4 then
          x0:=0;
        else
          x0:=x0+1;
        end if;
        prev:="0"&init(0 to 1);         -- first two pixels will be strange :/
      else
		  fbwd<=rule(to_integer(prev));
		  cell<=rule(to_integer(prev));
        prev(0 to 1):=prev(1 to 2);
        if x<mode.hdisp-1 then
          prev(2):=fbrd;
        else
          prev(2):='1';
        end if;
      end if;
    end if;
  end process wolfram;
 
   -- purpose: output a signal to the VGA port
   -- type   : sequential
   -- inputs : VGA_CLK
   -- outputs: VGA_R, VGA_G, VGA_B, VGA_HSYNC, VGA_VSYNC
   vgaout: process (VGA_CLK)
	  variable vdisparea : boolean := false;
   begin  -- process vgaout
     if rising_edge(VGA_CLK) then
       -- pixel value output
       if not (hblank or vblank) then
         case column is
           when 0|mode.hdisp-1 =>
             VGA_R <= (others => '1');
             VGA_G <= (others => '1');
             VGA_B <= (others => '1');
           when others =>
             case row is
               when 0|mode.vdisp-1 =>
                 VGA_R <= (others => '1');
                 VGA_G <= (others => '1');
                 VGA_B <= (others => '1');
               when others =>
                 VGA_R <= (others => cell);
                 VGA_G <= (others => cell);
                 VGA_B <= (others => cell);
             end case;
         end case;
       else
         VGA_R <= (others => '0');
         VGA_G <= (others => '0');
         VGA_B <= (others => '0');
       end if;
     end if;
   end process vgaout;
 
end Behavioral;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.