----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    16:39:57 12/11/2008 
-- Design Name: 
-- Module Name:    adrgen - 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.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity videogen is
    Port ( ROW : in  STD_LOGIC_VECTOR (9 downto 0);
           COLUMN : in  STD_LOGIC_VECTOR (9 downto 0);
           CLK : in  STD_LOGIC;
           RED, GREEN, BLUE : out STD_LOGIC_VECTOR(3 downto 0);
           VRAM_ADDR_O : out STD_LOGIC_VECTOR(9 downto 0);
           VRAM_DATA_I : in STD_LOGIC_VECTOR(7 downto 0)
          );
end videogen;

architecture Behavioral of videogen is
component charrom IS
	port (
	clka: IN std_logic;
	addra: IN std_logic_VECTOR(10 downto 0);
	douta: OUT std_logic_VECTOR(7 downto 0));
END component;
  
signal chrx_i: std_logic_vector(2 downto 0) := "000";  -- h pos in char
signal chry_i: std_logic_vector(3 downto 0) := "0000";  -- v pos in char
signal scradrx_i: std_logic_vector(6 downto 0) := "0001010";  -- adr in ram line
signal scradry_i: std_logic_vector(11 downto 0) := X"3C0";  -- line ofs
                                                                    -- in ram
signal oe_i, oe_d1, oe_d2, oe_d3, oe_o: std_logic := '0';  -- output enable
                                                           -- delay ff chain

signal charrom_addr : std_logic_vector(10 downto 0);
signal charrom_data : std_logic_vector(7 downto 0);
signal out_i : std_logic;
begin

adrgen:  process (CLK)
  begin
    if rising_edge(CLK) then
      chrx_i <= COLUMN(2 downto 0);
      chry_i <= ROW(3 downto 0);
			
      if (COLUMN < 384) and (ROW < 256) then  -- nascom 48x16 characters mode
        oe_i <= '1';
        if (chrx_i = "111") and (COLUMN(2 downto 0) = "000") then
          if scradrx_i = 57 then
            scradrx_i <= "0001010";
          else
            scradrx_i <= scradrx_i + 1;
          end if;
        end if;
      else
        oe_i <= '0';
      end if;

      if ROW < 256 then
        if (not (chry_i = "0000")) and (ROW(3 downto 0) = "0000") then
          if scradry_i = 960 then
            scradry_i <= X"000";
          else
            scradry_i <= scradry_i + 64;
          end if;
        end if;
      end if;
			
    end if;
  end process;

  VRAM_ADDR_O <= scradry_i(9 downto 0) + scradrx_i;

  charrom_addr(10 downto 4) <= VRAM_DATA_I(6 downto 0);
  charrom_addr(3 downto 0) <= chry_i;
	
  charrom_inst: charrom port map( clka => CLK,
                                  addra => charrom_addr,
                                  douta => charrom_data);

  vgen: process (CLK)
    variable bitmap: std_logic_vector(7 downto 0) := "00000000";
  begin
    if rising_edge(CLK) then
      if chrx_i = 3 then
        bitmap := charrom_data;
      end if;
      out_i <= bitmap(conv_integer(2 - chrx_i));
    end if;
  end process;

  oe_delay: process (CLK)
  begin
    if rising_edge(CLK) then
      oe_d1 <= oe_i;
      oe_d2 <= oe_d1;
      oe_d3 <= oe_d2;
      oe_o <= oe_d3;
    end if;
  end process;

RED <= (others => out_i) when oe_o = '1' else "0000";
GREEN <= (others => out_i) when oe_o = '1' else "0000";
BLUE <= (others => out_i) when oe_o = '1' else "0000";
  
--CHRX <= chrx_i;
--CHRY <= chry_i;
--SCRADR <= scradrx_i + scradry_i;
--OE <= oe_i;
end Behavioral;

