// --------------------------------------------------------------------
//   ==================================================================
//   >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
//   ------------------------------------------------------------------
//   Copyright (c) 2014 by Lattice Semiconductor Corporation
//   ALL RIGHTS RESERVED 
//   ------------------------------------------------------------------
//
//   Permission:
//
//      Lattice SG Pte. Ltd. grants permission to use this code
//      pursuant to the terms of the Lattice Reference Design License Agreement. 
//
//
//   Disclaimer:
//
//      This VHDL or Verilog source code is intended as a design reference
//      which illustrates how these types of functions can be implemented.
//      It is the user's responsibility to verify their design for
//      consistency and functionality through the use of formal
//      verification methods.  Lattice provides no warranty
//      regarding the use or functionality of this code.
//
//   --------------------------------------------------------------------
//
//                  Lattice SG Pte. Ltd.
//                  101 Thomson Road, United Square #07-02 
//                  Singapore 307591
//
//
//                  TEL: 1-800-Lattice (USA and Canada)
//                       +65-6631-2000 (Singapore)
//                       +1-503-268-8001 (other locations)
//
//                  web: http://www.latticesemi.com/
//                  email: techsupport@latticesemi.com
//
//   --------------------------------------------------------------------
//
// This is a serial DDR LVDS to SDR CMOS parallel bridge 
// 
//
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   V1.0 :| GJenning          :| 05/09/12  :| Alpha Release
//------------------------------------------------------------------------------------------------------------------------------------------

module MIPI_CSI2_Serial2Parallel_Bridge #(
   parameter bus_width          = 10        ,   // 6-24            - the width of the pixel data, only formats supported by CSI2 Specification 
   parameter lane_width         = 4         ,   // 1, 2, 4         - the number of lanes used, 10 bit or 12 bit widths supported
   parameter lp_mode            = "OFF"      ,   // OFF, ON         - changes clocking scheme for use when clock contains both HS and LP modes; OFF = free running clock, ON=LP mode in blanking periods
   parameter line_length_detect = 0         ,   // 0, 1            - setting this to one will only allow line valid to go active for lines of size line_length
   parameter line_length        = 2400      ,   //                 - Only valid if line_length_detect = 1.  Number of bytes in a line.  Example: 1920, 10 bit pixels per line = 1920*10/8 = 2400.  Should be set to the expected value of word count in the CSI2 Packet Header
   parameter format             = "RAW10"     )   // RAW, RGB, YUV   - Defines output format type
   (                                          
   input  wire                     rstn        ,   // reset, active low
   input  wire                     DCK         ,   // serial input clock
                                      
   input                           CH0     ,
   input                           CH1     ,
   input                           CH2     ,
   input                           CH3     ,   // LVDS DDR input data
   output                          pixclk_adj  ,   // output pixel clock
   output [bus_width-1:0]          pixdata     ,   // output SDR data(LVCMOS)    
   output                          fv          ,   // frame valid output 
   output                          lv          ,   // line valid output
   
   input                           sensor_clk  , 
   input                           scl_in  ,
   input                           sda_in  ,
   output                          scl     ,
   output                          sda     ,
   output                          XCLR    ,
   output                          m27_clk_out,
   
   input                           CMOS_D0_P,
   input                           CMOS_D0_N,
   output                          LED0,
   output                          LED1
);

wire [31:0] din, ch_din;
wire pixclk;
reg [21:0] xclr_dly;
deser deser(.clkin(DCK), .sync_reset(~rstn), .start(1), .sync_clk(sensor_clk), .sclk(sclk_l), .datain({CH3,CH2,CH1,CH0}), .q(din16));

gearing_converter_fifo gearing_converter_fifo(.Data(din16), .WrClock(sclk_l), .RdClock(sclk), .WrEn(1'b1), .RdEn(1'b1), .Reset(~rstn), .RPReset(~rstn), .Q(din32));

MIPI_CSI2_Serial2Parallel #(.bus_width(bus_width), .lane_width(lane_width), .format(format)) serial2parallel(.rstn(lock), .din(ch_din), .fv(fv), .lv(lv), .pixdata(pixdata), .pixclk(pixclk), .sclk(sclk), .vc(), .dt(), .wc(), .ecc(), .line_length_detect(line_length_detect), .line_length(line_length));
generate
     if (bus_width==10 & lane_width == 4 & lp_mode=="ON")
          pll_10bit_4lane_lp pll(.CLKI(sensor_clk), .RST(~rstn), .CLKOP(pixclk), .CLKOS(pixclk_adj), .CLKOS2(sclk), .LOCK(lock));
     else if (bus_width==10 & lane_width == 2 & lp_mode=="ON")
          pll_10bit_2lane_lp pll(.CLKI(sensor_clk), .RST(~rstn), .CLKOP(pixclk), .CLKOS(pixclk_adj), .CLKOS2(sclk),  .LOCK(lock));
	 else if (bus_width==10 & lane_width == 4 & lp_mode=="OFF") begin
           pll_10bit_4lane pll(.CLKI(sclk_l), .RST(~rstn), .CLKOP(pixclk), .CLKOS(pixclk_adj), .CLKOS2(sclk), .LOCK(lock)); /*assign sclk = sclk_in;*/ end
     else if (bus_width==10 & lane_width == 2 & lp_mode=="OFF") begin
          pll_10bit_2lane pll(.CLK(clkdiv4), .RESET(~rstn), .CLKOP(pixclk), .CLKOS(pixclk_adj), .LOCK(lock)); /*assign sclk = sclk_in;*/ end
	 
endgenerate


generate
     if       (lp_mode=="ON")    
          LP_crossclk_cnvrt LP_crossclk_cnvrt(.Data(din32), .WrClock(sclk), .RdClock(sclk), .WrEn(1), .RdEn(1), .Reset(~rstn), .RPReset(~rstn), .Q(ch_din), .Empty(deser_ready));
     else if  (lp_mode=="OFF") 
          assign ch_din = din32;
endgenerate

//IMX169 Demo specific
          assign scl = scl_in;
          assign sda = sda_in;

          always @(posedge sensor_clk or negedge rstn)
              if (!rstn)
                   xclr_dly <=0;
              else
                   xclr_dly <= {xclr_dly[20:0], rstn};

          assign XCLR = xclr_dly[20];    
          
		  assign m27_clk_out = sensor_clk;

          assign LED0 = CMOS_D0_P;
          assign LED1 = CMOS_D0_N;


endmodule
      
      
      