--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    11:25:45 10/15/05
-- Design Name:    
-- Module Name:    vga_backend - Behavioral
-- Project Name:   
-- Target Device:  
-- 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;

use work.vga_types.all;

entity vga_backend is
	Generic
	(
		tsvga				: vga_timespec_t	:= ts_vga_800_600_72
	);
	Port
	(
		-- System signals
		sys_rst				: in std_logic;
		sys_clk				: in std_logic;
		
		-- Color channels
		color_in			: in color_array_t;
		color_op			: in color_op_t;
		color_en			: unsigned (VGA_NUM_CH-1 downto 0);

		-- Control signals
		ctrl_scan_en		: in std_logic;

		-- Status signals
		stat_vga_rdy		: out std_logic;
		stat_scan			: out std_logic;
		stat_hsync			: out std_logic;
		stat_vsync			: out std_logic;
		stat_hready			: out std_logic;
		stat_vready			: out std_logic;
		stat_hscan			: out std_logic;
		stat_vscan			: out std_logic;
		stat_hpos			: out natural range 0 to tsvga.ts_h.ncyc_scan-1;
		stat_vpos			: out natural range 0 to tsvga.ts_v.ncyc_scan-1;
		
		-- VGA domain signals
		vga_clk_in			: in  std_logic;
		vga_clk_ce			: in  std_logic;
		vga_red				: out unsigned(7 downto 0);
		vga_green			: out unsigned(7 downto 0);
		vga_blue			: out unsigned(7 downto 0);
		vga_blank_n			: out std_logic;
		vga_sync_n			: out std_logic;
		vga_hsync			: out std_logic;
		vga_vsync			: out std_logic
	);
end vga_backend;

architecture Behavioral of vga_backend is

	signal scan_enable			: std_logic;
	signal is_scan				: std_logic;
	signal is_hscan				: std_logic;
	signal is_vscan				: std_logic;
	signal hsync				: std_logic;
	signal vsync				: std_logic;
	signal hready				: std_logic;
	signal vready				: std_logic;
	signal rst					: std_logic;

begin

inst_vga_timing: entity work.vga_timing 
	GENERIC MAP
	(
		tsvga => tsvga
	)		
	PORT MAP
	(
		sys_rst		=> sys_rst,
		vga_clk		=> vga_clk_in,
		vga_ce		=> vga_clk_ce,
		sync_h		=> hsync,
		sync_v		=> vsync,
		scan_pos_h	=> stat_hpos,
		scan_pos_v	=> stat_vpos,
		is_scan_h	=> is_hscan,
		is_scan_v	=> is_vscan,
		scan_rdy_h	=> hready,
		scan_rdy_v	=> vready
	);

	---------------------------------------------------------------------------------------------
	rst					<= not vga_clk_ce;
	stat_vga_rdy		<= vga_clk_ce;
	stat_hsync			<= hsync;
	stat_vsync			<= vsync;
	stat_hscan			<= is_hscan;
	stat_vscan			<= is_vscan;
	stat_hready			<= hready;
	stat_vready			<= vready;
	stat_scan			<= is_scan;
	
	vga_blank_n			<= '1';
	vga_sync_n			<= '0';
	is_scan				<= is_hscan and is_vscan and scan_enable;
	
	---------------------------------------------------------------------------------------------
	proc_vga_start:
	process (rst, vga_clk_in)
	begin
		if rst = '1' then
			scan_enable <= '0';
		elsif rising_edge(vga_clk_in) then
			if vsync = '1' then
				if ctrl_scan_en = '1' then
					scan_enable <= '1';
				else
					scan_enable <= '0';
				end if;	
			end if;	
		end if;
	end process;

	proc_vga_color_out:
	process (vga_clk_in)
	variable do_scan : std_logic;
	variable color : color_t;
	begin
		if rising_edge(vga_clk_in) then
			vga_red		<= X"00";
			vga_green	<= X"00";
			vga_blue	<= X"00";
			if is_scan = '1' then
				for i in 0 to VGA_NUM_CH-1 loop
					color := 	color_in(i);		
					if color_en(i) = '1' then
						vga_red		<= color(r);	-- ToDo: color_op over channels
						vga_green	<= color(g);	-- ToDo: color_op over channels
						vga_blue	<= color(b);	-- ToDo: color_op over channels
					end if;
				end loop;
			end if;
		end if;
	end process;
		
	---------------------------------------------------------------------------------------------
	proc_vga_sync_out:
	process (rst, vga_clk_in)
	variable hsync_r : std_logic;
	variable vsync_r : std_logic;
	begin
		if rst = '1' then
			vga_hsync	<= tsvga.ts_h.sync_polarity;
			vga_vsync	<= tsvga.ts_v.sync_polarity;
			hsync_r		:= tsvga.ts_h.sync_polarity;
			vsync_r		:= tsvga.ts_v.sync_polarity;
		elsif rising_edge(vga_clk_in) then
			vga_hsync	<= hsync_r;
			vga_vsync	<= vsync_r;
			hsync_r		:= hsync xor (not tsvga.ts_h.sync_polarity);
			vsync_r		:= vsync xor (not tsvga.ts_v.sync_polarity);
		end if;
	end process;

end Behavioral;
