/* 
(C) OOMusou 2008 http://oomusou.cnblogs.com

Filename    : DE2_CCD.v
Compiler    : Quartus II 7.2 SP3
Description : Demo how to use 130m CMOS to make gray after SDRAM on DE2
Release     : 08/23/2008 1.0
*/

module DE2_CCD (
  ////////////////////////  Clock Input ////////////////////////
  input           CLOCK_27,       //  27 MHz
  input           CLOCK_50,       //  50 MHz
  input           EXT_CLOCK,      //  External Clock
  ////////////////////////  Push Button ////////////////////////
  input   [3:0]   KEY,            //  Pushbutton[3:0]
  ////////////////////////  DPDT Switch ////////////////////////
  input   [17:0]  SW,             //  Toggle Switch[17:0]
  ////////////////////////  7-SEG Dispaly ////////////////////////
  output  [6:0]   HEX0,           //  Seven Segment Digit 0
  output  [6:0]   HEX1,           //  Seven Segment Digit 1
  output  [6:0]   HEX2,           //  Seven Segment Digit 2
  output  [6:0]   HEX3,           //  Seven Segment Digit 3
  output  [6:0]   HEX4,           //  Seven Segment Digit 4
  output  [6:0]   HEX5,           //  Seven Segment Digit 5
  output  [6:0]   HEX6,           //  Seven Segment Digit 6
  output  [6:0]   HEX7,           //  Seven Segment Digit 7
  ////////////////////////////  LED ////////////////////////////
  output  [8:0]   LEDG,           //  LED Green[8:0]
  output  [17:0]  LEDR,           //  LED Red[17:0]
  ////////////////////////////  UART  ////////////////////////////
  output          UART_TXD,       //  UART Transmitter
  input           UART_RXD,       //  UART Receiver
  ////////////////////////////  IRDA  ////////////////////////////
  output          IRDA_TXD,       //  IRDA Transmitter
  input           IRDA_RXD,       //  IRDA Receiver
  /////////////////////// SDRAM Interface ////////////////////////
  inout   [15:0]  DRAM_DQ,        //  SDRAM Data bus 16 Bits
  output  [11:0]  DRAM_ADDR,      //  SDRAM Address bus 12 Bits
  output          DRAM_LDQM,      //  SDRAM Low-byte Data Mask 
  output          DRAM_UDQM,      //  SDRAM High-byte Data Mask
  output          DRAM_WE_N,      //  SDRAM Write Enable
  output          DRAM_CAS_N,     //  SDRAM Column Address Strobe
  output          DRAM_RAS_N,     //  SDRAM Row Address Strobe
  output          DRAM_CS_N,      //  SDRAM Chip Select
  output          DRAM_BA_0,      //  SDRAM Bank Address 0
  output          DRAM_BA_1,      //  SDRAM Bank Address 0
  output          DRAM_CLK,       //  SDRAM Clock
  output          DRAM_CKE,       //  SDRAM Clock Enable
  ////////////////////////  Flash Interface ////////////////////////
  inout   [7:0]   FL_DQ,          //  FLASH Data bus 8 Bits
  output  [21:0]  FL_ADDR,        //  FLASH Address bus 22 Bits
  output          FL_WE_N,        //  FLASH Write Enable
  output          FL_RST_N,       //  FLASH Reset
  output          FL_OE_N,        //  FLASH Output Enable
  output          FL_CE_N,        //  FLASH Chip Enable
  ////////////////////////  SRAM Interface  ////////////////////////
  inout   [15:0]  SRAM_DQ,        //  SRAM Data bus 16 Bits
  output  [17:0]  SRAM_ADDR,      //  SRAM Address bus 18 Bits
  output          SRAM_UB_N,      //  SRAM High-byte Data Mask 
  output          SRAM_LB_N,      //  SRAM Low-byte Data Mask 
  output          SRAM_WE_N,      //  SRAM Write Enable
  output          SRAM_CE_N,      //  SRAM Chip Enable
  output          SRAM_OE_N,      //  SRAM Output Enable
  ////////////////////  ISP1362 Interface ////////////////////////
  inout   [15:0]  OTG_DATA,       //  ISP1362 Data bus 16 Bits
  output  [1:0]   OTG_ADDR,       //  ISP1362 Address 2 Bits
  output          OTG_CS_N,       //  ISP1362 Chip Select
  output          OTG_RD_N,       //  ISP1362 Write
  output          OTG_WR_N,       //  ISP1362 Read
  output          OTG_RST_N,      //  ISP1362 Reset
  output          OTG_FSPEED,     //  USB Full Speed, 0 = Enable, Z = Disable
  output          OTG_LSPEED,     //  USB Low Speed,  0 = Enable, Z = Disable
  input           OTG_INT0,       //  ISP1362 Interrupt 0
  input           OTG_INT1,       //  ISP1362 Interrupt 1
  input           OTG_DREQ0,      //  ISP1362 DMA Request 0
  input           OTG_DREQ1,      //  ISP1362 DMA Request 1
  output          OTG_DACK0_N,    //  ISP1362 DMA Acknowledge 0
  output          OTG_DACK1_N,    //  ISP1362 DMA Acknowledge 1
  ////////////////////  LCD Module 16X2 ////////////////////////////
  inout   [7:0]   LCD_DATA,       //  LCD Data bus 8 bits
  output          LCD_ON,         //  LCD Power ON/OFF
  output          LCD_BLON,       //  LCD Back Light ON/OFF
  output          LCD_RW,         //  LCD Read/Write Select, 0 = Write, 1 = Read
  output          LCD_EN,         //  LCD Enable
  output          LCD_RS,         //  LCD Command/Data Select, 0 = Command, 1 = Data
  ////////////////////  SD Card Interface ////////////////////////
  inout           SD_DAT,         //  SD Card Data
  inout           SD_DAT3,        //  SD Card Data 3
  inout           SD_CMD,         //  SD Card Command Signal
  output          SD_CLK,         //  SD Card Clock
  ////////////////////////  I2C ////////////////////////////////
  inout           I2C_SDAT,       //  I2C Data
  output          I2C_SCLK,       //  I2C Clock
  ////////////////////////  PS2 ////////////////////////////////
  input           PS2_DAT,        //  PS2 Data
  input           PS2_CLK,        //  PS2 Clock
  ////////////////////  USB JTAG link ////////////////////////////
  input           TDI,            // CPLD -> FPGA (data in)
  input           TCK,            // CPLD -> FPGA (clk)
  input           TCS,            // CPLD -> FPGA (CS)
  output          TDO,            // FPGA -> CPLD (data out)
  ////////////////////////  VGA ////////////////////////////
  output          VGA_CLK,        //  VGA Clock
  output          VGA_HS,         //  VGA H_SYNC
  output          VGA_VS,         //  VGA V_SYNC
  output          VGA_BLANK,      //  VGA BLANK
  output          VGA_SYNC,       //  VGA SYNC
  output  [9:0]   VGA_R,          //  VGA Red[9:0]
  output  [9:0]   VGA_G,          //  VGA Green[9:0]
  output  [9:0]   VGA_B,          //  VGA Blue[9:0]
  ////////////////  Ethernet Interface  ////////////////////////////
  inout   [15:0]  ENET_DATA,      //  DM9000A DATA bus 16Bits
  output          ENET_CMD,       //  DM9000A Command/Data Select, 0 = Command, 1 = Data
  output          ENET_CS_N,      //  DM9000A Chip Select
  output          ENET_WR_N,      //  DM9000A Write
  output          ENET_RD_N,      //  DM9000A Read
  output          ENET_RST_N,     //  DM9000A Reset
  input           ENET_INT,       //  DM9000A Interrupt
  output          ENET_CLK,       //  DM9000A Clock 25 MHz
  ////////////////////  Audio CODEC ////////////////////////////
  inout           AUD_ADCLRCK,    //  Audio CODEC ADC LR Clock
  input           AUD_ADCDAT,     //  Audio CODEC ADC Data
  inout           AUD_DACLRCK,    //  Audio CODEC DAC LR Clock
  output          AUD_DACDAT,     //  Audio CODEC DAC Data
  inout           AUD_BCLK,       //  Audio CODEC Bit-Stream Clock
  output          AUD_XCK,        //  Audio CODEC Chip Clock
  ////////////////////  TV Devoder  ////////////////////////////
  input   [7:0]   TD_DATA,        //  TV Decoder Data bus 8 bits
  input           TD_HS,          //  TV Decoder H_SYNC
  input           TD_VS,          //  TV Decoder V_SYNC
  output          TD_RESET,       //  TV Decoder Reset
  ////////////////////////  GPIO  ////////////////////////////////
  inout   [35:0]  GPIO_0,         //  GPIO Connection 0
  inout   [35:0]  GPIO_1          //  GPIO Connection 1
);

assign  LCD_ON    = 1'b1;
assign  LCD_BLON  = 1'b1;
assign  TD_RESET  = 1'b1;

//  All inout port turn to tri-state
assign  FL_DQ       = 8'hzz;
assign  SRAM_DQ     = 16'hzzzz;
assign  OTG_DATA    = 16'hzzzz;
assign  LCD_DATA    = 8'hzz;
assign  SD_DAT      = 1'bz;
assign  I2C_SDAT    = 1'bz;
assign  ENET_DATA   = 16'hzzzz;
assign  AUD_ADCLRCK = 1'bz;
assign  AUD_DACLRCK = 1'bz;
assign  AUD_BCLK    = 1'bz;

//  CCD
wire  [9:0]   CCD_DATA;
wire          CCD_SDAT;
wire          CCD_SCLK;
wire          CCD_FLASH;
wire          CCD_FVAL;
wire          CCD_LVAL;
wire          CCD_PIXCLK;
reg           CCD_MCLK; //  CCD Master Clock

wire  [15:0]  Read_DATA1;
wire  [15:0]  Read_DATA2;
wire          VGA_CTRL_CLK;
wire          AUD_CTRL_CLK;
wire  [9:0]   mCCD_DATA;
wire          mCCD_DVAL;
wire          mCCD_DVAL_d;
wire  [10:0]  X_Cont;
wire  [10:0]  Y_Cont;
wire  [9:0]   X_ADDR;
wire  [31:0]  Frame_Cont;
wire  [9:0]   mCCD_R;
wire  [9:0]   mCCD_G;
wire  [9:0]   mCCD_B;
wire          DLY_RST_0;
wire          DLY_RST_1;
wire          DLY_RST_2;
wire          Read;
reg   [9:0]   rCCD_DATA;
reg           rCCD_LVAL;
reg           rCCD_FVAL;
wire  [9:0]   sCCD_R;
wire  [9:0]   sCCD_G;
wire  [9:0]   sCCD_B;
wire          sCCD_DVAL;

//  For Sensor 1
assign  CCD_DATA[0] = GPIO_1[0];
assign  CCD_DATA[1] = GPIO_1[1];
assign  CCD_DATA[2] = GPIO_1[5];
assign  CCD_DATA[3] = GPIO_1[3];
assign  CCD_DATA[4] = GPIO_1[2];
assign  CCD_DATA[5] = GPIO_1[4];
assign  CCD_DATA[6] = GPIO_1[6];
assign  CCD_DATA[7] = GPIO_1[7];
assign  CCD_DATA[8] = GPIO_1[8];
assign  CCD_DATA[9] = GPIO_1[9];
assign  GPIO_1[11]  = CCD_MCLK;
assign  CCD_FVAL    = GPIO_1[13];
assign  CCD_LVAL    = GPIO_1[12];
assign  CCD_PIXCLK  = GPIO_1[10];

assign  LEDR        = SW;
assign  LEDG        = Y_Cont;
assign  VGA_CTRL_CLK= CCD_MCLK;
assign  VGA_CLK     = ~CCD_MCLK;

always@(posedge CLOCK_50)
  CCD_MCLK  <=  ~CCD_MCLK;

always@(posedge CCD_PIXCLK) begin
  rCCD_DATA	<=	CCD_DATA;
  rCCD_LVAL	<=	CCD_LVAL;
  rCCD_FVAL	<=	CCD_FVAL;
end

VGA_Controller  vga0 (
  //  Host Side
  .oRequest(Read),
  .iRed({Read_DATA1[14:10],Read_DATA2[14:10]}),
  .iGreen({Read_DATA1[14:10],Read_DATA2[14:10]}),
  .iBlue({Read_DATA1[14:10],Read_DATA2[14:10]}),
  //  VGA Side
  .oVGA_R(VGA_R),
  .oVGA_G(VGA_G),
  .oVGA_B(VGA_B),
  .oVGA_H_SYNC(VGA_HS),
  .oVGA_V_SYNC(VGA_VS),
  .oVGA_SYNC(VGA_SYNC),
  .oVGA_BLANK(VGA_BLANK),
  //  Control Signal
  .iCLK(VGA_CTRL_CLK),
  .iRST_N(DLY_RST_2)
);

Reset_Delay reset0  (
  .iCLK(CLOCK_50),
  .iRST(KEY[0]),
  .oRST_0(DLY_RST_0),
  .oRST_1(DLY_RST_1),
  .oRST_2(DLY_RST_2)
);

CCD_Capture capture0 (
  .oDATA(mCCD_DATA),
  .oDVAL(mCCD_DVAL),
  .oX_Cont(X_Cont),
  .oY_Cont(Y_Cont),
  .oFrame_Cont(Frame_Cont),
  .iDATA(rCCD_DATA),
  .iFVAL(rCCD_FVAL),
  .iLVAL(rCCD_LVAL),
  .iSTART(!KEY[3]),
  .iEND(!KEY[2]),
  .iCLK(CCD_PIXCLK),
  .iRST(DLY_RST_1)
);

RAW2RGB rgb0 (
  .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)
);

SEG7_LUT_8 seg0 (
  .oSEG0(HEX0),
  .oSEG1(HEX1),
  .oSEG2(HEX2),
  .oSEG3(HEX3),
  .oSEG4(HEX4),
  .oSEG5(HEX5),
  .oSEG6(HEX6),
  .oSEG7(HEX7),
  .iDIG(Frame_Cont)
);

Sdram_Control_4Port sdram0  (
  //  HOST Side
  .REF_CLK(CLOCK_50),
  .RESET_N(1'b1),
  //  FIFO Write Side 1
  .WR1_DATA({sCCD_G[9:5], sCCD_B[9:0]}),
  .WR1(sCCD_DVAL),
  .WR1_ADDR(0),
  .WR1_MAX_ADDR(640*512),
  .WR1_LENGTH(9'h100),
  .WR1_LOAD(!DLY_RST_0),
  .WR1_CLK(CCD_PIXCLK),
  //  FIFO Write Side 2
  .WR2_DATA({sCCD_G[4:0], sCCD_R[9:0]}),
  .WR2(sCCD_DVAL),
  .WR2_ADDR(22'h100000),
  .WR2_MAX_ADDR(22'h100000+640*512),
  .WR2_LENGTH(9'h100),
  .WR2_LOAD(!DLY_RST_0),
  .WR2_CLK(CCD_PIXCLK),
  //  FIFO Read Side 1
  .RD1_DATA(Read_DATA1),
  .RD1(Read),
  .RD1_ADDR(640*16),
  .RD1_MAX_ADDR(640*496),
  .RD1_LENGTH(9'h100),
  .RD1_LOAD(!DLY_RST_0),
  .RD1_CLK(VGA_CTRL_CLK),
  //  FIFO Read Side 2
  .RD2_DATA(Read_DATA2),
  .RD2(Read),
  .RD2_ADDR(22'h100000+640*16),
  .RD2_MAX_ADDR(22'h100000+640*496),
  .RD2_LENGTH(9'h100),
  .RD2_LOAD(!DLY_RST_0),
  .RD2_CLK(VGA_CTRL_CLK),
  //  SDRAM Side
  .SA(DRAM_ADDR),
  .BA({DRAM_BA_1,DRAM_BA_0}),
  .CS_N(DRAM_CS_N),
  .CKE(DRAM_CKE),
  .RAS_N(DRAM_RAS_N),
  .CAS_N(DRAM_CAS_N),
  .WE_N(DRAM_WE_N),
  .DQ(DRAM_DQ),
  .DQM({DRAM_UDQM,DRAM_LDQM}),
  .SDR_CLK(DRAM_CLK)
);

I2C_CCD_Config  ccd_config0 (
  //  Host Side
  .iCLK(CLOCK_50),
  .iRST_N(KEY[1]),
  .iExposure(SW[15:0]),
  //  I2C Side
  .I2C_SCLK(GPIO_1[14]),
  .I2C_SDAT(GPIO_1[15])
);

Mirror_Col  mirror0 (
  //  Input Side
  .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),
  //  Output Side
  .oCCD_R(sCCD_R),
  .oCCD_G(sCCD_G),
  .oCCD_B(sCCD_B),
  .oCCD_DVAL(sCCD_DVAL)
);

endmodule
