library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_unsigned.all;

entity Dig_Cam is

  port (
    -- Clocks

    CLOCK_25,                                      -- 25 MHz
    CLOCK_50,                                      -- 50 MHz
    EXT_CLOCK : in std_logic;                      -- External Clock

    -- Buttons and switches

    KEY : in std_logic_vector(3 downto 0);         -- Push buttons
    SW : in std_logic_vector(17 downto 0);         -- DPDT switches

    -- LED displays

    HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7 -- 7-segment displays
       : out std_logic_vector(6 downto 0);
    LEDG : out std_logic_vector(8 downto 0);       -- Green LEDs
    LEDR : out std_logic_vector(17 downto 0);      -- Red LEDs

    -- RS-232 interface

    UART_TXD : out std_logic;                      -- UART transmitter   
    UART_RXD : in std_logic;                       -- UART receiver

     -- SDRAM

    DRAM_DQ : inout std_logic_vector(15 downto 0); -- Data Bus
    DRAM_ADDR : out std_logic_vector(11 downto 0); -- Address Bus
    DRAM_LDQM,                                     -- Low-byte Data Mask 
    DRAM_UDQM,                                     -- High-byte Data Mask
    DRAM_WE_N,                                     -- Write Enable
    DRAM_CAS_N,                                    -- Column Address Strobe
    DRAM_RAS_N,                                    -- Row Address Strobe
    DRAM_CS_N,                                     -- Chip Select
    DRAM_BA_0,                                     -- Bank Address 0
    DRAM_BA_1,                                     -- Bank Address 0
    DRAM_CLK,                                      -- Clock
    DRAM_CKE : out std_logic;                      -- Clock Enable

    -- FLASH
    
    FL_DQ : inout std_logic_vector(7 downto 0);      -- Data bus
    FL_ADDR : out std_logic_vector(21 downto 0);  -- Address bus
    FL_WE_N,                                         -- Write Enable
    FL_RST_N,                                        -- Reset
    FL_OE_N,                                         -- Output Enable
    FL_CE_N : out std_logic;                         -- Chip Enable

    -- SRAM

    SRAM_DQ : inout std_logic_vector(15 downto 0); -- Data bus 16 Bits
    SRAM_ADDR : out std_logic_vector(17 downto 0); -- Address bus 18 Bits
    SRAM_UB_N,                                     -- High-byte Data Mask 
    SRAM_LB_N,                                     -- Low-byte Data Mask
    SRAM_WE_N,                                     -- Write Enable
    SRAM_CE_N,                                     -- Chip Enable
    SRAM_OE_N : out std_logic;                     -- Output Enable

    -- USB controller

    OTG_DATA : inout std_logic_vector(15 downto 0); -- Data bus
    OTG_ADDR : out std_logic_vector(1 downto 0);    -- Address
    OTG_CS_N,                                       -- Chip Select
    OTG_RD_N,                                       -- Write
    OTG_WR_N,                                       -- Read
    OTG_RST_N,                                      -- Reset
    OTG_FSPEED,                     -- USB Full Speed, 0 = Enable, Z = Disable
    OTG_LSPEED : out std_logic;     -- USB Low Speed, 0 = Enable, Z = Disable
    OTG_INT0,                                       -- Interrupt 0
    OTG_INT1,                                       -- Interrupt 1
    OTG_DREQ0,                                      -- DMA Request 0
    OTG_DREQ1 : in std_logic;                       -- DMA Request 1
    OTG_DACK0_N,                                    -- DMA Acknowledge 0
    OTG_DACK1_N : out std_logic;                    -- DMA Acknowledge 1

    -- 16 X 2 LCD Module
    
    LCD_ON,                     -- Power ON/OFF
    LCD_BLON,                   -- Back Light ON/OFF
    LCD_RW,                     -- Read/Write Select, 0 = Write, 1 = Read
    LCD_EN,                     -- Enable
    LCD_RS : out std_logic;     -- Command/Data Select, 0 = Command, 1 = Data
    LCD_DATA : inout std_logic_vector(7 downto 0); -- Data bus 8 bits

    -- SD card interface

    SD_DAT,                     -- SD Card Data
    SD_DAT3,                    -- SD Card Data 3
    SD_CMD : inout std_logic;   -- SD Card Command Signal
    SD_CLK : out std_logic;     -- SD Card Clock

    -- USB JTAG link
    
    TDI,                        -- CPLD -> FPGA (data in)
    TCK,                        -- CPLD -> FPGA (clk)
    TCS : in std_logic;         -- CPLD -> FPGA (CS)
    TDO : out std_logic;        -- FPGA -> CPLD (data out)

    -- I2C bus

    I2C_SDAT : inout std_logic; -- I2C Data
    I2C_SCLK : out std_logic;   -- I2C Clock

    -- PS/2 port

    PS2_DAT,                    -- Data
    PS2_CLK : in std_logic;     -- Clock

    -- VGA output

    VGA_CLK,                                            -- Clock
    VGA_HS,                                             -- H_SYNC
    VGA_VS,                                             -- V_SYNC
    VGA_BLANK,                                          -- BLANK
    VGA_SYNC : out std_logic;                           -- SYNC
    VGA_R,                                              -- Red[9:0]
    VGA_G,                                              -- Green[9:0]
    VGA_B : out std_logic_vector(9 downto 0);           -- Blue[9:0]

    --  Ethernet Interface
    
    ENET_DATA : inout std_logic_vector(15 downto 0);    -- DATA bus 16Bits
    ENET_CMD,           -- Command/Data Select, 0 = Command, 1 = Data
    ENET_CS_N,                                          -- Chip Select
    ENET_WR_N,                                          -- Write
    ENET_RD_N,                                          -- Read
    ENET_RST_N,                                         -- Reset
    ENET_CLK : out std_logic;                           -- Clock 25 MHz
    ENET_INT : in std_logic;                            -- Interrupt

    -- Audio CODEC

    AUD_ADCLRCK : inout std_logic;                      -- ADC LR Clock
    AUD_ADCDAT : in std_logic;                          -- ADC Data
    AUD_DACLRCK : inout std_logic;                      -- DAC LR Clock
    AUD_DACDAT : out std_logic;                         -- DAC Data
    AUD_BCLK : inout std_logic;                         -- Bit-Stream Clock
    AUD_XCK : out std_logic;                            -- Chip Clock
    
    -- Video Decoder
    
    TD_DATA : in std_logic_vector(7 downto 0);  -- Data bus 8 bits
    TD_HS,                                      -- H_SYNC
    TD_VS : in std_logic;                       -- V_SYNC
    TD_RESET : out std_logic;                   -- Reset

    -- General-purpose I/O

    GPIO_0,                                      -- GPIO Connection 0
    GPIO_1 : inout std_logic_vector(35 downto 0) -- GPIO Connection 1
    );

end Dig_Cam;

architecture datapath of Dig_Cam is

component CCD_Capture is 
	port(	oDATA : out std_logic_vector(9 downto 0);
			oDVAL : out std_logic;
			oX_Cont,
			oY_Cont : out std_logic_vector(10 downto 0);
			oFrame_Cont : out std_logic_vector(31 downto 0);
			iDATA : in std_logic_vector(9 downto 0);
			iFVAL,
			iLVAL,
			iSTART,
			iEND,
			iCLK,
			iRST : in std_logic	);
end component;
			
  component I2C_CCD_Config is
	port( iCLK : in std_logic;
		  iRST_N : in std_logic;
		  iExposure : in std_logic_vector(15 downto 0);
		  I2C_SCLK : out std_logic;
		  I2C_SDAT : inout std_logic
		);
		
  end component;

component RAW2RGB is
	port( iX_Cont,
	      iY_Cont : in std_logic_vector(10 downto 0);
		  iDATA : in std_logic_vector(9 downto 0);
		  iDVAL : in std_logic;
		  oRed,
		  oGreen,
		  oBlue : out std_logic_vector(9 downto 0);
		  oDVAL : out std_logic;
		  
		  iCLK,
		  iRST : in std_logic
		);
end component;

component Reset_Delay is
	port( iCLK,
		  iRST :in std_logic;
		  signal oRST_0,
			     oRST_1,
				 oRST_2 : out std_logic
		);
end component;

component Mirror_Col is
	port( iCCD_R,
		  iCCD_G,
		  iCCD_B : in std_logic_vector(9 downto 0);
		  iCCD_DVAL,
		  iCCD_PIXCLK,
		  iRST_N : in std_logic;
		
		  oCCD_R,
		  oCCD_G,
		  oCCD_B : out std_logic_vector(9 downto 0);
		  oCCD_DVAL: out std_logic
		);
end component;

  component VGA_Controller is
   port(iRed,
	 	iGreen, 
	 	iBlue : in std_logic_vector( 9 downto 0);
 	 	oRequest : out std_logic;

    	oVGA_CLOCK,                                 
    	oVGA_H_SYNC,                                
    	oVGA_V_SYNC,                                
     	oVGA_BLANK,                               
     	oVGA_SYNC : out std_logic;                
	 	oVGA_R,
    	oVGA_G,
	 	oVGA_B : out std_logic_vector(9 downto 0);

	 	iRST_N : in std_logic;
    	iCLK   : in std_logic                    
  );
  end component;

  component sram_controller is
	port(	REF_CLK, RESET_N : in std_logic;
			
			WR1_Data : in std_logic_vector(15 downto 0);
			WR1 : in std_logic;
			WR1_ADDR, WR1_MAX_ADDR : in std_logic_vector(21 downto 0);
			WR1_Length : in std_logic_vector(8 downto 0);
			WR1_Load, WR1_CLK : in std_logic;

			WR2_Data : in std_logic_vector(15 downto 0);
			WR2 : in std_logic;
			WR2_ADDR, WR2_MAX_ADDR : in std_logic_vector(21 downto 0);
			WR2_Length : in std_logic_vector(8 downto 0);
			WR2_Load, WR2_CLK : in std_logic;

			RD1_Data : out std_logic_vector(15 downto 0);
			RD1 : in std_logic;
			RD1_ADDR, RD1_MAX_ADDR : in std_logic_vector(21 downto 0);
			RD1_Length : in std_logic_vector(8 downto 0);
			RD1_Load, RD1_CLK : in std_logic;
			RD1_Empty : out std_logic;
			RD1_Use : out std_logic_vector(8 downto 0);
			
			RD2_Data : out std_logic_vector(15 downto 0);
			RD2 : in std_logic;
			RD2_ADDR, RD2_MAX_ADDR : in std_logic_vector(21 downto 0);
			RD2_Length : in std_logic_vector(8 downto 0);
			RD2_Load, RD2_CLK : in std_logic;

			SA : out std_logic_vector(11 downto 0);
			BA, CS_N : out std_logic_vector(1 downto 0);
			CKE, RAS_N, CAS_N, WE : out std_logic;
			DQ : inout std_logic_vector(15 downto 0);
			DQM : out std_logic_vector(1 downto 0);
			SDR_CLK : out std_logic
		);
	end component;	
	

signal clk25 : std_logic := '1';
signal read : std_logic;
signal Vals : std_logic_vector(9 downto 0);
signal CCD_SDATA : std_logic;
signal CCD_SCLK,
       CCD_Mclk : std_logic;
signal CCD_Data,
       mCCD_DATA : std_logic_vector(9 downto 0);
signal CCD_SDAT,
	   CCD_FVAL,
	   CCD_LVal,
	   CCD_PIXCLK,
	   mCCD_Dval_d,
	   mCCD_Dval : std_logic;

signal Read_Data1,
	   Read_Data2 : std_logic_vector(15 downto 0);

signal VGA_CTRL_CLK,
	   AUD_CTRL_CLK : std_logic;

signal X_ADDR,
	   green_data,
	   mCCD_R,
	   mCCD_G,
	   mCCD_B,
	   sCCD_R,
	   sCCD_G,
	   sCCD_B,
	   rCCD_Data : std_logic_vector(9 downto 0);

signal DRAM_BA_3, DRAM_DQM : std_logic_vector(1 downto 0);
	
signal DLY_RST_0,
	   DLY_RST_1,
	   DLY_RST_2,
	   rCCD_LVAL,
	   rCCD_FVAL,
	   sCCD_DVAL : std_logic;

signal X_Cont,
       Y_Cont : std_logic_vector(10 downto 0);

signal Frame_Cont : std_logic_vector(31 downto 0);
signal c : std_logic_vector( 1 downto 0);
begin 

process(CLOCK_50)
begin
	
CCD_Data(0) <= GPIO_1(0);
CCD_Data(1) <= GPIO_1(1);
CCD_Data(2) <= GPIO_1(5);
CCD_Data(3) <= GPIO_1(3);
CCD_Data(4) <= GPIO_1(2);
CCD_Data(5) <= GPIO_1(4);
CCD_Data(6) <= GPIO_1(6);
CCD_Data(7) <= GPIO_1(7);
CCD_Data(8) <= GPIO_1(8);
CCD_Data(9) <= GPIO_1(9);

GPIO_1(11) <= CCD_Mclk;
GPIO_1(15) <= CCD_SDAT;
GPIO_1(14) <= CCD_SCLK;

CCD_FVal <= GPIO_1(13);
CCD_LVal <= GPIO_1(12);
CCD_PIXCLK <= GPIO_1(10);

green_data(9 downto 5) <= Read_Data1(14 downto 10);
green_data(4 downto 0) <= Read_Data2(14 downto 10);
DRAM_BA_1 <= DRAM_BA_3(1);
DRAM_BA_0 <= DRAM_BA_3(0);
DRAM_UDQM <= DRAM_DQM(1);
DRAM_LDQM <= DRAM_DQM(0);
DRAM_CS_N <= c(0);
DRAM_CS_N <= c(1);
end process;

process(CCD_PIXCLK)
begin
	rCCD_DATA <= CCD_DATA;
	rCCD_LVAL <= CCD_LVAL;
	rCCD_FVAL <= CCD_FVAL;
end process;


CCD : CCD_Capture port map(
	oDATA => mCCD_DATA,
	oDVAL => mCCD_DVAL,
	oX_Cont => X_Cont,
	oY_Cont => Y_Cont,
	oFrame_Cont => Frame_Cont,
	iDATA => CCD_Data,
	iFVAL => CCD_FVal,
	iLVAL => CCD_LVal,
	iSTART => not key(3),
	iEND => not key(2),
	iCLK => CCD_PIXCLK,
	iRST => DLY_RST_1	
);

IC_Config : I2C_CCD_Config port map(
iCLK => CLOCK_50,
iRST_N => key(1),
iExposure => sw(15 downto 0),
I2C_SCLK => CCD_SCLK,
I2C_SDAT => CCD_SDATA
);

VGA: VGA_Controller port map (
  iRed => Read_Data2(9 downto 0),
  iGreen => green_data,
  iBlue => Read_Data1(9 downto 0),
  oRequest => read,

  oVGA_CLOCK => VGA_CLK,
  oVGA_H_SYNC => VGA_HS,
  oVGA_V_SYNC => VGA_VS,
  oVGA_BLANK => VGA_BLANK,
  oVGA_SYNC => VGA_SYNC,
  oVGA_G => VGA_G,
  oVGA_R => VGA_R,
  oVGA_B => VGA_B,

  iCLK => VGA_CTRL_CLK,
  iRST_N => DLY_RST_2
);
  
Res : Reset_Delay port map(
  iCLK => CLOCK_50,
  iRST => key(0),
  oRST_0 => DLY_RST_0,
  oRST_1 => DLY_RST_1,
  oRST_2 => DLY_RST_2
);

Colors : RAW2RGB port map(
  oRed => mCCD_R,
  oGreen => mCCD_G,
  oBlue => mCCD_B,
  oDVAL => mCCD_DVAL_d,
  iX_Cont => X_Cont,
  iY_Cont => Y_Cont,
  iDATA => mCCD_Data,
  iDVAL => mCCD_DVAL,
  iCLK => CCD_PIXCLK,
  iRST => DLY_RST_1
);

Pic : Mirror_Col port map(
  iCCD_R => mCCD_R,
  iCCD_G => mCCD_G,
  iCCD_B => mCCD_B,
  iCCD_DVAL => mCCD_DVAL_d,
  iCCD_PIXCLK => CCD_PIXCLK,
  iRST_N => DLY_RST_1,
  oCCD_R => sCCD_R,
  oCCD_G => sCCD_G,
  oCCD_B => sCCD_B,
  oCCD_DVAL => sCCD_DVAL
); 

SRAM : sram_controller port map(
	REF_CLK => CLOCK_50,
	RESET_N => '1',
		
	WR1_Data => (sCCD_G(9 downto 5) & sCCD_B(9 downto 0) & '0'),
	WR1 => sCCD_DVAL,
	WR1_ADDR => "0000000000000000000000",
	WR1_MAX_ADDR => "0001010000000000000000",
	WR1_Length => "100000000",
	WR1_Load => not DLY_RST_0,
	WR1_CLK => CCD_PIXCLK,
	
	WR2_Data => (sCCD_G(4 downto 0) & sCCD_R(9 downto 0) & '0'),
	WR2 => sCCD_DVAL,
	WR2_ADDR => "0100000000000000000000",
	WR2_MAX_ADDR => "0101010000000000000000",
	WR2_Length => "100000000",
	WR2_Load => not DLY_RST_0,
	WR2_CLK => CCD_PIXCLK,
	
	RD1_Data => Read_Data1,
	RD1 => Read,
	RD1_ADDR => "0000000010100000000000",
	RD1_MAX_ADDR => "0001001101100000000000",
	RD1_Length => "100000000",
	RD1_Load => not DLY_RST_0,
	RD1_CLK => VGA_CTRL_CLK,
			
	RD2_Data => Read_Data2,
	RD2 => Read,
	RD2_ADDR => "0100000010100000000000",
	RD2_MAX_ADDR => "0101001101100000000000",
	RD2_Length => "100000000",
	RD2_Load => not DLY_RST_0,
	RD2_CLK => VGA_CTRL_CLK,
	
	SA => DRAM_ADDR, 
	BA => DRAM_BA_3,
	CS_N => c,
	CKE => DRAM_CKE,
	RAS_N => DRAM_RAS_N,
	CAS_N => DRAM_CAS_N,
	WE => DRAM_WE_N,
	DQ => DRAM_DQ,
	DQM => DRAM_DQM,
	SDR_CLK => DRAM_CLK
);
  
--  HEX7     <= "0001001"; -- Leftmost
--  HEX6     <= "0000110";
--  HEX5     <= "1000111";
--  HEX4     <= "1000111";
--  HEX3     <= "1000000";
--  HEX2     <= (others => '1');
--  HEX1     <= (others => '1');
--  HEX0     <= (others => '1');          -- Rightmost
--  LCD_ON   <= '1';
--  LCD_BLON <= '1';

  -- Set all bidirectional ports to tri-state
--  DRAM_DQ     <= (others => 'Z');
--  FL_DQ       <= (others => 'Z');
--  SRAM_DQ     <= (others => 'Z');
-- OTG_DATA    <= (others => 'Z');
--  LCD_DATA    <= (others => 'Z');
--  SD_DAT      <= 'Z';
--  I2C_SDAT    <= 'Z';
--  ENET_DATA   <= (others => 'Z');
--  AUD_ADCLRCK <= 'Z';
--  AUD_DACLRCK <= 'Z';
--  AUD_BCLK    <= 'Z';

  process (CLOCK_50)
  begin
    if CLOCK_50'event and CLOCK_50 = '1' then
      clk25 <= not clk25;
    end if;
  end process;

end datapath;
